linux Kernel--wait_event_interruptible_timeout() Function Analysis

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

Posted by Irksome on Fri, 21 Dec 2018 18:09:05 -0800