3 // xos_thread.h - XOS Thread API interface and data structures.
5 // Copyright (c) 2003-2015 Cadence Design Systems, Inc.
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:
15 // The above copyright notice and this permission notice shall be included
16 // in all copies or substantial portions of the Software.
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.
26 // NOTE: Do not include this file directly in your application. Including
27 // xos.h will automatically include this file.
30 #ifndef __XOS_THREAD_H__
31 #define __XOS_THREAD_H__
37 #include "xos_types.h"
38 #include "xos_params.h"
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)."
47 #if XOS_NUM_PRIORITY > 32
48 #error "The number of thread priority levels (XOS_NUM_PRIORITY) must be <= 32."
50 #define XOS_MAX_PRIORITY (XOS_NUM_PRIORITY)
53 //-----------------------------------------------------------------------------
54 // Macro for thread self pointer.
55 //-----------------------------------------------------------------------------
56 #define XOS_THREAD_SELF (xos_thread_id())
59 //-----------------------------------------------------------------------------
61 /// Thread entry function pointer type.
63 //-----------------------------------------------------------------------------
64 typedef int32_t (XosThreadFunc)(void * arg, int32_t wake_value);
67 //-----------------------------------------------------------------------------
68 // Thread switcher function signature.
69 //-----------------------------------------------------------------------------
70 typedef struct XosThread XosThread;
71 typedef int32_t (XosSwitchFunc)(XosThread *);
74 //-----------------------------------------------------------------------------
76 /// Condition evaluation callback function pointer type.
78 //-----------------------------------------------------------------------------
79 typedef int32_t (XosCondFunc)(void * arg, int32_t sig_value, XosThread * thread);
82 //-----------------------------------------------------------------------------
84 /// Thread exit handler function pointer type.
86 //-----------------------------------------------------------------------------
87 typedef int32_t (XosThdExitFunc)(int32_t exitcode);
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
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
113 //-----------------------------------------------------------------------------
114 // Thread Control Block. Tracks the state and control information associated
117 // IMPORTANT: keep this in sync with TCB_*** offsets in xos_common.h .
118 //-----------------------------------------------------------------------------
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.
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.
128 XosThread * all_next; // 08 Next in list of all threads.
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
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.
140 void * tie_save; // 20 TIE state save area. May be NULL if there
141 // is not TIE state saved for this thread.
143 int32_t wake_value; // 24 Value returned from block call (by wake call)
144 // (for RTC: pass this to start function??)
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.
151 void * stack_base; // 32 Base of stack as specified by thread creator.
153 void * stack_end; // 36 End of stack (adjusted for TIE state save area
156 XosThreadFunc * entry; // 40 Pointer to thread entry function. Used for
157 // RTC thread restart.
159 void * arg; // 44 Argument value passed to entry function.
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).
165 bool in_exit; // Exit flag, nonzero when in exit processing.
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().
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
179 uint32_t flags; // 52 Thread creation flags.
181 const char * name; // 56 Thread name (mainly for debug).
183 const char * block_cause; // 60 Reason for blocking. Valid only when thread
184 // not ready (r_pprev == 0).
186 XosThread * container; // 64 Thread whose stack will be used to run
187 // this thread. Valid for RTC threads only, else NULL.
189 XosThdExitFunc * exit_func; // 68 Thread exit handler function pointer.
191 XosThreadQueue exit_waiters; // 72 Queue of threads waiting for this one to exit.
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.
197 XosCondFunc * cond_fn; // 84 Condition function. Valid only while thread
198 // is blocked on condition.
200 void * cond_arg; // 88 Argument to be passed to condition function.
202 uint16_t cp_mask; // 92 Mask of coprocessors used.
203 uint16_t cp_saved; // 94 Mask of coprocessors saved.
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
209 void * clib_ptr; // 108 Pointer to C lib context struct.
211 uint32_t sig; // 112 Signature of valid TCB
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.
219 #if XOS_OPT_THREAD_SAFE_CLIB
220 CLIB_THREAD_STRUCT; // C library context area.
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
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
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.
248 uint16_t cp_mask; // Mask of coprocessors the thread can access.
250 uint32_t preempt_pri; // Initial preemption blocking priority. Can be
251 // changed later via xos_thread_set_priority().
253 XosThdExitFunc * handler; // Exit handler function.
258 //-----------------------------------------------------------------------------
259 // Wrapper struct for RTC (run to completion) thread.
260 //-----------------------------------------------------------------------------
261 typedef struct XosRtcThread {
262 struct XosThread thread;
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
274 //-----------------------------------------------------------------------------
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.
282 /// NOTE: Support for this is not currently implemented. If a thread uses
283 /// any coprocessor, space for all coprocessors must be reserved.
285 /// \param parms Thread creation parameter structure. Must be
286 /// allocated by the caller.
288 /// \param cp_mask Bitmask of coprocessors thread is allowed to
289 /// use. Bit 0 for coprocessor 0, etc.
291 /// \return Returns nothing.
293 //-----------------------------------------------------------------------------
295 xos_threadp_set_cp_mask(XosThreadParm * parms, uint16_t cp_mask)
297 if (parms != XOS_NULL) {
298 parms->parms_mask |= XOS_TP_COPROC_MASK;
299 parms->cp_mask = cp_mask;
304 //-----------------------------------------------------------------------------
306 /// Set thread creation parameter: thread pre-emption priority.
308 /// \param parms Thread creation parameter structure. Must be
309 /// allocated by caller.
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).
316 /// \return Returns nothing.
318 //-----------------------------------------------------------------------------
320 xos_threadp_set_preemption_priority(XosThreadParm * parms, int8_t preempt_pri)
322 if (parms != XOS_NULL) {
323 parms->parms_mask |= XOS_TP_PREEMPT_PRI;
324 parms->preempt_pri = preempt_pri;
329 //-----------------------------------------------------------------------------
331 /// Set thread creation parameter: thread exit handler.
333 /// \param parms Thread creation parameter structure. Must be
334 /// allocated by caller.
336 /// \param handler Exit handler function.
338 /// \return Returns nothing.
339 //-----------------------------------------------------------------------------
341 xos_threadp_set_exit_handler(XosThreadParm * parms, XosThdExitFunc * handler)
343 if (parms != XOS_NULL) {
344 parms->parms_mask |= XOS_TP_EXIT_HANDLER;
345 parms->handler = handler;
350 //-----------------------------------------------------------------------------
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.
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).
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).
370 /// \param entry Thread entry function, takes one argument.
372 /// \param arg Argument "void*" that is passed to the thread function.
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.
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.
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.
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
400 /// \param priority Initial thread priority. From 0 .. XOS_MAX_PRI - 1.
401 /// Higher numbers are higher priority.
403 /// \param parms Pointer to extra parameters structure, or 0 if none given.
404 /// Use xos_thread_p_***() functions to set parameters in the
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
418 /// NOTE: xos_start_main() calls xos_thread_create() to convert main() into the 'main'
421 /// \return Returns XOS_OK if successful, error code otherwise.
423 //-----------------------------------------------------------------------------
425 xos_thread_create(XosThread * thread,
426 XosThread * container,
427 XosThreadFunc * entry,
433 XosThreadParm * parms,
437 //-----------------------------------------------------------------------------
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.
443 /// \param thread Handle of thread to be deleted.
445 /// \return Returns XOS_OK on success, else error code.
447 /// NOTE: A thread cannot call this on itself.
449 //-----------------------------------------------------------------------------
451 xos_thread_delete(XosThread * thread);
454 //-----------------------------------------------------------------------------
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.
461 /// \param thread Handle of thread to be aborted.
463 /// \param exitcode Exit code returned to any waiting threads.
465 /// \return Returns XOS_OK on success, else error code.
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.
474 //-----------------------------------------------------------------------------
476 xos_thread_abort(XosThread * thread, int32_t exitcode);
479 //-----------------------------------------------------------------------------
481 /// Exit the current thread. The exit handler (if any) will be run before the
482 /// thread terminates.
484 /// \param exitcode Exit code to be returned to any waiting threads.
486 /// \return This function does not return.
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
492 //-----------------------------------------------------------------------------
494 xos_thread_exit(int32_t exitcode);
497 //-----------------------------------------------------------------------------
499 /// Wait until the specified thread exits and get its exit code. If the thread
500 /// has exited already, an error will be returned.
502 /// \param thread The thread to wait for. Cannot be "self", i.e.
503 /// one cannot wait on one's own exit.
505 /// \param p_exitcode If not null, the exit code will be returned here.
507 /// \return Returns XOS_OK on sucess, else error code.
509 //-----------------------------------------------------------------------------
511 xos_thread_join(XosThread * thread, int32_t * p_exitcode);
514 //-----------------------------------------------------------------------------
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.
521 /// \return Returns nothing.
523 //-----------------------------------------------------------------------------
528 //-----------------------------------------------------------------------------
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.
534 /// \param thread Handle of thread being suspended. A thread can
535 /// use the special handle XOS_THREAD_SELF to suspend
538 /// \return Returns XOS_OK on success, else error code.
540 //-----------------------------------------------------------------------------
542 xos_thread_suspend(XosThread * thread);
545 //-----------------------------------------------------------------------------
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.
552 /// \param thread Handle of thread being resumed.
554 /// \return Returns XOS_OK on success, else error code.
556 //-----------------------------------------------------------------------------
558 xos_thread_resume(XosThread * thread);
561 //-----------------------------------------------------------------------------
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.
567 /// \param thread Handle of thread being queried. A thread can use
568 /// the special handle XOS_THREAD_SELF to query itself.
570 /// \return Returns the thread's current priority, or -1 if the thread handle
573 //-----------------------------------------------------------------------------
574 static inline int32_t
575 xos_thread_get_priority(XosThread * thread)
578 return thread ? thread->priority : -1;
582 //-----------------------------------------------------------------------------
584 /// Set the priority of the specified thread. The thread must exist.
586 /// \param thread Handle of thread being affected. A thread can
587 /// use the special handle XOS_THREAD_SELF to specify
590 /// \param priority The new priority level to be set.
592 /// \return Returns XOS_OK on success, else error code.
594 /// NOTE: Calling this function can result in a scheduler activation, and the
595 /// caller may be suspended as a result.
597 //-----------------------------------------------------------------------------
599 xos_thread_set_priority(XosThread * thread, int32_t priority);
602 //-----------------------------------------------------------------------------
604 /// Return the name of the specified thread.
606 /// \param thread Handle of thread being queried. A thread can use
607 /// the special handle XOS_THREAD_SELF to specify
610 /// \return Returns a pointer to the name string if available, else NULL.
612 //-----------------------------------------------------------------------------
613 static inline const char *
614 xos_thread_get_name(XosThread * thread)
617 return thread ? thread->name : 0;
621 //-----------------------------------------------------------------------------
623 /// Set the name of the specified thread.
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
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.
633 /// \return Returns XOS_OK on success, else error code.
635 //-----------------------------------------------------------------------------
636 static inline int32_t
637 xos_thread_set_name(XosThread * thread, const char * name)
640 if (thread != XOS_NULL) {
645 return XOS_ERR_INVALID_PARAMETER;
649 //-----------------------------------------------------------------------------
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.
656 /// The handler must be a function defined as e.g.:
658 /// int32_t exit_handler(int32_t exitcode);
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.
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.
670 /// \param func Pointer to exit handler function. To clear an
671 /// existing handler, pass NULL as the pointer.
673 /// \return Returns XOS_OK on success, else error code.
675 //-----------------------------------------------------------------------------
677 xos_thread_set_exit_handler(XosThread * thread, XosThdExitFunc * func);
680 //-----------------------------------------------------------------------------
682 /// Return the ID (handle) of the current thread.
684 /// \return Returns the handle of the current thread. This handle can be
685 /// used in all XOS system calls.
687 /// NOTE: If called from interrupt context, returns the handle of the thread
688 /// that was preempted.
690 //-----------------------------------------------------------------------------
691 static inline XosThread *
694 return xos_curr_threadptr;
698 //-----------------------------------------------------------------------------
700 /// Return the coprocessor mask for the specified thread.
702 /// \param thread Handle of thread being queried.
704 /// \return Returns the mask for the specified thread if available, else 0.
706 //-----------------------------------------------------------------------------
707 static inline uint16_t
708 xos_thread_cp_mask(XosThread * thread)
711 return thread ? thread->cp_mask : 0;
715 //-----------------------------------------------------------------------------
717 /// Return the wake value for the specified thread.
719 /// \return thread Handle of thread being queried.
721 /// \return Returns The last set wake value. There is no way to detect what
722 /// action set the wake value and when.
724 //-----------------------------------------------------------------------------
725 static inline int32_t
726 xos_thread_get_wake_value(XosThread * thread)
729 return thread ? thread->wake_value : 0;
733 //-----------------------------------------------------------------------------
735 /// Return the current value of the event bits for the current thread.
736 /// This function takes no parameters.
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.
743 //-----------------------------------------------------------------------------
744 static inline uint32_t
745 xos_thread_get_event_bits(void)
747 XosThread * thread = xos_thread_id();
748 return thread ? thread->event_bits : 0;
752 //-----------------------------------------------------------------------------
754 /// Enum values for thread state.
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;
766 //-----------------------------------------------------------------------------
768 /// Return the state of the specified thread.
770 /// \param thread Handle of thread being queried.
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.
779 //-----------------------------------------------------------------------------
781 xos_thread_get_state(XosThread * thread);
784 //-----------------------------------------------------------------------------
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.
794 /// \return Returns the new value of preemption disable flag after this call.
796 /// NOTE: Cannot be called from interrupt context.
798 //-----------------------------------------------------------------------------
800 xos_preemption_disable(void);
803 //-----------------------------------------------------------------------------
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.
809 /// \return Returns the new value of preemption disable flag after this call.
811 /// NOTE: If scheduling gets enabled, it may cause an immediate context switch
812 /// if higher priority threads are ready.
814 //-----------------------------------------------------------------------------
816 xos_preemption_enable(void);
819 //-----------------------------------------------------------------------------
821 /// Initialize XOS thread support and start scheduler.
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.
830 /// NOTE: This function does not initialize timer/tick support. For timer
831 /// services to be available xos_start_system_timer() must be called.
833 /// NOTE: xos_start() and xos_start_main() are exclusive, both cannot be
834 /// called within the same application.
836 /// \param flags Currently unused (pass 0).
838 /// \return Does not return.
840 //-----------------------------------------------------------------------------
842 xos_start(uint32_t flags);
845 //-----------------------------------------------------------------------------
847 /// Initialize XOS thread support and create init (main) thread.
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.
853 /// NOTE: This function does not initialize timer/tick support. For timer
854 /// services to be available xos_start_system_timer() must be called.
856 /// NOTE: xos_start_main() and xos_start() are exclusive, both cannot be
857 /// called within the same application.
859 /// \param name Name of main thread (see xos_thread_create()).
861 /// \param priority Initial priority of main thread.
863 /// \param flags Currently unused (pass 0).
865 /// \return Returns nothing.
867 //-----------------------------------------------------------------------------
869 xos_start_main(const char * name, int8_t priority, uint32_t flags);
872 //-----------------------------------------------------------------------------
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%.
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.
889 //-----------------------------------------------------------------------------
890 // Thread pseudo-handles.
891 //-----------------------------------------------------------------------------
892 #define XOS_THD_STATS_IDLE ((XosThread *) 1)
893 #define XOS_THD_STATS_INTR ((XosThread *) 2)
896 //-----------------------------------------------------------------------------
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.
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
907 /// \param stats Pointer to XosThreadStats struct to be filled in.
909 /// \return Returns XOS_OK on success, else error code.
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.
916 //-----------------------------------------------------------------------------
918 xos_thread_get_stats(XosThread * thread, XosThreadStats * stats);
921 //-----------------------------------------------------------------------------
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
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.
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.
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.
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.
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.
959 /// \return Returns XOS_OK on success, else error code. In particular,
960 /// XOS_ERR_INVALID_PARAMETER will be returned if the output buffer
963 //-----------------------------------------------------------------------------
965 xos_get_cpu_load(XosThreadStats * stats, int32_t * size, int32_t reset);
968 #ifdef _XOS_INCLUDE_INTERNAL_
970 // Signature of valid thread object
971 #define XOS_THREAD_SIG 0x54485244
985 xos_schedule(XosThread * curr_thread);
988 xos_q_remove(XosThreadQueue * queue, XosThread * thread);
991 xos_q_pop(XosThreadQueue * queue);
994 xos_wake_queue(XosThreadQueue * queue, const char * expected_cause, int32_t wake_value);
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;
1009 //-----------------------------------------------------------------------------
1010 // Blocks the current active thread.
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.
1017 // block_cause Reason for blocking.
1019 // block_queue Queue on to which this thread should be pushed once it
1020 // is blocked. Can be NULL.
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.
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.
1031 // Returns: The value passed by xos_thread_wake().
1032 //-----------------------------------------------------------------------------
1034 xos_block(const char * block_cause,
1035 XosThreadQueue * block_queue,
1036 int32_t must_schedule,
1037 int32_t use_priority);
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.
1045 // thread The thread to wake up (make ready).
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.
1051 // wake_value The value to be passed to the woken thread as a return
1052 // value from xos_thread_block().
1054 // Returns: nothing.
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 //-----------------------------------------------------------------------------
1061 xos_thread_wake(XosThread * thread, const char * expected_cause, int32_t wakevalue);
1064 //-----------------------------------------------------------------------------
1065 // Function to init C library per-thread and reentrancy support.
1066 //-----------------------------------------------------------------------------
1067 #if XOS_OPT_THREAD_SAFE_CLIB
1069 xos_clib_init(void);
1072 xos_clib_thread_init(XosThread * thread);
1075 xos_clib_thread_cleanup(XosThread * thread);
1085 #endif // __XOS_THREAD_H__