clinux-kernellinux-device-driversystem-callsepoll

Why do we need to call poll_wait in poll?


In LDD3, i saw such codes

static unsigned int scull_p_poll(struct file *filp, poll_table *wait)
{
    struct scull_pipe *dev = filp->private_data;
    unsigned int mask = 0;

    /*
     * The buffer is circular; it is considered full
     * if "wp" is right behind "rp" and empty if the
     * two are equal.
     */
    down(&dev->sem);
    poll_wait(filp, &dev->inq,  wait);
    poll_wait(filp, &dev->outq, wait);
    if (dev->rp != dev->wp)
        mask |= POLLIN | POLLRDNORM;    /* readable */
    if (spacefree(dev))
        mask |= POLLOUT | POLLWRNORM;   /* writable */
    up(&dev->sem);
    return mask;
}

But it says poll_wait won't wait and will return immediately. Then why do we need to call it? Why can't we just return mask?


Solution

  • poll_wait adds your device (represented by the "struct file") to the list of those that can wake the process up.

    The idea is that the process can use poll (or select or epoll etc) to add a bunch of file descriptors to the list on which it wishes to wait. The poll entry for each driver gets called. Each one adds itself (via poll_wait) to the waiter list.

    Then the core kernel blocks the process in one place. That way, any one of the devices can wake up the process. If you return non-zero mask bits, that means those "ready" attributes (readable/writable/etc) apply now.

    So, in pseudo-code, it's roughly like this:

    foreach fd:
        find device corresponding to fd
        call device poll function to setup wait queues (with poll_wait) and to collect its "ready-now" mask
    
    while time remaining in timeout and no devices are ready:
        sleep
    
    return from system call (either due to timeout or to ready devices)