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; //时间到被唤醒,没有收到信号
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;
}