Usually, sleep_on() and wake_up() are used in the read()/write()/request() and interrupt functions respectively. However, some drivers do not have an interrupt routine but still need to sleep and be woken after some time delay.
There is an easy way to write a function to support this requirement in just a few lines of code:
#include <linux/sched.h> extern unsigned long jiffies; void my_delay(unsigned long jiffs) { current->state = TASK_INTERRUPTIBLE; current->timeout = jiffies+jiffs; schedule 0; }
The jiffies variable is globally declared and is a timer whose value is initialized at machine boot time and which is incremented 100 times per second (i.e. every 10 ms). The jiffs parameter to my_delay() should also be specified in 10 ms chunks.
It is also possible that, due to a hardware failure or similar cause, an expected interrupt never arrives. This could mean that a sleeping process may never get woken up. A solution in this case is to use a kernel timer via a pair of functions called add_timer() and del_timer() and a structure called struct timer_list:
struct timer_list { struct timer_list *next, *prev; unsigned long expires, data; void (*function) (unsigned long); }; void add_timer(struct timer_list *timer); void del_timer(struct timer_list *timer);
The add_timer() call sets up a specified function to be executed at a given time (given in jiffies). The chosen function will be executed at the specified time unless the timer is canceled. If the event for which the process is waiting occurs normally, then the interrupt service routine can cancel the timer (with del_timer()). If the interrupt fails to occur for any reason, then the timer will expire and call the specified function. This will usually flag that the error has taken place and wake_up() the sleeping process to deal with it.