I'm trying to understand how the select() system call works. My understanding is the following:
- The select() is called in the user space.
- The do_select() is called in the kernel as the result of select() call.
- The poll() function of device driver is called by do_select(). In the poll() function, the calling process is added to the wait queues of the device driver by calling poll_wait(). poll() returns a bit mask to do_select() indicating if the device is ready for read or write or there's exception.
- Back in do_select(), results from all files specified in the user space are collected and checked, and if no file has event, do_select() calls a schedule function to put the calling process to sleep.
- In the meantime, if an interrupt happens to the device, the interrupt service routine of the device calls wake_up() on the wait queue to wake up the processes sleeping in the queue.
- Process woken up in do_select() and checks the files again. This time it might find an event happened and returns the result back to the user space.

My questions:
- Is the above description correct?
- Does wake_up() in ISR cause context switch of current process immediately?
- Is there any problem if wake_up() from ISR happens before the process calls schedule()?