Notes on wait_event()
About every 20:th ms the LegOS operating system makes a context
switch and checks if there are any other tasks that should be
running instead of the current task. All tasks waiting in the OS
are either waiting because that current executing task has a
higher priority or because it is waiting for some condition to be
fulfilled.
If a task wants to suspend itself until a certain condition has
been fulfilled, e.g. until some sensor has been pressed, it can
call the wait_event system call. The wait_event
system call is declared as wakeup_t
wait_event(wakeup_t(*wakeup) (wakeup_t), wakeup_t data);
. The function wait_event takes the name of a wakeup
function as its first argument. Every time the OS does a context
switch it will release the task with the highest priority which
wakeup function returns a non-zero value (unless the current
executing task has higher priority).
As second argument to wait_event a parameter is given
that can be used by the wakeup function to determine if the
calling task should be invocted. Both the argument and the return
value of a wakeup function should be of wakeup_t type.
For example, a wakeup function which returns if the touch
sensors 1 or 3 are pressed can be declared like:
wakeup_t sensor_press_wakeup(wakeup_t data) {
return TOUCH_1 || TOUCH_3;
}
A task that wants to wait for the event that one of the two
sensors has been pressed, e.g. to move a vehicle away from the
obstacle causing the sensors to react, are calling the
wait_event function with sensor_press_wakeup as
argument, something like:
...
/* run some code */
...
wait_event(sensor_press_wakeup, NULL);
...
/* run code to move away from obstacle */
...
Many LegOS system calls are indirectly implemented as
wait_event calls, e.g. semaphore handling and the
sleep and msleep commands. For example the code
for the operating system call msleep, which delays the
current task for some ms, is declared as (slightly simplified, see
the file tm.c for the real code):
unsigned int msleep(unsigned int msec)
{
(void) wait_event(tm_sleep_wakeup, sys_time + msec);
return 0;
}
The corresponding wakeup function tm_sleep_wakeup
looks like:
static wakeup_t tm_sleep_wakeup(wakeup_t data)
{
return ((time_t)data <= sys_time);
}
That is, the msleep function calculates the absolute
time the calling task should be waken up and the
tm_sleep_wakeup will return false (= 0) as long as system
time is smaller than this value.
In most cases you don't need to give any arguments to your
wakeup function but instead checks if some global variable or
sensor has been set.
|