chschd.h 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716
  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 chschd.h
  17. * @brief Scheduler macros and structures.
  18. *
  19. * @addtogroup scheduler
  20. * @{
  21. */
  22. #ifndef CHSCHD_H
  23. #define CHSCHD_H
  24. /*===========================================================================*/
  25. /* Module constants. */
  26. /*===========================================================================*/
  27. /**
  28. * @name Wakeup status codes
  29. * @{
  30. */
  31. #define MSG_OK (msg_t)0 /**< @brief Normal wakeup message. */
  32. #define MSG_TIMEOUT (msg_t)-1 /**< @brief Wakeup caused by a timeout
  33. condition. */
  34. #define MSG_RESET (msg_t)-2 /**< @brief Wakeup caused by a reset
  35. condition. */
  36. /** @} */
  37. /**
  38. * @name Priority constants
  39. * @{
  40. */
  41. #define NOPRIO (tprio_t)0 /**< @brief Ready list header
  42. priority. */
  43. #define IDLEPRIO (tprio_t)1 /**< @brief Idle priority. */
  44. #define LOWPRIO (tprio_t)2 /**< @brief Lowest priority. */
  45. #define NORMALPRIO (tprio_t)128 /**< @brief Normal priority. */
  46. #define HIGHPRIO (tprio_t)255 /**< @brief Highest priority. */
  47. /** @} */
  48. /**
  49. * @name Thread states
  50. * @{
  51. */
  52. #define CH_STATE_READY (tstate_t)0 /**< @brief Waiting on the
  53. ready list. */
  54. #define CH_STATE_CURRENT (tstate_t)1 /**< @brief Currently running. */
  55. #define CH_STATE_WTSTART (tstate_t)2 /**< @brief Just created. */
  56. #define CH_STATE_SUSPENDED (tstate_t)3 /**< @brief Suspended state. */
  57. #define CH_STATE_QUEUED (tstate_t)4 /**< @brief On a queue. */
  58. #define CH_STATE_WTSEM (tstate_t)5 /**< @brief On a semaphore. */
  59. #define CH_STATE_WTMTX (tstate_t)6 /**< @brief On a mutex. */
  60. #define CH_STATE_WTCOND (tstate_t)7 /**< @brief On a cond.variable.*/
  61. #define CH_STATE_SLEEPING (tstate_t)8 /**< @brief Sleeping. */
  62. #define CH_STATE_WTEXIT (tstate_t)9 /**< @brief Waiting a thread. */
  63. #define CH_STATE_WTOREVT (tstate_t)10 /**< @brief One event. */
  64. #define CH_STATE_WTANDEVT (tstate_t)11 /**< @brief Several events. */
  65. #define CH_STATE_SNDMSGQ (tstate_t)12 /**< @brief Sending a message,
  66. in queue. */
  67. #define CH_STATE_SNDMSG (tstate_t)13 /**< @brief Sent a message,
  68. waiting answer. */
  69. #define CH_STATE_WTMSG (tstate_t)14 /**< @brief Waiting for a
  70. message. */
  71. #define CH_STATE_FINAL (tstate_t)15 /**< @brief Thread terminated. */
  72. /**
  73. * @brief Thread states as array of strings.
  74. * @details Each element in an array initialized with this macro can be
  75. * indexed using the numeric thread state values.
  76. */
  77. #define CH_STATE_NAMES \
  78. "READY", "CURRENT", "WTSTART", "SUSPENDED", "QUEUED", "WTSEM", "WTMTX", \
  79. "WTCOND", "SLEEPING", "WTEXIT", "WTOREVT", "WTANDEVT", "SNDMSGQ", \
  80. "SNDMSG", "WTMSG", "FINAL"
  81. /** @} */
  82. /**
  83. * @name Thread flags and attributes
  84. * @{
  85. */
  86. #define CH_FLAG_MODE_MASK (tmode_t)3U /**< @brief Thread memory mode
  87. mask. */
  88. #define CH_FLAG_MODE_STATIC (tmode_t)0U /**< @brief Static thread. */
  89. #define CH_FLAG_MODE_HEAP (tmode_t)1U /**< @brief Thread allocated
  90. from a Memory Heap. */
  91. #define CH_FLAG_MODE_MPOOL (tmode_t)2U /**< @brief Thread allocated
  92. from a Memory Pool. */
  93. #define CH_FLAG_TERMINATE (tmode_t)4U /**< @brief Termination requested
  94. flag. */
  95. /** @} */
  96. /*===========================================================================*/
  97. /* Module pre-compile time settings. */
  98. /*===========================================================================*/
  99. /*===========================================================================*/
  100. /* Derived constants and error checks. */
  101. /*===========================================================================*/
  102. /*===========================================================================*/
  103. /* Module data structures and types. */
  104. /*===========================================================================*/
  105. /**
  106. * @brief Generic threads single link list, it works like a stack.
  107. */
  108. struct ch_threads_list {
  109. thread_t *next; /**< @brief Next in the list/queue. */
  110. };
  111. /**
  112. * @brief Generic threads bidirectional linked list header and element.
  113. */
  114. struct ch_threads_queue {
  115. thread_t *next; /**< @brief Next in the list/queue. */
  116. thread_t *prev; /**< @brief Previous in the queue. */
  117. };
  118. /**
  119. * @brief Structure representing a thread.
  120. * @note Not all the listed fields are always needed, by switching off some
  121. * not needed ChibiOS/RT subsystems it is possible to save RAM space
  122. * by shrinking this structure.
  123. */
  124. struct ch_thread {
  125. threads_queue_t queue; /**< @brief Threads queue header. */
  126. tprio_t prio; /**< @brief Thread priority. */
  127. struct port_context ctx; /**< @brief Processor context. */
  128. #if (CH_CFG_USE_REGISTRY == TRUE) || defined(__DOXYGEN__)
  129. thread_t *newer; /**< @brief Newer registry element. */
  130. thread_t *older; /**< @brief Older registry element. */
  131. #endif
  132. /* End of the fields shared with the ReadyList structure. */
  133. #if (CH_CFG_USE_REGISTRY == TRUE) || defined(__DOXYGEN__)
  134. /**
  135. * @brief Thread name or @p NULL.
  136. */
  137. const char *name;
  138. #endif
  139. #if (CH_DBG_ENABLE_STACK_CHECK == TRUE) || (CH_CFG_USE_DYNAMIC == TRUE) || \
  140. defined(__DOXYGEN__)
  141. /**
  142. * @brief Working area base address.
  143. * @note This pointer is used for stack overflow checks and for
  144. * dynamic threading.
  145. */
  146. stkalign_t *wabase;
  147. #endif
  148. /**
  149. * @brief Current thread state.
  150. */
  151. tstate_t state;
  152. /**
  153. * @brief Various thread flags.
  154. */
  155. tmode_t flags;
  156. #if (CH_CFG_USE_REGISTRY == TRUE) || defined(__DOXYGEN__)
  157. /**
  158. * @brief References to this thread.
  159. */
  160. trefs_t refs;
  161. #endif
  162. /**
  163. * @brief Number of ticks remaining to this thread.
  164. */
  165. #if (CH_CFG_TIME_QUANTUM > 0) || defined(__DOXYGEN__)
  166. tslices_t ticks;
  167. #endif
  168. #if (CH_DBG_THREADS_PROFILING == TRUE) || defined(__DOXYGEN__)
  169. /**
  170. * @brief Thread consumed time in ticks.
  171. * @note This field can overflow.
  172. */
  173. volatile systime_t time;
  174. #endif
  175. /**
  176. * @brief State-specific fields.
  177. * @note All the fields declared in this union are only valid in the
  178. * specified state or condition and are thus volatile.
  179. */
  180. union {
  181. /**
  182. * @brief Thread wakeup code.
  183. * @note This field contains the low level message sent to the thread
  184. * by the waking thread or interrupt handler. The value is valid
  185. * after exiting the @p chSchWakeupS() function.
  186. */
  187. msg_t rdymsg;
  188. /**
  189. * @brief Thread exit code.
  190. * @note The thread termination code is stored in this field in order
  191. * to be retrieved by the thread performing a @p chThdWait() on
  192. * this thread.
  193. */
  194. msg_t exitcode;
  195. /**
  196. * @brief Pointer to a generic "wait" object.
  197. * @note This field is used to get a generic pointer to a synchronization
  198. * object and is valid when the thread is in one of the wait
  199. * states.
  200. */
  201. void *wtobjp;
  202. /**
  203. * @brief Pointer to a generic thread reference object.
  204. * @note This field is used to get a pointer to a synchronization
  205. * object and is valid when the thread is in @p CH_STATE_SUSPENDED
  206. * state.
  207. */
  208. thread_reference_t *wttrp;
  209. #if (CH_CFG_USE_MESSAGES == TRUE) || defined(__DOXYGEN__)
  210. /**
  211. * @brief Thread sent message.
  212. */
  213. msg_t sentmsg;
  214. #endif
  215. #if (CH_CFG_USE_SEMAPHORES == TRUE) || defined(__DOXYGEN__)
  216. /**
  217. * @brief Pointer to a generic semaphore object.
  218. * @note This field is used to get a pointer to a synchronization
  219. * object and is valid when the thread is in @p CH_STATE_WTSEM
  220. * state.
  221. */
  222. struct ch_semaphore *wtsemp;
  223. #endif
  224. #if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__)
  225. /**
  226. * @brief Pointer to a generic mutex object.
  227. * @note This field is used to get a pointer to a synchronization
  228. * object and is valid when the thread is in @p CH_STATE_WTMTX
  229. * state.
  230. */
  231. struct ch_mutex *wtmtxp;
  232. #endif
  233. #if (CH_CFG_USE_EVENTS == TRUE) || defined(__DOXYGEN__)
  234. /**
  235. * @brief Enabled events mask.
  236. * @note This field is only valid while the thread is in the
  237. * @p CH_STATE_WTOREVT or @p CH_STATE_WTANDEVT states.
  238. */
  239. eventmask_t ewmask;
  240. #endif
  241. } u;
  242. #if (CH_CFG_USE_WAITEXIT == TRUE) || defined(__DOXYGEN__)
  243. /**
  244. * @brief Termination waiting list.
  245. */
  246. threads_list_t waiting;
  247. #endif
  248. #if (CH_CFG_USE_MESSAGES == TRUE) || defined(__DOXYGEN__)
  249. /**
  250. * @brief Messages queue.
  251. */
  252. threads_queue_t msgqueue;
  253. #endif
  254. #if (CH_CFG_USE_EVENTS == TRUE) || defined(__DOXYGEN__)
  255. /**
  256. * @brief Pending events mask.
  257. */
  258. eventmask_t epending;
  259. #endif
  260. #if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__)
  261. /**
  262. * @brief List of the mutexes owned by this thread.
  263. * @note The list is terminated by a @p NULL in this field.
  264. */
  265. struct ch_mutex *mtxlist;
  266. /**
  267. * @brief Thread's own, non-inherited, priority.
  268. */
  269. tprio_t realprio;
  270. #endif
  271. #if ((CH_CFG_USE_DYNAMIC == TRUE) && (CH_CFG_USE_MEMPOOLS == TRUE)) || \
  272. defined(__DOXYGEN__)
  273. /**
  274. * @brief Memory Pool where the thread workspace is returned.
  275. */
  276. void *mpool;
  277. #endif
  278. #if (CH_DBG_STATISTICS == TRUE) || defined(__DOXYGEN__)
  279. /**
  280. * @brief Thread statistics.
  281. */
  282. time_measurement_t stats;
  283. #endif
  284. #if defined(CH_CFG_THREAD_EXTRA_FIELDS)
  285. /* Extra fields defined in chconf.h.*/
  286. CH_CFG_THREAD_EXTRA_FIELDS
  287. #endif
  288. };
  289. /**
  290. * @extends virtual_timers_list_t
  291. *
  292. * @brief Virtual Timer descriptor structure.
  293. */
  294. struct ch_virtual_timer {
  295. virtual_timer_t *next; /**< @brief Next timer in the list. */
  296. virtual_timer_t *prev; /**< @brief Previous timer in the list. */
  297. sysinterval_t delta; /**< @brief Time delta before timeout. */
  298. vtfunc_t func; /**< @brief Timer callback function
  299. pointer. */
  300. void *par; /**< @brief Timer callback function
  301. parameter. */
  302. };
  303. /**
  304. * @brief Virtual timers list header.
  305. * @note The timers list is implemented as a double link bidirectional list
  306. * in order to make the unlink time constant, the reset of a virtual
  307. * timer is often used in the code.
  308. */
  309. struct ch_virtual_timers_list {
  310. virtual_timer_t *next; /**< @brief Next timer in the delta
  311. list. */
  312. virtual_timer_t *prev; /**< @brief Last timer in the delta
  313. list. */
  314. sysinterval_t delta; /**< @brief Must be initialized to -1. */
  315. #if (CH_CFG_ST_TIMEDELTA == 0) || defined(__DOXYGEN__)
  316. volatile systime_t systime; /**< @brief System Time counter. */
  317. #endif
  318. #if (CH_CFG_ST_TIMEDELTA > 0) || defined(__DOXYGEN__)
  319. /**
  320. * @brief System time of the last tick event.
  321. */
  322. systime_t lasttime; /**< @brief System time of the last
  323. tick event. */
  324. #endif
  325. };
  326. /**
  327. * @extends threads_queue_t
  328. */
  329. struct ch_ready_list {
  330. threads_queue_t queue; /**< @brief Threads queue. */
  331. tprio_t prio; /**< @brief This field must be
  332. initialized to zero. */
  333. struct port_context ctx; /**< @brief Not used, present because
  334. offsets. */
  335. #if (CH_CFG_USE_REGISTRY == TRUE) || defined(__DOXYGEN__)
  336. thread_t *newer; /**< @brief Newer registry element. */
  337. thread_t *older; /**< @brief Older registry element. */
  338. #endif
  339. /* End of the fields shared with the thread_t structure.*/
  340. thread_t *current; /**< @brief The currently running
  341. thread. */
  342. };
  343. /**
  344. * @brief System debug data structure.
  345. */
  346. struct ch_system_debug {
  347. /**
  348. * @brief Pointer to the panic message.
  349. * @details This pointer is meant to be accessed through the debugger, it is
  350. * written once and then the system is halted.
  351. * @note Accesses to this pointer must never be optimized out so the
  352. * field itself is declared volatile.
  353. */
  354. const char * volatile panic_msg;
  355. #if (CH_DBG_SYSTEM_STATE_CHECK == TRUE) || defined(__DOXYGEN__)
  356. /**
  357. * @brief ISR nesting level.
  358. */
  359. cnt_t isr_cnt;
  360. /**
  361. * @brief Lock nesting level.
  362. */
  363. cnt_t lock_cnt;
  364. #endif
  365. #if (CH_DBG_TRACE_MASK != CH_DBG_TRACE_MASK_DISABLED) || defined(__DOXYGEN__)
  366. /**
  367. * @brief Public trace buffer.
  368. */
  369. ch_trace_buffer_t trace_buffer;
  370. #endif
  371. };
  372. /**
  373. * @brief System data structure.
  374. * @note This structure contain all the data areas used by the OS except
  375. * stacks.
  376. */
  377. struct ch_system {
  378. /**
  379. * @brief Ready list header.
  380. */
  381. ready_list_t rlist;
  382. /**
  383. * @brief Virtual timers delta list header.
  384. */
  385. virtual_timers_list_t vtlist;
  386. /**
  387. * @brief System debug.
  388. */
  389. system_debug_t dbg;
  390. /**
  391. * @brief Main thread descriptor.
  392. */
  393. thread_t mainthread;
  394. #if (CH_CFG_USE_TM == TRUE) || defined(__DOXYGEN__)
  395. /**
  396. * @brief Time measurement calibration data.
  397. */
  398. tm_calibration_t tm;
  399. #endif
  400. #if (CH_DBG_STATISTICS == TRUE) || defined(__DOXYGEN__)
  401. /**
  402. * @brief Global kernel statistics.
  403. */
  404. kernel_stats_t kernel_stats;
  405. #endif
  406. CH_CFG_SYSTEM_EXTRA_FIELDS
  407. };
  408. /*===========================================================================*/
  409. /* Module macros. */
  410. /*===========================================================================*/
  411. /**
  412. * @brief Returns the priority of the first thread on the given ready list.
  413. *
  414. * @notapi
  415. */
  416. #define firstprio(rlp) ((rlp)->next->prio)
  417. /**
  418. * @brief Current thread pointer access macro.
  419. * @note This macro is not meant to be used in the application code but
  420. * only from within the kernel, use @p chThdGetSelfX() instead.
  421. */
  422. #define currp ch.rlist.current
  423. /*===========================================================================*/
  424. /* External declarations. */
  425. /*===========================================================================*/
  426. #if !defined(__DOXYGEN__)
  427. extern ch_system_t ch;
  428. #endif
  429. /*
  430. * Scheduler APIs.
  431. */
  432. #ifdef __cplusplus
  433. extern "C" {
  434. #endif
  435. void _scheduler_init(void);
  436. thread_t *chSchReadyI(thread_t *tp);
  437. thread_t *chSchReadyAheadI(thread_t *tp);
  438. void chSchGoSleepS(tstate_t newstate);
  439. msg_t chSchGoSleepTimeoutS(tstate_t newstate, sysinterval_t timeout);
  440. void chSchWakeupS(thread_t *ntp, msg_t msg);
  441. void chSchRescheduleS(void);
  442. bool chSchIsPreemptionRequired(void);
  443. void chSchDoRescheduleBehind(void);
  444. void chSchDoRescheduleAhead(void);
  445. void chSchDoReschedule(void);
  446. #if CH_CFG_OPTIMIZE_SPEED == FALSE
  447. void queue_prio_insert(thread_t *tp, threads_queue_t *tqp);
  448. void queue_insert(thread_t *tp, threads_queue_t *tqp);
  449. thread_t *queue_fifo_remove(threads_queue_t *tqp);
  450. thread_t *queue_lifo_remove(threads_queue_t *tqp);
  451. thread_t *queue_dequeue(thread_t *tp);
  452. void list_insert(thread_t *tp, threads_list_t *tlp);
  453. thread_t *list_remove(threads_list_t *tlp);
  454. #endif /* CH_CFG_OPTIMIZE_SPEED == FALSE */
  455. #ifdef __cplusplus
  456. }
  457. #endif
  458. /*===========================================================================*/
  459. /* Module inline functions. */
  460. /*===========================================================================*/
  461. /**
  462. * @brief Threads list initialization.
  463. *
  464. * @param[in] tlp pointer to the threads list object
  465. *
  466. * @notapi
  467. */
  468. static inline void list_init(threads_list_t *tlp) {
  469. tlp->next = (thread_t *)tlp;
  470. }
  471. /**
  472. * @brief Evaluates to @p true if the specified threads list is empty.
  473. *
  474. * @param[in] tlp pointer to the threads list object
  475. * @return The status of the list.
  476. *
  477. * @notapi
  478. */
  479. static inline bool list_isempty(threads_list_t *tlp) {
  480. return (bool)(tlp->next == (thread_t *)tlp);
  481. }
  482. /**
  483. * @brief Evaluates to @p true if the specified threads list is not empty.
  484. *
  485. * @param[in] tlp pointer to the threads list object
  486. * @return The status of the list.
  487. *
  488. * @notapi
  489. */
  490. static inline bool list_notempty(threads_list_t *tlp) {
  491. return (bool)(tlp->next != (thread_t *)tlp);
  492. }
  493. /**
  494. * @brief Threads queue initialization.
  495. *
  496. * @param[in] tqp pointer to the threads queue object
  497. *
  498. * @notapi
  499. */
  500. static inline void queue_init(threads_queue_t *tqp) {
  501. tqp->next = (thread_t *)tqp;
  502. tqp->prev = (thread_t *)tqp;
  503. }
  504. /**
  505. * @brief Evaluates to @p true if the specified threads queue is empty.
  506. *
  507. * @param[in] tqp pointer to the threads queue object
  508. * @return The status of the queue.
  509. *
  510. * @notapi
  511. */
  512. static inline bool queue_isempty(const threads_queue_t *tqp) {
  513. return (bool)(tqp->next == (const thread_t *)tqp);
  514. }
  515. /**
  516. * @brief Evaluates to @p true if the specified threads queue is not empty.
  517. *
  518. * @param[in] tqp pointer to the threads queue object
  519. * @return The status of the queue.
  520. *
  521. * @notapi
  522. */
  523. static inline bool queue_notempty(const threads_queue_t *tqp) {
  524. return (bool)(tqp->next != (const thread_t *)tqp);
  525. }
  526. /* If the performance code path has been chosen then all the following
  527. functions are inlined into the various kernel modules.*/
  528. #if CH_CFG_OPTIMIZE_SPEED == TRUE
  529. static inline void list_insert(thread_t *tp, threads_list_t *tlp) {
  530. tp->queue.next = tlp->next;
  531. tlp->next = tp;
  532. }
  533. static inline thread_t *list_remove(threads_list_t *tlp) {
  534. thread_t *tp = tlp->next;
  535. tlp->next = tp->queue.next;
  536. return tp;
  537. }
  538. static inline void queue_prio_insert(thread_t *tp, threads_queue_t *tqp) {
  539. thread_t *cp = (thread_t *)tqp;
  540. do {
  541. cp = cp->queue.next;
  542. } while ((cp != (thread_t *)tqp) && (cp->prio >= tp->prio));
  543. tp->queue.next = cp;
  544. tp->queue.prev = cp->queue.prev;
  545. tp->queue.prev->queue.next = tp;
  546. cp->queue.prev = tp;
  547. }
  548. static inline void queue_insert(thread_t *tp, threads_queue_t *tqp) {
  549. tp->queue.next = (thread_t *)tqp;
  550. tp->queue.prev = tqp->prev;
  551. tp->queue.prev->queue.next = tp;
  552. tqp->prev = tp;
  553. }
  554. static inline thread_t *queue_fifo_remove(threads_queue_t *tqp) {
  555. thread_t *tp = tqp->next;
  556. tqp->next = tp->queue.next;
  557. tqp->next->queue.prev = (thread_t *)tqp;
  558. return tp;
  559. }
  560. static inline thread_t *queue_lifo_remove(threads_queue_t *tqp) {
  561. thread_t *tp = tqp->prev;
  562. tqp->prev = tp->queue.prev;
  563. tqp->prev->queue.next = (thread_t *)tqp;
  564. return tp;
  565. }
  566. static inline thread_t *queue_dequeue(thread_t *tp) {
  567. tp->queue.prev->queue.next = tp->queue.next;
  568. tp->queue.next->queue.prev = tp->queue.prev;
  569. return tp;
  570. }
  571. #endif /* CH_CFG_OPTIMIZE_SPEED == TRUE */
  572. /**
  573. * @brief Determines if the current thread must reschedule.
  574. * @details This function returns @p true if there is a ready thread with
  575. * higher priority.
  576. *
  577. * @return The priorities situation.
  578. * @retval false if rescheduling is not necessary.
  579. * @retval true if there is a ready thread at higher priority.
  580. *
  581. * @iclass
  582. */
  583. static inline bool chSchIsRescRequiredI(void) {
  584. chDbgCheckClassI();
  585. return firstprio(&ch.rlist.queue) > currp->prio;
  586. }
  587. /**
  588. * @brief Determines if yielding is possible.
  589. * @details This function returns @p true if there is a ready thread with
  590. * equal or higher priority.
  591. *
  592. * @return The priorities situation.
  593. * @retval false if yielding is not possible.
  594. * @retval true if there is a ready thread at equal or higher priority.
  595. *
  596. * @sclass
  597. */
  598. static inline bool chSchCanYieldS(void) {
  599. chDbgCheckClassS();
  600. return firstprio(&ch.rlist.queue) >= currp->prio;
  601. }
  602. /**
  603. * @brief Yields the time slot.
  604. * @details Yields the CPU control to the next thread in the ready list with
  605. * equal or higher priority, if any.
  606. *
  607. * @sclass
  608. */
  609. static inline void chSchDoYieldS(void) {
  610. chDbgCheckClassS();
  611. if (chSchCanYieldS()) {
  612. chSchDoRescheduleBehind();
  613. }
  614. }
  615. /**
  616. * @brief Inline-able preemption code.
  617. * @details This is the common preemption code, this function must be invoked
  618. * exclusively from the port layer.
  619. *
  620. * @special
  621. */
  622. static inline void chSchPreemption(void) {
  623. tprio_t p1 = firstprio(&ch.rlist.queue);
  624. tprio_t p2 = currp->prio;
  625. #if CH_CFG_TIME_QUANTUM > 0
  626. if (currp->ticks > (tslices_t)0) {
  627. if (p1 > p2) {
  628. chSchDoRescheduleAhead();
  629. }
  630. }
  631. else {
  632. if (p1 >= p2) {
  633. chSchDoRescheduleBehind();
  634. }
  635. }
  636. #else /* CH_CFG_TIME_QUANTUM == 0 */
  637. if (p1 > p2) {
  638. chSchDoRescheduleAhead();
  639. }
  640. #endif /* CH_CFG_TIME_QUANTUM == 0 */
  641. }
  642. #endif /* CHSCHD_H */
  643. /** @} */