等待队列实例 wait_for_avail_min
2011-08-10 13:58
274 查看
static int wait_for_avail_min(struct snd_pcm_substream *substream,
snd_pcm_uframes_t *availp)
{
struct snd_pcm_runtime *runtime = substream->runtime;
int is_playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
wait_queue_t wait; //定义一个等待队列
int err = 0;
snd_pcm_uframes_t avail = 0;
long tout;
init_waitqueue_entry(&wait, current); //动态初始化一个等待队列入口项,将其和当前进程关联起来,以便唤醒当前进程
add_wait_queue(&runtime->tsleep, &wait); //向等待队列头中添加等待队列
for (;;) {
if (signal_pending(current)) {// 检查当前进程是否有待处理的信号,返回不为0表示有信号需要处理。
err = -ERESTARTSYS;
/*-ERESTARTSYS表示信号函数处理完毕后重新执行信号函数前的某个系统调用。
也就是说,如果信号函数前有发生系统调用,在调度用户信号函数之前,内核会检查系统调用的返回值,看看是不是因为这个信号而中断了系统调用.
如果返回值-ERESTARTSYS,并且当前调度的信号具备-ERESTARTSYS属性,系统就会在用户信号函数返回之后再执行该系统调用。*/
break;
}
set_current_state(TASK_INTERRUPTIBLE); //设置当前进程的状态为可中断的。当满足“条件达成”、“收到信号”之一时就被唤醒
snd_pcm_stream_unlock_irq(substream);
tout = schedule_timeout(msecs_to_jiffies(10000));
//在指定的时间内没有获得等待的资源就返回
snd_pcm_stream_lock_irq(substream);
switch (runtime->status->state) {
case SNDRV_PCM_STATE_SUSPENDED:
err = -ESTRPIPE;
goto _endloop;
case SNDRV_PCM_STATE_XRUN:
err = -EPIPE;
goto _endloop;
case SNDRV_PCM_STATE_DRAINING:
if (is_playback)
err = -EPIPE;
else
avail = 0; /* indicate draining */
goto _endloop;
case SNDRV_PCM_STATE_OPEN:
case SNDRV_PCM_STATE_SETUP:
case SNDRV_PCM_STATE_DISCONNECTED:
err = -EBADFD;
goto _endloop;
}
//时间到被唤醒,没有收到信号
if (!tout) { snd_printd("%s write error (DMA or IRQ trouble?)\n",
is_playback ? "playback" : "capture");
err = -EIO;
break;
}
//收到信号被唤醒
if (is_playback)
avail = snd_pcm_playback_avail(runtime);
else
avail = snd_pcm_capture_avail(runtime);
if (avail >= runtime->control->avail_min)
break;
}
_endloop:
remove_wait_queue(&runtime->tsleep, &wait); //在等待的资源或条件满足时,进程被唤醒,将等待队列从等待头中删除
*availp = avail;
return err;
}
snd_pcm_uframes_t *availp)
{
struct snd_pcm_runtime *runtime = substream->runtime;
int is_playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
wait_queue_t wait; //定义一个等待队列
int err = 0;
snd_pcm_uframes_t avail = 0;
long tout;
init_waitqueue_entry(&wait, current); //动态初始化一个等待队列入口项,将其和当前进程关联起来,以便唤醒当前进程
add_wait_queue(&runtime->tsleep, &wait); //向等待队列头中添加等待队列
for (;;) {
if (signal_pending(current)) {// 检查当前进程是否有待处理的信号,返回不为0表示有信号需要处理。
err = -ERESTARTSYS;
/*-ERESTARTSYS表示信号函数处理完毕后重新执行信号函数前的某个系统调用。
也就是说,如果信号函数前有发生系统调用,在调度用户信号函数之前,内核会检查系统调用的返回值,看看是不是因为这个信号而中断了系统调用.
如果返回值-ERESTARTSYS,并且当前调度的信号具备-ERESTARTSYS属性,系统就会在用户信号函数返回之后再执行该系统调用。*/
break;
}
set_current_state(TASK_INTERRUPTIBLE); //设置当前进程的状态为可中断的。当满足“条件达成”、“收到信号”之一时就被唤醒
snd_pcm_stream_unlock_irq(substream);
tout = schedule_timeout(msecs_to_jiffies(10000));
//在指定的时间内没有获得等待的资源就返回
snd_pcm_stream_lock_irq(substream);
switch (runtime->status->state) {
case SNDRV_PCM_STATE_SUSPENDED:
err = -ESTRPIPE;
goto _endloop;
case SNDRV_PCM_STATE_XRUN:
err = -EPIPE;
goto _endloop;
case SNDRV_PCM_STATE_DRAINING:
if (is_playback)
err = -EPIPE;
else
avail = 0; /* indicate draining */
goto _endloop;
case SNDRV_PCM_STATE_OPEN:
case SNDRV_PCM_STATE_SETUP:
case SNDRV_PCM_STATE_DISCONNECTED:
err = -EBADFD;
goto _endloop;
}
//时间到被唤醒,没有收到信号
if (!tout) { snd_printd("%s write error (DMA or IRQ trouble?)\n",
is_playback ? "playback" : "capture");
err = -EIO;
break;
}
//收到信号被唤醒
if (is_playback)
avail = snd_pcm_playback_avail(runtime);
else
avail = snd_pcm_capture_avail(runtime);
if (avail >= runtime->control->avail_min)
break;
}
_endloop:
remove_wait_queue(&runtime->tsleep, &wait); //在等待的资源或条件满足时,进程被唤醒,将等待队列从等待头中删除
*availp = avail;
return err;
}
相关文章推荐
- 31 completion完成量,wait_queue_head_t等待队列和epoll
- 对话框中WaitForSingleObject等待线程退出导致程序阻塞的原因及解决
- 对话框中WaitForSingleObject等待线程退出导致程序阻塞的原因及解决
- linux等待队列wait_queue_head_t和wait_queue_t
- linux等待队列wait_queue_head_t和wait_queue_t
- Linux 设备驱动--- 内核等待队列 --- wait_queue_head --- wait_event_interruptible --- 按键驱动程序优化
- Linux内核驱动开发与等待队列机制实例
- Linux等待队列wait_queue_head_t和wait_queue_t
- linux等待队列wait_queue_head_t和wait_queue_t
- 父进程 等待子进程初始化后才使用子进程_waitforinputidle
- linux等待队列wait_queue_head_t和wait_queue_t
- 关于 CreateEvent 和WaitForMultipleObjects以及 WaitForSingleObject 等函数的使用实例
- WaitForMultipleObjects等待多个事件对象
- 开启后需要等待APB1时钟与RTC时钟同步才能读写寄存器 RTC_WaitForSynchro
- 等待队列wait queue(wait_event() interruptible_sleep_on()等应用方法)
- WaitForSingleObject 和 WaitForMultipleObjects函数 (让线程挂起等待事件)
- WaitForSingleObject 等待线程句柄
- linux内核中等待队列 (函数wait_event与wake_up)
- kobox : key_waitqueue.c -v1 如何内核线程,如何使用等待队列
- linux内核中等待队列(wait_event,wake_up...)