/** @file */ // xos_thread.h - XOS Thread API interface and data structures. // Copyright (c) 2003-2015 Cadence Design Systems, Inc. // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // NOTE: Do not include this file directly in your application. Including // xos.h will automatically include this file. #ifndef __XOS_THREAD_H__ #define __XOS_THREAD_H__ #ifdef __cplusplus extern "C" { #endif #include "xos_types.h" #include "xos_params.h" //----------------------------------------------------------------------------- // Number of thread priority levels. //----------------------------------------------------------------------------- #ifndef XOS_NUM_PRIORITY #error "XOS_NUM_PRIORITY must be defined (in xos_params.h)." #endif #if XOS_NUM_PRIORITY > 32 #error "The number of thread priority levels (XOS_NUM_PRIORITY) must be <= 32." #endif #define XOS_MAX_PRIORITY (XOS_NUM_PRIORITY) //----------------------------------------------------------------------------- // Macro for thread self pointer. //----------------------------------------------------------------------------- #define XOS_THREAD_SELF (xos_thread_id()) //----------------------------------------------------------------------------- /// /// Thread entry function pointer type. /// //----------------------------------------------------------------------------- typedef int32_t (XosThreadFunc)(void * arg, int32_t wake_value); //----------------------------------------------------------------------------- // Thread switcher function signature. //----------------------------------------------------------------------------- typedef struct XosThread XosThread; typedef int32_t (XosSwitchFunc)(XosThread *); //----------------------------------------------------------------------------- /// /// Condition evaluation callback function pointer type. /// //----------------------------------------------------------------------------- typedef int32_t (XosCondFunc)(void * arg, int32_t sig_value, XosThread * thread); //----------------------------------------------------------------------------- /// /// Thread exit handler function pointer type. /// //----------------------------------------------------------------------------- typedef int32_t (XosThdExitFunc)(int32_t exitcode); //----------------------------------------------------------------------------- // Thread queue structure. Used to implement the ready queues as well // as the wait queues. //----------------------------------------------------------------------------- typedef struct XosThreadQueue { XosThread * head; // Pointer to first thread in queue, or 0 if none. XosThread ** tail; // Pointer to last thread's r_next pointer, or // to "head" if none. } XosThreadQueue; //----------------------------------------------------------------------------- // Stack frame for a thread that is not running. That is, it has either // been preempted or has yielded. //----------------------------------------------------------------------------- typedef union XosFrame { XosExcFrame e; // resume_fn == &xos_resume_preempted_thread XosCoopFrame c; // resume_fn == &xos_resume_cooperative_thread // nothing for resume_fn == &xos_resume_idle_thread // nothing for resume_fn == &xos_resume_by_restart } XosFrame; //----------------------------------------------------------------------------- // Thread Control Block. Tracks the state and control information associated // with a thread. // // IMPORTANT: keep this in sync with TCB_*** offsets in xos_common.h . //----------------------------------------------------------------------------- struct XosThread { XosThread * r_next; // 00 Next thread in queue (eg. ready queue of // its priority, or some queue of blocked threads) // Should be NULL if not in any queue. XosThread ** r_pprev; // 04 Points to previous queue entry's r_next // pointer (i.e. to itself), or to queue head // if first in queue. NULL if not in any queue. XosThread * all_next; // 08 Next in list of all threads. void * resume_fn; // 12 Pointer to the routine to be called to // resume this thread. On entry to such code: // a2 == xos_curr_threadptr (thread being resumed) // a3 == &xos_globals XosFrame * esf; // 16 Pointer to saved exception stack frame, // just below thread's current stack pointer. // For RTC threads, this is valid only while the // thread is preempted, not when it is blocked. void * tie_save; // 20 TIE state save area. May be NULL if there // is not TIE state saved for this thread. int32_t wake_value; // 24 Value returned from block call (by wake call) // (for RTC: pass this to start function??) XosSwitchFunc * switch_fn; // 28 Pointer to a function that // can be called from within this thread, to save // this thread's state and switch to a specified // other thread. Returns wake value. void * stack_base; // 32 Base of stack as specified by thread creator. void * stack_end; // 36 End of stack (adjusted for TIE state save area // if any). XosThreadFunc * entry; // 40 Pointer to thread entry function. Used for // RTC thread restart. void * arg; // 44 Argument value passed to entry function. bool ready; // 48 Set when thread is ready to run, and is in // its priority queue (i.e. r_pprev is set when // this flag is set). bool in_exit; // Exit flag, nonzero when in exit processing. int8_t priority; // Thread priority, 0 .. (XOS_MAX_PRI - 1). Higher // numbers have higher priority. This must only be // changed when thread is not ready, or by calling // xos_thread_set_priority(). int8_t preempt_pri; // This thread's preemption blocking priority. // (preempt_pri >= priority). A thread's priority // must be higher than another's preempt_pri to be // able to preempt it. Note that preempt_pri can // change during runtime e.g. due to priority // inheritance. uint32_t flags; // 52 Thread creation flags. const char * name; // 56 Thread name (mainly for debug). const char * block_cause; // 60 Reason for blocking. Valid only when thread // not ready (r_pprev == 0). XosThread * container; // 64 Thread whose stack will be used to run // this thread. Valid for RTC threads only, else NULL. XosThdExitFunc * exit_func; // 68 Thread exit handler function pointer. XosThreadQueue exit_waiters; // 72 Queue of threads waiting for this one to exit. XosThreadQueue * wq_ptr; // 80 If this thread is in a wait queue, this // points to the queue. Must be NULL when // thread not in a queue. XosCondFunc * cond_fn; // 84 Condition function. Valid only while thread // is blocked on condition. void * cond_arg; // 88 Argument to be passed to condition function. uint16_t cp_mask; // 92 Mask of coprocessors used. uint16_t cp_saved; // 94 Mask of coprocessors saved. uint32_t event_bits; // 96 event bits uint32_t event_mask; // 100 event bit mask uint32_t event_flags; // 104 event flags void * clib_ptr; // 108 Pointer to C lib context struct. uint32_t sig; // 112 Signature of valid TCB uint32_t resume_ccount; // 116 cycle count at resume uint64_t cycle_count; // 120 number of cycles consumed (approx). // NOTE: must be 8-byte aligned uint32_t normal_resumes; // 128 Number of non-preemptive resumptions. uint32_t preempt_resumes;// 132 Number of preemptive resumptions. #if XOS_OPT_THREAD_SAFE_CLIB CLIB_THREAD_STRUCT; // C library context area. #endif }; //----------------------------------------------------------------------------- // User-visible flags for xos_thread_create(). //----------------------------------------------------------------------------- #define XOS_THREAD_SUSPEND 0x0001 ///< Create suspended instead of ready #define XOS_THREAD_RTC 0x0002 ///< Run-to-completion thread #define XOS_THREAD_NO_CP 0x0004 ///< Thread does not use coprocessors //----------------------------------------------------------------------------- // Flags used by thread creation extra parameters. //----------------------------------------------------------------------------- #define XOS_TP_COPROC_MASK 0x0001 #define XOS_TP_PREEMPT_PRI 0x0002 #define XOS_TP_EXIT_HANDLER 0x0004 //----------------------------------------------------------------------------- // Thread creation extra parameters. //----------------------------------------------------------------------------- typedef struct XosThreadParm { uint32_t parms_mask; // Combination of XOS_TP_xxx flags indicating // which parameters are valid. uint16_t cp_mask; // Mask of coprocessors the thread can access. uint32_t preempt_pri; // Initial preemption blocking priority. Can be // changed later via xos_thread_set_priority(). XosThdExitFunc * handler; // Exit handler function. } XosThreadParm; //----------------------------------------------------------------------------- // Wrapper struct for RTC (run to completion) thread. //----------------------------------------------------------------------------- typedef struct XosRtcThread { struct XosThread thread; } XosRtcThread; //----------------------------------------------------------------------------- // External variables. //----------------------------------------------------------------------------- extern XosThread * xos_curr_threadptr; // Current active thread extern XosThread * xos_next_threadptr; // Next ready thread extern XosThread * xos_all_threads; // List of all threads //----------------------------------------------------------------------------- /// /// Set thread creation parameter: the group of coprocessors that this thread /// will use. This must be set during thread creation, and cannot be changed /// after the thread has been created. Defining this allows reduction of /// memory usage (for CP state saving) in some circumstances, and can also /// speed up the context switch time. /// /// NOTE: Support for this is not currently implemented. If a thread uses /// any coprocessor, space for all coprocessors must be reserved. /// /// \param parms Thread creation parameter structure. Must be /// allocated by the caller. /// /// \param cp_mask Bitmask of coprocessors thread is allowed to /// use. Bit 0 for coprocessor 0, etc. /// /// \return Returns nothing. /// //----------------------------------------------------------------------------- static inline void xos_threadp_set_cp_mask(XosThreadParm * parms, uint16_t cp_mask) { if (parms != XOS_NULL) { parms->parms_mask |= XOS_TP_COPROC_MASK; parms->cp_mask = cp_mask; } } //----------------------------------------------------------------------------- /// /// Set thread creation parameter: thread pre-emption priority. /// /// \param parms Thread creation parameter structure. Must be /// allocated by caller. /// /// \param preempt_pri Thread pre-emption blocking priority. /// From 0 .. XOS_NUM_PRIORITY - 1. /// Must be greater or equal to the thread priority /// (if not, is automatically set to thread priority). /// /// \return Returns nothing. /// //----------------------------------------------------------------------------- static inline void xos_threadp_set_preemption_priority(XosThreadParm * parms, int8_t preempt_pri) { if (parms != XOS_NULL) { parms->parms_mask |= XOS_TP_PREEMPT_PRI; parms->preempt_pri = preempt_pri; } } //----------------------------------------------------------------------------- /// /// Set thread creation parameter: thread exit handler. /// /// \param parms Thread creation parameter structure. Must be /// allocated by caller. /// /// \param handler Exit handler function. /// /// \return Returns nothing. //----------------------------------------------------------------------------- static inline void xos_threadp_set_exit_handler(XosThreadParm * parms, XosThdExitFunc * handler) { if (parms != XOS_NULL) { parms->parms_mask |= XOS_TP_EXIT_HANDLER; parms->handler = handler; } } //----------------------------------------------------------------------------- /// /// Create a new thread. If the thread is not created suspended, then it will /// be made ready as soon as it is created, and will immediately run if it is /// the highest priority non-blocked thread in the system. /// /// \param thread Pointer to the thread descriptor (an otherwise /// unused XosThread structure, usually allocated /// by the caller for the lifetime of the thread, /// for example as a global variable). /// /// \param container Pointer to separate thread acting as "container" /// for this one. At the moment, this is only meaningful /// for run-to-completion (RTC) threads (identified with /// the XOS_THREAD_RTC flag), in which case the container /// must have the same priority and also be an RTC thread. /// (The priority restriction may be lifted in a future /// implementation, with appropriate constraints on dynamic /// reprioritization of the created thread). /// /// \param entry Thread entry function, takes one argument. /// /// \param arg Argument "void*" that is passed to the thread function. /// /// \param name Unique name of the thread, for debug/display purposes. /// This string must be valid for the lifetime of the thread /// (only a pointer to it is stored in the thread control block). /// Typically consists of identifier chars with no spaces. /// /// \param stack Base of initial stack for the thread, allocated by the /// caller. Need not be aligned (initial stack pointer will be /// computed and aligned from given stack base and size). /// Required argument, except for run-to-completion threads /// when container is non-NULL, in which case the container's /// stack is used and this argument must be NULL. /// /// \param stack_size Size of the stack, in bytes. /// NOTE: stack should be at least XOS_STACK_EXTRA bytes plus /// whatever the thread actually needs if the thread will use /// coprocessors/TIE state. If the thread will not touch the /// coprocessors, then it should be XOS_STACK_EXTRA_NO_CP /// plus whatever the thread actually needs. /// Recommended minimum stack sizes are defined by the constants /// XOS_STACK_MIN_SIZE and XOS_STACK_MIN_SIZE_NO_CP. /// /// For run-to-completion threads where container is non-NULL, /// stack_size specifies the minimum stack size required for /// the thread; it should be smaller or equal to the container's /// stack. /// /// \param priority Initial thread priority. From 0 .. XOS_MAX_PRI - 1. /// Higher numbers are higher priority. /// /// \param parms Pointer to extra parameters structure, or 0 if none given. /// Use xos_thread_p_***() functions to set parameters in the /// structure. /// /// \param flags Option flags: /// - XOS_THREAD_SUSPEND -- Leave thread suspended instead of /// making it ready. The thread can be made ready to run later /// by calling xos_thread_resume(). /// - XOS_THREAD_RTC -- Run-to-completion thread. /// - XOS_THREAD_NO_CP -- Thread does not use coprocessors. /// No coprocessor state will be saved for this thread. /// Threads that have this flag set will not allocate any /// storage for saving coprocessor state and so can have /// smaller stacks. /// /// NOTE: xos_start_main() calls xos_thread_create() to convert main() into the 'main' /// thread. /// /// \return Returns XOS_OK if successful, error code otherwise. /// //----------------------------------------------------------------------------- int32_t xos_thread_create(XosThread * thread, XosThread * container, XosThreadFunc * entry, void * arg, const char * name, void * stack, uint32_t stack_size, int32_t priority, XosThreadParm * parms, uint32_t flags ); //----------------------------------------------------------------------------- /// /// Remove thread and free up all resources. Thread must have exited already. /// After this call returns, all resources allocated to the thread (e.g. TCB, /// stack space, etc.) can be reused. /// /// \param thread Handle of thread to be deleted. /// /// \return Returns XOS_OK on success, else error code. /// /// NOTE: A thread cannot call this on itself. /// //----------------------------------------------------------------------------- int32_t xos_thread_delete(XosThread * thread); //----------------------------------------------------------------------------- /// /// Force the thread to terminate. The thread execution is aborted, but exit /// processing will still happen, i.e. the exit handler (if any) will be run. /// After termination, any other threads waiting on this thread are notified. /// This function cannot be called on the current thread. /// /// \param thread Handle of thread to be aborted. /// /// \param exitcode Exit code returned to any waiting threads. /// /// \return Returns XOS_OK on success, else error code. /// /// NOTE: If the thread is blocked waiting for something, the wait is aborted /// and the thread is made ready. /// NOTE: The thread is not guaranteed to have exited when this call returns. /// It will be made ready and set up for exit processing, but when the exit /// processing will actually happen depends on the state of the system and /// the priority of the thread being aborted. /// //----------------------------------------------------------------------------- int32_t xos_thread_abort(XosThread * thread, int32_t exitcode); //----------------------------------------------------------------------------- /// /// Exit the current thread. The exit handler (if any) will be run before the /// thread terminates. /// /// \param exitcode Exit code to be returned to any waiting threads. /// /// \return This function does not return. /// /// NOTE: This is automatically called if the thread returns from its entry /// function. The entry function's return value will be passed as the exit /// code. /// //----------------------------------------------------------------------------- void xos_thread_exit(int32_t exitcode); //----------------------------------------------------------------------------- /// /// Wait until the specified thread exits and get its exit code. If the thread /// has exited already, an error will be returned. /// /// \param thread The thread to wait for. Cannot be "self", i.e. /// one cannot wait on one's own exit. /// /// \param p_exitcode If not null, the exit code will be returned here. /// /// \return Returns XOS_OK on sucess, else error code. /// //----------------------------------------------------------------------------- int32_t xos_thread_join(XosThread * thread, int32_t * p_exitcode); //----------------------------------------------------------------------------- /// /// Yield the CPU to the next thread in line. The calling thread remains ready /// and is placed at the tail of the ready queue at its current priority level. /// If there are no threads at the same priority level that are ready to run, /// then this call will return immediately. /// /// \return Returns nothing. /// //----------------------------------------------------------------------------- void xos_thread_yield(); //----------------------------------------------------------------------------- /// /// Suspend the specified thread. The thread will remain suspended until /// xos_thread_resume() has been called on it. If the thread is already blocked /// on some other condition, then this function will return an error. /// /// \param thread Handle of thread being suspended. A thread can /// use the special handle XOS_THREAD_SELF to suspend /// itself. /// /// \return Returns XOS_OK on success, else error code. /// //----------------------------------------------------------------------------- int32_t xos_thread_suspend(XosThread * thread); //----------------------------------------------------------------------------- /// /// Resume a suspended thread. If the thread is not suspended or is blocked on /// some other condition then this function will do nothing. Otherwise, it will /// be made ready, and this can cause an immediate context switch if the thread /// is at a higher priority than the calling thread. /// /// \param thread Handle of thread being resumed. /// /// \return Returns XOS_OK on success, else error code. /// //----------------------------------------------------------------------------- int32_t xos_thread_resume(XosThread * thread); //----------------------------------------------------------------------------- /// /// Get the priority of the specified thread. This returns the priority of the /// queried thread at this instant, however this can change at any time due to /// other activity in the system. /// /// \param thread Handle of thread being queried. A thread can use /// the special handle XOS_THREAD_SELF to query itself. /// /// \return Returns the thread's current priority, or -1 if the thread handle /// is not valid. /// //----------------------------------------------------------------------------- static inline int32_t xos_thread_get_priority(XosThread * thread) { XOS_ASSERT(thread); return thread ? thread->priority : -1; } //----------------------------------------------------------------------------- /// /// Set the priority of the specified thread. The thread must exist. /// /// \param thread Handle of thread being affected. A thread can /// use the special handle XOS_THREAD_SELF to specify /// itself. /// /// \param priority The new priority level to be set. /// /// \return Returns XOS_OK on success, else error code. /// /// NOTE: Calling this function can result in a scheduler activation, and the /// caller may be suspended as a result. /// //----------------------------------------------------------------------------- int32_t xos_thread_set_priority(XosThread * thread, int32_t priority); //----------------------------------------------------------------------------- /// /// Return the name of the specified thread. /// /// \param thread Handle of thread being queried. A thread can use /// the special handle XOS_THREAD_SELF to specify /// itself. /// /// \return Returns a pointer to the name string if available, else NULL. /// //----------------------------------------------------------------------------- static inline const char * xos_thread_get_name(XosThread * thread) { XOS_ASSERT(thread); return thread ? thread->name : 0; } //----------------------------------------------------------------------------- /// /// Set the name of the specified thread. /// /// \param thread Handle of thread whose name is to be set. A thread /// can use the special handle XOS_THREAD_SELF to specify /// itself. /// /// \param name Pointer to the new name string. The string is not /// copied, only the pointer is saved. So the string /// must be persistent for the life of the thread. /// /// \return Returns XOS_OK on success, else error code. /// //----------------------------------------------------------------------------- static inline int32_t xos_thread_set_name(XosThread * thread, const char * name) { XOS_ASSERT(thread); if (thread != XOS_NULL) { thread->name = name; return XOS_OK; } return XOS_ERR_INVALID_PARAMETER; } //----------------------------------------------------------------------------- /// /// Set an exit handler for the specified thread. The exit handler is run when /// the thread terminates, either by calling xos_thread_exit() or by returning /// from its entry function. It will also be called if the thread is being /// terminated due to e.g. an unhandled exception. /// /// The handler must be a function defined as e.g.: /// /// int32_t exit_handler(int32_t exitcode); /// /// The exit handler runs in the context of the exiting thread, and can call /// system services. It is provided with a single parameter which is the /// thread's exit code (the exit code may be set to an error code if the /// thread is being terminated due to an error or exception). The handler /// must return a value which will be set as the thread's exit code. /// /// \param thread Handle of the thread for which the handler is /// to be installed. A thread can use the special /// handle XOS_THREAD_SELF to specify itself. /// /// \param func Pointer to exit handler function. To clear an /// existing handler, pass NULL as the pointer. /// /// \return Returns XOS_OK on success, else error code. /// //----------------------------------------------------------------------------- int32_t xos_thread_set_exit_handler(XosThread * thread, XosThdExitFunc * func); //----------------------------------------------------------------------------- /// /// Return the ID (handle) of the current thread. /// /// \return Returns the handle of the current thread. This handle can be /// used in all XOS system calls. /// /// NOTE: If called from interrupt context, returns the handle of the thread /// that was preempted. /// //----------------------------------------------------------------------------- static inline XosThread * xos_thread_id() { return xos_curr_threadptr; } //----------------------------------------------------------------------------- /// /// Return the coprocessor mask for the specified thread. /// /// \param thread Handle of thread being queried. /// /// \return Returns the mask for the specified thread if available, else 0. /// //----------------------------------------------------------------------------- static inline uint16_t xos_thread_cp_mask(XosThread * thread) { XOS_ASSERT(thread); return thread ? thread->cp_mask : 0; } //----------------------------------------------------------------------------- /// /// Return the wake value for the specified thread. /// /// \return thread Handle of thread being queried. /// /// \return Returns The last set wake value. There is no way to detect what /// action set the wake value and when. /// //----------------------------------------------------------------------------- static inline int32_t xos_thread_get_wake_value(XosThread * thread) { XOS_ASSERT(thread); return thread ? thread->wake_value : 0; } //----------------------------------------------------------------------------- /// /// Return the current value of the event bits for the current thread. /// This function takes no parameters. /// /// \return Returns the current value of the event bits. The event bits /// are set when the thread is woken from an event wait. They will /// not change while the thread is running. There is no way to /// determine when the event bits were last updated. /// //----------------------------------------------------------------------------- static inline uint32_t xos_thread_get_event_bits(void) { XosThread * thread = xos_thread_id(); return thread ? thread->event_bits : 0; } //----------------------------------------------------------------------------- /// /// Enum values for thread state. /// //----------------------------------------------------------------------------- typedef enum xos_thread_state_t { XOS_THREAD_STATE_INVALID = 0, ///< Invalid thread XOS_THREAD_STATE_BLOCKED, ///< Thread is blocked XOS_THREAD_STATE_READY, ///< Thread is ready to run XOS_THREAD_STATE_RUNNING, ///< Thread is running XOS_THREAD_STATE_EXITED, ///< Thread has exited } xos_thread_state_t; //----------------------------------------------------------------------------- /// /// Return the state of the specified thread. /// /// \param thread Handle of thread being queried. /// /// \return Returns one of the following values: /// - XOS_THREAD_STATE_RUNNING -- The thread is currently running. /// - XOS_THREAD_STATE_READY -- The thread is ready to run. /// - XOS_THREAD_STATE_BLOCKED -- The thread is blocked on something. /// - XOS_THREAD_STATE_INVALID -- The thread handle is invalid. /// - XOS_THREAD_STATE_EXITED -- The thread has exited. /// //----------------------------------------------------------------------------- xos_thread_state_t xos_thread_get_state(XosThread * thread); //----------------------------------------------------------------------------- /// /// Disable thread preemption. Prevents context switching to another thread. /// However, interrupt handlers will still continue to be run. Multiple calls /// will nest, and the same number of calls to xos_preemption_enable() will be /// required to re-enable preemption. If the calling thread yields the CPU or /// exits without enabling preemption, it will cause a system halt. /// If the calling thread encounters a fatal error, preemption will be enabled /// during fatal error handling. /// /// \return Returns the new value of preemption disable flag after this call. /// /// NOTE: Cannot be called from interrupt context. /// //----------------------------------------------------------------------------- uint32_t xos_preemption_disable(void); //----------------------------------------------------------------------------- /// /// Enable thread preemption. Has no effect if preemption was already enabled. /// Otherwise, it decrements the value of the preemption disable flag and if /// the value goes to zero, enables preemption. /// /// \return Returns the new value of preemption disable flag after this call. /// /// NOTE: If scheduling gets enabled, it may cause an immediate context switch /// if higher priority threads are ready. /// //----------------------------------------------------------------------------- uint32_t xos_preemption_enable(void); //----------------------------------------------------------------------------- /// /// Initialize XOS thread support and start scheduler. /// /// Must be called from main() before calling any other thread function. /// This function initializes thread support, creates the idle thread, and /// starts the scheduler. It does not return to its caller. This means that /// at least one user thread must be created before calling xos_start(). /// Otherwise, the scheduler will run the idle thread since it will be the /// only thread in the system, and no other thread can be created. /// /// NOTE: This function does not initialize timer/tick support. For timer /// services to be available xos_start_system_timer() must be called. /// /// NOTE: xos_start() and xos_start_main() are exclusive, both cannot be /// called within the same application. /// /// \param flags Currently unused (pass 0). /// /// \return Does not return. /// //----------------------------------------------------------------------------- void xos_start(uint32_t flags); //----------------------------------------------------------------------------- /// /// Initialize XOS thread support and create init (main) thread. /// /// Must be called from main() before calling any other thread function. /// This function converts the caller into the 'main' or 'init' thread, and /// returns to the caller after completing initialization. /// /// NOTE: This function does not initialize timer/tick support. For timer /// services to be available xos_start_system_timer() must be called. /// /// NOTE: xos_start_main() and xos_start() are exclusive, both cannot be /// called within the same application. /// /// \param name Name of main thread (see xos_thread_create()). /// /// \param priority Initial priority of main thread. /// /// \param flags Currently unused (pass 0). /// /// \return Returns nothing. /// //----------------------------------------------------------------------------- void xos_start_main(const char * name, int8_t priority, uint32_t flags); //----------------------------------------------------------------------------- /// /// Per-thread stats structure. /// Note that the CPU use % is approximate, both because of cycle counting /// and because of integer division. So all the threads' CPU % will not add /// up to exactly 100%. /// //----------------------------------------------------------------------------- typedef struct XosThreadStats { XosThread * thread; ///< Thread handle (or pseudo-handle) uint32_t cpu_pct; ///< CPU use % for this thread uint32_t normal_switches; ///< Number of non-preemptive switches. uint32_t preempt_switches; ///< Number of preemptive switches. uint64_t cycle_count; ///< Number of cycles consumed. } XosThreadStats; //----------------------------------------------------------------------------- // Thread pseudo-handles. //----------------------------------------------------------------------------- #define XOS_THD_STATS_IDLE ((XosThread *) 1) #define XOS_THD_STATS_INTR ((XosThread *) 2) //----------------------------------------------------------------------------- /// /// Get the thread statistics for the specified thread. Statistics are only /// available if XOS_OPT_STATS has been enabled. Otherwise, the function /// will return XOS_OK, but the structure contents will be undefined. /// /// \param thread Handle of thread being queried. The following /// special pseudo-handles can be used: /// - XOS_THD_STATS_IDLE -- stats for idle thread /// - XOS_THD_STATS_INTR -- stats for interrupt processing /// /// \param stats Pointer to XosThreadStats struct to be filled in. /// /// \return Returns XOS_OK on success, else error code. /// /// NOTE: Can be called from interrupt context. /// NOTE: This call will not fill in the "thread" and "cpu_pct" fields in the /// "stats" structure. The thread handle is already known, and calculating the /// CPU loading can take quite a bit of time so is not done here. /// //----------------------------------------------------------------------------- int32_t xos_thread_get_stats(XosThread * thread, XosThreadStats * stats); //----------------------------------------------------------------------------- /// /// Get CPU loading statistics for the system. This function computes the CPU /// percentage use for all threads in the system (including the idle thread and /// the 'interrupt thread' (interrupt context). It also returns the cycle count /// and number of context switches for each thread. /// Statistics are only available if XOS_OPT_STATS has been enabled. /// Otherwise, the function will return XOS_OK, but the structure contents will /// be undefined. /// /// IMPORTANT: The entry for interrupt context does not contain a real thread /// handle. It uses the pseudo-handle XOS_THD_STATS_INTR to indicate that this /// entry reports interrupt statistics. This pseudo-handle cannot be used for /// any other thread operations or queries. /// /// NOTE: This function disables interrupts while traversing the thread list. /// It does not leave interrupts disabled during the computations, as that can /// take a fair amount of time. /// /// \param stats Pointer to an array of XosThreadStats structures. /// The array must be large enough to accommodate all /// threads in the system. /// /// \param size The number of elements available in the array. If /// this is smaller than the number of threads plus one /// (for the interrupt context) then XOS_ERR_INVALID_PARAMETER /// will be returned and '*size' will be set to the /// minimum number of elements required. On a successful /// return, '*size' is set to the number of elements /// actually filled in. /// /// \param reset If nonzero, then thread stats counters are reset /// after reading. This is useful if you want to track /// the stats so as to get a better idea of current /// system loading. E.g. calling this function once a /// second with 'reset' nonzero will provide CPU load /// information for the last second on each call. /// /// \return Returns XOS_OK on success, else error code. In particular, /// XOS_ERR_INVALID_PARAMETER will be returned if the output buffer /// is too small. /// //----------------------------------------------------------------------------- int32_t xos_get_cpu_load(XosThreadStats * stats, int32_t * size, int32_t reset); #ifdef _XOS_INCLUDE_INTERNAL_ // Signature of valid thread object #define XOS_THREAD_SIG 0x54485244 // Extern functions void xos_init(void); bool xos_init_done(void); bool xos_started(void); int32_t xos_schedule(XosThread * curr_thread); void xos_q_remove(XosThreadQueue * queue, XosThread * thread); XosThread * xos_q_pop(XosThreadQueue * queue); int32_t xos_wake_queue(XosThreadQueue * queue, const char * expected_cause, int32_t wake_value); // Well known block causes extern const char * const xos_blkon_idle; // (for idle thread only) extern const char * const xos_blkon_suspend; extern const char * const xos_blkon_delay; extern const char * const xos_blkon_exited; extern const char * const xos_blkon_join; extern const char * const xos_blkon_event; extern const char * const xos_blkon_condition; extern const char * const xos_blkon_mutex; extern const char * const xos_blkon_sem; extern const char * const xos_blkon_msgq; //----------------------------------------------------------------------------- // Blocks the current active thread. // // Currently, this can be called from an interrupt handler to block the thread // that was interrupted. Note that in interrupt context the current thread can // already be in the blocked state, due to a previous call to this function. // Can be called with interrupts enabled. // // block_cause Reason for blocking. // // block_queue Queue on to which this thread should be pushed once it // is blocked. Can be NULL. // // must_schedule If nonzero, then forces a scheduling operation to pick // the next thread to run, even if there are ready threads // at the same priority level as the blocked thread. // // use_priority If nonzero, then the blocked thread will be queued in // priority order in the specified block queue. If zero, // the thread is queued in FIFO order. If no queue has // been specified, this parameter is ignored. // // Returns: The value passed by xos_thread_wake(). //----------------------------------------------------------------------------- int32_t xos_block(const char * block_cause, XosThreadQueue * block_queue, int32_t must_schedule, int32_t use_priority); //----------------------------------------------------------------------------- // Unblocks the specified blocked thread and puts it at the tail end of its // ready queue. Schedules it if it is higher priority than the current thread. // No effect if the thread is not blocked with the specified cause. // // thread The thread to wake up (make ready). // // expected_cause The expected block cause of the thread. Thread will be // woken only if its block cause matches this cause, or if // expected_cause is zero. // // wake_value The value to be passed to the woken thread as a return // value from xos_thread_block(). // // Returns: nothing. // // The target thread can be woken at a different priority by changing its // priority while the thread is blocked. // Can be called with interrupts enabled. Can be called in interrupt context. //----------------------------------------------------------------------------- void xos_thread_wake(XosThread * thread, const char * expected_cause, int32_t wakevalue); //----------------------------------------------------------------------------- // Function to init C library per-thread and reentrancy support. //----------------------------------------------------------------------------- #if XOS_OPT_THREAD_SAFE_CLIB void xos_clib_init(void); void xos_clib_thread_init(XosThread * thread); void xos_clib_thread_cleanup(XosThread * thread); #endif #endif #ifdef __cplusplus } #endif #endif // __XOS_THREAD_H__