0
点赞
收藏
分享

微信扫一扫

MySQL体系架构解析

扒皮狼 2024-07-24 阅读 16

线程同步第一篇

completion

数据结构

struct swait_queue_head {
    raw_spinlock_t      lock;
    struct list_head    task_list;
};
struct completion {
    unsigned int done;
    struct swait_queue_head wait;
};

Linux APIs

static inline void init_completion(struct completion *x);
void wait_for_completion(struct completion *);
int __sched wait_for_completion_interruptible(struct completion *x);
void complete(struct completion *);

bool completion_done(struct completion *x);

在Linux驱动器中的应用

imx SPI 驱动器

变量定义

在结构中,定义两个completion 变量,dma_rx_completion 和 dma_tx_completion。

struct spi_imx_data {
...
    struct completion dma_rx_completion;
    struct completion dma_tx_completion;
...
};
初始化

在sdma初始化程序中,调用init_completion函数初始化这两个变量。见下列的程序代码段。

static int spi_imx_sdma_init(struct device *dev, struct spi_imx_data *spi_imx,
                 struct spi_master *master)
{
 ...
    init_completion(&spi_imx->dma_rx_completion);
    init_completion(&spi_imx->dma_tx_completion);
...
}

等待任务完成

在触发sdma传送之后,调用wait_for_completion_interruptible函数等待sdma传送结束。

static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx,
                struct spi_transfer *transfer)
{
...
        spi_imx->devtype_data->trigger(spi_imx);

        if (wait_for_completion_interruptible(&spi_imx->dma_tx_completion) ||
            spi_imx->slave_aborted) {
            dev_dbg(spi_imx->dev,
                "I/O Error in DMA TX interrupted\n");
            dmaengine_terminate_all(master->dma_tx);
            dmaengine_terminate_all(master->dma_rx);
            return -EINTR;
        }

        if (wait_for_completion_interruptible(&spi_imx->dma_rx_completion) ||
            spi_imx->slave_aborted) {
            dev_dbg(spi_imx->dev,
                "I/O Error in DMA RX interrupted\n");
            dmaengine_terminate_all(master->dma_tx);
            dmaengine_terminate_all(master->dma_rx);
            return -EINTR;
        }
...
}
通知任务完成

在sdma完成回调函数中,使用complete API,通知任务已经完成。

static void spi_imx_dma_rx_callback(void *cookie)
{
    struct spi_imx_data *spi_imx = (struct spi_imx_data *)cookie;
    complete(&spi_imx->dma_rx_completion);
}
static void spi_imx_dma_tx_callback(void *cookie)
{
    struct spi_imx_data *spi_imx = (struct spi_imx_data *)cookie;
    complete(&spi_imx->dma_tx_completion);
}

spin_lock

数据结构

typedef volatile int pthread_spinlock_t;
typedef pthread_spinlock_t spinlock_t;

APIs

    spin_lock_init(spinlock_t *lock);
    int spin_is_locked(spinlock_t *lock)
    
    void spin_lock(spinlock_t *lock);
    void spin_unlock(spinlock_t *lock);
     
     int spin_trylock(spinlock_t *lock);
      
    spin_lock_irqsave(spinlock_t *lock, unsigned long flags);
    void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags);
    
    void spin_lock_irq(spinlock_t *lock);
    void spin_unlock_irq(spinlock_t *lock);
  
  	int  atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock);
  	int  atomic_dec_and_lock_irqsave((atomic_t *atomic, spinlock_t *lock, unsigned long *flags);
    

在Linux内核中的应用

AT91 SPI 驱动器

在设备探测代码中,初始化
int at91_usart_spi_probe(struct platform_device *pdev) {
    ...
	spin_lock_init(&aus->lock);
	....
}
在中断处理程序中使用

该中断处理程序是不可重入代码,在多CPU核心的系统中,这是必要的。
在加入中断处理代码时,使用spinlock给这个代码加锁,在执行完代码,返回之前,解锁。

irqreturn_t at91_usart_spi_interrupt(int irq, void *dev_id) {
        ...
		spin_lock(&aus->lock);
        ...
        if (at91_usart_spi_rx_ready(aus)) {
               at91_usart_spi_rx(aus);
               spin_unlock(&aus->lock);
               return IRQ_HANDLED;
        }
       spin_unlock(&aus->lock);
       return IRQ_NONE;
}
举报

相关推荐

0 条评论