I have two Contiki processes with one process, master
, posting two different events to a second process, send
. The first event sent is PROCESS_EVENT_CONTINUE
and the second event is PROCESS_EVENT_MSG
.
I am posting these events sequentially, one after another, from the process called main
.
The complete code is:
#include "contiki.h"
#include "lib/list.h"
#include "lib/memb.h"
#include "lib/random.h"
#include "net/rime/rime.h"
#include<stdio.h>
PROCESS(master, "master_DGHS");
PROCESS(send, "master_DGHS");
AUTOSTART_PROCESSES( &master, &send);
PROCESS_THREAD(master, ev, data)
{
PROCESS_BEGIN();
process_post(&send, PROCESS_EVENT_CONTINUE, NULL);
process_post(&send, PROCESS_EVENT_MSG, NULL);
PROCESS_END();
}
PROCESS_THREAD(send, ev, data)
{
static struct etimer et;
PROCESS_BEGIN();
while(1)
{
PROCESS_WAIT_EVENT();
if(ev == PROCESS_EVENT_CONTINUE)
{
printf("PROCESS_EVENT_CONTINUE\n");
etimer_set(&et, CLOCK_SECOND );
PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));
}else
if(ev == PROCESS_EVENT_MSG)
{
printf("PROCESS_EVENT_MSG\n");
etimer_set(&et, CLOCK_SECOND );
PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));
}
}
PROCESS_END();
}
The problem is that the second process send
sees the first event (it prints PROCESS_EVENT_CONTINUE
), but it doesn't see the second event (it does not print PROCESS_EVENT_MSG
).
In other words, the second event gets lost. However if I remove the source line
PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));
the second process send
sees both events (both PROCESS_EVENT_CONTINUE
and PROCESS_EVENT_MSG
are printed). So, adding this source line causes the second event, PROCESS_EVENT_MSG
, to be ignored or discarded.
Why does adding this source line result in the second event getting lost?
The problem is that PROCESS_WAIT_EVENT_UNTIL
consumes all events until the loop's condition becomes true.
By calling PROCESS_WAIT_EVENT_UNTIL() in the area separated by the PROCESS_BEGIN() and PROCESS_END() calls, one can yield control to the scheduler, and only resume execution when an event is delivered. A condition is given as an argument to PROCESS_WAIT_EVENT_UNTIL(), and this condition must be fulfilled for the processes to continue execution after the call to PROCESS_WAIT_EVENT_UNTIL(). If the condition is not fulfilled, the process yields control back to the OS until a new event is delivered.
This is the sequence of actions in your example:
send
process gets PROCESS_EVENT_CONTINUE
event.printf
, sets up a timer, and enters PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));
send
process gets PROCESS_EVENT_MSG
event immediately after.WAIT_EVENT_UNTIL
loop and discards the second event, because the timer is not expired yet.send
process gets PROCESS_EVENT_TIMER
event.So, the second event is received by the process, but not acted upon, since the process is waiting for another event. Hope that now you understand why removing the WAIT_EVENT_UNTIL
macro solves this issue.