blob: d9d313e7a6738e5355f7327911541bd390064404 [file] [log] [blame]
adamdunkels27642552004-07-04 11:54:10 +00001/**
adamdunkels442bdc82005-02-22 22:46:33 +00002 * \defgroup ek The Contiki event kernel
3 * @{
4 *
5 * At the heart of the Contiki desktop environment is the event driven
6 * Contiki kernel. Using non-preemptive multitasking, the Contiki
7 * event kernel makes it possible to run several programs in
8 * parallel. It also provides message passing mechanisms to the
9 * running programs.
10 *
11 * The Contiki kernel is a simple event driven dispatcher which
12 * handles processes and events. All code execution is
13 * initiated by the kernel, and applications are implemented as C
14 * functions that must return within a short time after being
15 * called.
16 *
17 * The kernel does not provide multi-threading. Rather, this is
18 * implemented as an application library. For threads, see the
19 * \ref mt "Multithreading library" and \ref pt "Protothreads".
20 *
21 * The kernel is the initiator of all program execution in
22 * Contiki. After the system has been initialized by the boot up code,
23 * the ek_run() function is called. This function never
24 * returns, but will sit in a loop in which it does two things.
25 *
26 * - Pulls the first event of the event queue and dispatches this to
27 * all listening processes (ek_process_event()).
28 *
29 * - Executes the "poll" handlers of all processes that have
30 * registered (ek_process_poll()).
31 *
32 * Only one event is processes at a time, and the poll handlers of
33 * all processes are called between two events are handled.
34 *
35 *
36 * A process is defined by an initialization function, a event
37 * handler, a uIP event handler, and an poll handler. The event
38 * handler is called when a event has been posted, for which the
39 * process is currently listening. The uIP event handler is called
40 * when the uIP TCP/IP stack has an event to deliver to the
41 * process. Such events can be that new data has arrived on a
42 * connection, that previously sent data has been acknowledged or that
43 * a connection has been closed. The poll handler is periodically
44 * called by the system.
45 *
46 * A process is started by calling the ek_start()
47 * function. This function must be called by the initialization
48 * function before any other kernel function is called. When the
49 * function returns, the new process is running.
50 *
51 * The initialization function is declared with the special
52 * LOADER_INIT() macro. The initializaition function takes a single
53 * argument; a char * pointer.
54 *
55 * The function ek_exit() is used to tell the kernel that
56 * a process has exited. This function must be called by the process
57 * itself, and must be called the process unloads itself.
58 *
59 * \note It is not possible to call ek_exit() on behalf of
60 * another process - instead, post the event ek_event_quit
61 * with the process as a receiver. The other process should then
62 * listen for this event, and call ek_exit() when the event
63 * is received.
64 *
65 *
66 * The kernel can pass events between different
67 * processes. Events are simple messages that consist of a event
68 * number and a generic data pointer called the event data. The
69 * event data can be used to pass messages between processes. In
70 * order for a event to be delivered to a process, the process must
71 * be listening for the event number.
72 *
73 * If a process has registered an poll handler, the kernel will
74 * call it as often as possible. The poll handler can be used to
75 * implement timer based functionality (by checking the ek_clock()
76 * function), or other background processing. The poll handler must
77 * return to the caller within a short time, or otherwise the system
78 * will become sluggish.
79 *
80 *
81 */
82
83
84/**
adamdunkels27642552004-07-04 11:54:10 +000085 * \file
adamdunkels442bdc82005-02-22 22:46:33 +000086 * Event kernel.
adamdunkels27642552004-07-04 11:54:10 +000087 * \author Adam Dunkels <adam@dunkels.com>
88 *
adamdunkels442bdc82005-02-22 22:46:33 +000089 * The kernel in Contiki handles processes and events. All process
90 * execution is initiated by the kernel.
adamdunkels27642552004-07-04 11:54:10 +000091 */
adamdunkelsca9ddcb2003-03-19 14:13:31 +000092/*
adamdunkels27642552004-07-04 11:54:10 +000093 * Copyright (c) 2002-2003, Adam Dunkels.
adamdunkelsca9ddcb2003-03-19 14:13:31 +000094 * All rights reserved.
95 *
96 * Redistribution and use in source and binary forms, with or without
97 * modification, are permitted provided that the following conditions
98 * are met:
99 * 1. Redistributions of source code must retain the above copyright
100 * notice, this list of conditions and the following disclaimer.
101 * 2. Redistributions in binary form must reproduce the above
102 * copyright notice, this list of conditions and the following
103 * disclaimer in the documentation and/or other materials provided
104 * with the distribution.
adamdunkels27642552004-07-04 11:54:10 +0000105 * 3. The name of the author may not be used to endorse or promote
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000106 * products derived from this software without specific prior
107 * written permission.
108 *
109 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
110 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
111 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
112 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
113 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
114 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
115 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
116 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
117 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
118 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
119 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
120 *
121 * This file is part of the "ek" event kernel.
122 *
ryohjic615a2d2007-06-02 07:32:05 +0000123 * $Id: ek.c,v 1.9 2007/06/02 07:32:05 ryohji Exp $
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000124 *
125 */
126
127#include "ek.h"
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000128
adamdunkels27642552004-07-04 11:54:10 +0000129#include <string.h> /* for strncmp() */
130
adamdunkels27642552004-07-04 11:54:10 +0000131/**
132 * \internal Pointer to the currently running process structure.
133 *
134 */
adamdunkelsd3bccb92004-08-09 20:36:39 +0000135struct ek_proc *ek_procs = NULL;
adamdunkels27642552004-07-04 11:54:10 +0000136struct ek_proc *ek_proclist[EK_CONF_MAXPROCS];
adamdunkelsd3bccb92004-08-09 20:36:39 +0000137struct ek_proc *ek_current = NULL;
138
adamdunkels27642552004-07-04 11:54:10 +0000139ek_event_t ek_event_quit;
adamdunkels27642552004-07-04 11:54:10 +0000140ek_event_t ek_event_msg;
adamdunkels27642552004-07-04 11:54:10 +0000141
142static ek_event_t lastevent;
143
144#if CC_FUNCTION_POINTER_ARGS
adamdunkelsd3bccb92004-08-09 20:36:39 +0000145
adamdunkels27642552004-07-04 11:54:10 +0000146#else /* CC_FUNCTION_POINTER_ARGS */
147ek_event_t ek_eventhandler_s;
148ek_data_t ek_eventhandler_data;
adamdunkels27642552004-07-04 11:54:10 +0000149#endif /* CC_FUNCTION_POINTER_ARGS */
150
151
152/**
153 * \internal Structure used for keeping the queue of active events.
154 */
155struct event_data {
156 ek_event_t s;
157 ek_data_t data;
158 ek_id_t id;
159};
160
161static ek_num_events_t nevents, fevent;
162static struct event_data events[EK_CONF_NUMEVENTS];
163
adamdunkels5acd9ef2004-09-01 18:19:43 +0000164volatile unsigned char ek_poll_request;
adamdunkels27642552004-07-04 11:54:10 +0000165
166
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000167/*-----------------------------------------------------------------------------------*/
adamdunkels27642552004-07-04 11:54:10 +0000168/**
169 * Allocates a event number.
170 *
171 * \return The allocated event number or EK_EVENT_NONE if no event
172 * number could be allocated.
173 */
174/*-----------------------------------------------------------------------------------*/
175ek_event_t
176ek_alloc_event(void)
177{
178 return lastevent++;
179}
180/*-----------------------------------------------------------------------------------*/
181static void
182procs_add(struct ek_proc *p)
183{
adamdunkels5acd9ef2004-09-01 18:19:43 +0000184 static struct ek_proc *q, *r;
PulkoMandybcf4d092014-06-28 17:11:23 +0200185
adamdunkels27642552004-07-04 11:54:10 +0000186 /* The process should be placed on the process list according to the
187 process' priority. The higher the priority, the earlier on the
188 list. */
adamdunkels5acd9ef2004-09-01 18:19:43 +0000189 r = NULL;
190 for(q = ek_procs; q != NULL; q = q->next) {
PulkoMandybcf4d092014-06-28 17:11:23 +0200191 if(q->prio < p->prio) {
192 if(r) {
193 r->next = p;
adamdunkels5acd9ef2004-09-01 18:19:43 +0000194 } else {
PulkoMandybcf4d092014-06-28 17:11:23 +0200195 ek_procs = p;
adamdunkels5acd9ef2004-09-01 18:19:43 +0000196 }
PulkoMandybcf4d092014-06-28 17:11:23 +0200197 p->next = q;
adamdunkels5acd9ef2004-09-01 18:19:43 +0000198 return;
199 }
200 r = q;
201 }
202
203 if(q == NULL) {
204 if(r == NULL) {
205 p->next = ek_procs;
206 ek_procs = p;
207 } else {
208 r->next = p;
209 p->next = NULL;
210 }
211 }
PulkoMandybcf4d092014-06-28 17:11:23 +0200212
adamdunkels27642552004-07-04 11:54:10 +0000213
adamdunkels27642552004-07-04 11:54:10 +0000214}
215/*-----------------------------------------------------------------------------------*/
216/**
217 * Starts a new process.
218 *
219 * Is called by a program in order to start a new process for the
220 * program. This function should be called quite early in the
221 * initialization procedure of a new process. In partcular, it must be
222 * called before any other dispatcher functions, or functions of other
223 * modules that make use of dispatcher functions. Most CTK functions
224 * call dispatcher functions, and should therefore not be called
225 * before ek_start() is called.
226 *
227 * Example:
228 \code
229static void app_poll(void);
230static EK_EVENTHANDLER(app_eventhandler, s, data);
231static struct ek_proc p =
232 {EK_PROC("Generic applications", app_poll, app_eventhandler, NULL)};
233static ek_id_t id = EK_ID_NONE;
234
235LOADER_INIT_FUNC(app_init, arg)
236{
237 arg_free(arg);
238
239 if(id == EK_ID_NONE) {
240 id = ek_start(&p);
241
242 rest_of_initialization();
243 }
244}
245 \endcode
246 *
247 * \param p A pointer to a ek_proc struct that must be found
248 * in the process own memory space.
249 *
250 * \return The process identifier for the new process or EK_ID_NONE
251 * if the process could not be started.
252 */
253/*-----------------------------------------------------------------------------------*/
254ek_id_t
255ek_start(CC_REGISTER_ARG struct ek_proc *p)
256{
257 ek_id_t id;
258
ryohjic615a2d2007-06-02 07:32:05 +0000259 for(id = 0; id < EK_CONF_MAXPROCS; ++id) {
adamdunkels27642552004-07-04 11:54:10 +0000260 if(ek_proclist[id] == NULL) {
261 break;
262 }
263 }
264 if(id == EK_CONF_MAXPROCS) {
265 return EK_ID_NONE;
266 }
267
268 ek_proclist[id] = p;
269
270 /* Put on the procs list.*/
271 procs_add(p);
272
273 p->id = id;
274
275 /* Post an asynchronous event to the process. */
276 ek_post(id, EK_EVENT_INIT, p);
PulkoMandybcf4d092014-06-28 17:11:23 +0200277
adamdunkels27642552004-07-04 11:54:10 +0000278 return id;
279}
280/*-----------------------------------------------------------------------------------*/
281/**
282 * Exit the currently running process
283 *
284 * This function causes the currently running process to exit. The
285 * function must be called by the process before it unloads itself, or
286 * the system will crash.
287 *
288 */
289/*-----------------------------------------------------------------------------------*/
290void
291ek_exit(void)
292{
adamdunkelsd3bccb92004-08-09 20:36:39 +0000293 register struct ek_proc *q, *p;
adamdunkels27642552004-07-04 11:54:10 +0000294
295 p = ek_current;
296
297 /* Post a synchronous event to all processes to inform them that
298 this process is about to exit. This will allow services to
299 dealloc state associated with this process. */
300 for(q = ek_procs; q != NULL; q = q->next) {
301 if(p != q) {
302 ek_current = q;
303 if(q->eventhandler != NULL) {
304 q->eventhandler(EK_EVENT_EXITED, (ek_data_t)p->id);
305 }
306 }
307 }
308
309 /* Remove process from the process lists. */
310 ek_proclist[p->id] = NULL;
311
312 if(p == ek_procs) {
313 ek_procs = ek_procs->next;
314 } else {
315 for(q = ek_procs; q != NULL; q = q->next) {
316 if(q->next == p) {
317 q->next = p->next;
318 break;
319 }
320 }
321 }
adamdunkels27642552004-07-04 11:54:10 +0000322
323 ek_current = NULL;
324}
325/**
326 * \addtogroup kernel
327 * @{
328 */
329
330/*-----------------------------------------------------------------------------------*/
331/**
332 * Finds the process structure for a specific process ID.
333 *
334 * \param id The process ID for the process.
335 *
336 * \return The process structure for the process, or NULL if there
337 * process ID was not found.
338 */
339/*-----------------------------------------------------------------------------------*/
340struct ek_proc *
341ek_process(ek_id_t id)
342{
343 struct ek_proc *p;
344 for(p = ek_procs; p != NULL; p = p->next) {
345 if(p->id == id) {
346 return p;
347 }
348 }
349 return NULL;
350}
351/*-----------------------------------------------------------------------------------*/
352/**
353 * Initializes the dispatcher module.
354 *
355 * Must be called during the initialization of Contiki.
356 *
357 */
358/*-----------------------------------------------------------------------------------*/
359void
360ek_init(void)
361{
362 int i;
363
364 lastevent = EK_EVENT_MAX;
365
366 nevents = fevent = 0;
367
adamdunkelsd3bccb92004-08-09 20:36:39 +0000368 ek_current = ek_procs = NULL;
369
adamdunkels27642552004-07-04 11:54:10 +0000370 arg_init();
371
372 for(i = 0; i < EK_CONF_MAXPROCS; ++i) {
373 ek_proclist[i] = NULL;
374 }
375}
376/*-----------------------------------------------------------------------------------*/
377/**
378 * Process the next event in the event queue and deliver it to
379 * listening processes.
380 *
381 */
382/*-----------------------------------------------------------------------------------*/
383void
384ek_process_event(void)
385{
386 static ek_event_t s;
387 static ek_data_t data;
388 static ek_id_t id;
389 static struct ek_proc *p;
390
391 /* If there are any events in the queue, take the first one and
392 walk through the list of processes to see if the event should be
393 delivered to any of them. If so, we call the event handler
394 function for the process. We only process one event at a time
395 and call the poll handlers inbetween. */
396
397 if(nevents > 0) {
398
399 /* There are events that we should deliver. */
400 s = events[fevent].s;
401
402 data = events[fevent].data;
403 id = events[fevent].id;
404
405 /* Since we have seen the new event, we move pointer upwards
406 and decrese number. */
407 fevent = (fevent + 1) % EK_CONF_NUMEVENTS;
408 --nevents;
409
410 /* If this is a broadcast event, we deliver it to all events, in
411 order of their priority. */
412 if(id == EK_BROADCAST) {
413 for(p = ek_procs; p != NULL; p = p->next) {
414
415 if(ek_poll_request) {
416 ek_poll_request = 0;
417 ek_process_poll();
418 }
419
420 ek_current = p;
421 if(p->eventhandler != NULL) {
422 p->eventhandler(s, data);
423 }
424 }
425 } else {
adamdunkels442bdc82005-02-22 22:46:33 +0000426 /* This is not a broadcast event, so we deliver it to the
427 specified process. */
adamdunkels27642552004-07-04 11:54:10 +0000428 if(ek_poll_request) {
429 ek_poll_request = 0;
430 ek_process_poll();
431 }
adamdunkelsd3bccb92004-08-09 20:36:39 +0000432
adamdunkels27642552004-07-04 11:54:10 +0000433 p = ek_proclist[id];
434 if(p != NULL &&
435 p->eventhandler != NULL) {
436 ek_current = p;
adamdunkels442bdc82005-02-22 22:46:33 +0000437 p->eventhandler(s, data);
438
439 /* If the event was an INIT event, we should also put the
440 process on the process list. */
441 /* procs_add(p);*/
adamdunkels27642552004-07-04 11:54:10 +0000442 }
443 }
444 }
445
446}
447/*-----------------------------------------------------------------------------------*/
448/**
449 * Call each process' poll handler.
450 */
451/*-----------------------------------------------------------------------------------*/
452void
453ek_process_poll(void)
454{
455 struct ek_proc *p;
456
457 /* Call poll handlers. */
458 for(p = ek_procs; p != NULL; p = p->next) {
adamdunkels5acd9ef2004-09-01 18:19:43 +0000459 if(ek_poll_request) {
460 ek_poll_request = 0;
461 p = ek_procs;
462 }
463
adamdunkels27642552004-07-04 11:54:10 +0000464 if(p->pollhandler != NULL) {
465 ek_current = p;
466 p->pollhandler();
467 }
468 }
469
470}
471/*-----------------------------------------------------------------------------------*/
472/**
473 * Run the system once - call poll handlers and process one event.
474 *
475 * This function should be called repeatedly from the main() program
476 * to actuall run the Contiki system. It calls the necessary poll
477 * handlers, and processes one event. The function returns the number
478 * of events that are waiting in the event queue so that the caller
479 * may choose to put the CPU to sleep when there are no pending
480 * events.
481 *
482 * \return The number of events that are currently waiting in the
483 * event queue.
484 */
485/*-----------------------------------------------------------------------------------*/
486int
487ek_run(void)
488{
489 /* Process "poll" events. */
adamdunkels5acd9ef2004-09-01 18:19:43 +0000490 do {
491 ek_poll_request = 0;
492 ek_process_poll();
493 } while(ek_poll_request != 0);
adamdunkels27642552004-07-04 11:54:10 +0000494
495 /* Process one event */
496 ek_process_event();
497
498 return nevents;
499}
500/*-----------------------------------------------------------------------------------*/
501/**
502 * Post an asynchronous event.
503 *
504 * This function posts an asynchronous event to one or more
505 * processes. The handing of the event is deferred until the target
506 * process is scheduled by the kernel. An event can be broadcast to
507 * all processes, in which case all processes in the system will be
508 * scheduled to handle the event.
509 *
510 * \param s The event to be posted.
511 *
512 * \param data The auxillary data to be sent with the event
513 *
514 * \param id The process ID to which the event should be posted, or
515 * EK_BROADCAST if the event should be posted to all
516 * processes.
517 *
518 * \retval EK_ERR_OK The event could be posted.
519 *
520 * \retval EK_ERR_FULL The event queue was full and the event could
521 * not be posted.
522 */
523/*-----------------------------------------------------------------------------------*/
524ek_err_t
525ek_post(ek_id_t id, ek_event_t s, ek_data_t data)
526{
527 static unsigned char snum;
528
529 if(nevents == EK_CONF_NUMEVENTS) {
530 return EK_ERR_FULL;
531 }
532
533 snum = (fevent + nevents) % EK_CONF_NUMEVENTS;
534 events[snum].s = s;
535 events[snum].data = data;
536 events[snum].id = id;
537 ++nevents;
538
539 return EK_ERR_OK;
540}
541/*-----------------------------------------------------------------------------------*/
542void
543ek_post_synch(ek_id_t id, ek_event_t ev, ek_data_t data)
544{
adamdunkelsd3bccb92004-08-09 20:36:39 +0000545 struct ek_proc *p = ek_current;
546
adamdunkels27642552004-07-04 11:54:10 +0000547 ek_current = ek_proclist[id];
548 ek_current->eventhandler(ev, data);
549 ek_current = p;
550}
551/*-----------------------------------------------------------------------------------*/
552ek_id_t
553ek_find(const char *prefix)
554{
555 struct ek_proc *p;
556 unsigned short len;
557
558 /* Search through all processes and search for the specified process
559 name. */
560 len = strlen(prefix);
561 for(p = ek_procs; p != NULL; p = p->next) {
562 if(strncmp(prefix, p->name, len) == 0) {
563 return p->id;
564 }
565 }
566
567 return EK_ID_NONE;
568}
569/*-----------------------------------------------------------------------------------*/
570void
571ek_replace(struct ek_proc *newp, void *arg)
572{
adamdunkelsd3bccb92004-08-09 20:36:39 +0000573 register struct ek_proc *p = ek_current;
574
adamdunkels27642552004-07-04 11:54:10 +0000575 /* Remove the currently executing process. */
576 ek_exit();
577
578 ek_proclist[p->id] = newp;
579
580 /* Put on the procs list.*/
581 procs_add(newp);
582
583 newp->id = p->id;
584
585 /* Post an asynchronous event to the process. */
adamdunkelsd3bccb92004-08-09 20:36:39 +0000586 ek_post(p->id, EK_EVENT_REPLACE, arg);
adamdunkels27642552004-07-04 11:54:10 +0000587}
588/*-----------------------------------------------------------------------------------*/
589void *
590ek_procstate(ek_id_t id)
591{
592 struct ek_proc *p;
593
594 p = ek_proclist[id];
595 if(p == NULL) {
596 return NULL;
597 }
598 return p->procstate;
599}
600/*-----------------------------------------------------------------------------------*/
601/** @} */