xos_thread.h 45 KB

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