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)
***************************************队列
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)
***************************************队列