1 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
2 // ==== Thread Management ====
4 \addtogroup CMSIS_RTOS_ThreadMgmt Thread Management
5 \ingroup CMSIS_RTOS CMSIS_RTOSv2
6 \brief Define, create, and control thread functions.
8 The Thread Management function group allows defining, creating, and controlling thread functions in the system. The function
9 \b main is a special thread function that is started at system initialization and has the initial priority
14 Threads can be in the following states:
16 - \b RUNNING: The thread that is currently running is in the \b RUNNING state. Only one thread at a time can be in this state.
18 - \b READY: Threads which are ready to run are in the \b READY state. Once the \b RUNNING thread has terminated, or is \b BLOCKED, the next \b READY thread with the highest priority becomes the \b RUNNING thread.
20 - \b BLOCKED: Threads that are blocked either delayed, waiting for an event to occur or suspended are in the \b BLOCKED state.
22 - \b TERMINATED: When \ref osThreadTerminate is called, and threads that joined are in \b TERMINATED state. When all joined threads have terminated, resources are released an the threads are in state \b INACTIVE.
24 - \b INACTIVE: Threads that are not created or have been terminated with all resources released are in the \b INACTIVE state.
26 \image html "ThreadStatus.png" "Thread State and State Transitions"
29 A CMSIS-RTOS assumes that threads are scheduled as shown in the figure <b>Thread State and State Transitions</b>. The thread
30 states change as follows:
31 - A thread is created using the function \ref osThreadNew. This puts the thread into the \b READY or \b RUNNING state
32 (depending on the thread priority).
33 - CMSIS-RTOS is pre-emptive. The active thread with the highest priority becomes the \b RUNNING thread provided it does not
34 wait for any event. The initial priority of a thread is defined with the \ref osThreadAttr_t but may be changed during
35 execution using the function \ref osThreadSetPriority.
36 - The \b RUNNING thread transfers into the \b BLOCKED state when it is delayed, waiting for an event or suspended.
37 - Active threads can be terminated any time using the function \ref osThreadTerminate. Threads can terminate also by just
38 returning from the thread function. Threads that are terminated are in the \b INACTIVE state and typically do not consume
39 any dynamic memory resources.
41 By using sizeof on the object control block.
43 For example RTX5 has the following internal defines (starting with os_ which is not RTOS prefix but rather RTX implementation prefix):
44 /// Control Block sizes
46 #define os_ThreadCbSize sizeof(os_thread_t)
47 #define os_TimerCbSize sizeof(os_timer_t)
48 #define os_EventFlagsCbSize sizeof(os_event_flags_t)
49 #define os_MutexCbSize sizeof(os_mutex_t)
50 #define os_SemaphoreCbSize sizeof(os_semaphore_t)
51 #define os_MemoryPoolCbSize sizeof(os_memory_pool_t)
52 #define os_MessageQueueCbSize sizeof(os_message_queue_t)
55 \anchor Thread Examples
56 The following examples show various scenarios to create threads:
58 \b Example 1 - Create a simple thread
61 __NO_RETURN void thread1 (void *argument) {
69 osThreadNew(thread1, NULL, NULL); // Create thread with default settings
74 \b Example 2 - Create thread with statically allocated stack
77 __NO_RETURN void thread1 (void *argument) {
82 static uint64_t thread1_stk_1[64];
85 osThreadAttr_t thread1_attr;
86 thread1_attr.stack_mem = &thread1_stk_1[0];
87 thread1_attr.stack_size = sizeof(thread1_stk_1);
89 osThreadNew(thread1, NULL, &thread1_attr); // Create thread with statically allocated stack memory
94 \b 3. Example 3 - Thread with statically allocated tcb
99 __NO_RETURN void thread1 (void *argument) {
104 static os_thread_t thread1_tcb;
107 osThreadAttr_t thread1_attr;
108 thread1_attr.cb_mem = &thread1_tcb;
109 thread1_attr.cb_size = sizeof(os_thread_t);
111 osThreadNew(thread1, NULL, &thread1_attr); // Create thread with custom tcb memory
116 \b Example 4 - Create thread with a different priority
119 __NO_RETURN void thread1 (void *argument) {
125 osThreadAttr_t thread1_attr;
126 thread1_attr.priority = osPriorityHigh; //Set initial thread priority to high
128 osThreadNew(thread1, NULL, &thread1_attr);
133 \(b)Example 5 - Joinable threads
136 __NO_RETURN void worker (void *argument) {
137 ; // work a lot on data
142 __NO_RETURN void thread1 (void *argument) {
143 osThreadAttr_t worker_attr;
144 osThreadId_t worker_ids[4];
148 worker_attr.attr_bits |= osThreadJoinable;
149 worker_attr.priority = osPriorityHigh;
151 worker_ids[0] = osThreadNew(worker, &data[0][0], &worker_attr);
152 worker_ids[1] = osThreadNew(worker, &data[1][0], &worker_attr);
153 worker_ids[2] = osThreadNew(worker, &data[2][0], &worker_attr);
154 worker_ids[3] = osThreadNew(worker, &data[3][0], &worker_attr);
156 osThreadJoin(worker_ids[0]);
157 osThreadJoin(worker_ids[1]);
158 osThreadJoin(worker_ids[2]);
159 osThreadJoin(worker_ids[3]);
173 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
175 \enum osThreadState_t
179 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
184 The \b osPriority_t value specifies the priority for a thread. The default thread priority should be \a osPriorityNormal.
185 If a Thread is active that has a higher priority than the currently executing thread, then a thread switch occurs immediately
186 to execute the new task.
188 To prevent from a priority inversion, a CMSIS-RTOS compliant OS may optionally implement a <b>priority inheritance</b> method.
189 A priority inversion occurs when a high priority thread is waiting for a resource or event that is controlled by a thread
190 with a lower priority.
193 Cannot be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines".
196 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
198 \typedef void *(*os_thread_func_t) (void *argument)
203 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
205 \typedef osThreadId_t
208 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
210 \struct osThreadAttr_t
213 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
215 \def osThreadJoinable
220 \def osThreadDetached
224 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
226 \fn osThreadId_t osThreadNew (os_thread_func_t func, void *argument, const osThreadAttr_t *attr)
229 Start a thread function by adding it to the Active Threads list and set it to state \b READY. Arguments for the thread function are passed
230 using the parameter pointer \em *argument. When the priority of the created thread function is higher than the current \b RUNNING thread,
231 the created thread function starts instantly and becomes the new \b RUNNING thread. Thread attributes are defined with the parameter pointer \em attr.
232 Attributes include settings for thread priority, stack size, or memory allocation.
235 Cannot be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines".
239 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
241 \fn const char *osThreadGetName (osThreadId_t thread_id)
246 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
248 \fn osThreadId_t osThreadGetId (void)
251 Get the thread ID of the current running thread.
254 Cannot be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines".
258 void ThreadGetId_example (void) {
259 osThreadId id; // id for the currently running thread
261 id = osThreadGetId ();
263 // Failed to get the id; not in a thread
268 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
270 \fn osThreadState_t osThreadGetState (osThreadId_t thread_id)
273 Return the state of the thread identified by parameter \em thread_id.
274 See \ref osThreadState_t for possible states.
277 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
279 \fn osStatus_t osThreadSetPriority (osThreadId_t thread_id, osPriority_t priority)
282 Change the priority of an active thread.
284 \ref osStatus_t return values:
285 - \em osOK: the priority of the specified thread has been changed successfully.
286 - \em osErrorParameter: the value of the parameter \em thread_id or parameter \em priority is incorrect.
287 - \em osErrorResource: parameter \em thread_id refers to a thread that is not an active thread.
288 - \em osErrorISR: the function \b osThreadSetPriority cannot be called from interrupt service routines.
291 Cannot be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines".
295 #include "cmsis_os2.h"
297 void Thread_1 (void const *arg) { // Thread function
298 osThreadId_t id; // id for the currently running thread
299 osStatus status; // status of the executed function
302 id = osThreadGetId (); // Obtain ID of current running thread
305 status = osThreadSetPriority (id, osPriorityBelowNormal);
306 if (status == osOK) {
307 // Thread priority changed to BelowNormal
310 // Failed to set the priority
314 // Failed to get the id
320 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
322 \fn osPriority_t osThreadGetPriority (osThreadId_t thread_id)
325 Get the priority of an active thread. In case of failure, the value \b osPriorityError is returned.
328 Cannot be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines".
332 #include "cmsis_os2.h"
334 void Thread_1 (void const *arg) { // Thread function
335 osThreadId_t id; // id for the currently running thread
336 osPriority_t priority; // thread priority
338 id = osThreadGetId (); // Obtain ID of current running thread
341 priority = osThreadGetPriority (id);
344 // Failed to get the id
349 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
351 \fn osStatus_t osThreadYield (void)
354 Pass control to the next thread that is in state \b READY. If there is no other thread in state \b READY,
355 then the current thread continues execution and no thread switching occurs.
358 Cannot be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines".
362 #include "cmsis_os2.h"
364 void Thread_1 (void const *arg) { // Thread function
365 osStatus_t status; // status of the executed function
368 status = osThreadYield(); //
369 if (status != osOK) {
370 // thread switch not occurred, not in a thread function
376 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
378 \fn osStatus_t osThreadSuspend (osThreadId_t thread_id)
380 Suspends execution of the thread identified by parameter \em thread_id. Thread is put into the state \em Blocked (\ref osThreadBlocked).
381 The thread is not executed until restarted with the function \ref osThreadResume.
384 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
386 \fn osStatus_t osThreadResume (osThreadId_t thread_id)
388 Forces a thread in BLOCKED state, specified with \em thread_id, to resume operation.
389 Functions that will put a thread into BLOCKED state are:
390 \ref osEventFlagsWait and \ref osThreadFlagsWait,
391 \ref osDelay and \ref osDelayUntil,
392 \ref osMutexAcquire and \ref osSemaphoreAcquire,
393 \ref osMessageQueueGet,
395 \ref osThreadSuspend.
398 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
400 \fn osStatus_t osThreadDetach (osThreadId_t thread_id)
402 Changes the attribute of a thread specified in \em thread_id to \ref osThreadDetached. Detached threads are not joinable with \ref osThreadJoin.
403 When a detached thread is terminated all resources are returned to the system. The behaviour of \ref osThreadDetach on an already detached thread is undefined.
408 Cannot be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines".
410 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
412 \fn osStatus_t osThreadJoin (osThreadId_t thread_id)
414 Waits for the thread specified by \em thread_id to terminate.
415 If that thread has already terminated, then \ref osThreadJoin returns immediately.
416 The thread referred to by thread_id must joinable. By default threads are created with the attribute \ref osThreadJoinable. The thread may not have been detached by \ref osThreadDetach.
419 Cannot be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines".
423 \todo this example may not compile.... void *worker ???
425 #include "cmsis_os2.h"
427 void *worker(void *arg)
434 int join_threads(void)
436 osThreadId_t th1, th2;
438 th1 = osThreadNew(worker, ¶m, NULL);
439 th2 = osThreadNew(worker, ¶m, NULL);
441 (void) osThreadJoin(th1, NULL);
442 (void) osThreadJoin(th2, NULL);
448 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
450 \fn __NO_RETURN void osThreadExit (void)
453 Exit the \b RUNNING thread an exit point defined by parameter pointer \em exit_ptr.
456 Cannot be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines".
458 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
460 \fn osStatus_t osThreadTerminate (osThreadId_t thread_id)
462 Remove the thread function from the active thread list. If the thread is currently /b RUNNING the execution stops and the thread
466 Cannot be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines".
469 #include "cmsis_os2.h"
471 void *Thread_1 (void c*arg); // function prototype for Thread_1
473 void ThreadTerminate_example (void) {
477 id = osThreadNew (Thread_1, NULL, NULL); // create the thread
479 status = osThreadTerminate (id); // stop the thread
480 if (status == osOK) {
481 // Thread was terminated successfully
484 // Failed to terminate a thread
492 // these struct members must stay outside the group to avoid double entries in documentation
494 \var osThreadAttr_t::attr_bits
496 The following predefined bit masks can be assigned to set options for a thread object.
498 Bit Mask | Description
499 :-----------------------|:-----------------------------------------
500 osThreadJoinable | Thread is created in a join-able state (default).
501 osThreadDettached | Thread is created in a detached state.
503 \var osThreadAttr_t::cb_mem
505 Pointer to a memory location for the thread object. This can optionally be used for custom memory management systems.
506 Specify \token{NULL} to use the kernel memory management.
508 \var osThreadAttr_t::cb_size
510 The size of the memory block passed with \ref cb_mem. Must be the size of a thread control block object or larger.
512 \var osThreadAttr_t::name
514 String with a human readable name of the thread object.
516 \var osThreadAttr_t::priority
518 Specifies the initial thread priority with a value from #osPriority_t.
520 \var osThreadAttr_t::reserved
522 Reserved for future use. Must be \token{0}.
524 \var osThreadAttr_t::stack_mem
526 Pointer to a memory location for the thread stack. This can optionally be used for custom memory management systems.
527 Specify \token{NULL} to use the kernel memory management.
529 \var osThreadAttr_t::stack_size
531 The size of the stack specified by \ref stack_mem in Bytes.