linux 内核-信号-队列

static ssize_t mxc_v4l_read(struct file *file, char *buf, size_t count,
                loff_t *ppos)
{
    int err = 0;
    u8 *v_address[2];
    struct video_device *dev = video_devdata(file);
    cam_data *cam = video_get_drvdata(dev);

    if (down_interruptible(&cam->busy_lock))
        return -EINTR;

    /* Stop the viewfinder */
    if (cam->overlay_on == true)
        stop_preview(cam);

    v_address[0] = dma_alloc_coherent(0,
                       PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage),
                       &cam->still_buf[0],
                       GFP_DMA | GFP_KERNEL);

    v_address[1] = dma_alloc_coherent(0,
                       PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage),
                       &cam->still_buf[1],
                       GFP_DMA | GFP_KERNEL);

    if (!v_address[0] || !v_address[1]) {
        err = -ENOBUFS;
        goto exit0;
    }

    err = prp_still_select(cam);
    if (err != 0) {
        err = -EIO;
        goto exit0;
    }

    cam->still_counter = 0;
    err = cam->csi_start(cam);
    if (err != 0) {
        err = -EIO;
        goto exit1;
    }

    if (!wait_event_interruptible_timeout(cam->still_queue,
                          cam->still_counter != 0,
                          10 * HZ)) {
        pr_err("ERROR: v4l2 capture: mxc_v4l_read timeout counter %x/n",
               cam->still_counter);
        err = -ETIME;
        goto exit1;
    }
    err = copy_to_user(buf, v_address[1], cam->v2f.fmt.pix.sizeimage);

      exit1:
    prp_still_deselect(cam);

      exit0:
    if (v_address[0] != 0)
        dma_free_coherent(0, cam->v2f.fmt.pix.sizeimage, v_address[0],
                  cam->still_buf[0]);
    if (v_address[1] != 0)
        dma_free_coherent(0, cam->v2f.fmt.pix.sizeimage, v_address[1],
                  cam->still_buf[1]);

    cam->still_buf[0] = cam->still_buf[1] = 0;

    if (cam->overlay_on == true) {
        start_preview(cam);
    }

    up(&cam->busy_lock);
    if (err < 0)
        return err;

    return (cam->v2f.fmt.pix.sizeimage - err);
}

 

 

kernel/include/semaphore.h

 

#define init_MUTEX(sem)        sema_init(sem, 1)
#define init_MUTEX_LOCKED(sem)    sema_init(sem, 0)

 

kernel/semaphore.c


int down_interruptible(struct semaphore *sem)

 

  /**
  * down_interruptible - acquire the semaphore unless interrupted
  * @sem: the semaphore to be acquired
  *
  * Attempts to acquire the semaphore. If no more tasks are allowed to
  * acquire the semaphore, calling this function will put the task to sleep.
  * If the sleep is interrupted by a signal, this function will return -EINTR.
  * If the semaphore is successfully acquired, this function returns 0.
  */

 

 

   调用down_interruptible()的进程在调用down_interruptible()之后,如果sem<0,那么就进入到可中断的睡眠状态并调度其它进程运行, 但是一旦该进程获得信号,那么就会从down_interruptible函数中返回。如果是被别的信号中断则返回错误号-EINTR。

 

 

 

/**
 * up - release the semaphore
 * @sem: the semaphore to release
 *
 * Release the semaphore.  Unlike mutexes, up() may be called from any
 * context and even by tasks which have never called down().
 */
void up(struct semaphore *sem)

 

***************************************队列

 

 
wait_event_interruptible_timeout和schedule_timeout的
一、适用情况
wait_event_interruptible_timeout和schedule_timeout的区别
当在某个硬件驱动程序中使用wait_event_interruptible_timeout时,执行的继续可以通过以下两种方式获得:
1.其他人在等待队列上调用了wake_up(并且condition满足)
2.超时到期。
而调用schedule_timeout的进程始终会在超时到期时被唤醒。
二、函数原型
wait_event_interruptible_timeout(queue, condition, timeout)
返回值:
大于零:剩余时间(以jiffy计)
零:给定的时间到期。
signed long schedule_timeout(signed long timeout);
返回值:
零:正常返回值
大于零:函数提前返回(比如响应某个信号),返回值为剩余时间
三、使用实例
1.wait_event_interrruptible_timeout
(1)初始化等待队列
int flags = 0;
wait_queue_head_t    select_wait;
init_waitqueue_head(&select_wait);
(2)等待事件的发生(条件满足)
{
...
    wait_event_interruptible_timeout(select_wait, flags != 0, HZ/10);
...
}
(3)唤醒等待队列
{
...
   if(waitqueue_active(&select_wait))
   {
       flags = 1;
       wake_up_interruptible( &nd->select_in_wait );
   }
...
}   
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值