Online analysis of this function, but most of them are reprinted from the same article, there is no further analysis. Make a summary:
In addition to looking directly at code logic, the most effective way to understand function functions is to annotate content.
As follows:
Function prototype: wait_event_interruptible_timeout(wq, condition, timeout) * Function: ~Sleep ~, until condition is true, or timeout timeout; *@wq: Waiting queue *@condition: A condition waiting for an event to occur (a C expression) * @timeout: timeout The program is used for sleep (TASK_INTERRUPTIBLE state) until @condition is true or a signal is received. Check @condition every time waiting for queue @wq to wake up. If there is any change operation that can change the waiting condition, call wake_up(); If @timeout timeouts, the function returns 0; if interrupted by the signal, the function returns - ERESTARTSYS; The condition is true before the timeout, otherwise the remaining jiffies will continue.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
Understanding the need:
1. TASK_INTERRUPTIBLE can be awakened by signals and wake_up(), when signals arrive, the process will be set to run, while TASK_UNINTERRUPTIBLE can only be awakened by wake_up().
2. Signal is a simulation of interrupt mechanism at software level, which is called soft interrupt.
3, signal_pending(current): Check whether the current process has signal processing. If the return value is not zero, it means that there is a signal to be processed.
Return - ERESTARTSYS indicates that a system call before the signal function is re-executed after the signal function has been processed. (This function only checks if there is a signal and does not process the signal)
If the condition is not satisfied, the signal will be generated and the waiting will begin. If it returns non-zero, it means that there is no signal to be processed, and the system call continues to be recycled to restart; if it returns zero, it means that there is signal to be processed, data is processed directly, and the system call ends normally.
4. schedule_timeout() is used to let the CPU run until the specified time is exhausted or when other events arrive and wake up the process (such as receiving a semaphore) before it can continue to run.
[Function returns 0 to indicate that timeout is awakened when it is exhausted; return integer to indicate that timeout is awakened when it is not exhausted, and a semaphore may be received at this time]
wait_event series functions (function: wait for events, put into sleep). The difference can be seen from the literal meaning:
wait_event(queue, conditon); wait_event_interruptible(queue, condition); wait_event_timeout(queue, condition, timeout); wait_event_interruptible_timeout(queue, condition, timeout); *queue:Waiting queue awakened as head of waiting queue *conditon: Must be satisfied or blocked *[timeout and conditon It has a higher priority than that.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
Reference to Kernel Source Understanding (in wait.h file)
#define __wait_event_interruptible_timeout(wq, condition, ret)
do {
DEFINE_WAIT(__wait);
for (;;) {
prepare_to_wait(&wq, &__wait, TASK_INTERRUPTIBLE);
if (condition)
break;
if (!signal_pending(current)) {
ret = schedule_timeout(ret);
if (!ret)
break;
continue;
}
ret = -ERESTARTSYS;
break;
}
finish_wait(&wq, &__wait);
} while (0)
/**
* wait_event_interruptible_timeout - sleep until a condition gets true or a timeout elapses
* @wq: the waitqueue to wait on
* @condition: a C expression for the event to wait for
* @timeout: timeout, in jiffies
*
* The process is put to sleep (TASK_INTERRUPTIBLE) until the
* @condition evaluates to true or a signal is received.
* The @condition is checked each time the waitqueue @wq is woken up.
*
* wake_up() has to be called after changing any variable that could
* change the result of the wait condition.
*
* The function returns 0 if the @timeout elapsed, -ERESTARTSYS if it
* was interrupted by a signal, and the remaining jiffies otherwise
* if the condition evaluated to true before the timeout elapsed.
*/
#define wait_event_interruptible_timeout(wq, condition, timeout)
({
long __ret = timeout;
if (!(condition))
__wait_event_interruptible_timeout(wq, condition, __ret);
__ret;
})