等待队列实例 wait_for_avail_min

 

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;
}

 

你可能感兴趣的:(等待队列实例 wait_for_avail_min)