le_thread.h

Go to the documentation of this file.
1 /**
2  * @page c_threading Thread Control API
3  *
4  * @subpage le_thread.h "API Reference"
5  *
6  * <HR>
7  *
8  * Generally, using single-threaded, event-driven programming (registering callbacks to be called
9  * by an event handling loop running in a single thread) is more efficient than using
10  * multiple threads. With single-threaded, event driven designs:
11  * - there's no CPU time spent switching between threads.
12  * - there's only one copy of thread-specific memory objects, like the procedure call stack.
13  * - there's no need to use thread synchronization mechanisms, like mutexes, to prevent race
14  * conditions between threads.
15  *
16  * Sometimes, this style doesn't fit well with a problem being solved,
17  * so you're forced to implement workarounds that severely complicate
18  * the software design. In these cases, it is far better to take advantage of multi-threading
19  * to simplify the design, even if it means that the program uses more memory or more
20  * CPU cycles. In some cases, the workarounds required to avoid multi-threading will
21  * cost more memory and/or CPU cycles than using multi-threading would.
22  *
23  * But you must <b> be careful </b> with multi-threading. Some of the most tenacious,
24  * intermittent defects known to humankind have resulted from the misuse of multi-threading.
25  * Ensure you know what you are doing.
26  *
27  * @section threadCreating Creating a Thread
28  *
29  * To create a thread, call @c le_thread_Create().
30  *
31  * All threads are @b named for two reasons:
32  * -# To make it possible to address them by name.
33  * -# For diagnostics.
34  *
35  * Threads are created in a suspended state. In this state, attributes like
36  * scheduling priority and stack size can use the appropriate "Set" functions.
37  * All attributes have default values so it is not necessary to set any
38  * attributes (other than the name and main function address, which are passed into
39  * le_thread_Create() ). When all attributes have been set, the thread can be started by calling
40  * le_thread_Start().
41  *
42  * @warning It is assumed that if a thread @e T1 creates another thread @e T2 then @b only thread
43  * @e T1 will set the attributes and start thread @e T2. No other thread should try
44  * to set any attributes of @e T2 or try to start it.
45  *
46  *
47  * @section threadTerminating Terminating a Thread
48  *
49  * Threads can terminate themselves by:
50  * - returning from their main function
51  * - calling le_thread_Exit().
52  *
53  * Threads can also tell other threads to terminate by "canceling" them; done
54  * through a call to @c le_thread_Cancel().
55  *
56  * If a thread terminates itself, and it is "joinable", it can pass a @c void* value to another
57  * thread that "joins" with it. See @ref threadJoining for more information.
58  *
59  * Canceling a thread may not cause the thread to terminate immediately. If it is
60  * in the middle of doing something that can't be interrupted, it will not terminate until it
61  * is finished. See 'man 7 pthreads' for more information on cancellation
62  * and cancellation points.
63  *
64  * To prevent cancellation during a critical section (e.g., when a mutex lock is held),
65  * pthread_setcancelstate() can be called. If a cancellation request is made (by calling
66  * le_thread_Cancel() or <c>pthread_cancel()</c>), it will be blocked and remain in a pending state
67  * until cancellation is unblocked (also using pthread_setcancelstate()), at which time the thread
68  * will be immediately cancelled.
69  *
70  *
71  * @section threadJoining Joining
72  *
73  * Sometimes, you want single execution thread split (fork) into separate
74  * threads of parallel execution and later join back together into one thread later. Forking
75  * is done by creating and starting a thread. Joining is done by a call to le_thread_Join().
76  * le_thread_Join(T) blocks the calling thread until thread T exits.
77  *
78  * For a thread to be joinable, it must have its "joinable" attribute set (using
79  * le_thread_SetJoinable()) prior to being started. Normally, when a thread terminates, it
80  * disappears. But, a joinable thread doesn't disappear until another thread "joins" with it.
81  * This also means that if a thread is joinable, someone must join with it, or its
82  * resources will never get cleaned up (until the process terminates).
83  *
84  * le_thread_Join() fetches the return/exit value of the thread that it joined with.
85  *
86  *
87  * @section threadLocalData Thread-Local Data
88  *
89  * Often, you want data specific to a particular thread. A classic example
90  * of is the ANSI C variable @c errno. If one instance of @c errno was shared by all the
91  * threads in the process, then it would essentially become useless in a multi-threaded program
92  * because it would be impossible to ensure another thread hadn't killed @c errno before
93  * its value could be read. As a result, POSIX has mandated that @c errno be a @a thread-local
94  * variable; each thread has its own unique copy of @c errno.
95  *
96  * If a component needs to make use of other thread-local data, it can do so using the pthread
97  * functions pthread_key_create(), pthread_getspecific(), pthread_setspecific(),
98  * pthread_key_delete(). See the pthread man pages for more details.
99  *
100  *
101  * @section threadSynchronization Thread Synchronization
102  *
103  * Nasty multi-threading defects arise as a result of thread synchronization, or a
104  * lack of synchronization. If threads share data, they @b MUST be synchronized with each other to
105  * avoid destroying that data and incorrect thread behaviour.
106  *
107  * @warning This documentation assumes that the reader is familiar with multi-thread synchronization
108  * techniques and mechanisms.
109  *
110  * The Legato C APIs provide the following thread synchronization mechanisms:
111  * - @ref c_mutex
112  * - @ref c_semaphore
113  * - @ref c_messaging
114  *
115  *
116  * @section threadDestructors Thread Destructors
117  *
118  * When a thread dies, some clean-up action is needed (e.g., a connection
119  * needs to be closed or some objects need to be released). If a thread doesn't always terminate
120  * the same way (e.g., if it might be canceled by another thread or exit in several places due
121  * to error detection code), then a clean-up function (destructor) is probably needed.
122  *
123  * A Legato thread can use @c le_thread_AddDestructor() to register a function to be called
124  * by that thread just before it terminates.
125  *
126  * A parent thread can also call @c le_thread_AddChildDestructor() to register
127  * a destructor for a child thread before it starts the child thread.
128  *
129  * Multiple destructors can be registered for the same thread. They will be called in reverse
130  * order of registration (i.e, the last destructor to be registered will be called first).
131  *
132  * A Legato thread can also use le_thread_RemoveDestructor() to remove its own destructor
133  * function that it no longer wants called in the event of its death. (There is no way to remove
134  * destructors from other threads.)
135  *
136  *
137  * @section threadLegatoizing Using Legato APIs from Non-Legato Threads
138  *
139  * If a thread is started using some other means besides le_thread_Start() (e.g., if
140  * pthread_create() is used directly), then the Legato thread-specific data will not have
141  * been initialized for that thread. Therefore, if that thread tries to call some Legato APIs,
142  * a fatal error message like, "Legato threading API used in non-Legato thread!" may be seen.
143  *
144  * To work around this, a "non-Legato thread" can call le_thread_InitLegatoThreadData() to
145  * initialize the thread-specific data that the Legato framework needs.
146  *
147  * If you have done this for a thread, and that thread will die before the process it is inside
148  * dies, then that thread must call le_thread_CleanupLegatoThreadData() before it exits. Otherwise
149  * the process will leak memory. Furthermore, if the thread will ever be cancelled by another
150  * thread before the process dies, a cancellation clean-up handler can be used to ensure that
151  * the clean-up is done, if the thread's cancellation type is set to "deferred".
152  * See 'man 7 pthreads' for more information on cancellation and cancellation points.
153  *
154  *
155  * <HR>
156  *
157  * Copyright (C) Sierra Wireless Inc.
158  */
159 
160 
161 /** @file le_thread.h
162  *
163  * Legato @ref c_threading include file.
164  *
165  * Copyright (C) Sierra Wireless Inc.
166  */
167 
168 #ifndef LEGATO_THREAD_INCLUDE_GUARD
169 #define LEGATO_THREAD_INCLUDE_GUARD
170 
171 #include "le_cdata.h"
172 
173 //--------------------------------------------------------------------------------------------------
174 /**
175  * Reference to a thread of execution.
176  *
177  * @note NULL can be used as an invalid value.
178  */
179 //--------------------------------------------------------------------------------------------------
180 typedef struct le_thread* le_thread_Ref_t;
181 
182 
183 //--------------------------------------------------------------------------------------------------
184 /**
185  * Thread priority levels.
186  *
187  * Real-time priority levels should be avoided unless absolutely necessary for the application.
188  * They are privileged levels and will therefore not be allowed unless the application is executed
189  * by an identity with the appropriate permissions. If a thread running at a real-time priority
190  * level does not block, no other thread at a lower priority level will run, so be careful with
191  * these.
192  *
193  * @note Higher numbers are higher priority.
194  */
195 //--------------------------------------------------------------------------------------------------
196 typedef enum
197 {
198  LE_THREAD_PRIORITY_IDLE = 0, ///< Lowest priority level. Only runs when nothing else to do.
199 
200  LE_THREAD_PRIORITY_LOW, ///< Low, non-realtime priority level.
201  ///< Low, medium, high: intended for normal processes that
202  ///< contend for the CPU. Processes with these priorities don't
203  ///< preempt each other, but their priorities affect how they're
204  ///< inserted into the scheduling queue (high to low).
205  LE_THREAD_PRIORITY_MEDIUM, ///< Medium, non-real-time priority level. THIS IS THE DEFAULT.
206  LE_THREAD_PRIORITY_HIGH, ///< High, non-real-time priority level.
207 
208  LE_THREAD_PRIORITY_RT_1, ///< Real-time priority level 1. The lowest realtime priority
209  /// level.
210  LE_THREAD_PRIORITY_RT_2, ///< Real-time priority level 2.
211  LE_THREAD_PRIORITY_RT_3, ///< Real-time priority level 3.
212  LE_THREAD_PRIORITY_RT_4, ///< Real-time priority level 4.
213  LE_THREAD_PRIORITY_RT_5, ///< Real-time priority level 5.
214  LE_THREAD_PRIORITY_RT_6, ///< Real-time priority level 6.
215  LE_THREAD_PRIORITY_RT_7, ///< Real-time priority level 7.
216  LE_THREAD_PRIORITY_RT_8, ///< Real-time priority level 8.
217  LE_THREAD_PRIORITY_RT_9, ///< Real-time priority level 9.
218  LE_THREAD_PRIORITY_RT_10, ///< Real-time priority level 10.
219  LE_THREAD_PRIORITY_RT_11, ///< Real-time priority level 11.
220  LE_THREAD_PRIORITY_RT_12, ///< Real-time priority level 12.
221  LE_THREAD_PRIORITY_RT_13, ///< Real-time priority level 13.
222  LE_THREAD_PRIORITY_RT_14, ///< Real-time priority level 14.
223  LE_THREAD_PRIORITY_RT_15, ///< Real-time priority level 15.
224  LE_THREAD_PRIORITY_RT_16, ///< Real-time priority level 16.
225  LE_THREAD_PRIORITY_RT_17, ///< Real-time priority level 17.
226  LE_THREAD_PRIORITY_RT_18, ///< Real-time priority level 18.
227  LE_THREAD_PRIORITY_RT_19, ///< Real-time priority level 19.
228  LE_THREAD_PRIORITY_RT_20, ///< Real-time priority level 20.
229  LE_THREAD_PRIORITY_RT_21, ///< Real-time priority level 21.
230  LE_THREAD_PRIORITY_RT_22, ///< Real-time priority level 22.
231  LE_THREAD_PRIORITY_RT_23, ///< Real-time priority level 23.
232  LE_THREAD_PRIORITY_RT_24, ///< Real-time priority level 24.
233  LE_THREAD_PRIORITY_RT_25, ///< Real-time priority level 25.
234  LE_THREAD_PRIORITY_RT_26, ///< Real-time priority level 26.
235  LE_THREAD_PRIORITY_RT_27, ///< Real-time priority level 27.
236  LE_THREAD_PRIORITY_RT_28, ///< Real-time priority level 28.
237  LE_THREAD_PRIORITY_RT_29, ///< Real-time priority level 29.
238  LE_THREAD_PRIORITY_RT_30, ///< Real-time priority level 30.
239  LE_THREAD_PRIORITY_RT_31, ///< Real-time priority level 31.
240  LE_THREAD_PRIORITY_RT_32 ///< Real-time priority level 32.
241 }
243 
244 #define LE_THREAD_PRIORITY_RT_LOWEST LE_THREAD_PRIORITY_RT_1 ///< Lowest real-time priority.
245 #define LE_THREAD_PRIORITY_RT_HIGHEST LE_THREAD_PRIORITY_RT_32 ///< Highest real-time priority.
246 
247 
248 //--------------------------------------------------------------------------------------------------
249 /**
250  * Main functions for threads must look like this:
251  *
252  * @param context [IN] Context value that was passed to le_thread_Create().
253  *
254  * @return Thread result value. If the thread is joinable, then this value can be obtained by
255  * another thread through a call to vt_thread_Join(). Otherwise, the return value is ignored.
256  */
257 //--------------------------------------------------------------------------------------------------
258 typedef void* (* le_thread_MainFunc_t)
259 (
260  void* context ///< See parameter documentation above.
261 );
262 
263 
264 #if LE_CONFIG_THREAD_NAMES_ENABLED
265 //--------------------------------------------------------------------------------------------------
266 /**
267  * Creates a new Legato thread of execution. After creating the thread, you have the opportunity
268  * to set attributes before it starts. It won't start until le_thread_Start() is called.
269  *
270  * @param[in] name Thread name (will be copied, so can be temporary).
271  * @param[in] mainFunc Thread's main function.
272  * @param[in] context Value to pass to mainFunc when it is called.
273  *
274  * @return A reference to the thread (doesn't return if fails).
275  */
276 //--------------------------------------------------------------------------------------------------
278 (
279  const char* name,
280  le_thread_MainFunc_t mainFunc,
281  void* context
282 );
283 #else /* if not LE_CONFIG_THREAD_NAMES_ENABLED */
284 /// @cond HIDDEN_IN_USER_DOCS
285 //--------------------------------------------------------------------------------------------------
286 /**
287  * Internal function used to implement le_thread_Create().
288  */
289 //--------------------------------------------------------------------------------------------------
290 le_thread_Ref_t _le_thread_Create(le_thread_MainFunc_t mainFunc, void* context);
291 /// @endcond
292 //--------------------------------------------------------------------------------------------------
293 /**
294  * Creates a new Legato thread of execution. After creating the thread, you have the opportunity
295  * to set attributes before it starts. It won't start until le_thread_Start() is called.
296  *
297  * @param[in] name Thread name (will be copied, so can be temporary).
298  * @param[in] mainFunc Thread's main function.
299  * @param[in] context Value to pass to mainFunc when it is called.
300  *
301  * @return A reference to the thread (doesn't return if fails).
302  */
303 //--------------------------------------------------------------------------------------------------
305 (
306  const char* name,
307  le_thread_MainFunc_t mainFunc,
308  void* context
309 )
310 {
311  return _le_thread_Create(mainFunc, context);
312 }
313 #endif /* end LE_CONFIG_THREAD_NAMES_ENABLED */
314 
315 
316 //--------------------------------------------------------------------------------------------------
317 /**
318  * Sets the priority of a thread.
319  *
320  * @return
321  * - LE_OK if successful.
322  * - LE_OUT_OF_RANGE if the priority level requested is out of range.
323  */
324 //--------------------------------------------------------------------------------------------------
326 (
327  le_thread_Ref_t thread, ///< [IN]
328  le_thread_Priority_t priority ///< [IN]
329 );
330 
331 
332 //--------------------------------------------------------------------------------------------------
333 /**
334  * Sets the stack size of a thread.
335  *
336  * @note It's generally not necessary to set the stack size. Some reasons why you might are:
337  * - to increase it beyond the system's default stack size to prevent overflow
338  * for a thread that makes extremely heavy use of the stack;
339  * - to decrease it to save memory when:
340  * - running in a system that does not support virtual memory
341  * - the thread has very tight real-time constraints that require that the stack
342  * memory be locked into physical memory to avoid page faults.
343  *
344  * @return
345  * - LE_OK if successful.
346  * - LE_OVERFLOW if the stack size requested is too small.
347  * - LE_OUT_OF_RANGE if the stack size requested is too large.
348  */
349 //--------------------------------------------------------------------------------------------------
351 (
352  le_thread_Ref_t thread, ///< [IN]
353  size_t size ///< [IN] Stack size, in bytes. May be rounded up to the
354  /// nearest virtual memory page size.
355 );
356 
357 
358 //--------------------------------------------------------------------------------------------------
359 /**
360  * Define a static thread stack region.
361  *
362  * @param name Stack variable name.
363  * @param bytes Number of bytes in the stack.
364  */
365 //--------------------------------------------------------------------------------------------------
366 #define LE_THREAD_DEFINE_STATIC_STACK(name, bytes) \
367  static uint8_t _thread_stack_##name[LE_THREAD_STACK_EXTRA_SIZE + \
368  ((bytes) < LE_THREAD_STACK_MIN_SIZE ? LE_THREAD_STACK_MIN_SIZE : (bytes))] \
369  __attribute__((aligned(LE_THREAD_STACK_ALIGNMENT)))
370 
371 
372 //--------------------------------------------------------------------------------------------------
373 /**
374  * Set a static stack for a thread.
375  *
376  * @see le_thread_SetStack() for details.
377  *
378  * @param thread Thread to set the stack for.
379  * @param name Stack variable name that was previously passed to
380  * LE_THREAD_DEFINE_STATIC_STACK().
381  *
382  * @return Return value of le_thread_SetStack().
383  */
384 //--------------------------------------------------------------------------------------------------
385 #define LE_THREAD_SET_STATIC_STACK(thread, name) \
386  le_thread_SetStack((thread), &_thread_stack_##name, sizeof(_thread_stack_##name))
387 
388 
389 //--------------------------------------------------------------------------------------------------
390 /**
391  * Sets the stack of a thread.
392  *
393  * Setting the stack explicitly allows the caller to control the memory allocation of the thread's
394  * stack and, in some cases, control data. This can be useful for allocating the space out of
395  * static memory, for example.
396  *
397  * The macro LE_THREAD_DEFINE_STATIC_STACK() may be used to create a statically allocated stack for
398  * use with this function, and LE_THREAD_SET_STATIC_STACK() may be used to call it properly.
399  *
400  * @attention In general, this function is only useful on embedded, RTOS based systems in order to
401  * perform up-front allocation of thread resources. On more capable systems it is
402  * safer to allow the operating system to set up the stack (which may optionally be
403  * sized using le_thread_SetStackSize()).
404  *
405  * @return
406  * - LE_OK if successful.
407  * - LE_BAD_PARAMETER if the size or stack is invalid (NULL or improperly aligned).
408  */
409 //--------------------------------------------------------------------------------------------------
411 (
412  le_thread_Ref_t thread, ///< [IN] Thread instance.
413  void *stack, ///< [IN] Address of the lowest byte of the stack. This must be
414  /// appropriately aligned (LE_THREAD_DEFINE_STATIC_STACK()
415  /// will do this).
416  size_t size ///< [IN] Stack size, in bytes.
417 );
418 
419 
420 //--------------------------------------------------------------------------------------------------
421 /**
422  * Makes a thread "joinable", meaning that when it finishes, it will remain in existence until
423  * another thread "joins" with it by calling le_thread_Join(). By default, threads are not
424  * joinable and will be destroyed automatically when they finish.
425  */
426 //--------------------------------------------------------------------------------------------------
428 (
429  le_thread_Ref_t thread ///< [IN]
430 );
431 
432 
433 //--------------------------------------------------------------------------------------------------
434 /**
435  * Starts a new Legato execution thread. After creating the thread, you have the opportunity
436  * to set attributes before it starts. It won't start until le_thread_Start() is called.
437  */
438 //--------------------------------------------------------------------------------------------------
439 void le_thread_Start
440 (
441  le_thread_Ref_t thread ///< [IN]
442 );
443 
444 
445 //--------------------------------------------------------------------------------------------------
446 /**
447  * "Joins" the calling thread with another thread. Blocks the calling thread until the other
448  * thread finishes.
449  *
450  * After a thread has been joined with, its thread reference is no longer valid and must never
451  * be used again.
452  *
453  * The other thread's result value (the value it returned from its main function or passed into
454  * le_thread_Exit()) can be obtained.
455  *
456  * @return
457  * - LE_OK if successful.
458  * - LE_DEADLOCK if a thread tries to join with itself or two threads try to join each other.
459  * - LE_NOT_FOUND if the other thread doesn't exist.
460  * - LE_FAULT if the other thread can't be joined with.
461  *
462  * @warning The other thread must be "joinable". See le_thread_SetJoinable();
463  *
464  * @warning It's an error for two or more threads try to join with the same thread.
465  */
466 //--------------------------------------------------------------------------------------------------
468 (
469  le_thread_Ref_t thread, ///< [IN]
470  void** resultValuePtr ///< [OUT] Ptr to where the finished thread's result value
471  /// will be stored. Can be NULL if the result is
472  /// not needed.
473 );
474 
475 
476 //--------------------------------------------------------------------------------------------------
477 /**
478  * Terminates the calling thread.
479  */
480 //--------------------------------------------------------------------------------------------------
481 void le_thread_Exit
482 (
483  void* resultValue ///< [IN] Result value. If this thread is joinable, this result
484  /// can be obtained by another thread calling le_thread_Join()
485  /// on this thread.
486 );
487 
488 
489 //--------------------------------------------------------------------------------------------------
490 /**
491  * Tells another thread to terminate. Returns immediately, but the termination of the
492  * thread happens asynchronously and is not guaranteed to occur when this function returns.
493  *
494  * @note This function is not available on RTOS.
495 
496  *
497  * @return
498  * - LE_OK if successful.
499  * - LE_NOT_FOUND if the thread doesn't exist.
500  */
501 //--------------------------------------------------------------------------------------------------
503 (
504  le_thread_Ref_t threadToCancel ///< [IN] Thread to cancel.
505 );
506 
507 
508 //--------------------------------------------------------------------------------------------------
509 /**
510  * Causes the calling thread to sleep.
511  *
512  * @return
513  * - 0 if the sleep is successful.
514  * - -1 if the call is interrupted by a signal handler or encounters an error.
515  *
516  * @note This function is not a full equivalence of nanosleep() as the remaining sleep time will not
517  * be available to the caller if nanosleep() returns due to being interrupted by a signal.
518  */
519 //--------------------------------------------------------------------------------------------------
520 int le_thread_Sleep
521 (
522  unsigned int seconds ///< [IN] Time to sleep in seconds.
523 );
524 
525 
526 //--------------------------------------------------------------------------------------------------
527 /**
528  * Gets the calling thread's thread reference.
529  *
530  * @return Calling thread's thread reference.
531  */
532 //--------------------------------------------------------------------------------------------------
534 (
535  void
536 );
537 
538 
539 //--------------------------------------------------------------------------------------------------
540 /**
541  * Gets the name of a given thread.
542  */
543 //--------------------------------------------------------------------------------------------------
545 (
546  le_thread_Ref_t threadRef, ///< [IN] Thread to get the name for.
547  char* buffPtr, ///< [OUT] Buffer to store the name of the thread.
548  size_t buffSize ///< [IN] Size of the buffer.
549 );
550 
551 
552 //--------------------------------------------------------------------------------------------------
553 /**
554  * Gets the name of the calling thread.
555  */
556 //--------------------------------------------------------------------------------------------------
557 const char* le_thread_GetMyName
558 (
559  void
560 );
561 
562 
563 //--------------------------------------------------------------------------------------------------
564 /**
565  * Destructor functions for threads must look like this:
566  *
567  * @param context [IN] Context parameter that was passed into le_thread_SetDestructor() when
568  * this destructor was registered.
569  */
570 //--------------------------------------------------------------------------------------------------
571 typedef void (* le_thread_Destructor_t)
572 (
573  void* context ///< [IN] Context parameter that was passed into le_thread_SetDestructor() when
574  /// this destructor was registered.
575 );
576 
577 
578 //--------------------------------------------------------------------------------------------------
579 /**
580  * Reference to a registered destructor function.
581  */
582 //--------------------------------------------------------------------------------------------------
583 typedef struct le_thread_Destructor* le_thread_DestructorRef_t;
584 
585 
586 //--------------------------------------------------------------------------------------------------
587 /**
588  * Registers a destructor function for the calling thread. The destructor will be called by that
589  * thread just before it terminates.
590  *
591  * A thread can register (or remove) its own destructor functions any time.
592  *
593  * @return Reference to the destructor that can be passed to le_thread_RemoveDestructor().
594  *
595  * See @ref threadDestructors for more information on destructors.
596  */
597 //--------------------------------------------------------------------------------------------------
599 (
600  le_thread_Destructor_t destructor, ///< [IN] Function to be called.
601  void* context ///< [IN] Parameter to pass to the destructor.
602 );
603 
604 
605 //--------------------------------------------------------------------------------------------------
606 /**
607  * Registers a destructor function for a child thread. The destructor will be called by the
608  * child thread just before it terminates.
609  *
610  * This can only be done before the child thread is started. After that, only the child thread
611  * can add its own destructors.
612  *
613  * The reason for allowing another thread to register a destructor function is to
614  * avoid a race condition that can cause resource leakage when a parent thread passes dynamically
615  * allocated resources to threads that they create. This is only a problem if the child thread
616  * is expected to release the resources when they are finished with them, and the child thread
617  * may get cancelled at any time.
618  *
619  * For example, a thread @e T1 could allocate an object from a memory pool, create a thread @e T2,
620  * and pass that object to @e T2 for processing and release. @e T2 could register a destructor
621  * function to release the resource whenever it terminates, whether through cancellation or
622  * normal exit. But, if it's possible that @e T2 could get cancelled before it even has a
623  * chance to register a destructor function for itself, the memory pool object could never get
624  * released. So, we allow @e T1 to register a destructor function for @e T2 before starting @e T2.
625  *
626  * See @ref threadDestructors for more information on destructors.
627  */
628 //--------------------------------------------------------------------------------------------------
630 (
631  le_thread_Ref_t thread, ///< [IN] Thread to attach the destructor to.
632  le_thread_Destructor_t destructor, ///< [IN] Function to be called.
633  void* context ///< [IN] Parameter to pass to the destructor.
634 );
635 
636 
637 //--------------------------------------------------------------------------------------------------
638 /**
639  * Removes a destructor function from the calling thread's list of destructors.
640  */
641 //--------------------------------------------------------------------------------------------------
643 (
644  le_thread_DestructorRef_t destructor ///< [in] Reference to the destructor to remove.
645 );
646 
647 //--------------------------------------------------------------------------------------------------
648 /**
649  * Gets the calling thread's component instance data record.
650  */
651 //--------------------------------------------------------------------------------------------------
653 (
654  void
655 );
656 
657 //--------------------------------------------------------------------------------------------------
658 /**
659  * Sets the calling thread's component instance data record.
660  */
661 //--------------------------------------------------------------------------------------------------
663 (
664  const _le_cdata_ThreadRec_t *cdataPtr ///< CData instance for the thread.
665 );
666 
667 #if LE_CONFIG_THREAD_NAMES_ENABLED
668 //--------------------------------------------------------------------------------------------------
669 /**
670  * Initialize the thread-specific data needed by the Legato framework for the calling thread.
671  *
672  * This is used to turn a non-Legato thread (a thread that was created using a non-Legato API,
673  * such as pthread_create() ) into a Legato thread.
674  *
675  * @param[in] name A name for the thread (will be copied, so can be temporary).
676  *
677  * @note This is not needed if the thread was started using le_thread_Start().
678  **/
679 //--------------------------------------------------------------------------------------------------
681 (
682  const char* name
683 );
684 #else /* if not LE_CONFIG_THREAD_NAMES_ENABLED */
685 /// @cond HIDDEN_IN_USER_DOCS
686 //--------------------------------------------------------------------------------------------------
687 /**
688  * Internal function used to implement le_thread_InitLegatoThreadData().
689  */
690 //--------------------------------------------------------------------------------------------------
691 void _le_thread_InitLegatoThreadData(void);
692 /// @endcond
693 //--------------------------------------------------------------------------------------------------
694 /**
695  * Initialize the thread-specific data needed by the Legato framework for the calling thread.
696  *
697  * This is used to turn a non-Legato thread (a thread that was created using a non-Legato API,
698  * such as pthread_create() ) into a Legato thread.
699  *
700  * @param[in] name A name for the thread (will be copied, so can be temporary).
701  *
702  * @note This is not needed if the thread was started using le_thread_Start().
703  **/
704 //--------------------------------------------------------------------------------------------------
706 (
707  const char* name
708 )
709 {
710  _le_thread_InitLegatoThreadData();
711 }
712 #endif /* end LE_CONFIG_THREAD_NAMES_ENABLED */
713 
714 
715 //--------------------------------------------------------------------------------------------------
716 /**
717  * Clean-up the thread-specific data that was initialized using le_thread_InitLegatoThreadData().
718  *
719  * To prevent memory leaks, this must be called by the thread when it dies (unless the whole
720  * process is dying).
721  *
722  * @note This is not needed if the thread was started using le_thread_Start().
723  **/
724 //--------------------------------------------------------------------------------------------------
726 (
727  void
728 );
729 
730 
731 #endif // LEGATO_THREAD_INCLUDE_GUARD
LE_FULL_API le_result_t le_thread_Cancel(le_thread_Ref_t threadToCancel)
struct le_thread * le_thread_Ref_t
Definition: le_thread.h:180
void *(* le_thread_MainFunc_t)(void *context)
Definition: le_thread.h:259
Real-time priority level 32.
Definition: le_thread.h:240
Real-time priority level 8.
Definition: le_thread.h:216
Real-time priority level 2.
Definition: le_thread.h:210
Definition: le_cdata.h:57
Real-time priority level 3.
Definition: le_thread.h:211
Real-time priority level 22.
Definition: le_thread.h:230
le_result_t
Definition: le_basics.h:46
void le_thread_RemoveDestructor(le_thread_DestructorRef_t destructor)
struct le_thread_Destructor * le_thread_DestructorRef_t
Definition: le_thread.h:583
Real-time priority level 10.
Definition: le_thread.h:218
le_result_t le_thread_SetStackSize(le_thread_Ref_t thread, size_t size)
le_result_t le_thread_SetPriority(le_thread_Ref_t thread, le_thread_Priority_t priority)
Real-time priority level 25.
Definition: le_thread.h:233
Real-time priority level 12.
Definition: le_thread.h:220
Real-time priority level 28.
Definition: le_thread.h:236
Real-time priority level 7.
Definition: le_thread.h:215
Real-time priority level 27.
Definition: le_thread.h:235
Real-time priority level 26.
Definition: le_thread.h:234
Real-time priority level 29.
Definition: le_thread.h:237
Real-time priority level 23.
Definition: le_thread.h:231
Real-time priority level 14.
Definition: le_thread.h:222
Real-time priority level 16.
Definition: le_thread.h:224
void le_thread_GetName(le_thread_Ref_t threadRef, char *buffPtr, size_t buffSize)
le_result_t le_thread_Join(le_thread_Ref_t thread, void **resultValuePtr)
void le_thread_SetJoinable(le_thread_Ref_t thread)
le_thread_Ref_t le_thread_GetCurrent(void)
Real-time priority level 17.
Definition: le_thread.h:225
Real-time priority level 9.
Definition: le_thread.h:217
le_thread_Priority_t
Definition: le_thread.h:196
Medium, non-real-time priority level. THIS IS THE DEFAULT.
Definition: le_thread.h:205
void _le_thread_SetCDataInstancePtr(const _le_cdata_ThreadRec_t *cdataPtr)
Real-time priority level 15.
Definition: le_thread.h:223
le_result_t le_thread_SetStack(le_thread_Ref_t thread, void *stack, size_t size)
Real-time priority level 20.
Definition: le_thread.h:228
const _le_cdata_ThreadRec_t * _le_thread_GetCDataInstancePtr(void)
Real-time priority level 6.
Definition: le_thread.h:214
void le_thread_CleanupLegatoThreadData(void)
#define LE_FULL_API
Definition: le_apiFeatures.h:40
Real-time priority level 24.
Definition: le_thread.h:232
void le_thread_InitLegatoThreadData(const char *name)
Real-time priority level 21.
Definition: le_thread.h:229
void le_thread_Exit(void *resultValue)
le_thread_DestructorRef_t le_thread_AddDestructor(le_thread_Destructor_t destructor, void *context)
Real-time priority level 31.
Definition: le_thread.h:239
void le_thread_AddChildDestructor(le_thread_Ref_t thread, le_thread_Destructor_t destructor, void *context)
Definition: le_thread.h:200
Real-time priority level 18.
Definition: le_thread.h:226
Real-time priority level 4.
Definition: le_thread.h:212
const char * le_thread_GetMyName(void)
void(* le_thread_Destructor_t)(void *context)
Definition: le_thread.h:572
Lowest priority level. Only runs when nothing else to do.
Definition: le_thread.h:198
void le_thread_Start(le_thread_Ref_t thread)
Definition: le_thread.h:208
le_thread_Ref_t le_thread_Create(const char *name, le_thread_MainFunc_t mainFunc, void *context)
High, non-real-time priority level.
Definition: le_thread.h:206
Real-time priority level 5.
Definition: le_thread.h:213
Real-time priority level 13.
Definition: le_thread.h:221
Real-time priority level 11.
Definition: le_thread.h:219
Real-time priority level 30.
Definition: le_thread.h:238
Real-time priority level 19.
Definition: le_thread.h:227
int le_thread_Sleep(unsigned int seconds)
#define LE_DECLARE_INLINE
Definition: le_basics.h:333