ChibiOS/RT  5.1.0
chthreads.c
Go to the documentation of this file.
1 /*
2  ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
3 
4  This file is part of ChibiOS.
5 
6  ChibiOS is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 3 of the License, or
9  (at your option) any later version.
10 
11  ChibiOS is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 /**
21  * @file chthreads.c
22  * @brief Threads code.
23  *
24  * @addtogroup threads
25  * @details Threads related APIs and services.
26  * <h2>Operation mode</h2>
27  * A thread is an abstraction of an independent instructions flow.
28  * In ChibiOS/RT a thread is represented by a "C" function owning
29  * a processor context, state informations and a dedicated stack
30  * area. In this scenario static variables are shared among all
31  * threads while automatic variables are local to the thread.<br>
32  * Operations defined for threads:
33  * - <b>Create</b>, a thread is started on the specified thread
34  * function. This operation is available in multiple variants,
35  * both static and dynamic.
36  * - <b>Exit</b>, a thread terminates by returning from its top
37  * level function or invoking a specific API, the thread can
38  * return a value that can be retrieved by other threads.
39  * - <b>Wait</b>, a thread waits for the termination of another
40  * thread and retrieves its return value.
41  * - <b>Resume</b>, a thread created in suspended state is started.
42  * - <b>Sleep</b>, the execution of a thread is suspended for the
43  * specified amount of time or the specified future absolute time
44  * is reached.
45  * - <b>SetPriority</b>, a thread changes its own priority level.
46  * - <b>Yield</b>, a thread voluntarily renounces to its time slot.
47  * .
48  * @{
49  */
50 
51 #include "ch.h"
52 
53 /*===========================================================================*/
54 /* Module local definitions. */
55 /*===========================================================================*/
56 
57 /*===========================================================================*/
58 /* Module exported variables. */
59 /*===========================================================================*/
60 
61 /*===========================================================================*/
62 /* Module local types. */
63 /*===========================================================================*/
64 
65 /*===========================================================================*/
66 /* Module local variables. */
67 /*===========================================================================*/
68 
69 /*===========================================================================*/
70 /* Module local functions. */
71 /*===========================================================================*/
72 
73 /*===========================================================================*/
74 /* Module exported functions. */
75 /*===========================================================================*/
76 
77 /**
78  * @brief Initializes a thread structure.
79  * @note This is an internal functions, do not use it in application code.
80  *
81  * @param[in] tp pointer to the thread
82  * @param[in] name thread name
83  * @param[in] prio the priority level for the new thread
84  * @return The same thread pointer passed as parameter.
85  *
86  * @notapi
87  */
88 thread_t *_thread_init(thread_t *tp, const char *name, tprio_t prio) {
89 
90  tp->prio = prio;
91  tp->state = CH_STATE_WTSTART;
93 #if CH_CFG_TIME_QUANTUM > 0
94  tp->ticks = (tslices_t)CH_CFG_TIME_QUANTUM;
95 #endif
96 #if CH_CFG_USE_MUTEXES == TRUE
97  tp->realprio = prio;
98  tp->mtxlist = NULL;
99 #endif
100 #if CH_CFG_USE_EVENTS == TRUE
101  tp->epending = (eventmask_t)0;
102 #endif
103 #if CH_DBG_THREADS_PROFILING == TRUE
104  tp->time = (systime_t)0;
105 #endif
106 #if CH_CFG_USE_REGISTRY == TRUE
107  tp->refs = (trefs_t)1;
108  tp->name = name;
109  REG_INSERT(tp);
110 #else
111  (void)name;
112 #endif
113 #if CH_CFG_USE_WAITEXIT == TRUE
114  list_init(&tp->waiting);
115 #endif
116 #if CH_CFG_USE_MESSAGES == TRUE
117  queue_init(&tp->msgqueue);
118 #endif
119 #if CH_DBG_STATISTICS == TRUE
120  chTMObjectInit(&tp->stats);
121 #endif
123  return tp;
124 }
125 
126 #if (CH_DBG_FILL_THREADS == TRUE) || defined(__DOXYGEN__)
127 /**
128  * @brief Memory fill utility.
129  *
130  * @param[in] startp first address to fill
131  * @param[in] endp last address to fill +1
132  * @param[in] v filler value
133  *
134  * @notapi
135  */
136 void _thread_memfill(uint8_t *startp, uint8_t *endp, uint8_t v) {
137 
138  while (startp < endp) {
139  *startp++ = v;
140  }
141 }
142 #endif /* CH_DBG_FILL_THREADS == TRUE */
143 
144 /**
145  * @brief Creates a new thread into a static memory area.
146  * @details The new thread is initialized but not inserted in the ready list,
147  * the initial state is @p CH_STATE_WTSTART.
148  * @post The created thread has a reference counter set to one, it is
149  * caller responsibility to call @p chThdRelease() or @p chthdWait()
150  * in order to release the reference. The thread persists in the
151  * registry until its reference counter reaches zero.
152  * @post The initialized thread can be subsequently started by invoking
153  * @p chThdStart(), @p chThdStartI() or @p chSchWakeupS()
154  * depending on the execution context.
155  * @note A thread can terminate by calling @p chThdExit() or by simply
156  * returning from its main function.
157  * @note Threads created using this function do not obey to the
158  * @p CH_DBG_FILL_THREADS debug option because it would keep
159  * the kernel locked for too much time.
160  *
161  * @param[out] tdp pointer to the thread descriptor
162  * @return The pointer to the @p thread_t structure allocated for
163  * the thread into the working space area.
164  *
165  * @iclass
166  */
168  thread_t *tp;
169 
171  chDbgCheck(tdp != NULL);
172  chDbgCheck(MEM_IS_ALIGNED(tdp->wbase, PORT_WORKING_AREA_ALIGN) &&
173  MEM_IS_ALIGNED(tdp->wend, PORT_STACK_ALIGN) &&
174  (tdp->wend > tdp->wbase) &&
175  (((size_t)tdp->wend - (size_t)tdp->wbase) >= THD_WORKING_AREA_SIZE(0)));
176  chDbgCheck((tdp->prio <= HIGHPRIO) && (tdp->funcp != NULL));
177 
178  /* The thread structure is laid out in the upper part of the thread
179  workspace. The thread position structure is aligned to the required
180  stack alignment because it represents the stack top.*/
181  tp = (thread_t *)((uint8_t *)tdp->wend -
182  MEM_ALIGN_NEXT(sizeof (thread_t), PORT_STACK_ALIGN));
183 
184 #if (CH_DBG_ENABLE_STACK_CHECK == TRUE) || (CH_CFG_USE_DYNAMIC == TRUE)
185  /* Stack boundary.*/
186  tp->wabase = tdp->wbase;
187 #endif
188 
189  /* Setting up the port-dependent part of the working area.*/
190  PORT_SETUP_CONTEXT(tp, tdp->wbase, tp, tdp->funcp, tdp->arg);
191 
192  /* The driver object is initialized but not started.*/
193  return _thread_init(tp, tdp->name, tdp->prio);
194 }
195 
196 /**
197  * @brief Creates a new thread into a static memory area.
198  * @details The new thread is initialized but not inserted in the ready list,
199  * the initial state is @p CH_STATE_WTSTART.
200  * @post The created thread has a reference counter set to one, it is
201  * caller responsibility to call @p chThdRelease() or @p chthdWait()
202  * in order to release the reference. The thread persists in the
203  * registry until its reference counter reaches zero.
204  * @post The initialized thread can be subsequently started by invoking
205  * @p chThdStart(), @p chThdStartI() or @p chSchWakeupS()
206  * depending on the execution context.
207  * @note A thread can terminate by calling @p chThdExit() or by simply
208  * returning from its main function.
209  *
210  * @param[out] tdp pointer to the thread descriptor
211  * @return The pointer to the @p thread_t structure allocated for
212  * the thread into the working space area.
213  *
214  * @api
215  */
217  thread_t *tp;
218 
219 #if CH_CFG_USE_REGISTRY == TRUE
221  "working area in use");
222 #endif
223 
224 #if CH_DBG_FILL_THREADS == TRUE
225  _thread_memfill((uint8_t *)tdp->wbase,
226  (uint8_t *)tdp->wend,
228 #endif
229 
230  chSysLock();
231  tp = chThdCreateSuspendedI(tdp);
232  chSysUnlock();
233 
234  return tp;
235 }
236 
237 /**
238  * @brief Creates a new thread into a static memory area.
239  * @details The new thread is initialized and make ready to execute.
240  * @post The created thread has a reference counter set to one, it is
241  * caller responsibility to call @p chThdRelease() or @p chthdWait()
242  * in order to release the reference. The thread persists in the
243  * registry until its reference counter reaches zero.
244  * @post The initialized thread can be subsequently started by invoking
245  * @p chThdStart(), @p chThdStartI() or @p chSchWakeupS()
246  * depending on the execution context.
247  * @note A thread can terminate by calling @p chThdExit() or by simply
248  * returning from its main function.
249  * @note Threads created using this function do not obey to the
250  * @p CH_DBG_FILL_THREADS debug option because it would keep
251  * the kernel locked for too much time.
252  *
253  * @param[out] tdp pointer to the thread descriptor
254  * @return The pointer to the @p thread_t structure allocated for
255  * the thread into the working space area.
256  *
257  * @iclass
258  */
260 
261  return chSchReadyI(chThdCreateSuspendedI(tdp));
262 }
263 
264 /**
265  * @brief Creates a new thread into a static memory area.
266  * @details The new thread is initialized and make ready to execute.
267  * @post The created thread has a reference counter set to one, it is
268  * caller responsibility to call @p chThdRelease() or @p chthdWait()
269  * in order to release the reference. The thread persists in the
270  * registry until its reference counter reaches zero.
271  * @note A thread can terminate by calling @p chThdExit() or by simply
272  * returning from its main function.
273  *
274  * @param[out] tdp pointer to the thread descriptor
275  * @return The pointer to the @p thread_t structure allocated for
276  * the thread into the working space area.
277  *
278  * @iclass
279  */
281  thread_t *tp;
282 
283 #if (CH_CFG_USE_REGISTRY == TRUE) && \
284  ((CH_DBG_ENABLE_STACK_CHECK == TRUE) || (CH_CFG_USE_DYNAMIC == TRUE))
286  "working area in use");
287 #endif
288 
289 #if CH_DBG_FILL_THREADS == TRUE
290  _thread_memfill((uint8_t *)tdp->wbase,
291  (uint8_t *)tdp->wend,
293 #endif
294 
295  chSysLock();
296  tp = chThdCreateSuspendedI(tdp);
297  chSchWakeupS(tp, MSG_OK);
298  chSysUnlock();
299 
300  return tp;
301 }
302 
303 /**
304  * @brief Creates a new thread into a static memory area.
305  * @post The created thread has a reference counter set to one, it is
306  * caller responsibility to call @p chThdRelease() or @p chthdWait()
307  * in order to release the reference. The thread persists in the
308  * registry until its reference counter reaches zero.
309  * @note A thread can terminate by calling @p chThdExit() or by simply
310  * returning from its main function.
311  *
312  * @param[out] wsp pointer to a working area dedicated to the thread stack
313  * @param[in] size size of the working area
314  * @param[in] prio the priority level for the new thread
315  * @param[in] pf the thread function
316  * @param[in] arg an argument passed to the thread function. It can be
317  * @p NULL.
318  * @return The pointer to the @p thread_t structure allocated for
319  * the thread into the working space area.
320  *
321  * @api
322  */
323 thread_t *chThdCreateStatic(void *wsp, size_t size,
324  tprio_t prio, tfunc_t pf, void *arg) {
325  thread_t *tp;
326 
327  chDbgCheck((wsp != NULL) &&
328  MEM_IS_ALIGNED(wsp, PORT_WORKING_AREA_ALIGN) &&
329  (size >= THD_WORKING_AREA_SIZE(0)) &&
330  MEM_IS_ALIGNED(size, PORT_STACK_ALIGN) &&
331  (prio <= HIGHPRIO) && (pf != NULL));
332 
333 #if (CH_CFG_USE_REGISTRY == TRUE) && \
334  ((CH_DBG_ENABLE_STACK_CHECK == TRUE) || (CH_CFG_USE_DYNAMIC == TRUE))
336  "working area in use");
337 #endif
338 
339 #if CH_DBG_FILL_THREADS == TRUE
340  _thread_memfill((uint8_t *)wsp,
341  (uint8_t *)wsp + size,
343 #endif
344 
345  chSysLock();
346 
347  /* The thread structure is laid out in the upper part of the thread
348  workspace. The thread position structure is aligned to the required
349  stack alignment because it represents the stack top.*/
350  tp = (thread_t *)((uint8_t *)wsp + size -
351  MEM_ALIGN_NEXT(sizeof (thread_t), PORT_STACK_ALIGN));
352 
353 #if (CH_DBG_ENABLE_STACK_CHECK == TRUE) || (CH_CFG_USE_DYNAMIC == TRUE)
354  /* Stack boundary.*/
355  tp->wabase = (stkalign_t *)wsp;
356 #endif
357 
358  /* Setting up the port-dependent part of the working area.*/
359  PORT_SETUP_CONTEXT(tp, wsp, tp, pf, arg);
360 
361  tp = _thread_init(tp, "noname", prio);
362 
363  /* Starting the thread immediately.*/
364  chSchWakeupS(tp, MSG_OK);
365  chSysUnlock();
366 
367  return tp;
368 }
369 
370 /**
371  * @brief Resumes a thread created with @p chThdCreateI().
372  *
373  * @param[in] tp pointer to the thread
374  * @return The pointer to the @p thread_t structure allocated for
375  * the thread into the working space area.
376  *
377  * @api
378  */
380 
381  chSysLock();
382  chDbgAssert(tp->state == CH_STATE_WTSTART, "wrong state");
383  chSchWakeupS(tp, MSG_OK);
384  chSysUnlock();
385 
386  return tp;
387 }
388 
389 #if (CH_CFG_USE_REGISTRY == TRUE) || defined(__DOXYGEN__)
390 /**
391  * @brief Adds a reference to a thread object.
392  * @pre The configuration option @p CH_CFG_USE_REGISTRY must be enabled in
393  * order to use this function.
394  *
395  * @param[in] tp pointer to the thread
396  * @return The same thread pointer passed as parameter
397  * representing the new reference.
398  *
399  * @api
400  */
402 
403  chSysLock();
404  chDbgAssert(tp->refs < (trefs_t)255, "too many references");
405  tp->refs++;
406  chSysUnlock();
407 
408  return tp;
409 }
410 
411 /**
412  * @brief Releases a reference to a thread object.
413  * @details If the references counter reaches zero <b>and</b> the thread
414  * is in the @p CH_STATE_FINAL state then the thread's memory is
415  * returned to the proper allocator and the thread is removed
416  * from the registry.<br>
417  * Threads whose counter reaches zero and are still active become
418  * "detached" and will be removed from registry on termination.
419  * @pre The configuration option @p CH_CFG_USE_REGISTRY must be enabled in
420  * order to use this function.
421  * @note Static threads are not affected.
422  *
423  * @param[in] tp pointer to the thread
424  *
425  * @api
426  */
428 
429  chSysLock();
430  chDbgAssert(tp->refs > (trefs_t)0, "not referenced");
431  tp->refs--;
432 
433  /* If the references counter reaches zero and the thread is in its
434  terminated state then the memory can be returned to the proper
435  allocator.*/
436  if ((tp->refs == (trefs_t)0) && (tp->state == CH_STATE_FINAL)) {
437  REG_REMOVE(tp);
438  chSysUnlock();
439 
440 #if CH_CFG_USE_DYNAMIC == TRUE
441  switch (tp->flags & CH_FLAG_MODE_MASK) {
442 #if CH_CFG_USE_HEAP == TRUE
443  case CH_FLAG_MODE_HEAP:
445  break;
446 #endif
447 #if CH_CFG_USE_MEMPOOLS == TRUE
448  case CH_FLAG_MODE_MPOOL:
450  break;
451 #endif
452  default:
453  /* Nothing else to do for static threads.*/
454  break;
455  }
456 #endif /* CH_CFG_USE_DYNAMIC == TRUE */
457  return;
458  }
459  chSysUnlock();
460 }
461 #endif /* CH_CFG_USE_REGISTRY == TRUE */
462 
463 /**
464  * @brief Terminates the current thread.
465  * @details The thread goes in the @p CH_STATE_FINAL state holding the
466  * specified exit status code, other threads can retrieve the
467  * exit status code by invoking the function @p chThdWait().
468  * @post Eventual code after this function will never be executed,
469  * this function never returns. The compiler has no way to
470  * know this so do not assume that the compiler would remove
471  * the dead code.
472  *
473  * @param[in] msg thread exit code
474  *
475  * @api
476  */
477 void chThdExit(msg_t msg) {
478 
479  chSysLock();
480  chThdExitS(msg);
481  /* The thread never returns here.*/
482 }
483 
484 /**
485  * @brief Terminates the current thread.
486  * @details The thread goes in the @p CH_STATE_FINAL state holding the
487  * specified exit status code, other threads can retrieve the
488  * exit status code by invoking the function @p chThdWait().
489  * @post Exiting a non-static thread that does not have references
490  * (detached) causes the thread to remain in the registry.
491  * It can only be removed by performing a registry scan operation.
492  * @post Eventual code after this function will never be executed,
493  * this function never returns. The compiler has no way to
494  * know this so do not assume that the compiler would remove
495  * the dead code.
496  *
497  * @param[in] msg thread exit code
498  *
499  * @sclass
500  */
501 void chThdExitS(msg_t msg) {
502  thread_t *tp = currp;
503 
504  /* Storing exit message.*/
505  tp->u.exitcode = msg;
506 
507  /* Exit handler hook.*/
509 
510 #if CH_CFG_USE_WAITEXIT == TRUE
511  /* Waking up any waiting thread.*/
512  while (list_notempty(&tp->waiting)) {
513  (void) chSchReadyI(list_remove(&tp->waiting));
514  }
515 #endif
516 
517 #if CH_CFG_USE_REGISTRY == TRUE
518  /* Static threads with no references are immediately removed from the
519  registry because there is no memory to recover.*/
520 #if CH_CFG_USE_DYNAMIC == TRUE
521  if ((tp->refs == (trefs_t)0) &&
523  REG_REMOVE(tp);
524  }
525 #else
526  if (tp->refs == (trefs_t)0) {
527  REG_REMOVE(tp);
528  }
529 #endif
530 #endif
531 
532  /* Going into final state.*/
534 
535  /* The thread never returns here.*/
536  chDbgAssert(false, "zombies apocalypse");
537 }
538 
539 #if (CH_CFG_USE_WAITEXIT == TRUE) || defined(__DOXYGEN__)
540 /**
541  * @brief Blocks the execution of the invoking thread until the specified
542  * thread terminates then the exit code is returned.
543  * @details This function waits for the specified thread to terminate then
544  * decrements its reference counter, if the counter reaches zero then
545  * the thread working area is returned to the proper allocator and
546  * the thread is removed from registry.
547  * @pre The configuration option @p CH_CFG_USE_WAITEXIT must be enabled in
548  * order to use this function.
549  * @post Enabling @p chThdWait() requires 2-4 (depending on the
550  * architecture) extra bytes in the @p thread_t structure.
551  * @note If @p CH_CFG_USE_DYNAMIC is not specified this function just waits
552  * for the thread termination, no memory allocators are involved.
553  *
554  * @param[in] tp pointer to the thread
555  * @return The exit code from the terminated thread.
556  *
557  * @api
558  */
559 msg_t chThdWait(thread_t *tp) {
560  msg_t msg;
561 
562  chDbgCheck(tp != NULL);
563 
564  chSysLock();
565  chDbgAssert(tp != currp, "waiting self");
566 #if CH_CFG_USE_REGISTRY == TRUE
567  chDbgAssert(tp->refs > (trefs_t)0, "no references");
568 #endif
569 
570  if (tp->state != CH_STATE_FINAL) {
571  list_insert(currp, &tp->waiting);
573  }
574  msg = tp->u.exitcode;
575  chSysUnlock();
576 
577 #if CH_CFG_USE_REGISTRY == TRUE
578  /* Releasing a reference to the thread.*/
579  chThdRelease(tp);
580 #endif
581 
582  return msg;
583 }
584 #endif /* CH_CFG_USE_WAITEXIT */
585 
586 /**
587  * @brief Changes the running thread priority level then reschedules if
588  * necessary.
589  * @note The function returns the real thread priority regardless of the
590  * current priority that could be higher than the real priority
591  * because the priority inheritance mechanism.
592  *
593  * @param[in] newprio the new priority level of the running thread
594  * @return The old priority level.
595  *
596  * @api
597  */
598 tprio_t chThdSetPriority(tprio_t newprio) {
599  tprio_t oldprio;
600 
601  chDbgCheck(newprio <= HIGHPRIO);
602 
603  chSysLock();
604 #if CH_CFG_USE_MUTEXES == TRUE
605  oldprio = currp->realprio;
606  if ((currp->prio == currp->realprio) || (newprio > currp->prio)) {
607  currp->prio = newprio;
608  }
609  currp->realprio = newprio;
610 #else
611  oldprio = currp->prio;
612  currp->prio = newprio;
613 #endif
615  chSysUnlock();
616 
617  return oldprio;
618 }
619 
620 /**
621  * @brief Requests a thread termination.
622  * @pre The target thread must be written to invoke periodically
623  * @p chThdShouldTerminate() and terminate cleanly if it returns
624  * @p true.
625  * @post The specified thread will terminate after detecting the termination
626  * condition.
627  *
628  * @param[in] tp pointer to the thread
629  *
630  * @api
631  */
633 
634  chSysLock();
635  tp->flags |= CH_FLAG_TERMINATE;
636  chSysUnlock();
637 }
638 
639 /**
640  * @brief Suspends the invoking thread for the specified time.
641  *
642  * @param[in] time the delay in system ticks, the special values are
643  * handled as follow:
644  * - @a TIME_INFINITE the thread enters an infinite sleep
645  * state.
646  * - @a TIME_IMMEDIATE this value is not allowed.
647  * .
648  *
649  * @api
650  */
652 
653  chSysLock();
654  chThdSleepS(time);
655  chSysUnlock();
656 }
657 
658 /**
659  * @brief Suspends the invoking thread until the system time arrives to the
660  * specified value.
661  * @note The function has no concept of "past", all specifiable times
662  * are in the future, this means that if you call this function
663  * exceeding your calculated intervals then the function will
664  * return in a far future time, not immediately.
665  * @see chThdSleepUntilWindowed()
666  *
667  * @param[in] time absolute system time
668  *
669  * @api
670  */
672  sysinterval_t interval;
673 
674  chSysLock();
675  interval = chTimeDiffX(chVTGetSystemTimeX(), time);
676  if (interval > (sysinterval_t)0) {
677  chThdSleepS(interval);
678  }
679  chSysUnlock();
680 }
681 
682 /**
683  * @brief Suspends the invoking thread until the system time arrives to the
684  * specified value.
685  * @note The system time is assumed to be between @p prev and @p time
686  * else the call is assumed to have been called outside the
687  * allowed time interval, in this case no sleep is performed.
688  * @see chThdSleepUntil()
689  *
690  * @param[in] prev absolute system time of the previous deadline
691  * @param[in] next absolute system time of the next deadline
692  * @return the @p next parameter
693  *
694  * @api
695  */
697  systime_t time;
698 
699  chSysLock();
700  time = chVTGetSystemTimeX();
701  if (chTimeIsInRangeX(time, prev, next)) {
702  chThdSleepS(chTimeDiffX(time, next));
703  }
704  chSysUnlock();
705 
706  return next;
707 }
708 
709 /**
710  * @brief Yields the time slot.
711  * @details Yields the CPU control to the next thread in the ready list with
712  * equal priority, if any.
713  *
714  * @api
715  */
716 void chThdYield(void) {
717 
718  chSysLock();
719  chSchDoYieldS();
720  chSysUnlock();
721 }
722 
723 /**
724  * @brief Sends the current thread sleeping and sets a reference variable.
725  * @note This function must reschedule, it can only be called from thread
726  * context.
727  *
728  * @param[in] trp a pointer to a thread reference object
729  * @return The wake up message.
730  *
731  * @sclass
732  */
734  thread_t *tp = chThdGetSelfX();
735 
736  chDbgAssert(*trp == NULL, "not NULL");
737 
738  *trp = tp;
739  tp->u.wttrp = trp;
741 
742  return chThdGetSelfX()->u.rdymsg;
743 }
744 
745 /**
746  * @brief Sends the current thread sleeping and sets a reference variable.
747  * @note This function must reschedule, it can only be called from thread
748  * context.
749  *
750  * @param[in] trp a pointer to a thread reference object
751  * @param[in] timeout the timeout in system ticks, the special values are
752  * handled as follow:
753  * - @a TIME_INFINITE the thread enters an infinite sleep
754  * state.
755  * - @a TIME_IMMEDIATE the thread is not enqueued and
756  * the function returns @p MSG_TIMEOUT as if a timeout
757  * occurred.
758  * .
759  * @return The wake up message.
760  * @retval MSG_TIMEOUT if the operation timed out.
761  *
762  * @sclass
763  */
765  thread_t *tp = chThdGetSelfX();
766 
767  chDbgAssert(*trp == NULL, "not NULL");
768 
769  if (TIME_IMMEDIATE == timeout) {
770  return MSG_TIMEOUT;
771  }
772 
773  *trp = tp;
774  tp->u.wttrp = trp;
775 
776  return chSchGoSleepTimeoutS(CH_STATE_SUSPENDED, timeout);
777 }
778 
779 /**
780  * @brief Wakes up a thread waiting on a thread reference object.
781  * @note This function must not reschedule because it can be called from
782  * ISR context.
783  *
784  * @param[in] trp a pointer to a thread reference object
785  * @param[in] msg the message code
786  *
787  * @iclass
788  */
789 void chThdResumeI(thread_reference_t *trp, msg_t msg) {
790 
791  if (*trp != NULL) {
792  thread_t *tp = *trp;
793 
794  chDbgAssert(tp->state == CH_STATE_SUSPENDED, "not CH_STATE_SUSPENDED");
795 
796  *trp = NULL;
797  tp->u.rdymsg = msg;
798  (void) chSchReadyI(tp);
799  }
800 }
801 
802 /**
803  * @brief Wakes up a thread waiting on a thread reference object.
804  * @note This function must reschedule, it can only be called from thread
805  * context.
806  *
807  * @param[in] trp a pointer to a thread reference object
808  * @param[in] msg the message code
809  *
810  * @iclass
811  */
812 void chThdResumeS(thread_reference_t *trp, msg_t msg) {
813 
814  if (*trp != NULL) {
815  thread_t *tp = *trp;
816 
817  chDbgAssert(tp->state == CH_STATE_SUSPENDED, "not CH_STATE_SUSPENDED");
818 
819  *trp = NULL;
820  chSchWakeupS(tp, msg);
821  }
822 }
823 
824 /**
825  * @brief Wakes up a thread waiting on a thread reference object.
826  * @note This function must reschedule, it can only be called from thread
827  * context.
828  *
829  * @param[in] trp a pointer to a thread reference object
830  * @param[in] msg the message code
831  *
832  * @api
833  */
834 void chThdResume(thread_reference_t *trp, msg_t msg) {
835 
836  chSysLock();
837  chThdResumeS(trp, msg);
838  chSysUnlock();
839 }
840 
841 /**
842  * @brief Enqueues the caller thread on a threads queue object.
843  * @details The caller thread is enqueued and put to sleep until it is
844  * dequeued or the specified timeouts expires.
845  *
846  * @param[in] tqp pointer to the threads queue object
847  * @param[in] timeout the timeout in system ticks, the special values are
848  * handled as follow:
849  * - @a TIME_INFINITE the thread enters an infinite sleep
850  * state.
851  * - @a TIME_IMMEDIATE the thread is not enqueued and
852  * the function returns @p MSG_TIMEOUT as if a timeout
853  * occurred.
854  * .
855  * @return The message from @p osalQueueWakeupOneI() or
856  * @p osalQueueWakeupAllI() functions.
857  * @retval MSG_TIMEOUT if the thread has not been dequeued within the
858  * specified timeout or if the function has been
859  * invoked with @p TIME_IMMEDIATE as timeout
860  * specification.
861  *
862  * @sclass
863  */
865 
866  if (TIME_IMMEDIATE == timeout) {
867  return MSG_TIMEOUT;
868  }
869 
870  queue_insert(currp, tqp);
871 
872  return chSchGoSleepTimeoutS(CH_STATE_QUEUED, timeout);
873 }
874 
875 /**
876  * @brief Dequeues and wakes up one thread from the threads queue object,
877  * if any.
878  *
879  * @param[in] tqp pointer to the threads queue object
880  * @param[in] msg the message code
881  *
882  * @iclass
883  */
884 void chThdDequeueNextI(threads_queue_t *tqp, msg_t msg) {
885 
886  if (queue_notempty(tqp)) {
887  chThdDoDequeueNextI(tqp, msg);
888  }
889 }
890 
891 /**
892  * @brief Dequeues and wakes up all threads from the threads queue object.
893  *
894  * @param[in] tqp pointer to the threads queue object
895  * @param[in] msg the message code
896  *
897  * @iclass
898  */
899 void chThdDequeueAllI(threads_queue_t *tqp, msg_t msg) {
900 
901  while (queue_notempty(tqp)) {
902  chThdDoDequeueNextI(tqp, msg);
903  }
904 }
905 
906 /** @} */
void chThdExitS(msg_t msg)
Terminates the current thread.
Definition: chthreads.c:501
thread_t * chThdAddRef(thread_t *tp)
Adds a reference to a thread object.
Definition: chthreads.c:401
static systime_t chVTGetSystemTimeX(void)
Current system time.
Definition: chvt.h:115
#define CH_STATE_WTEXIT
Waiting a thread.
Definition: chschd.h:76
#define CH_CFG_THREAD_EXIT_HOOK(tp)
Threads finalization hook.
Definition: chconf.h:607
thread_t * chThdCreateI(const thread_descriptor_t *tdp)
Creates a new thread into a static memory area.
Definition: chthreads.c:259
uint64_t systime_t
Type of system time.
Definition: chtime.h:138
uint64_t sysinterval_t
Type of time interval.
Definition: chtime.h:150
eventmask_t epending
Pending events mask.
Definition: chschd.h:287
msg_t chThdSuspendTimeoutS(thread_reference_t *trp, sysinterval_t timeout)
Sends the current thread sleeping and sets a reference variable.
Definition: chthreads.c:764
static void chSysLock(void)
Enters the kernel lock state.
Definition: chsys.h:353
tprio_t prio
Thread priority.
Definition: chschd.h:155
struct ch_mutex * mtxlist
List of the mutexes owned by this thread.
Definition: chschd.h:294
void chPoolFree(memory_pool_t *mp, void *objp)
Releases an object into a memory pool.
Definition: chmempools.c:202
thread_t * chThdCreateSuspendedI(const thread_descriptor_t *tdp)
Creates a new thread into a static memory area.
Definition: chthreads.c:167
void chThdExit(msg_t msg)
Terminates the current thread.
Definition: chthreads.c:477
thread_t * chSchReadyI(thread_t *tp)
Inserts a thread in the Ready List placing it behind its peers.
Definition: chschd.c:218
Type of a thread descriptor.
Definition: chthreads.h:57
void chThdDequeueAllI(threads_queue_t *tqp, msg_t msg)
Dequeues and wakes up all threads from the threads queue object.
Definition: chthreads.c:899
thread_t * chThdCreateStatic(void *wsp, size_t size, tprio_t prio, tfunc_t pf, void *arg)
Creates a new thread into a static memory area.
Definition: chthreads.c:323
#define CH_STATE_WTSTART
Just created.
Definition: chschd.h:69
trefs_t refs
References to this thread.
Definition: chschd.h:189
#define CH_STATE_SUSPENDED
Suspended state.
Definition: chschd.h:70
msg_t chThdEnqueueTimeoutS(threads_queue_t *tqp, sysinterval_t timeout)
Enqueues the caller thread on a threads queue object.
Definition: chthreads.c:864
Generic threads bidirectional linked list header and element.
Definition: chschd.h:142
stkalign_t * wbase
Pointer to the working area base.
Definition: chthreads.h:65
static sysinterval_t chTimeDiffX(systime_t start, systime_t end)
Subtracts two system times returning an interval.
Definition: chtime.h:491
#define currp
Current thread pointer access macro.
Definition: chschd.h:459
void(* tfunc_t)(void *p)
Thread function.
Definition: chthreads.h:52
msg_t rdymsg
Thread wakeup code.
Definition: chschd.h:216
void chThdTerminate(thread_t *tp)
Requests a thread termination.
Definition: chthreads.c:632
#define CH_CFG_THREAD_INIT_HOOK(tp)
Threads initialization hook.
Definition: chconf.h:599
static void chSysUnlock(void)
Leaves the kernel lock state.
Definition: chsys.h:365
static bool chTimeIsInRangeX(systime_t time, systime_t start, systime_t end)
Checks if the specified time is within the specified time range.
Definition: chtime.h:512
void chThdResumeS(thread_reference_t *trp, msg_t msg)
Wakes up a thread waiting on a thread reference object.
Definition: chthreads.c:812
#define CH_FLAG_MODE_HEAP
Thread allocated from a Memory Heap.
Definition: chschd.h:109
threads_queue_t msgqueue
Messages queue.
Definition: chschd.h:281
static void list_init(threads_list_t *tlp)
Threads list initialization.
Definition: chschd.h:510
void chHeapFree(void *p)
Frees a previously allocated memory block.
Definition: chheap.c:293
stkalign_t * wend
End of the working area.
Definition: chthreads.h:69
void _thread_memfill(uint8_t *startp, uint8_t *endp, uint8_t v)
Memory fill utility.
Definition: chthreads.c:136
static stkalign_t * chThdGetWorkingAreaX(thread_t *tp)
Returns the working area base of the specified thread.
Definition: chthreads.h:317
static void chSchDoYieldS(void)
Yields the time slot.
Definition: chschd.h:687
#define REG_INSERT(tp)
Adds a thread to the registry list.
Definition: chregistry.h:94
msg_t chThdWait(thread_t *tp)
Blocks the execution of the invoking thread until the specified thread terminates then the exit code ...
Definition: chthreads.c:559
stkalign_t * wabase
Working area base address.
Definition: chschd.h:175
#define MEM_IS_ALIGNED(p, a)
Returns whatever a pointer or memory size is aligned.
Definition: chalign.h:89
static void chThdDoDequeueNextI(threads_queue_t *tqp, msg_t msg)
Dequeues and wakes up one thread from the threads queue object.
Definition: chthreads.h:425
thread_t * chRegFindThreadByWorkingArea(stkalign_t *wa)
Confirms that a working area is being used by some active thread.
Definition: chregistry.c:250
#define HIGHPRIO
Highest priority.
Definition: chschd.h:58
void chDbgCheckClassI(void)
I-class functions context check.
Definition: chdebug.c:235
#define MSG_TIMEOUT
Wakeup caused by a timeout condition.
Definition: chschd.h:40
void chSchRescheduleS(void)
Performs a reschedule if a higher priority thread is runnable.
Definition: chschd.c:456
const char * name
Thread name or NULL.
Definition: chschd.h:166
static bool list_notempty(threads_list_t *tlp)
Evaluates to true if the specified threads list is not empty.
Definition: chschd.h:536
tprio_t chThdSetPriority(tprio_t newprio)
Changes the running thread priority level then reschedules if necessary.
Definition: chthreads.c:598
volatile systime_t time
Thread consumed time in ticks.
Definition: chschd.h:202
threads_list_t waiting
Termination waiting list.
Definition: chschd.h:275
#define CH_STATE_FINAL
Thread terminated.
Definition: chschd.h:88
systime_t chThdSleepUntilWindowed(systime_t prev, systime_t next)
Suspends the invoking thread until the system time arrives to the specified value.
Definition: chthreads.c:696
tslices_t ticks
Number of ticks remaining to this thread.
Definition: chschd.h:195
void chSchGoSleepS(tstate_t newstate)
Puts the current thread to sleep into the specified state.
Definition: chschd.c:289
static void chThdSleepS(sysinterval_t ticks)
Suspends the invoking thread for the specified number of ticks.
Definition: chthreads.h:378
static void queue_init(threads_queue_t *tqp)
Threads queue initialization.
Definition: chschd.h:548
#define chDbgCheck(c)
Function parameters check.
Definition: chdebug.h:101
void chThdResumeI(thread_reference_t *trp, msg_t msg)
Wakes up a thread waiting on a thread reference object.
Definition: chthreads.c:789
msg_t chSchGoSleepTimeoutS(tstate_t newstate, sysinterval_t timeout)
Puts the current thread to sleep into the specified state with timeout specification.
Definition: chschd.c:375
#define CH_FLAG_MODE_MPOOL
Thread allocated from a Memory Pool.
Definition: chschd.h:112
tfunc_t funcp
Thread function pointer.
Definition: chthreads.h:77
const char * name
Thread name.
Definition: chthreads.h:61
thread_t * list_remove(threads_list_t *tlp)
Pops a thread from the top of a stack list and returns it.
Definition: chschd.c:193
void * arg
Thread argument.
Definition: chthreads.h:81
#define MSG_OK
Normal wakeup message.
Definition: chschd.h:39
void chThdDequeueNextI(threads_queue_t *tqp, msg_t msg)
Dequeues and wakes up one thread from the threads queue object, if any.
Definition: chthreads.c:884
void queue_insert(thread_t *tp, threads_queue_t *tqp)
Inserts a thread into a queue.
Definition: chschd.c:106
void * mpool
Memory Pool where the thread workspace is returned.
Definition: chschd.h:305
#define chDbgAssert(c, r)
Condition assertion.
Definition: chdebug.h:127
tstate_t state
Current thread state.
Definition: chschd.h:180
#define CH_FLAG_MODE_MASK
Thread memory mode mask.
Definition: chschd.h:105
void chThdYield(void)
Yields the time slot.
Definition: chthreads.c:716
void chThdResume(thread_reference_t *trp, msg_t msg)
Wakes up a thread waiting on a thread reference object.
Definition: chthreads.c:834
msg_t chThdSuspendS(thread_reference_t *trp)
Sends the current thread sleeping and sets a reference variable.
Definition: chthreads.c:733
time_measurement_t stats
Thread statistics.
Definition: chschd.h:311
union ch_thread::@0 u
State-specific fields.
#define CH_CFG_TIME_QUANTUM
Round robin interval.
Definition: chconf.h:108
void chThdSleep(sysinterval_t time)
Suspends the invoking thread for the specified time.
Definition: chthreads.c:651
#define TIME_IMMEDIATE
Zero interval specification for some functions with a timeout specification.
Definition: chtime.h:45
thread_t * _thread_init(thread_t *tp, const char *name, tprio_t prio)
Initializes a thread structure.
Definition: chthreads.c:88
static thread_t * chThdGetSelfX(void)
Returns a pointer to the current thread_t.
Definition: chthreads.h:272
static bool queue_notempty(const threads_queue_t *tqp)
Evaluates to true if the specified threads queue is not empty.
Definition: chschd.h:575
thread_t * chThdCreate(const thread_descriptor_t *tdp)
Creates a new thread into a static memory area.
Definition: chthreads.c:280
void chSchWakeupS(thread_t *ntp, msg_t msg)
Wakes up a thread.
Definition: chschd.c:412
thread_t * chThdStart(thread_t *tp)
Resumes a thread created with chThdCreateI().
Definition: chthreads.c:379
#define CH_STATE_QUEUED
On a queue.
Definition: chschd.h:71
#define REG_REMOVE(tp)
Removes a thread from the registry list.
Definition: chregistry.h:83
#define CH_FLAG_MODE_STATIC
Static thread.
Definition: chschd.h:108
void list_insert(thread_t *tp, threads_list_t *tlp)
Pushes a thread_t on top of a stack list.
Definition: chschd.c:178
void chThdRelease(thread_t *tp)
Releases a reference to a thread object.
Definition: chthreads.c:427
void chThdSleepUntil(systime_t time)
Suspends the invoking thread until the system time arrives to the specified value.
Definition: chthreads.c:671
void chTMObjectInit(time_measurement_t *tmp)
Initializes a TimeMeasurement object.
Definition: chtm.c:97
thread_reference_t * wttrp
Pointer to a generic thread reference object.
Definition: chschd.h:237
#define THD_WORKING_AREA_SIZE(n)
Calculates the total Working Area size.
Definition: chthreads.h:122
ChibiOS/RT main include file.
thread_t * chThdCreateSuspended(const thread_descriptor_t *tdp)
Creates a new thread into a static memory area.
Definition: chthreads.c:216
tmode_t flags
Various thread flags.
Definition: chschd.h:184
#define MEM_ALIGN_NEXT(p, a)
Aligns to the next aligned memory address.
Definition: chalign.h:78
#define CH_FLAG_TERMINATE
Termination requested flag.
Definition: chschd.h:115
tprio_t realprio
Thread&#39;s own, non-inherited, priority.
Definition: chschd.h:298
#define CH_DBG_STACK_FILL_VALUE
Fill value for thread stack area in debug mode.
Definition: chdebug.h:47
msg_t exitcode
Thread exit code.
Definition: chschd.h:223
tprio_t prio
Thread priority.
Definition: chthreads.h:73
Structure representing a thread.
Definition: chschd.h:153