]> granicus.if.org Git - esp-idf/blob - components/esp32/include/xtensa/xos_thread.h
Initial public version
[esp-idf] / components / esp32 / include / xtensa / xos_thread.h
1 /** @file */
2
3 // xos_thread.h - XOS Thread API interface and data structures.
4
5 // Copyright (c) 2003-2015 Cadence Design Systems, Inc.
6 //
7 // Permission is hereby granted, free of charge, to any person obtaining
8 // a copy of this software and associated documentation files (the
9 // "Software"), to deal in the Software without restriction, including
10 // without limitation the rights to use, copy, modify, merge, publish,
11 // distribute, sublicense, and/or sell copies of the Software, and to
12 // permit persons to whom the Software is furnished to do so, subject to
13 // the following conditions:
14 //
15 // The above copyright notice and this permission notice shall be included
16 // in all copies or substantial portions of the Software.
17 //
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22 // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
26 // NOTE: Do not include this file directly in your application. Including
27 // xos.h will automatically include this file.
28
29
30 #ifndef __XOS_THREAD_H__
31 #define __XOS_THREAD_H__
32
33 #ifdef __cplusplus
34 extern "C" {
35 #endif
36
37 #include "xos_types.h"
38 #include "xos_params.h"
39
40
41 //-----------------------------------------------------------------------------
42 //  Number of thread priority levels.
43 //-----------------------------------------------------------------------------
44 #ifndef XOS_NUM_PRIORITY
45 #error "XOS_NUM_PRIORITY must be defined (in xos_params.h)."
46 #endif
47 #if XOS_NUM_PRIORITY > 32
48 #error "The number of thread priority levels (XOS_NUM_PRIORITY) must be <= 32."
49 #endif
50 #define XOS_MAX_PRIORITY        (XOS_NUM_PRIORITY)
51
52
53 //-----------------------------------------------------------------------------
54 //  Macro for thread self pointer.
55 //-----------------------------------------------------------------------------
56 #define XOS_THREAD_SELF         (xos_thread_id())
57
58
59 //-----------------------------------------------------------------------------
60 ///
61 ///  Thread entry function pointer type.
62 ///
63 //-----------------------------------------------------------------------------
64 typedef int32_t (XosThreadFunc)(void * arg, int32_t wake_value);
65
66
67 //-----------------------------------------------------------------------------
68 //  Thread switcher function signature.
69 //-----------------------------------------------------------------------------
70 typedef struct XosThread XosThread;
71 typedef int32_t (XosSwitchFunc)(XosThread *);
72
73
74 //-----------------------------------------------------------------------------
75 ///
76 ///  Condition evaluation callback function pointer type.
77 ///
78 //-----------------------------------------------------------------------------
79 typedef int32_t (XosCondFunc)(void * arg, int32_t sig_value, XosThread * thread);
80
81
82 //-----------------------------------------------------------------------------
83 ///
84 ///  Thread exit handler function pointer type.
85 ///
86 //-----------------------------------------------------------------------------
87 typedef int32_t (XosThdExitFunc)(int32_t exitcode);
88
89
90 //-----------------------------------------------------------------------------
91 //  Thread queue structure. Used to implement the ready queues as well
92 //  as the wait queues.
93 //-----------------------------------------------------------------------------
94 typedef struct XosThreadQueue {
95   XosThread *  head;    // Pointer to first thread in queue, or 0 if none.
96   XosThread ** tail;    // Pointer to last thread's r_next pointer, or
97                         // to "head" if none.
98 } XosThreadQueue;
99
100
101 //-----------------------------------------------------------------------------
102 //  Stack frame for a thread that is not running. That is, it has either
103 //  been preempted or has yielded.
104 //-----------------------------------------------------------------------------
105 typedef union XosFrame {
106   XosExcFrame   e;      // resume_fn == &xos_resume_preempted_thread
107   XosCoopFrame  c;      // resume_fn == &xos_resume_cooperative_thread
108   // nothing for resume_fn == &xos_resume_idle_thread
109   // nothing for resume_fn == &xos_resume_by_restart
110 } XosFrame;
111
112
113 //-----------------------------------------------------------------------------
114 //  Thread Control Block. Tracks the state and control information associated
115 //  with a thread.
116 //
117 //  IMPORTANT:  keep this in sync with TCB_*** offsets in xos_common.h .
118 //-----------------------------------------------------------------------------
119 struct XosThread {
120   XosThread *   r_next;         // 00 Next thread in queue (eg. ready queue of
121                                 // its priority, or some queue of blocked threads)
122                                 // Should be NULL if not in any queue.
123
124   XosThread **  r_pprev;        // 04 Points to previous queue entry's r_next
125                                 // pointer (i.e. to itself), or to queue head
126                                 // if first in queue. NULL if not in any queue.
127
128   XosThread *   all_next;       // 08 Next in list of all threads.
129   
130   void *        resume_fn;      // 12 Pointer to the routine to be called to
131                                 // resume this thread. On entry to such code:
132                                 //   a2 == xos_curr_threadptr (thread being resumed)
133                                 //   a3 == &xos_globals
134
135   XosFrame *    esf;            // 16 Pointer to saved exception stack frame,
136                                 // just below thread's current stack pointer.
137                                 // For RTC threads, this is valid only while the
138                                 // thread is preempted, not when it is blocked.
139
140   void *        tie_save;       // 20 TIE state save area. May be NULL if there
141                                 // is not TIE state saved for this thread.
142   
143   int32_t       wake_value;     // 24 Value returned from block call (by wake call)
144                                 // (for RTC: pass this to start function??)
145   
146   XosSwitchFunc * switch_fn;    // 28 Pointer to a function that
147                                 // can be called from within this thread, to save
148                                 // this thread's state and switch to a specified
149                                 // other thread. Returns wake value.
150
151   void *        stack_base;     // 32 Base of stack as specified by thread creator.
152   
153   void *        stack_end;      // 36 End of stack (adjusted for TIE state save area
154                                 // if any).
155
156   XosThreadFunc * entry;        // 40 Pointer to thread entry function. Used for
157                                 // RTC thread restart.
158   
159   void *        arg;            // 44 Argument value passed to entry function.
160
161   bool          ready;          // 48 Set when thread is ready to run, and is in
162                                 // its priority queue (i.e. r_pprev is set when
163                                 // this flag is set).
164
165   bool          in_exit;        // Exit flag, nonzero when in exit processing.
166
167   int8_t        priority;       // Thread priority, 0 .. (XOS_MAX_PRI - 1). Higher
168                                 // numbers have higher priority. This must only be
169                                 // changed when thread is not ready, or by calling
170                                 // xos_thread_set_priority().
171
172   int8_t        preempt_pri;    // This thread's preemption blocking priority.
173                                 // (preempt_pri >= priority). A thread's priority
174                                 // must be higher than another's preempt_pri to be
175                                 // able to preempt it. Note that preempt_pri can
176                                 // change during runtime e.g. due to priority
177                                 // inheritance.
178
179   uint32_t      flags;          // 52 Thread creation flags.
180
181   const char *  name;           // 56 Thread name (mainly for debug).
182
183   const char *  block_cause;    // 60 Reason for blocking. Valid only when thread
184                                 // not ready (r_pprev == 0).
185
186   XosThread *   container;      // 64 Thread whose stack will be used to run
187                                 // this thread. Valid for RTC threads only, else NULL.
188
189   XosThdExitFunc * exit_func;   // 68 Thread exit handler function pointer.
190
191   XosThreadQueue  exit_waiters; // 72 Queue of threads waiting for this one to exit.
192
193   XosThreadQueue * wq_ptr;      // 80 If this thread is in a wait queue, this
194                                 // points to the queue. Must be NULL when
195                                 // thread not in a queue.
196
197   XosCondFunc * cond_fn;        // 84 Condition function. Valid only while thread
198                                 // is blocked on condition.
199
200   void *        cond_arg;       // 88 Argument to be passed to condition function.
201
202   uint16_t      cp_mask;        // 92 Mask of coprocessors used.
203   uint16_t      cp_saved;       // 94 Mask of coprocessors saved.
204
205   uint32_t      event_bits;     // 96 event bits
206   uint32_t      event_mask;     // 100 event bit mask
207   uint32_t      event_flags;    // 104 event flags
208
209   void *        clib_ptr;       // 108 Pointer to C lib context struct.
210
211   uint32_t      sig;            // 112 Signature of valid TCB
212
213   uint32_t      resume_ccount;  // 116 cycle count at resume
214   uint64_t      cycle_count;    // 120 number of cycles consumed (approx).
215                                 // NOTE: must be 8-byte aligned
216   uint32_t      normal_resumes; // 128 Number of non-preemptive resumptions.
217   uint32_t      preempt_resumes;// 132 Number of preemptive resumptions.
218
219 #if XOS_OPT_THREAD_SAFE_CLIB
220   CLIB_THREAD_STRUCT;           // C library context area.
221 #endif
222 };
223
224
225 //-----------------------------------------------------------------------------
226 //  User-visible flags for xos_thread_create().
227 //-----------------------------------------------------------------------------
228 #define XOS_THREAD_SUSPEND      0x0001  ///< Create suspended instead of ready
229 #define XOS_THREAD_RTC          0x0002  ///< Run-to-completion thread
230 #define XOS_THREAD_NO_CP        0x0004  ///< Thread does not use coprocessors
231
232
233 //-----------------------------------------------------------------------------
234 //  Flags used by thread creation extra parameters.
235 //-----------------------------------------------------------------------------
236 #define XOS_TP_COPROC_MASK      0x0001
237 #define XOS_TP_PREEMPT_PRI      0x0002
238 #define XOS_TP_EXIT_HANDLER     0x0004
239
240
241 //-----------------------------------------------------------------------------
242 //  Thread creation extra parameters.
243 //-----------------------------------------------------------------------------
244 typedef struct XosThreadParm {
245   uint32_t      parms_mask;     // Combination of XOS_TP_xxx flags indicating
246                                 // which parameters are valid.
247
248   uint16_t      cp_mask;        // Mask of coprocessors the thread can access.
249
250   uint32_t      preempt_pri;    // Initial preemption blocking priority. Can be
251                                 // changed later via xos_thread_set_priority().
252
253   XosThdExitFunc * handler;     // Exit handler function.
254
255 } XosThreadParm;
256
257
258 //-----------------------------------------------------------------------------
259 //  Wrapper struct for RTC (run to completion) thread.
260 //-----------------------------------------------------------------------------
261 typedef struct XosRtcThread {
262   struct XosThread thread;
263 } XosRtcThread;
264
265
266 //-----------------------------------------------------------------------------
267 //  External variables.
268 //-----------------------------------------------------------------------------
269 extern XosThread *      xos_curr_threadptr;     // Current active thread
270 extern XosThread *      xos_next_threadptr;     // Next ready thread
271 extern XosThread *      xos_all_threads;        // List of all threads
272
273
274 //-----------------------------------------------------------------------------
275 ///
276 ///  Set thread creation parameter: the group of coprocessors that this thread
277 ///  will use. This must be set during thread creation, and cannot be changed
278 ///  after the thread has been created. Defining this allows reduction of
279 ///  memory usage (for CP state saving) in some circumstances, and can also
280 ///  speed up the context switch time.
281 ///
282 ///  NOTE: Support for this is not currently implemented. If a thread uses
283 ///  any coprocessor, space for all coprocessors must be reserved.
284 ///
285 ///  \param     parms           Thread creation parameter structure. Must be
286 ///                             allocated by the caller.
287 ///
288 ///  \param     cp_mask         Bitmask of coprocessors thread is allowed to
289 ///                             use. Bit 0 for coprocessor 0, etc.
290 ///
291 ///  \return    Returns nothing.
292 ///
293 //-----------------------------------------------------------------------------
294 static inline void
295 xos_threadp_set_cp_mask(XosThreadParm * parms, uint16_t cp_mask)
296 {   
297     if (parms != XOS_NULL) {
298         parms->parms_mask |= XOS_TP_COPROC_MASK;
299         parms->cp_mask = cp_mask;
300     }
301 }
302
303
304 //-----------------------------------------------------------------------------
305 ///
306 ///  Set thread creation parameter: thread pre-emption priority.
307 ///
308 ///  \param     parms           Thread creation parameter structure. Must be
309 ///                             allocated by caller.
310 ///
311 ///  \param     preempt_pri     Thread pre-emption blocking priority.
312 ///                             From 0 .. XOS_NUM_PRIORITY - 1.
313 ///                             Must be greater or equal to the thread priority
314 ///                             (if not, is automatically set to thread priority).
315 ///
316 ///  \return    Returns nothing.
317 ///
318 //-----------------------------------------------------------------------------
319 static inline void
320 xos_threadp_set_preemption_priority(XosThreadParm * parms, int8_t preempt_pri)
321 {
322     if (parms != XOS_NULL) {
323         parms->parms_mask |= XOS_TP_PREEMPT_PRI;
324         parms->preempt_pri = preempt_pri;
325     }
326 }
327
328
329 //-----------------------------------------------------------------------------
330 ///
331 ///  Set thread creation parameter: thread exit handler.
332 ///
333 ///  \param     parms           Thread creation parameter structure. Must be
334 ///                             allocated by caller.
335 ///
336 ///  \param     handler         Exit handler function.
337 ///
338 ///  \return    Returns nothing.
339 //-----------------------------------------------------------------------------
340 static inline void
341 xos_threadp_set_exit_handler(XosThreadParm * parms, XosThdExitFunc * handler)
342 {
343     if (parms != XOS_NULL) {
344         parms->parms_mask |= XOS_TP_EXIT_HANDLER;
345         parms->handler     = handler;
346     }
347 }
348
349
350 //-----------------------------------------------------------------------------
351 ///
352 ///  Create a new thread. If the thread is not created suspended, then it will
353 ///  be made ready as soon as it is created, and will immediately run if it is
354 ///  the highest priority non-blocked thread in the system.
355 ///
356 ///  \param     thread          Pointer to the thread descriptor (an otherwise
357 ///                             unused XosThread structure, usually allocated
358 ///                             by the caller for the lifetime of the thread,
359 ///                             for example as a global variable).
360 ///
361 ///  \param     container       Pointer to separate thread acting as "container"
362 ///                             for this one. At the moment, this is only meaningful
363 ///                             for run-to-completion (RTC) threads (identified with
364 ///                             the XOS_THREAD_RTC flag), in which case the container
365 ///                             must have the same priority and also be an RTC thread.
366 ///                             (The priority restriction may be lifted in a future
367 ///                             implementation, with appropriate constraints on dynamic
368 ///                             reprioritization of the created thread).
369 ///
370 ///  \param     entry           Thread entry function, takes one argument.
371 ///
372 ///  \param     arg             Argument "void*" that is passed to the thread function.
373 ///
374 ///  \param     name            Unique name of the thread, for debug/display purposes.
375 ///                             This string must be valid for the lifetime of the thread
376 ///                             (only a pointer to it is stored in the thread control block).
377 ///                             Typically consists of identifier chars with no spaces.
378 ///
379 ///  \param     stack           Base of initial stack for the thread, allocated by the 
380 ///                             caller. Need not be aligned (initial stack pointer will be
381 ///                             computed and aligned from given stack base and size).
382 ///                             Required argument, except for run-to-completion threads 
383 ///                             when container is non-NULL, in which case the container's
384 ///                             stack is used and this argument must be NULL.
385 ///
386 ///  \param     stack_size      Size of the stack, in bytes.
387 ///                             NOTE: stack should be at least XOS_STACK_EXTRA bytes plus
388 ///                             whatever the thread actually needs if the thread will use
389 ///                             coprocessors/TIE state. If the thread will not touch the
390 ///                             coprocessors, then it should be XOS_STACK_EXTRA_NO_CP
391 ///                             plus whatever the thread actually needs.
392 ///                             Recommended minimum stack sizes are defined by the constants
393 ///                             XOS_STACK_MIN_SIZE and XOS_STACK_MIN_SIZE_NO_CP.
394 ///
395 ///                             For run-to-completion threads where container is non-NULL, 
396 ///                             stack_size specifies the minimum stack size required for
397 ///                             the thread; it should be smaller or equal to the container's
398 ///                             stack.
399 ///
400 ///  \param     priority        Initial thread priority. From 0 .. XOS_MAX_PRI - 1.
401 ///                             Higher numbers are higher priority.
402 ///
403 ///  \param     parms           Pointer to extra parameters structure, or 0 if none given.
404 ///                             Use xos_thread_p_***() functions to set parameters in the
405 ///                             structure.
406 ///
407 ///  \param     flags           Option flags:
408 ///                             - XOS_THREAD_SUSPEND -- Leave thread suspended instead of
409 ///                               making it ready. The thread can be made ready to run later
410 ///                               by calling xos_thread_resume().
411 ///                             - XOS_THREAD_RTC -- Run-to-completion thread.
412 ///                             - XOS_THREAD_NO_CP -- Thread does not use coprocessors.
413 ///                               No coprocessor state will be saved for this thread.
414 ///                               Threads that have this flag set will not allocate any
415 ///                               storage for saving coprocessor state and so can have
416 ///                               smaller stacks.
417 /// 
418 ///  NOTE: xos_start_main() calls xos_thread_create() to convert main() into the 'main'
419 ///  thread.
420 ///
421 ///  \return    Returns XOS_OK if successful, error code otherwise.
422 ///
423 //-----------------------------------------------------------------------------
424 int32_t
425 xos_thread_create(XosThread *     thread,
426                   XosThread *     container,
427                   XosThreadFunc * entry,
428                   void *          arg,
429                   const char *    name, 
430                   void *          stack,
431                   uint32_t        stack_size,
432                   int32_t         priority,
433                   XosThreadParm * parms,
434                   uint32_t        flags );
435
436
437 //-----------------------------------------------------------------------------
438 ///
439 ///  Remove thread and free up all resources. Thread must have exited already.
440 ///  After this call returns, all resources allocated to the thread (e.g. TCB,
441 ///  stack space, etc.) can be reused.
442 ///
443 ///  \param     thread          Handle of thread to be deleted.
444 ///
445 ///  \return    Returns XOS_OK on success, else error code.
446 ///
447 ///  NOTE: A thread cannot call this on itself.
448 ///
449 //-----------------------------------------------------------------------------
450 int32_t     
451 xos_thread_delete(XosThread * thread);
452
453
454 //-----------------------------------------------------------------------------
455 ///
456 ///  Force the thread to terminate. The thread execution is aborted, but exit
457 ///  processing will still happen, i.e. the exit handler (if any) will be run.
458 ///  After termination, any other threads waiting on this thread are notified.
459 ///  This function cannot be called on the current thread.
460 ///
461 ///  \param     thread          Handle of thread to be aborted.
462 ///
463 ///  \param     exitcode        Exit code returned to any waiting threads.
464 ///
465 ///  \return    Returns XOS_OK on success, else error code.
466 ///
467 ///  NOTE: If the thread is blocked waiting for something, the wait is aborted
468 ///  and the thread is made ready.
469 ///  NOTE: The thread is not guaranteed to have exited when this call returns.
470 ///  It will be made ready and set up for exit processing, but when the exit
471 ///  processing will actually happen depends on the state of the system and
472 ///  the priority of the thread being aborted.
473 ///
474 //-----------------------------------------------------------------------------
475 int32_t
476 xos_thread_abort(XosThread * thread, int32_t exitcode);
477
478
479 //-----------------------------------------------------------------------------
480 ///
481 ///  Exit the current thread. The exit handler (if any) will be run before the
482 ///  thread terminates.
483 ///
484 ///  \param     exitcode                Exit code to be returned to any waiting threads.
485 ///
486 ///  \return    This function does not return.
487 ///
488 ///  NOTE: This is automatically called if the thread returns from its entry
489 ///  function. The entry function's return value will be passed as the exit
490 ///  code.
491 ///
492 //-----------------------------------------------------------------------------
493 void
494 xos_thread_exit(int32_t exitcode);
495
496
497 //-----------------------------------------------------------------------------
498 ///
499 ///  Wait until the specified thread exits and get its exit code. If the thread
500 ///  has exited already, an error will be returned.
501 ///
502 ///  \param     thread          The thread to wait for. Cannot be "self", i.e.
503 ///                             one cannot wait on one's own exit.
504 ///
505 ///  \param     p_exitcode      If not null, the exit code will be returned here.
506 ///
507 ///  \return    Returns XOS_OK on sucess, else error code.
508 ///
509 //-----------------------------------------------------------------------------
510 int32_t
511 xos_thread_join(XosThread * thread, int32_t * p_exitcode);
512
513
514 //-----------------------------------------------------------------------------
515 ///
516 ///  Yield the CPU to the next thread in line. The calling thread remains ready
517 ///  and is placed at the tail of the ready queue at its current priority level.
518 ///  If there are no threads at the same priority level that are ready to run,
519 ///  then this call will return immediately.
520 ///
521 ///  \return    Returns nothing.
522 ///
523 //-----------------------------------------------------------------------------
524 void
525 xos_thread_yield();
526
527
528 //-----------------------------------------------------------------------------
529 ///
530 ///  Suspend the specified thread. The thread will remain suspended until 
531 ///  xos_thread_resume() has been called on it. If the thread is already blocked
532 ///  on some other condition, then this function will return an error.
533 ///
534 ///  \param     thread          Handle of thread being suspended. A thread can
535 ///                             use the special handle XOS_THREAD_SELF to suspend
536 ///                             itself.
537 ///
538 ///  \return    Returns XOS_OK on success, else error code.
539 ///
540 //-----------------------------------------------------------------------------
541 int32_t
542 xos_thread_suspend(XosThread * thread);
543
544
545 //-----------------------------------------------------------------------------
546 ///
547 ///  Resume a suspended thread. If the thread is not suspended or is blocked on
548 ///  some other condition then this function will do nothing. Otherwise, it will
549 ///  be made ready, and this can cause an immediate context switch if the thread
550 ///  is at a higher priority than the calling thread.
551 ///
552 ///  \param     thread          Handle of thread being resumed.
553 ///
554 ///  \return    Returns XOS_OK on success, else error code.
555 ///
556 //-----------------------------------------------------------------------------
557 int32_t
558 xos_thread_resume(XosThread * thread);
559
560
561 //-----------------------------------------------------------------------------
562 ///
563 ///  Get the priority of the specified thread. This returns the priority of the
564 ///  queried thread at this instant, however this can change at any time due to
565 ///  other activity in the system.
566 ///
567 ///  \param     thread          Handle of thread being queried. A thread can use
568 ///                             the special handle XOS_THREAD_SELF to query itself.
569 ///
570 ///  \return    Returns the thread's current priority, or -1 if the thread handle
571 ///             is not valid.
572 ///
573 //-----------------------------------------------------------------------------
574 static inline int32_t
575 xos_thread_get_priority(XosThread * thread)
576 {
577     XOS_ASSERT(thread);
578     return thread ? thread->priority : -1;
579 }
580
581
582 //-----------------------------------------------------------------------------
583 ///
584 ///  Set the priority of the specified thread. The thread must exist. 
585 ///
586 ///  \param     thread          Handle of thread being affected. A thread can
587 ///                             use the special handle XOS_THREAD_SELF to specify
588 ///                             itself.
589 ///
590 ///  \param     priority        The new priority level to be set.
591 ///
592 ///  \return    Returns XOS_OK on success, else error code.
593 ///
594 ///  NOTE: Calling this function can result in a scheduler activation, and the
595 ///  caller may be suspended as a result.
596 ///
597 //-----------------------------------------------------------------------------
598 int32_t
599 xos_thread_set_priority(XosThread * thread, int32_t priority);
600
601
602 //-----------------------------------------------------------------------------
603 ///
604 ///  Return the name of the specified thread.
605 ///
606 ///  \param     thread          Handle of thread being queried. A thread can use
607 ///                             the special handle XOS_THREAD_SELF to specify
608 ///                             itself.
609 ///
610 ///  \return    Returns a pointer to the name string if available, else NULL.
611 ///
612 //-----------------------------------------------------------------------------
613 static inline const char *
614 xos_thread_get_name(XosThread * thread)
615 {
616     XOS_ASSERT(thread);
617     return thread ? thread->name : 0;
618 }
619
620
621 //-----------------------------------------------------------------------------
622 ///
623 ///  Set the name of the specified thread.
624 ///
625 ///  \param     thread          Handle of thread whose name is to be set. A thread
626 ///                             can use the special handle XOS_THREAD_SELF to specify
627 ///                             itself.
628 ///
629 ///  \param     name            Pointer to the new name string. The string is not
630 ///                             copied, only the pointer is saved. So the string
631 ///                             must be persistent for the life of the thread.
632 ///
633 ///  \return    Returns XOS_OK on success, else error code.
634 ///
635 //-----------------------------------------------------------------------------
636 static inline int32_t
637 xos_thread_set_name(XosThread * thread, const char * name)
638 {
639     XOS_ASSERT(thread);
640     if (thread != XOS_NULL) {
641         thread->name = name;
642         return XOS_OK;
643     }
644
645     return XOS_ERR_INVALID_PARAMETER;
646 }
647
648
649 //-----------------------------------------------------------------------------
650 ///
651 ///  Set an exit handler for the specified thread. The exit handler is run when
652 ///  the thread terminates, either by calling xos_thread_exit() or by returning
653 ///  from its entry function. It will also be called if the thread is being
654 ///  terminated due to e.g. an unhandled exception.
655 ///
656 ///  The handler must be a function defined as e.g.:
657 ///
658 ///      int32_t exit_handler(int32_t exitcode);
659 ///
660 ///  The exit handler runs in the context of the exiting thread, and can call
661 ///  system services. It is provided with a single parameter which is the
662 ///  thread's exit code (the exit code may be set to an error code if the
663 ///  thread is being terminated due to an error or exception). The handler
664 ///  must return a value which will be set as the thread's exit code.
665 ///
666 ///  \param     thread          Handle of the thread for which the handler is
667 ///                             to be installed. A thread can use the special
668 ///                             handle XOS_THREAD_SELF to specify itself.
669 ///
670 ///  \param     func            Pointer to exit handler function. To clear an
671 ///                             existing handler, pass NULL as the pointer.
672 ///
673 ///  \return    Returns XOS_OK on success, else error code.
674 ///
675 //-----------------------------------------------------------------------------
676 int32_t
677 xos_thread_set_exit_handler(XosThread * thread, XosThdExitFunc * func);
678
679
680 //-----------------------------------------------------------------------------
681 ///
682 ///  Return the ID (handle) of the current thread.
683 ///
684 ///  \return    Returns the handle of the current thread. This handle can be
685 ///             used in all XOS system calls.
686 ///
687 ///  NOTE: If called from interrupt context, returns the handle of the thread
688 ///  that was preempted.
689 ///
690 //-----------------------------------------------------------------------------
691 static inline XosThread *
692 xos_thread_id()
693 {
694     return xos_curr_threadptr;
695 }
696
697
698 //-----------------------------------------------------------------------------
699 ///
700 ///  Return the coprocessor mask for the specified thread.
701 ///
702 ///  \param     thread          Handle of thread being queried.
703 ///
704 ///  \return    Returns the mask for the specified thread if available, else 0.
705 ///
706 //-----------------------------------------------------------------------------
707 static inline uint16_t
708 xos_thread_cp_mask(XosThread * thread)
709 {
710     XOS_ASSERT(thread);
711     return thread ? thread->cp_mask : 0;
712 }
713
714
715 //-----------------------------------------------------------------------------
716 ///
717 ///  Return the wake value for the specified thread.
718 ///
719 ///  \return    thread          Handle of thread being queried.
720 ///
721 ///  \return    Returns The last set wake value. There is no way to detect what
722 ///             action set the wake value and when.
723 ///
724 //-----------------------------------------------------------------------------
725 static inline int32_t
726 xos_thread_get_wake_value(XosThread * thread)
727 {
728     XOS_ASSERT(thread);
729     return thread ? thread->wake_value : 0;
730 }
731
732
733 //-----------------------------------------------------------------------------
734 ///
735 ///  Return the current value of the event bits for the current thread.
736 ///  This function takes no parameters.
737 ///
738 ///  \return    Returns the current value of the event bits. The event bits
739 ///             are set when the thread is woken from an event wait. They will
740 ///             not change while the thread is running. There is no way to
741 ///             determine when the event bits were last updated.
742 ///
743 //-----------------------------------------------------------------------------
744 static inline uint32_t
745 xos_thread_get_event_bits(void)
746 {
747     XosThread * thread = xos_thread_id();
748     return thread ? thread->event_bits : 0;
749 }
750
751
752 //-----------------------------------------------------------------------------
753 ///
754 ///  Enum values for thread state.
755 ///
756 //-----------------------------------------------------------------------------
757 typedef enum xos_thread_state_t {
758     XOS_THREAD_STATE_INVALID = 0,       ///< Invalid thread
759     XOS_THREAD_STATE_BLOCKED,           ///< Thread is blocked
760     XOS_THREAD_STATE_READY,             ///< Thread is ready to run
761     XOS_THREAD_STATE_RUNNING,           ///< Thread is running
762     XOS_THREAD_STATE_EXITED,            ///< Thread has exited
763 } xos_thread_state_t;
764
765
766 //-----------------------------------------------------------------------------
767 ///
768 ///  Return the state of the specified thread.
769 ///
770 ///  \param     thread          Handle of thread being queried.
771 ///
772 ///  \return    Returns one of the following values:
773 ///             - XOS_THREAD_STATE_RUNNING -- The thread is currently running.
774 ///             - XOS_THREAD_STATE_READY   -- The thread is ready to run.
775 ///             - XOS_THREAD_STATE_BLOCKED -- The thread is blocked on something.
776 ///             - XOS_THREAD_STATE_INVALID -- The thread handle is invalid.
777 ///             - XOS_THREAD_STATE_EXITED  -- The thread has exited.
778 ///
779 //-----------------------------------------------------------------------------
780 xos_thread_state_t
781 xos_thread_get_state(XosThread * thread);
782
783
784 //-----------------------------------------------------------------------------
785 ///
786 ///  Disable thread preemption. Prevents context switching to another thread.
787 ///  However, interrupt handlers will still continue to be run. Multiple calls
788 ///  will nest, and the same number of calls to xos_preemption_enable() will be
789 ///  required to re-enable preemption. If the calling thread yields the CPU or
790 ///  exits without enabling preemption, it will cause a system halt.
791 ///  If the calling thread encounters a fatal error, preemption will be enabled
792 ///  during fatal error handling.
793 ///
794 ///  \return    Returns the new value of preemption disable flag after this call.
795 ///
796 ///  NOTE: Cannot be called from interrupt context.
797 ///
798 //-----------------------------------------------------------------------------
799 uint32_t
800 xos_preemption_disable(void);
801
802
803 //-----------------------------------------------------------------------------
804 ///
805 ///  Enable thread preemption. Has no effect if preemption was already enabled.
806 ///  Otherwise, it decrements the value of the preemption disable flag and if
807 ///  the value goes to zero, enables preemption.
808 ///
809 ///  \return    Returns the new value of preemption disable flag after this call.
810 ///
811 ///  NOTE: If scheduling gets enabled, it may cause an immediate context switch
812 ///  if higher priority threads are ready.
813 ///
814 //-----------------------------------------------------------------------------
815 uint32_t
816 xos_preemption_enable(void);
817
818
819 //-----------------------------------------------------------------------------
820 ///
821 ///  Initialize XOS thread support and start scheduler.
822 ///
823 ///  Must be called from main() before calling any other thread function.
824 ///  This function initializes thread support, creates the idle thread, and
825 ///  starts the scheduler. It does not return to its caller. This means that
826 ///  at least one user thread must be created before calling xos_start().
827 ///  Otherwise, the scheduler will run the idle thread since it will be the
828 ///  only thread in the system, and no other thread can be created.
829 ///
830 ///  NOTE: This function does not initialize timer/tick support. For timer
831 ///  services to be available xos_start_system_timer() must be called.
832 ///
833 ///  NOTE: xos_start() and xos_start_main() are exclusive, both cannot be
834 ///  called within the same application.
835 ///
836 ///  \param     flags           Currently unused (pass 0).
837 ///
838 ///  \return    Does not return.
839 ///
840 //-----------------------------------------------------------------------------
841 void
842 xos_start(uint32_t flags);
843
844
845 //-----------------------------------------------------------------------------
846 ///
847 ///  Initialize XOS thread support and create init (main) thread.
848 ///
849 ///  Must be called from main() before calling any other thread function.
850 ///  This function converts the caller into the 'main' or 'init' thread, and
851 ///  returns to the caller after completing initialization. 
852 ///
853 ///  NOTE: This function does not initialize timer/tick support. For timer
854 ///  services to be available xos_start_system_timer() must be called.
855 ///
856 ///  NOTE: xos_start_main() and xos_start() are exclusive, both cannot be
857 ///  called within the same application.
858 ///
859 ///  \param     name            Name of main thread (see xos_thread_create()).
860 ///
861 ///  \param     priority        Initial priority of main thread.
862 ///
863 ///  \param     flags           Currently unused (pass 0).
864 ///
865 ///  \return    Returns nothing.
866 ///
867 //-----------------------------------------------------------------------------
868 void
869 xos_start_main(const char * name, int8_t priority, uint32_t flags);
870
871
872 //-----------------------------------------------------------------------------
873 ///
874 ///  Per-thread stats structure.
875 ///  Note that the CPU use % is approximate, both because of cycle counting
876 ///  and because of integer division. So all the threads' CPU % will not add
877 ///  up to exactly 100%.
878 ///
879 //-----------------------------------------------------------------------------
880 typedef struct XosThreadStats {
881   XosThread *   thread;            ///< Thread handle (or pseudo-handle)
882   uint32_t      cpu_pct;           ///< CPU use % for this thread
883   uint32_t      normal_switches;   ///< Number of non-preemptive switches.
884   uint32_t      preempt_switches;  ///< Number of preemptive switches.
885   uint64_t      cycle_count;       ///< Number of cycles consumed.
886 } XosThreadStats;
887
888
889 //-----------------------------------------------------------------------------
890 //  Thread pseudo-handles.
891 //-----------------------------------------------------------------------------
892 #define XOS_THD_STATS_IDLE      ((XosThread *) 1)
893 #define XOS_THD_STATS_INTR      ((XosThread *) 2)
894
895
896 //-----------------------------------------------------------------------------
897 ///
898 ///  Get the thread statistics for the specified thread. Statistics are only
899 ///  available if XOS_OPT_STATS has been enabled. Otherwise, the function
900 ///  will return XOS_OK, but the structure contents will be undefined.
901 ///
902 ///  \param     thread          Handle of thread being queried. The following
903 ///                             special pseudo-handles can be used:
904 ///                             - XOS_THD_STATS_IDLE -- stats for idle thread
905 ///                             - XOS_THD_STATS_INTR -- stats for interrupt processing
906 ///
907 ///  \param     stats           Pointer to XosThreadStats struct to be filled in.
908 ///
909 ///  \return    Returns XOS_OK on success, else error code.
910 ///
911 ///  NOTE: Can be called from interrupt context.
912 ///  NOTE: This call will not fill in the "thread" and "cpu_pct" fields in the
913 ///  "stats" structure. The thread handle is already known, and calculating the
914 ///  CPU loading can take quite a bit of time so is not done here.
915 ///
916 //-----------------------------------------------------------------------------
917 int32_t
918 xos_thread_get_stats(XosThread * thread, XosThreadStats * stats);
919
920
921 //-----------------------------------------------------------------------------
922 ///
923 ///  Get CPU loading statistics for the system. This function computes the CPU
924 ///  percentage use for all threads in the system (including the idle thread and
925 ///  the 'interrupt thread' (interrupt context). It also returns the cycle count
926 ///  and number of context switches for each thread.
927 ///  Statistics are only available if XOS_OPT_STATS has been enabled.
928 ///  Otherwise, the function will return XOS_OK, but the structure contents will
929 ///  be undefined.
930 ///
931 ///  IMPORTANT: The entry for interrupt context does not contain a real thread
932 ///  handle. It uses the pseudo-handle XOS_THD_STATS_INTR to indicate that this
933 ///  entry reports interrupt statistics. This pseudo-handle cannot be used for
934 ///  any other thread operations or queries.
935 ///
936 ///  NOTE: This function disables interrupts while traversing the thread list.
937 ///  It does not leave interrupts disabled during the computations, as that can
938 ///  take a fair amount of time.
939 ///
940 ///  \param     stats           Pointer to an array of XosThreadStats structures.
941 ///                             The array must be large enough to accommodate all
942 ///                             threads in the system.
943 ///
944 ///  \param     size            The number of elements available in the array. If
945 ///                             this is smaller than the number of threads plus one
946 ///                             (for the interrupt context) then XOS_ERR_INVALID_PARAMETER
947 ///                             will be returned and '*size' will be set to the
948 ///                             minimum number of elements required. On a successful
949 ///                             return, '*size' is set to the number of elements
950 ///                             actually filled in.
951 ///
952 ///  \param     reset           If nonzero, then thread stats counters are reset
953 ///                             after reading. This is useful if you want to track
954 ///                             the stats so as to get a better idea of current
955 ///                             system loading. E.g. calling this function once a
956 ///                             second with 'reset' nonzero will provide CPU load
957 ///                             information for the last second on each call.
958 ///
959 ///  \return    Returns XOS_OK on success, else error code. In particular,
960 ///             XOS_ERR_INVALID_PARAMETER will be returned if the output buffer
961 ///             is too small.
962 ///
963 //-----------------------------------------------------------------------------
964 int32_t
965 xos_get_cpu_load(XosThreadStats * stats, int32_t * size, int32_t reset);
966
967
968 #ifdef _XOS_INCLUDE_INTERNAL_
969
970 // Signature of valid thread object
971 #define XOS_THREAD_SIG  0x54485244
972
973
974 // Extern functions
975 void
976 xos_init(void);
977
978 bool
979 xos_init_done(void);
980
981 bool
982 xos_started(void);
983
984 int32_t
985 xos_schedule(XosThread * curr_thread);
986
987 void
988 xos_q_remove(XosThreadQueue * queue, XosThread * thread);
989
990 XosThread *
991 xos_q_pop(XosThreadQueue * queue);
992
993 int32_t
994 xos_wake_queue(XosThreadQueue * queue, const char * expected_cause, int32_t wake_value);
995
996 // Well known block causes
997 extern const char * const xos_blkon_idle;       // (for idle thread only)
998 extern const char * const xos_blkon_suspend;
999 extern const char * const xos_blkon_delay;
1000 extern const char * const xos_blkon_exited;
1001 extern const char * const xos_blkon_join;
1002 extern const char * const xos_blkon_event;
1003 extern const char * const xos_blkon_condition;
1004 extern const char * const xos_blkon_mutex;
1005 extern const char * const xos_blkon_sem;
1006 extern const char * const xos_blkon_msgq;
1007
1008
1009 //-----------------------------------------------------------------------------
1010 //  Blocks the current active thread.
1011 //
1012 //  Currently, this can be called from an interrupt handler to block the thread
1013 //  that was interrupted. Note that in interrupt context the current thread can
1014 //  already be in the blocked state, due to a previous call to this function.
1015 //  Can be called with interrupts enabled.
1016 //
1017 //  block_cause         Reason for blocking.
1018 //
1019 //  block_queue         Queue on to which this thread should be pushed once it
1020 //                      is blocked. Can be NULL.
1021 //
1022 //  must_schedule       If nonzero, then forces a scheduling operation to pick
1023 //                      the next thread to run, even if there are ready threads
1024 //                      at the same priority level as the blocked thread.
1025 //
1026 //  use_priority        If nonzero, then the blocked thread will be queued in
1027 //                      priority order in the specified block queue. If zero,
1028 //                      the thread is queued in FIFO order. If no queue has
1029 //                      been specified, this parameter is ignored.
1030 //
1031 //  Returns: The value passed by xos_thread_wake().
1032 //-----------------------------------------------------------------------------
1033 int32_t
1034 xos_block(const char *     block_cause,
1035           XosThreadQueue * block_queue,
1036           int32_t          must_schedule,
1037           int32_t          use_priority);
1038
1039
1040 //-----------------------------------------------------------------------------
1041 //  Unblocks the specified blocked thread and puts it at the tail end of its
1042 //  ready queue. Schedules it if it is higher priority than the current thread.
1043 //  No effect if the thread is not blocked with the specified cause.
1044 //
1045 //  thread              The thread to wake up (make ready).
1046 //
1047 //  expected_cause      The expected block cause of the thread. Thread will be
1048 //                      woken only if its block cause matches this cause, or if
1049 //                      expected_cause is zero.
1050 //  
1051 //  wake_value          The value to be passed to the woken thread as a return
1052 //                      value from xos_thread_block().
1053 //
1054 //  Returns: nothing.
1055 //
1056 //  The target thread can be woken at a different priority by changing its
1057 //  priority while the thread is blocked.
1058 //  Can be called with interrupts enabled. Can be called in interrupt context.
1059 //-----------------------------------------------------------------------------
1060 void
1061 xos_thread_wake(XosThread * thread, const char * expected_cause, int32_t wakevalue);
1062
1063
1064 //-----------------------------------------------------------------------------
1065 //  Function to init C library per-thread and reentrancy support.
1066 //-----------------------------------------------------------------------------
1067 #if XOS_OPT_THREAD_SAFE_CLIB
1068 void
1069 xos_clib_init(void);
1070
1071 void
1072 xos_clib_thread_init(XosThread * thread);
1073
1074 void
1075 xos_clib_thread_cleanup(XosThread * thread);
1076 #endif
1077
1078 #endif
1079
1080
1081 #ifdef __cplusplus
1082 }
1083 #endif
1084
1085 #endif  // __XOS_THREAD_H__
1086