Rewrote the process code so that initialization events are posted synchronously instead of asynchronously, so that we don't have to explicitly wait for processes to be initialized. This also reduces the size of the event queue by half on the Tmote Sky platform since the queue was maximized during system bootup. This change also prompted an update of the process invokation code to ensure that a process is not invoked again when processing an event. General cleanup of the code also.

This commit is contained in:
adamdunkels 2008-01-23 15:18:06 +00:00
parent c8dccbbd40
commit f4dd9ccd5b
2 changed files with 79 additions and 99 deletions

View File

@ -28,7 +28,7 @@
* *
* This file is part of the Contiki operating system. * This file is part of the Contiki operating system.
* *
* @(#)$Id: process.c,v 1.5 2007/04/04 09:19:18 nifi Exp $ * @(#)$Id: process.c,v 1.6 2008/01/23 15:18:06 adamdunkels Exp $
*/ */
/** /**
@ -49,6 +49,8 @@
#include "sys/process.h" #include "sys/process.h"
#include "sys/arg.h" #include "sys/arg.h"
PROCESS_NAME(simple_cc2420_process);
/* /*
* Pointer to the currently running process structure. * Pointer to the currently running process structure.
*/ */
@ -66,20 +68,18 @@ struct event_data {
struct process *p; struct process *p;
}; };
#ifdef PROCESS_CONF_FASTPOLL
#define NPOLLS PROCESS_CONF_FASTPOLL
static volatile unsigned npolls;
static struct process *needpoll[NPOLLS];
#endif
static process_num_events_t nevents, fevent; static process_num_events_t nevents, fevent;
static struct event_data events[PROCESS_CONF_NUMEVENTS]; static struct event_data events[PROCESS_CONF_NUMEVENTS];
#if PROCESS_CONF_STATS
process_num_events_t process_maxevents;
#endif
static volatile unsigned char poll_requested; static volatile unsigned char poll_requested;
#define PROCESS_STATE_NONE 0 #define PROCESS_STATE_NONE 0
#define PROCESS_STATE_INIT 1 #define PROCESS_STATE_RUNNING 1
#define PROCESS_STATE_RUNNING 2 #define PROCESS_STATE_CALLED 2
#define PROCESS_STATE_NEEDS_POLL 3
static void call_process(struct process *p, process_event_t ev, process_data_t data); static void call_process(struct process *p, process_event_t ev, process_data_t data);
@ -99,7 +99,7 @@ process_alloc_event(void)
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
process_start(struct process *p, char *arg) process_start(struct process *p, const char *arg)
{ {
struct process *q; struct process *q;
@ -114,13 +114,13 @@ process_start(struct process *p, char *arg)
/* Put on the procs list.*/ /* Put on the procs list.*/
p->next = process_list; p->next = process_list;
process_list = p; process_list = p;
p->state = PROCESS_STATE_RUNNING;
p->state = PROCESS_STATE_INIT;
PT_INIT(&p->pt); PT_INIT(&p->pt);
/* Post an asynchronous event to the process. */ PRINTF("process: starting '%s'\n", p->name);
process_post(p, PROCESS_EVENT_INIT, (process_data_t)arg);
/* Post a synchronous initialization event to the process. */
process_post_synch(p, PROCESS_EVENT_INIT, (process_data_t)arg);
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static void static void
@ -129,7 +129,9 @@ exit_process(struct process *p, struct process *fromprocess)
register struct process *q; register struct process *q;
struct process *old_current = process_current; struct process *old_current = process_current;
if(p->state != PROCESS_STATE_NONE) { PRINTF("process: exit_process '%s'\n", p->name);
if(process_is_running(p)) {
/* Process was running */ /* Process was running */
p->state = PROCESS_STATE_NONE; p->state = PROCESS_STATE_NONE;
@ -168,20 +170,13 @@ exit_process(struct process *p, struct process *fromprocess)
for(n = nevents; n > 0; n--) { for(n = nevents; n > 0; n--) {
if(events[i].p == p) { if(events[i].p == p) {
events[i].p = PROCESS_ZOMBIE; events[i].p = PROCESS_ZOMBIE;
#if 0 #if DEBUG
printf("soft panic: exiting process has remaining event 0x%x\n", printf("soft panic: exiting process has remaining event 0x%x\n",
events[i].ev); events[i].ev);
#endif #endif
} }
i = (i + 1) % PROCESS_CONF_NUMEVENTS; i = (i + 1) % PROCESS_CONF_NUMEVENTS;
} }
#ifdef NPOLLS
for(i = 0; i < NPOLLS && i < npolls; i++) {
if(needpoll[i] == p) {
needpoll[i] = PROCESS_ZOMBIE;
}
}
#endif
} }
process_current = old_current; process_current = old_current;
} }
@ -190,17 +185,25 @@ static void
call_process(struct process *p, process_event_t ev, process_data_t data) call_process(struct process *p, process_event_t ev, process_data_t data)
{ {
int ret; int ret;
if((p->state == PROCESS_STATE_RUNNING ||
p->state == PROCESS_STATE_NEEDS_POLL) &&
p->thread != NULL) {
process_current = p;
#if DEBUG
if(p->state == PROCESS_STATE_CALLED) {
printf("process: process '%s' called again with event %d\n", p->name, ev);
}
#endif /* DEBUG */
if((p->state & PROCESS_STATE_RUNNING) &&
p->thread != NULL) {
PRINTF("process: calling process '%s' with event %d\n", p->name, ev);
process_current = p;
p->state = PROCESS_STATE_CALLED;
ret = p->thread(&p->pt, ev, data); ret = p->thread(&p->pt, ev, data);
if(ret == PT_EXITED || if(ret == PT_EXITED ||
ret == PT_ENDED || ret == PT_ENDED ||
ev == PROCESS_EVENT_EXIT) { ev == PROCESS_EVENT_EXIT) {
exit_process(p, p); exit_process(p, p);
} else {
p->state = PROCESS_STATE_RUNNING;
} }
} }
} }
@ -217,6 +220,9 @@ process_init(void)
lastevent = PROCESS_EVENT_MAX; lastevent = PROCESS_EVENT_MAX;
nevents = fevent = 0; nevents = fevent = 0;
#if PROCESS_CONF_STATS
process_maxevents = 0;
#endif /* PROCESS_CONF_STATS */
process_current = process_list = NULL; process_current = process_list = NULL;
} }
@ -229,56 +235,18 @@ static void
do_poll(void) do_poll(void)
{ {
struct process *p; struct process *p;
poll_requested = 0;
#ifdef NPOLLS
unsigned i;
int s;
/* Fastpoll */
//printf("F %d\n", npolls);
for(i = 0; i < npolls; i++) {
do_more:
if(i == NPOLLS) {
goto slowpoll;
}
if(needpoll[i] != PROCESS_ZOMBIE
&& needpoll[i]->state == PROCESS_STATE_NEEDS_POLL) {
needpoll[i]->state = PROCESS_STATE_RUNNING;
call_process(needpoll[i], PROCESS_EVENT_POLL, NULL);
}
}
s = splhigh();
if(i == npolls) {
npolls = 0;
splx(s);
return;
}
splx(s);
goto do_more;
/* Call poll handlers. */ do {
slowpoll: poll_requested = 0;
//printf("S %d\n", npolls); /* Call the processes that needs to be polled. */
npolls = 0; for(p = process_list; p != NULL; p = p->next) {
#endif if(p->needspoll) {
/* Call poll handlers. */ p->state = PROCESS_STATE_RUNNING;
for(p = process_list; p != NULL; p = p->next) { p->needspoll = 0;
call_process(p, PROCESS_EVENT_POLL, NULL);
if(p->state == PROCESS_STATE_NEEDS_POLL) { }
p->state = PROCESS_STATE_RUNNING;
call_process(p, PROCESS_EVENT_POLL, NULL);
} }
} while(poll_requested);
#if 0
/* If a poll has been requested for one of the processes, we start
from the beginning again. */
if(poll_requested) {
poll_requested = 0;
p = process_list;
}
#endif
}
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* /*
@ -347,12 +315,12 @@ do_event(void)
int int
process_run(void) process_run(void)
{ {
/* Process "poll" events. */ /* Process poll events. */
if(poll_requested) { if(poll_requested) {
do_poll(); do_poll();
} }
/* Process one event */ /* Process one event from the queue */
do_event(); do_event();
return nevents + poll_requested; return nevents + poll_requested;
@ -361,11 +329,7 @@ process_run(void)
int int
process_nevents(void) process_nevents(void)
{ {
#ifdef NPOLLS
return nevents + npolls;
#else
return nevents + poll_requested; return nevents + poll_requested;
#endif
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
int int
@ -390,6 +354,12 @@ process_post(struct process *p, process_event_t ev, process_data_t data)
events[snum].p = p; events[snum].p = p;
++nevents; ++nevents;
#if PROCESS_CONF_STATS
if(nevents > process_maxevents) {
process_maxevents = nevents;
}
#endif /* PROCESS_CONF_STATS */
return PROCESS_ERR_OK; return PROCESS_ERR_OK;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
@ -406,19 +376,18 @@ void
process_poll(struct process *p) process_poll(struct process *p)
{ {
if(p != NULL) { if(p != NULL) {
if(p->state == PROCESS_STATE_RUNNING) { if(p->state == PROCESS_STATE_RUNNING ||
p->state = PROCESS_STATE_NEEDS_POLL; p->state == PROCESS_STATE_CALLED) {
p->needspoll = 1;
poll_requested = 1; poll_requested = 1;
#ifdef NPOLLS
int s = splhigh();
if(npolls < NPOLLS) {
needpoll[npolls] = p;
}
if(npolls != ~0u) npolls++; /* Beware of overflow! */
splx(s);
#endif
} }
} }
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
int
process_is_running(struct process *p)
{
return p->state != PROCESS_STATE_NONE;
}
/*---------------------------------------------------------------------------*/
/** @} */ /** @} */

View File

@ -28,7 +28,7 @@
* *
* This file is part of the Contiki operating system. * This file is part of the Contiki operating system.
* *
* @(#)$Id: process.h,v 1.12 2007/11/17 22:11:19 adamdunkels Exp $ * @(#)$Id: process.h,v 1.13 2008/01/23 15:18:06 adamdunkels Exp $
*/ */
/** /**
@ -275,7 +275,6 @@ typedef unsigned char process_num_events_t;
static PT_THREAD(process_thread_##name(struct pt *process_pt, \ static PT_THREAD(process_thread_##name(struct pt *process_pt, \
process_event_t ev, \ process_event_t ev, \
process_data_t data)) process_data_t data))
#if PROCESS_LOADABLE #if PROCESS_LOADABLE
#define PROCESS_LOAD(name) const struct process *process_load = &name #define PROCESS_LOAD(name) const struct process *process_load = &name
#else /* PROCESS_LOADABLE */ #else /* PROCESS_LOADABLE */
@ -320,7 +319,7 @@ struct process {
const char *name; const char *name;
PT_THREAD((* thread)(struct pt *, process_event_t, process_data_t)); PT_THREAD((* thread)(struct pt *, process_event_t, process_data_t));
struct pt pt; struct pt pt;
unsigned char state; unsigned char state, needspoll;
}; };
/** /**
@ -337,7 +336,7 @@ struct process {
* process * process
* *
*/ */
void process_start(struct process *p, char *arg); void process_start(struct process *p, const char *arg);
/** /**
* Post an asynchronous event. * Post an asynchronous event.
@ -497,6 +496,18 @@ void process_init(void);
*/ */
int process_run(void); int process_run(void);
/**
* Check if a process is running.
*
* This function checks if a specific process is running.
*
* \param p The process.
* \retval Non-zero if the process is running.
* \retval Zero if the process is not running.
*/
int process_is_running(struct process *p);
/** /**
* Number of events waiting to be processed. * Number of events waiting to be processed.
* *