I am writing a kernel module that performs timing functions using an external clock. Basically, the module counts pulses from the clock, rolling over the count every so often. User processes can use an ioctl to ask to be woken up at a specific count; they then perform some task and invoke the same ioctl to wait until the next time the same count comes up. In this way they can execute periodically using this external timing.
I have created an array of wait_queue_head_t
s, one for each available schedule slot (i.e. each "count", as described above). When a user process invokes the ioctl, I simply call sleep_on()
with the ioctl argument specifying the schedule slot and thus the wait queue. When the kernel module receives a clock pulse and increments the count, it wakes up the wait queue corresponding to that count.
I know that it is considered bad practice to use sleep_on()
, because there is potential for state to change between a test to see if a process should sleep, and the corresponding call to sleep_on()
. But in this case I do not perform such a test before sleeping because the waking event is periodic. It doesn't matter if I "just miss" a waking event because another will come shortly (in fact, if the ioctl is invoked very close to the specified schedule slot, then something went wrong and I would prefer to wait until the next slot anyway).
I have looked at using wait_event_interruptible()
, which is considered safer, but I do not know what to put for the condition argument that wait_event_interruptible
requires. wait_event_interruptible
will check this condition before sleeping, but I want it to always sleep when the ioctl is invoked. I could use a flag that I clear before sleeping and set before waking up, but I'm worried this might not work in the case that there are multiple processes in the wait queue - one process might finish and clear the flag before the next is woken up.
Am I right to be worried about this? Or are all processes in a wait_queue guaranteed to be woken up before any of them run (and could therefore clear the flag)? Is there a better way to go about implementing a system such as this one? Is it actually okay to just use sleep_on()
? (If so, is there a version of sleep_on()
that is interruptible?)