PIC24 Support Libraries
esos_task.h
Go to the documentation of this file.
1 /*
2  * "Copyright (c) 2008 Robert B. Reese, Bryan A. Jones, J. W. Bruce ("AUTHORS")"
3  * All rights reserved.
4  * (R. Reese, reese_AT_ece.msstate.edu, Mississippi State University)
5  * (B. A. Jones, bjones_AT_ece.msstate.edu, Mississippi State University)
6  * (J. W. Bruce, jwbruce_AT_ece.msstate.edu, Mississippi State University)
7  *
8  * Permission to use, copy, modify, and distribute this software and its
9  * documentation for any purpose, without fee, and without written agreement is
10  * hereby granted, provided that the above copyright notice, the following
11  * two paragraphs and the authors appear in all copies of this software.
12  *
13  * IN NO EVENT SHALL THE "AUTHORS" BE LIABLE TO ANY PARTY FOR
14  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
15  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE "AUTHORS"
16  * HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
17  *
18  * THE "AUTHORS" SPECIFICALLY DISCLAIMS ANY WARRANTIES,
19  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
20  * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
21  * ON AN "AS IS" BASIS, AND THE "AUTHORS" HAS NO OBLIGATION TO
22  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
23  *
24  * Please maintain this header in its entirety when copying/modifying
25  * these files.
26  *
27  *
28  */
29 
30 /*
31  * This file defines the macros and structures needed to implement the
32  * ESOS cooperative mulitasking. It relies heavily on the PROTOTHREADS
33  * library created by Adam Dunkels at SICS. The SICS notices are
34  * found at the EOF.
35  */
36 
37 /**
38  * \addtogroup ESOS_Tasks
39  * @{
40  */
41 
42 /** \file
43  * This file contains macros for creating and managing
44  * ESOS tasks and semaphores. User need not include
45  * this file, but rather should include \ref esos.h
46  * instead.
47  */
48 
49 #ifndef __ESOS_TASK_H__
50 #define __ESOS_TASK_H__
51 
52 #include "lc.h"
53 #include "esos_mail.h"
54 
55 struct stTask {
56  lc_t lc;
57  uint8_t flags;
58  uint8_t (*pfn) (struct stTask *pst_Task);
59  uint32_t u32_savedTick;
60  uint32_t u32_waitLen;
61  uint16_t u16_taskID;
62  MAILBOX* pst_Mailbox;
63 };
64 
65 /** \struct ESOS_TASK_HANDLE
66  * Handle to an ESOS user task. This handle is used whenever a
67  * task needs to refer to another task, or whenever a task needs
68  * to retreive its own handle.
69  *
70  * \sa ESOS_TASK_GET_TASK_HANDLE
71  * \sa ESOS_ALLOCATE_CHILD_TASK
72  *
73  */
74 typedef struct stTask* ESOS_TASK_HANDLE;
75 
76 /******************************
77 ** create a typedef to represent pointers to ESOS
78 ** user task functions
79 *******************************/
80 // typedef uint8_t (*pfn_ESOS_USER_TASK)(struct stTask *pst_Task);
81 //#define __MAKE_UINT16_TASK_ID(pfn) esos_taskname_hash_u16( (pfn), sizeof((pfn)) )
82 //#define ESOS_DOES_TASK_HAVE_ID(pfn,taskID) ((taskID)==__MAKE_UINT16_TASK_ID((pfn)))
83 
84 /* Task "return" values. Used by scheduler to determine what to do with task **/
85 #define ESOS_TASK_WAITING 0
86 #define ESOS_TASK_ENDED 3
87 
88 
89 /* Task flag : task is waiting on ACK from other task reading mail */
90 #define __TASK_MAILNACK_MASK BIT5
91 /* Task flag : task has mail needing to be read */
92 #define __TASK_HASMAIL_MASK BIT4
93 
94 /* Task flag : task has ended (hit ESOS_TASK_END) */
95 #define __TASK_ENDED_MASK BIT3
96 /* Task flag : task has been flagged to be killed (will exit on next block/wait/yield) */
97 #define __TASK_KILLED_MASK BIT2
98 /* Task flag : task is sleeping */
99 #define __TASK_SLEEPING_MASK BIT1
100 /* Task flag : task is waiting */
101 #define __TASK_WAITING_MASK BIT0
102 /* Task flag : task has been called by scheduler */
103 #define __TASK_CALLED_MASK BIT7
104 
105 /* some helper macros to manage Task states **/
106 #define __ESOS_SET_TASK_SLEEPING_FLAG(TaskHandle) BIT_SET_MASK((TaskHandle)->flags, __TASK_SLEEPING_MASK)
107 #define __ESOS_CLEAR_TASK_SLEEPING_FLAG(TaskHandle) BIT_CLEAR_MASK((TaskHandle)->flags, __TASK_SLEEPING_MASK)
108 #define __ESOS_SET_TASK_KILLED_FLAG(TaskHandle) BIT_SET_MASK((TaskHandle)->flags, __TASK_KILLED_MASK)
109 #define __ESOS_CLEAR_TASK_KILLED_FLAG(TaskHandle) BIT_CLEAR_MASK((TaskHandle)->flags, __TASK_KILLED_MASK)
110 #define __ESOS_SET_TASK_WAITING_FLAG(TaskHandle) BIT_SET_MASK((TaskHandle)->flags, __TASK_WAITING_MASK)
111 #define __ESOS_CLEAR_TASK_WAITING_FLAG(TaskHandle) BIT_CLEAR_MASK((TaskHandle)->flags, __TASK_WAITING_MASK)
112 #define __ESOS_SET_TASK_CALLED_FLAG(TaskHandle) BIT_SET_MASK((TaskHandle)->flags, __TASK_CALLED_MASK)
113 #define __ESOS_CLEAR_TASK_CALLED_FLAG(TaskHandle) BIT_CLEAR_MASK((TaskHandle)->flags, __TASK_CALLED_MASK)
114 #define __ESOS_IS_TASK_CALLED(TaskHandle) IS_BIT_SET_MASK((TaskHandle)->flags, __TASK_CALLED_MASK)
115 #define __ESOS_SET_TASK_ENDED_FLAG(TaskHandle) BIT_SET_MASK((TaskHandle)->flags, __TASK_ENDED_MASK)
116 #define __ESOS_CLEAR_TASK_ENDED_FLAG(TaskHandle) BIT_CLEAR_MASK((TaskHandle)->flags, __TASK_ENDED_MASK)
117 
118 /* mailbox task flags */
119 #define __ESOS_SET_TASK_HASMAIL_FLAG(TaskHandle) BIT_SET_MASK((TaskHandle)->flags, __TASK_HASMAIL_MASK)
120 #define __ESOS_CLEAR_TASK_HASMAIL_FLAG(TaskHandle) BIT_CLEAR_MASK((TaskHandle)->flags, __TASK_HASMAIL_MASK)
121 #define __ESOS_SET_TASK_MAILNACK_FLAG(TaskHandle) BIT_SET_MASK((TaskHandle)->flags, __TASK_MAILNACK_MASK)
122 #define __ESOS_CLEAR_TASK_MAILNACK_FLAG(TaskHandle) BIT_CLEAR_MASK((TaskHandle)->flags, __TASK_MAILNACK_MASK)
123 
124 
125 /**
126  * \name Initialization
127  * @{
128  */
129 
130 /**
131  * Initialize an ESOS task.
132  *
133  * Initializes an ESOS task. Initialization must be done prior to
134  * starting to execute the task.
135  *
136  * \note Called by ESOS internally. Users have no real reason to call this function
137  * themselves.
138  * \param TaskHandle The \ref ESOS_TASK_HANDLE of the task to be initialized
139  * \sa ESOS_TASK_SPAWN_AND_WAIT
140  * \sa ESOS_TASK_GET_TASK_HANDLE
141  * \hideinitializer
142  */
143 #define __ESOS_INIT_TASK(TaskHandle) \
144  LC_INIT((TaskHandle)->lc);
145 
146 /** @} */
147 
148 /**
149  * \name Querying the state of a task
150  * @{
151  */
152 
153 /**
154  * Is ESOS task structure initialized?.
155  *
156  * Checks to see of the ESOS task structure is initialized. Initialization must be done prior to
157  * starting to execute the task. In reality, this checks to see if a task structure is available
158  * since a 'running' task structure will appear to be uninitialized since its state will not be
159  * NULL, ZERO, or whatever our implementation of uses as the initial state.
160  *
161  * \param TaskHandle The \ref ESOS_TASK_HANDLE of the task being queried
162  *
163  * \sa __ESOS_INIT_TASK
164  *
165  * \hideinitializer
166  */
167 #define ESOS_IS_TASK_INITED(TaskHandle) LC_IS_INITED((TaskHandle)->lc)
168 
169 /**
170  * Determines if a task is currently sleeping
171  *
172  * \param TaskHandle The \ref ESOS_TASK_HANDLE of the task being queried
173  * \sa ESOS_TASK_GET_TASK_HANDLE
174  * \hideinitializer
175  */
176 #define ESOS_IS_TASK_SLEEPING(TaskHandle) IS_BIT_SET_MASK((TaskHandle)->flags, __TASK_SLEEPING_MASK)
177 
178 /**
179  * Determines if a task is slated to be killed at its next execution.
180  *
181  * \param TaskHandle The \ref ESOS_TASK_HANDLE of the task being queried
182  * \sa ESOS_TASK_GET_TASK_HANDLE
183  * \hideinitializer
184  */
185 #define ESOS_IS_TASK_KILLED(TaskHandle) IS_BIT_SET_MASK((TaskHandle)->flags, __TASK_KILLED_MASK)
186 
187 /**
188  * Determines if a task is waiting to run/blocked by some condition.
189  *
190  * \param TaskHandle The \ref ESOS_TASK_HANDLE of the task being queried
191  * \sa ESOS_TASK_GET_TASK_HANDLE
192  * \hideinitializer
193  */
194 #define ESOS_IS_TASK_WAITING(TaskHandle) IS_BIT_SET_MASK((TaskHandle)->flags, __TASK_WAITING_MASK)
195 
196 /**
197  * Determines if a task is inactive/ended. Tasks in this state
198  * are subject to culling by the ESOS scheduler at some point in
199  * future.
200  *
201  * \param TaskHandle The \ref ESOS_TASK_HANDLE of the task being queried
202  * \sa ESOS_TASK_GET_TASK_HANDLE
203  * \hideinitializer
204  */
205 #define ESOS_IS_TASK_ENDED(TaskHandle) IS_BIT_SET_MASK((TaskHandle)->flags, __TASK_ENDED_MASK)
206 
207 /** @} */
208 
209 /**
210  * \name Declaration and definition
211  * @{
212  */
213 
214 /**
215  * Declaration of an ESOS task.
216  *
217  * This macro is used to declare an ESOS task. All ESOS tasks must
218  * be declared with this macro.
219  *
220  * \note ESOS tasks have no arguments passed in and cannot return values.
221  * \param taskname The name by which you wish for the user task to be known.
222  * In reality, this name is the name of the C function implementing the ESOS
223  * task. Therefore, your task names must be unique and adhere to C language
224  * naming restrictions.
225  *
226  * \hideinitializer
227  */
228 #define ESOS_USER_TASK(taskname) uint8_t taskname(ESOS_TASK_HANDLE __pstSelf)
229 
230 /**
231  * Declaration of an ESOS child task -- a task spawned by another
232  * ESOS task (a.k.a. the parent task)
233  *
234  * This macro is used to declare an ESOS child task. All ESOS child
235  * tasks must be declared with this macro. This macro relies on the
236  * compiler's ability to handle variadic arguments. GCC does this
237  * just fine. Other compilers may not work.
238  *
239  * \note ESOS child tasks can have zero or more input arguments passed in.
240  * However, ESOS child tasks <em>cannot</em> return values.
241  * \param taskname The name by which you wish for the child task to be known. In
242  * reality, this name is the name of a C function implementing the ESOS child task.
243  * \param ... (OPTIONAL) Any arguments to pass to the the child task
244  *
245  * \hideinitializer
246  */
247 #define ESOS_CHILD_TASK(taskname, ...) uint8_t taskname(ESOS_TASK_HANDLE __pstSelf, ##__VA_ARGS__)
248 
249 /**
250  * Declare the start of an ESOS task inside the C function
251  * implementing the ESOS task.
252  *
253  * This macro is used to declare the starting point of a
254  * ESOS task. It should be placed at the start of the function in
255  * which the ESOS task runs. All C statements above the ESOS_TASK_BEGIN()
256  * invokation will be executed each time the ESOS task is scheduled.
257  * \sa ESOS_TASK_END
258  * \hideinitializer
259  */
260 #define ESOS_TASK_BEGIN() \
261  { __ESOS_SET_TASK_CALLED_FLAG(__pstSelf); \
262  LC_RESUME(__pstSelf->lc)
263 
264 /**
265  * Declare the end of an ESOS task.
266  *
267  * This macro is used for declaring that an ESOS task ends. It must
268  * always be used together with a matching ESOS_TASK_BEGIN() macro.
269  * \sa ESOS_TASK_BEGIN
270  * \hideinitializer
271  */
272 #define ESOS_TASK_END() \
273  LC_END(__pstSelf->lc); \
274  __pstSelf->flags = __TASK_ENDED_MASK; \
275  __ESOS_INIT_TASK(__pstSelf); \
276  return ESOS_TASK_ENDED; }
277 
278 
279 /**
280  * Retrieve the task handle for the current task.
281  *
282  * This macro gets the task handle for the current task. Useful
283  * if the current task wishes to give its handle to some other task
284  * so that the other task can manipulate the current task externally.
285  *
286  * \sa ESOS_TASK_WAKE
287  * \sa ESOS_TASK_KILL
288  * \hideinitializer
289  */
290 #define ESOS_TASK_GET_TASK_HANDLE() __pstSelf
291 
292 /** @} */
293 
294 /**
295  * \name Calling an ESOS task
296  * @{
297  */
298 
299 /**
300  * Schedule an ESOS task.
301  *
302  * This function schedules an ESOS task. The return value of the
303  * function is non-zero if the ESOS task is running or zero if the
304  * ESOS task has exited.
305  *
306  * \note Typically, this macro is only called by other ESOS task macros and
307  * the ESOS task scheduler. I can't think of any reasonable reason why an
308  * user would need to call this macro!
309  * \param pfnThread The call to the C function implementing the ESOS task to
310  * be scheduled
311  *
312  * \hideinitializer
313  */
314 #define ESOS_SCHEDULE_TASK(pfnThread) ( (pfnThread) < ESOS_TASK_ENDED )
315 
316 /** @} */
317 
318 
319 /**
320  * \name Blocked waits
321  * @{
322  */
323 
324 /**
325  * Block and wait until condition is true.
326  *
327  * This macro blocks the ESOS task until the specified condition is
328  * true.
329  *
330  * \param condition The condition.
331  *
332  * \sa ESOS_TASK_WAIT_WHILE
333  *
334  * \hideinitializer
335  */
336 #define ESOS_TASK_WAIT_UNTIL(condition) \
337  do { \
338  LC_SET(__pstSelf->lc); \
339  if(ESOS_IS_TASK_KILLED(__pstSelf)) { \
340  __pstSelf->flags = __TASK_KILLED_MASK; \
341  return ESOS_TASK_ENDED; \
342  } \
343  if((condition)) { \
344  __ESOS_CLEAR_TASK_WAITING_FLAG(__pstSelf); \
345  } \
346  else { \
347  __ESOS_SET_TASK_WAITING_FLAG(__pstSelf); \
348  } \
349  if(ESOS_IS_TASK_WAITING(__pstSelf)) { \
350  return ESOS_TASK_WAITING; \
351  } \
352  } while(0)
353 
354 /**
355  * Block and wait while condition is true.
356  *
357  * This function blocks and waits while the specified condition is true.
358  * \param cond The condition.
359  *
360  * \sa ESOS_TASK_WAIT_UNTIL
361  *
362  * \hideinitializer
363  */
364 #define ESOS_TASK_WAIT_WHILE(cond) ESOS_TASK_WAIT_UNTIL(!(cond))
365 
366 /**
367  * Block and wait for a period of time/ticks
368  *
369  * This function blocks and waits for the duration of time requested.
370  *
371  * \param u32_duration Number of system ticks (currently milliseconds)
372  * to block
373  *
374  * \hideinitializer
375  */
376 #define ESOS_TASK_WAIT_TICKS(u32_duration) \
377 do { \
378  __pstSelf->u32_savedTick = esos_GetSystemTick(); \
379  __pstSelf->u32_waitLen = (u32_duration); \
380  ESOS_TASK_WAIT_UNTIL(__esos_hasTickDurationPassed(__pstSelf->u32_savedTick, __pstSelf->u32_waitLen) ); \
381 } while(0);
382 
383 /** @} */
384 
385 /* helper function to spawn child tasks */
386 #define __ESOS_TASK_SPAWN(pstChild, fcnCallWithArgs) \
387  do { \
388  __ESOS_INIT_TASK((pstChild)); \
389  ESOS_TASK_WAIT_THREAD((fcnCallWithArgs)); \
390  } while(0)
391 
392 /**
393  * \name Tasks and child tasks
394  * @{
395  */
396 
397 /**
398  * Block and wait until a child ESOS task completes.
399  *
400  * This macro schedules a child ESOS task. The current ESOS task
401  * will block until the child ESOS task completes.
402  *
403  * \todo I THINK THIS SHOULD BE REWRITTEN TO USE THE ESOS TASK STATE
404  * VARIABLES INSTEAD OF A CALL TO ESOS_SCHEDULE_TASK. DOESN'T WORK
405  * FOR BOTH PARENT AND CHILD TASKS AS WRITTEN!
406  *
407  * \note The child ESOS task must be manually initialized with the
408  * \ref __ESOS_INIT_TASK function before this function is used.
409  * \note Child task should have been defined with \ref ESOS_CHILD_TASK
410  *
411  * \param pfnChild Pointer to the child task function
412  * \param ... Arguments to the child task (if they exist)
413  *
414  * \sa ESOS_TASK_SPAWN_AND_WAIT
415  * \sa ESOS_CHILD_TASK
416  *
417  * \hideinitializer
418  */
419 #define ESOS_TASK_WAIT_THREAD(pfnChild, ...) ESOS_TASK_WAIT_WHILE(ESOS_SCHEDULE_TASK(pfnChild,##__VA_ARGS__ ))
420 
421 /**
422  * This macro initializes an ESOS child task structure, calls the child task and blocks
423  * the parent task until the child exits exits. The macro can only be used within an ESOS task.
424  *
425  * \param pstChild Pointer to the child ESOS task's control structure.
426  * \param pfnChild Pointer to the child task function
427  * \param ... Arguments to the child task (if they exist)
428  *
429  * \sa ESOS_TASK_WAIT_THREAD
430  * \sa ESOS_CHILD_TASK
431  *
432  * \note Child task should have been defined with \ref ESOS_CHILD_TASK
433  * \note Child task structure should have been obtained with \ref ESOS_ALLOCATE_CHILD_TASK
434  * \hideinitializer
435  */
436 #define ESOS_TASK_SPAWN_AND_WAIT(pstChild, pfnChild, ...) \
437  __ESOS_TASK_SPAWN((pstChild), (pfnChild)( (pstChild), ##__VA_ARGS__) )
438 
439 /**
440  * Allocates a child task storage structure in the local stack frame.
441  *
442  * This macro spawns a child ESOS task and waits until it exits. The
443  * macro can only be used within an ESOS task.
444  *
445  * \param pstName Name of variable to represent the allocated child task structure
446  * \hideinitializer
447  */
448 #define ESOS_ALLOCATE_CHILD_TASK(pstName) (pstName)=esos_GetFreeChildTaskStruct()
449 
450 /*
451  do { \
452  static ESOS_TASK_HANDLE pstName; \
453  pstName=esos_GetFreeChildTaskStruct(); \
454 } while(0)
455 */
456 
457 /** @} */
458 
459 /**
460  * \name Sleeping, killing, exiting and restarting tasks
461  * @{
462  */
463 
464 
465 /**
466  * Put the current task to sleep.
467  *
468  * This macro will cause the current task to "sleep" (block)
469  * until the task is awakened. The current task will not
470  * execute until it is explicitly wakened by some task caliing
471  * \ref ESOS_WAKE_TASK with the target task's identifier.
472  * The sleeping task will resume execution at the instruction
473  * following the ESOS_TASK_SLEEP().
474  *
475  * \sa ESOS_WAKE_TASK
476  *
477  * \hideinitializer
478  */
479 #define ESOS_TASK_SLEEP() \
480  do { \
481  __ESOS_SET_TASK_SLEEPING_FLAG(__pstSelf); \
482  ESOS_TASK_WAIT_WHILE(ESOS_IS_TASK_SLEEPING(__pstSelf)); \
483  } while(0)
484 
485 /**
486  * Restart the current ESOS task.
487  *
488  * This macro will block the current and cause the task to restart
489  * its execution at the place of the ESOS_TASK_BEGIN() call at its
490  * next scheduled execution time.
491  *
492  * \hideinitializer
493  */
494 #define ESOS_TASK_RESTART() \
495  do { \
496  __pstSelf->flags = 0; \
497  __ESOS_INIT_TASK(__pstSelf); \
498  return ESOS_TASK_WAITING; \
499  } while(0)
500 
501 /**
502  * Exit the current ESOS task.
503  *
504  * This macro causes the current ESOS task to exit. If the ESOS task was
505  * spawned by another ESOS task, the parent ESOS task will become
506  * unblocked and can continue to run.
507  *
508  * \sa ESOS_TASK_SPAWN
509  * \sa ESOS_TASK_WAIT_THREAD
510  *
511  * \hideinitializer
512  */
513 #define ESOS_TASK_EXIT() \
514  do { \
515  __pstSelf->flags = __TASK_ENDED_MASK; \
516  return ESOS_TASK_ENDED; \
517  } while(0)
518 
519 
520 /**
521  * Wake up a sleeping ESOS task.
522  *
523  * This macro will cause the target task to "wake" (resume)
524  * at its next opportunity. The sleeping task will resume
525  * execution at the instruction following the \ref ESOS_TASK_SLEEP
526  * that initially put the task to sleep.
527  *
528  * \param TaskHandle The \ref ESOS_TASK_HANDLE of the task to wake up.
529  * \sa ESOS_TASK_GET_TASK_HANDLE
530  * \sa ESOS_TASK_SLEEP
531  *
532  * \hideinitializer
533  */
534 #define ESOS_WAKE_TASK(TaskHandle) __ESOS_TASK_CLEAR_SLEEPING_FLAG((TaskHandle))
535 
536 /**
537  * Kill an scheduled ESOS task.
538  *
539  * This macro will cause the target task to "die" (exit)
540  * at its next scheduled execution.
541  * The target task will not execute any more instructions.
542  *
543  * \param TaskHandle The \ref ESOS_TASK_HANDLE of the task to kill
544  * \sa ESOS_TASK_GET_TASK_HANDLE
545  * \hideinitializer
546  */
547 #define ESOS_KILL_TASK(TaskHandle) __ESOS_TASK_SET_KILLED_FLAG((TaskHandle))
548 
549 
550 /**
551  * Restart a scheduled ESOS task
552  *
553  * This macro will cause the target task to "restart"
554  * (run from the beginning as if it were just created)
555  * at its next scheduled execution.
556  * \note Anything the target task has done and all of its
557  * local data variables and states will likely be lost.
558  * Do <em>NOT</em> restart another task unless you are very
559  * sure of how it will respond.
560  *
561  * \param TaskHandle The \ref ESOS_TASK_HANDLE of the task to kill
562  * \sa ESOS_TASK_GET_TASK_HANDLE
563  * \hideinitializer
564  */
565 #define ESOS_RESTART_TASK(TaskHandle) \
566  do { \
567  (TaskHandle)->flags = 0; \
568  __ESOS_INIT_TASK((TaskHandle)); \
569 } while(0)
570 
571 
572 /** @} */
573 
574 /**
575  * \name Yielding from an ESOS task
576  * @{
577  */
578 
579 /**
580  * Yield the current ESOS task.
581  *
582  * This function will yield the ESOS task IMMEDIATELY, thereby
583  * allowing other processing to take place in the system. The
584  * task will resume at the next instruction at its next invocation
585  * by the scheduler. (Of course, another task may "kill" it in
586  * the meantime and the task will not run again.)
587  *
588  * \hideinitializer
589  */
590 #define ESOS_TASK_YIELD() \
591  do { \
592  __ESOS_CLEAR_TASK_CALLED_FLAG(__pstSelf); \
593  ESOS_TASK_WAIT_UNTIL(__ESOS_IS_TASK_CALLED(__pstSelf)); \
594  } while(0)
595 
596 /** @} */
597 
598 /**
599  * ESOS semaphore structure
600  *
601  * \sa ESOS_INIT_SEMAPHORE
602  * \sa ESOS_TASK_WAIT_SEMAPHORE
603  * \sa ESOS_SIGNAL_SEMAPHORE
604  */
605 struct stSemaphore {
606  int16_t i16_cnt;
607 };
608 
609 
610 /* Not using these with this definition of semaphores */
611 // #define _SEMNAME_CAT( name, line ) name##line
612 // #define _SEMNAME( name, line ) _SEMNAME_CAT( name, line )
613 // #define SEMNAME( name ) _SEMNAME( name, __LINE__ )
614 
615 /**
616  * \name Task semaphores
617  * @{
618  */
619 
620 /**
621  * Declare (and create storage for) an ESOS counting semaphore
622  * \param semaphoreName The name by which the semaphore is to be known
623  * \note Declares the memory storage space along with the
624  * ESOS_SEMAPHORE "object" that is used by user code.
625  * \note Since semaphores are typically used for synchronization,
626  * this macro to allocate storage for a semaphore should almost
627  * always be used in the "global" variable section of your application.
628  * \todo Make sure semaphores are safe in ISRs. Probably need to make
629  * semaphore storage and associated macros <em>volatile</em>
630  * \hideinitializer
631  */
632 #define ESOS_SEMAPHORE(semaphoreName) struct stSemaphore (semaphoreName)
633 
634 /**
635  * Initialize a semaphore
636  *
637  * This macro initializes a semaphore with a value for the
638  * counter. Internally, the semaphores use an "signed 16 bit integer" to
639  * represent the counter, and therefore the "count" argument should be
640  * between -32768 and +32767
641  *
642  * \param semaphoreName An ESOS semaphore created by \ref ESOS_SEMAPHORE
643  * \param i16_val (int16_t) The initial count of the semaphore.
644  * \sa ESOS_SEMAPHORE
645  * \sa ESOS_TASK_WAIT_SEMAPHORE
646  * \sa ESOS_SIGNAL_SEMAPHORE
647  *
648  * \hideinitializer
649  */
650 #define ESOS_INIT_SEMAPHORE(semaphoreName, i16_val) (semaphoreName).i16_cnt=(i16_val)
651 
652 /**
653  * Wait for a semaphore
654  *
655  * This macro carries out the "wait" operation on the semaphore. The
656  * wait operation causes the current ESOS task to block while the counter is
657  * zero. When the counter reaches a value larger than zero, the
658  * task will continue.
659  * \param semaphoreName An ESOS semaphore created by \ref ESOS_SEMAPHORE
660  * \param i16_val (int16_t) number to decrement semaphore value
661  * \sa ESOS_SEMAPHORE
662  * \sa ESOS_INIT_SEMAPHORE
663  * \sa ESOS_SIGNAL_SEMAPHORE
664  *
665  * \hideinitializer
666  */
667 #define ESOS_TASK_WAIT_SEMAPHORE(semaphoreName, i16_val) \
668  do { \
669  ESOS_TASK_WAIT_UNTIL((semaphoreName).i16_cnt >= (i16_val) ); \
670  (semaphoreName).i16_cnt -= (i16_val); \
671  } while(0)
672 
673 /**
674  * Signal a semaphore
675  *
676  * This macro carries out the "signal" operation on the semaphore. The
677  * signal operation increments the counter inside the semaphore, which
678  * eventually will cause waiting protothreads to continue executing.
679  * \param semaphoreName An ESOS semaphore created by \ref ESOS_SEMAPHORE
680  * \param i16_val (int16_t) number to decrement semaphore value
681  * \sa ESOS_SEMAPHORE
682  * \sa ESOS_TASK_WAIT_SEMAPHORE
683  * \sa ESOS_INIT_SEMAPHORE
684  *
685  * \hideinitializer
686  */
687 #define ESOS_SIGNAL_SEMAPHORE(semaphoreName, i16_val) (semaphoreName).i16_cnt+=(i16_val)
688 
689 /* @} */
690 
691 
692 #endif /* __ESOS_TASK_H__ */
693 
694 /** @} */
695 
696 /***********************************************************************
697  *
698  * MUCH OF THIS CODE IS BASED ON PROTOTHREADS BY ADAM DUNKELS
699  * AT THE SWEDISH INSTITUTE OF COMPUTER SCIENCE
700  *
701  ***********************************************************************
702  *
703  * Copyright (c) 2004-2005, Swedish Institute of Computer Science.
704  * All rights reserved.
705  *
706  * Redistribution and use in source and binary forms, with or without
707  * modification, are permitted provided that the following conditions
708  * are met:
709  * 1. Redistributions of source code must retain the above copyright
710  * notice, this list of conditions and the following disclaimer.
711  * 2. Redistributions in binary form must reproduce the above copyright
712  * notice, this list of conditions and the following disclaimer in the
713  * documentation and/or other materials provided with the distribution.
714  * 3. Neither the name of the Institute nor the names of its contributors
715  * may be used to endorse or promote products derived from this software
716  * without specific prior written permission.
717  *
718  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
719  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
720  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
721  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
722  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
723  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
724  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
725  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
726  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
727  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
728  * SUCH DAMAGE.
729  *
730  * This file is part of the Contiki operating system.
731  *
732  * Author: Adam Dunkels <adam@sics.se>
733  *
734  */
unsigned char uint8_t
An abbreviation for an 8-bit unsigned integer.
Definition: dataXferImpl.h:194