chthreads.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440
  1. /*
  2. ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
  3. This file is part of ChibiOS.
  4. ChibiOS is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 3 of the License, or
  7. (at your option) any later version.
  8. ChibiOS is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. /**
  16. * @file chthreads.h
  17. * @brief Threads module macros and structures.
  18. *
  19. * @addtogroup threads
  20. * @{
  21. */
  22. #ifndef CHTHREADS_H
  23. #define CHTHREADS_H
  24. /*lint -sem(chThdExit, r_no) -sem(chThdExitS, r_no)*/
  25. /*===========================================================================*/
  26. /* Module constants. */
  27. /*===========================================================================*/
  28. /*===========================================================================*/
  29. /* Module pre-compile time settings. */
  30. /*===========================================================================*/
  31. /*===========================================================================*/
  32. /* Derived constants and error checks. */
  33. /*===========================================================================*/
  34. /*===========================================================================*/
  35. /* Module data structures and types. */
  36. /*===========================================================================*/
  37. /**
  38. * @brief Thread function.
  39. */
  40. typedef void (*tfunc_t)(void *p);
  41. /**
  42. * @brief Type of a thread descriptor.
  43. */
  44. typedef struct {
  45. /**
  46. * @brief Thread name.
  47. */
  48. const char *name;
  49. /**
  50. * @brief Pointer to the working area base.
  51. */
  52. stkalign_t *wbase;
  53. /**
  54. * @brief End of the working area.
  55. */
  56. stkalign_t *wend;
  57. /**
  58. * @brief Thread priority.
  59. */
  60. tprio_t prio;
  61. /**
  62. * @brief Thread function pointer.
  63. */
  64. tfunc_t funcp;
  65. /**
  66. * @brief Thread argument.
  67. */
  68. void *arg;
  69. } thread_descriptor_t;
  70. /*===========================================================================*/
  71. /* Module macros. */
  72. /*===========================================================================*/
  73. /**
  74. * @name Threads queues
  75. */
  76. /**
  77. * @brief Data part of a static threads queue object initializer.
  78. * @details This macro should be used when statically initializing a threads
  79. * queue that is part of a bigger structure.
  80. *
  81. * @param[in] name the name of the threads queue variable
  82. */
  83. #define _THREADS_QUEUE_DATA(name) {(thread_t *)&name, (thread_t *)&name}
  84. /**
  85. * @brief Static threads queue object initializer.
  86. * @details Statically initialized threads queues require no explicit
  87. * initialization using @p queue_init().
  88. *
  89. * @param[in] name the name of the threads queue variable
  90. */
  91. #define _THREADS_QUEUE_DECL(name) \
  92. threads_queue_t name = _THREADS_QUEUE_DATA(name)
  93. /** @} */
  94. /**
  95. * @name Working Areas
  96. */
  97. /**
  98. * @brief Calculates the total Working Area size.
  99. *
  100. * @param[in] n the stack size to be assigned to the thread
  101. * @return The total used memory in bytes.
  102. *
  103. * @api
  104. */
  105. #define THD_WORKING_AREA_SIZE(n) \
  106. MEM_ALIGN_NEXT(sizeof(thread_t) + PORT_WA_SIZE(n), PORT_STACK_ALIGN)
  107. /**
  108. * @brief Static working area allocation.
  109. * @details This macro is used to allocate a static thread working area
  110. * aligned as both position and size.
  111. *
  112. * @param[in] s the name to be assigned to the stack array
  113. * @param[in] n the stack size to be assigned to the thread
  114. *
  115. * @api
  116. */
  117. #define THD_WORKING_AREA(s, n) PORT_WORKING_AREA(s, n)
  118. /**
  119. * @brief Base of a working area casted to the correct type.
  120. *
  121. * @param[in] s name of the working area
  122. */
  123. #define THD_WORKING_AREA_BASE(s) ((stkalign_t *)(s))
  124. /**
  125. * @brief End of a working area casted to the correct type.
  126. *
  127. * @param[in] s name of the working area
  128. */
  129. #define THD_WORKING_AREA_END(s) (THD_WORKING_AREA_BASE(s) + \
  130. (sizeof (s) / sizeof (stkalign_t)))
  131. /** @} */
  132. /**
  133. * @name Threads abstraction macros
  134. */
  135. /**
  136. * @brief Thread declaration macro.
  137. * @note Thread declarations should be performed using this macro because
  138. * the port layer could define optimizations for thread functions.
  139. */
  140. #define THD_FUNCTION(tname, arg) PORT_THD_FUNCTION(tname, arg)
  141. /** @} */
  142. /**
  143. * @name Macro Functions
  144. * @{
  145. */
  146. /**
  147. * @brief Delays the invoking thread for the specified number of seconds.
  148. * @note The specified time is rounded up to a value allowed by the real
  149. * system tick clock.
  150. * @note The maximum specifiable value is implementation dependent.
  151. * @note Use of this macro for large values is not secure because
  152. * integer overflows, make sure your value can be correctly
  153. * converted.
  154. *
  155. * @param[in] sec time in seconds, must be different from zero
  156. *
  157. * @api
  158. */
  159. #define chThdSleepSeconds(sec) chThdSleep(TIME_S2I(sec))
  160. /**
  161. * @brief Delays the invoking thread for the specified number of
  162. * milliseconds.
  163. * @note The specified time is rounded up to a value allowed by the real
  164. * system tick clock.
  165. * @note The maximum specifiable value is implementation dependent.
  166. * @note Use of this macro for large values is not secure because
  167. * integer overflows, make sure your value can be correctly
  168. * converted.
  169. *
  170. * @param[in] msec time in milliseconds, must be different from zero
  171. *
  172. * @api
  173. */
  174. #define chThdSleepMilliseconds(msec) chThdSleep(TIME_MS2I(msec))
  175. /**
  176. * @brief Delays the invoking thread for the specified number of
  177. * microseconds.
  178. * @note The specified time is rounded up to a value allowed by the real
  179. * system tick clock.
  180. * @note The maximum specifiable value is implementation dependent.
  181. * @note Use of this macro for large values is not secure because
  182. * integer overflows, make sure your value can be correctly
  183. * converted.
  184. *
  185. * @param[in] usec time in microseconds, must be different from zero
  186. *
  187. * @api
  188. */
  189. #define chThdSleepMicroseconds(usec) chThdSleep(TIME_US2I(usec))
  190. /** @} */
  191. /*===========================================================================*/
  192. /* External declarations. */
  193. /*===========================================================================*/
  194. #ifdef __cplusplus
  195. extern "C" {
  196. #endif
  197. thread_t *_thread_init(thread_t *tp, const char *name, tprio_t prio);
  198. #if CH_DBG_FILL_THREADS == TRUE
  199. void _thread_memfill(uint8_t *startp, uint8_t *endp, uint8_t v);
  200. #endif
  201. thread_t *chThdCreateSuspendedI(const thread_descriptor_t *tdp);
  202. thread_t *chThdCreateSuspended(const thread_descriptor_t *tdp);
  203. thread_t *chThdCreateI(const thread_descriptor_t *tdp);
  204. thread_t *chThdCreate(const thread_descriptor_t *tdp);
  205. thread_t *chThdCreateStatic(void *wsp, size_t size,
  206. tprio_t prio, tfunc_t pf, void *arg);
  207. thread_t *chThdStart(thread_t *tp);
  208. #if CH_CFG_USE_REGISTRY == TRUE
  209. thread_t *chThdAddRef(thread_t *tp);
  210. void chThdRelease(thread_t *tp);
  211. #endif
  212. void chThdExit(msg_t msg);
  213. void chThdExitS(msg_t msg);
  214. #if CH_CFG_USE_WAITEXIT == TRUE
  215. msg_t chThdWait(thread_t *tp);
  216. #endif
  217. tprio_t chThdSetPriority(tprio_t newprio);
  218. void chThdTerminate(thread_t *tp);
  219. msg_t chThdSuspendS(thread_reference_t *trp);
  220. msg_t chThdSuspendTimeoutS(thread_reference_t *trp, sysinterval_t timeout);
  221. void chThdResumeI(thread_reference_t *trp, msg_t msg);
  222. void chThdResumeS(thread_reference_t *trp, msg_t msg);
  223. void chThdResume(thread_reference_t *trp, msg_t msg);
  224. msg_t chThdEnqueueTimeoutS(threads_queue_t *tqp, sysinterval_t timeout);
  225. void chThdDequeueNextI(threads_queue_t *tqp, msg_t msg);
  226. void chThdDequeueAllI(threads_queue_t *tqp, msg_t msg);
  227. void chThdSleep(sysinterval_t time);
  228. void chThdSleepUntil(systime_t time);
  229. systime_t chThdSleepUntilWindowed(systime_t prev, systime_t next);
  230. void chThdYield(void);
  231. #ifdef __cplusplus
  232. }
  233. #endif
  234. /*===========================================================================*/
  235. /* Module inline functions. */
  236. /*===========================================================================*/
  237. /**
  238. * @brief Returns a pointer to the current @p thread_t.
  239. *
  240. * @return A pointer to the current thread.
  241. *
  242. * @xclass
  243. */
  244. static inline thread_t *chThdGetSelfX(void) {
  245. return ch.rlist.current;
  246. }
  247. /**
  248. * @brief Returns the current thread priority.
  249. * @note Can be invoked in any context.
  250. *
  251. * @return The current thread priority.
  252. *
  253. * @xclass
  254. */
  255. static inline tprio_t chThdGetPriorityX(void) {
  256. return chThdGetSelfX()->prio;
  257. }
  258. /**
  259. * @brief Returns the number of ticks consumed by the specified thread.
  260. * @note This function is only available when the
  261. * @p CH_DBG_THREADS_PROFILING configuration option is enabled.
  262. *
  263. * @param[in] tp pointer to the thread
  264. * @return The number of consumed system ticks.
  265. *
  266. * @xclass
  267. */
  268. #if (CH_DBG_THREADS_PROFILING == TRUE) || defined(__DOXYGEN__)
  269. static inline systime_t chThdGetTicksX(thread_t *tp) {
  270. return tp->time;
  271. }
  272. #endif
  273. #if (CH_DBG_ENABLE_STACK_CHECK == TRUE) || (CH_CFG_USE_DYNAMIC == TRUE) || \
  274. defined(__DOXYGEN__)
  275. /**
  276. * @brief Returns the working area base of the specified thread.
  277. *
  278. * @param[in] tp pointer to the thread
  279. * @return The working area base pointer.
  280. *
  281. * @xclass
  282. */
  283. static inline stkalign_t *chThdGetWorkingAreaX(thread_t *tp) {
  284. return tp->wabase;
  285. }
  286. #endif /* CH_DBG_ENABLE_STACK_CHECK == TRUE */
  287. /**
  288. * @brief Verifies if the specified thread is in the @p CH_STATE_FINAL state.
  289. *
  290. * @param[in] tp pointer to the thread
  291. * @retval true thread terminated.
  292. * @retval false thread not terminated.
  293. *
  294. * @xclass
  295. */
  296. static inline bool chThdTerminatedX(thread_t *tp) {
  297. return (bool)(tp->state == CH_STATE_FINAL);
  298. }
  299. /**
  300. * @brief Verifies if the current thread has a termination request pending.
  301. *
  302. * @retval true termination request pending.
  303. * @retval false termination request not pending.
  304. *
  305. * @xclass
  306. */
  307. static inline bool chThdShouldTerminateX(void) {
  308. return (bool)((chThdGetSelfX()->flags & CH_FLAG_TERMINATE) != (tmode_t)0);
  309. }
  310. /**
  311. * @brief Resumes a thread created with @p chThdCreateI().
  312. *
  313. * @param[in] tp pointer to the thread
  314. * @return The pointer to the @p thread_t structure allocated for
  315. * the thread into the working space area.
  316. *
  317. * @iclass
  318. */
  319. static inline thread_t *chThdStartI(thread_t *tp) {
  320. chDbgAssert(tp->state == CH_STATE_WTSTART, "wrong state");
  321. return chSchReadyI(tp);
  322. }
  323. /**
  324. * @brief Suspends the invoking thread for the specified number of ticks.
  325. *
  326. * @param[in] ticks the delay in system ticks, the special values are
  327. * handled as follow:
  328. * - @a TIME_INFINITE the thread enters an infinite sleep
  329. * state.
  330. * - @a TIME_IMMEDIATE this value is not allowed.
  331. * .
  332. *
  333. * @sclass
  334. */
  335. static inline void chThdSleepS(sysinterval_t ticks) {
  336. chDbgCheck(ticks != TIME_IMMEDIATE);
  337. (void) chSchGoSleepTimeoutS(CH_STATE_SLEEPING, ticks);
  338. }
  339. /**
  340. * @brief Initializes a threads queue object.
  341. *
  342. * @param[out] tqp pointer to the threads queue object
  343. *
  344. * @init
  345. */
  346. static inline void chThdQueueObjectInit(threads_queue_t *tqp) {
  347. queue_init(tqp);
  348. }
  349. /**
  350. * @brief Evaluates to @p true if the specified queue is empty.
  351. *
  352. * @param[out] tqp pointer to the threads queue object
  353. * @return The queue status.
  354. * @retval false if the queue is not empty.
  355. * @retval true if the queue is empty.
  356. *
  357. * @iclass
  358. */
  359. static inline bool chThdQueueIsEmptyI(threads_queue_t *tqp) {
  360. chDbgCheckClassI();
  361. return queue_isempty(tqp);
  362. }
  363. /**
  364. * @brief Dequeues and wakes up one thread from the threads queue object.
  365. * @details Dequeues one thread from the queue without checking if the queue
  366. * is empty.
  367. * @pre The queue must contain at least an object.
  368. *
  369. * @param[in] tqp pointer to the threads queue object
  370. * @param[in] msg the message code
  371. *
  372. * @iclass
  373. */
  374. static inline void chThdDoDequeueNextI(threads_queue_t *tqp, msg_t msg) {
  375. thread_t *tp;
  376. chDbgAssert(queue_notempty(tqp), "empty queue");
  377. tp = queue_fifo_remove(tqp);
  378. chDbgAssert(tp->state == CH_STATE_QUEUED, "invalid state");
  379. tp->u.rdymsg = msg;
  380. (void) chSchReadyI(tp);
  381. }
  382. #endif /* CHTHREADS_H */
  383. /** @} */