le_thread.h

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 //--------------------------------------------------------------------------------------------------
172 /**
173  * Reference to a thread of execution.
174  *
175  * @note NULL can be used as an invalid value.
176  */
177 //--------------------------------------------------------------------------------------------------
178 typedef struct le_thread* le_thread_Ref_t;
179 
180 
181 //--------------------------------------------------------------------------------------------------
182 /**
183  * Thread priority levels.
184  *
185  * Real-time priority levels should be avoided unless absolutely necessary for the application.
186  * They are privileged levels and will therefore not be allowed unless the application is executed
187  * by an identity with the appropriate permissions. If a thread running at a real-time priority
188  * level does not block, no other thread at a lower priority level will run, so be careful with
189  * these.
190  *
191  * @note Higher numbers are higher priority.
192  */
193 //--------------------------------------------------------------------------------------------------
194 typedef enum
195 {
196  LE_THREAD_PRIORITY_IDLE = 0, ///< Lowest priority level. Only runs when nothing else to do.
197 
198  LE_THREAD_PRIORITY_LOW, ///< Low, non-realtime priority level.
199  ///< Low, medium, high: intended for normal processes that
200  ///< contend for the CPU. Processes with these priorities don't
201  ///< preempt each other, but their priorities affect how they're
202  ///< inserted into the scheduling queue (high to low).
203  LE_THREAD_PRIORITY_MEDIUM, ///< Medium, non-real-time priority level. THIS IS THE DEFAULT.
204  LE_THREAD_PRIORITY_HIGH, ///< High, non-real-time priority level.
205 
206  LE_THREAD_PRIORITY_RT_1, ///< Real-time priority level 1. The lowest realtime priority
207  /// level.
208  LE_THREAD_PRIORITY_RT_2, ///< Real-time priority level 2.
209  LE_THREAD_PRIORITY_RT_3, ///< Real-time priority level 3.
210  LE_THREAD_PRIORITY_RT_4, ///< Real-time priority level 4.
211  LE_THREAD_PRIORITY_RT_5, ///< Real-time priority level 5.
212  LE_THREAD_PRIORITY_RT_6, ///< Real-time priority level 6.
213  LE_THREAD_PRIORITY_RT_7, ///< Real-time priority level 7.
214  LE_THREAD_PRIORITY_RT_8, ///< Real-time priority level 8.
215  LE_THREAD_PRIORITY_RT_9, ///< Real-time priority level 9.
216  LE_THREAD_PRIORITY_RT_10, ///< Real-time priority level 10.
217  LE_THREAD_PRIORITY_RT_11, ///< Real-time priority level 11.
218  LE_THREAD_PRIORITY_RT_12, ///< Real-time priority level 12.
219  LE_THREAD_PRIORITY_RT_13, ///< Real-time priority level 13.
220  LE_THREAD_PRIORITY_RT_14, ///< Real-time priority level 14.
221  LE_THREAD_PRIORITY_RT_15, ///< Real-time priority level 15.
222  LE_THREAD_PRIORITY_RT_16, ///< Real-time priority level 16.
223  LE_THREAD_PRIORITY_RT_17, ///< Real-time priority level 17.
224  LE_THREAD_PRIORITY_RT_18, ///< Real-time priority level 18.
225  LE_THREAD_PRIORITY_RT_19, ///< Real-time priority level 19.
226  LE_THREAD_PRIORITY_RT_20, ///< Real-time priority level 20.
227  LE_THREAD_PRIORITY_RT_21, ///< Real-time priority level 21.
228  LE_THREAD_PRIORITY_RT_22, ///< Real-time priority level 22.
229  LE_THREAD_PRIORITY_RT_23, ///< Real-time priority level 23.
230  LE_THREAD_PRIORITY_RT_24, ///< Real-time priority level 24.
231  LE_THREAD_PRIORITY_RT_25, ///< Real-time priority level 25.
232  LE_THREAD_PRIORITY_RT_26, ///< Real-time priority level 26.
233  LE_THREAD_PRIORITY_RT_27, ///< Real-time priority level 27.
234  LE_THREAD_PRIORITY_RT_28, ///< Real-time priority level 28.
235  LE_THREAD_PRIORITY_RT_29, ///< Real-time priority level 29.
236  LE_THREAD_PRIORITY_RT_30, ///< Real-time priority level 30.
237  LE_THREAD_PRIORITY_RT_31, ///< Real-time priority level 31.
238  LE_THREAD_PRIORITY_RT_32 ///< Real-time priority level 32.
239 }
240 le_thread_Priority_t;
241 
242 #define LE_THREAD_PRIORITY_RT_LOWEST LE_THREAD_PRIORITY_RT_1 ///< Lowest real-time priority.
243 #define LE_THREAD_PRIORITY_RT_HIGHEST LE_THREAD_PRIORITY_RT_32 ///< Highest real-time priority.
244 
245 //--------------------------------------------------------------------------------------------------
246 /**
247  * @deprecated
248  *
249  * LE_THREAD_PRIORITY_NORMAL is deprecated, use LE_THREAD_PRIORITY_MEDIUM instead.
250  */
251 //--------------------------------------------------------------------------------------------------
252 #define LE_THREAD_PRIORITY_NORMAL LE_THREAD_PRIORITY_MEDIUM
253 
254 
255 //--------------------------------------------------------------------------------------------------
256 /**
257  * Main functions for threads must look like this:
258  *
259  * @param context [IN] Context value that was passed to le_thread_Create().
260  *
261  * @return Thread result value. If the thread is joinable, then this value can be obtained by
262  * another thread through a call to vt_thread_Join(). Otherwise, the return value is ignored.
263  */
264 //--------------------------------------------------------------------------------------------------
265 typedef void* (* le_thread_MainFunc_t)
266 (
267  void* context ///< See parameter documentation above.
268 );
269 
270 
271 #if LE_CONFIG_THREAD_NAMES_ENABLED
272 //--------------------------------------------------------------------------------------------------
273 /**
274  * Creates a new Legato thread of execution. After creating the thread, you have the opportunity
275  * to set attributes before it starts. It won't start until le_thread_Start() is called.
276  *
277  * @param[in] name Thread name (will be copied, so can be temporary).
278  * @param[in] mainFunc Thread's main function.
279  * @param[in] context Value to pass to mainFunc when it is called.
280  *
281  * @return A reference to the thread (doesn't return if fails).
282  */
283 //--------------------------------------------------------------------------------------------------
284 le_thread_Ref_t le_thread_Create
285 (
286  const char* name,
287  le_thread_MainFunc_t mainFunc,
288  void* context
289 );
290 #else /* if not LE_CONFIG_THREAD_NAMES_ENABLED */
291 /// @cond HIDDEN_IN_USER_DOCS
292 //--------------------------------------------------------------------------------------------------
293 /**
294  * Internal function used to implement le_thread_Create().
295  */
296 //--------------------------------------------------------------------------------------------------
297 le_thread_Ref_t _le_thread_Create(le_thread_MainFunc_t mainFunc, void* context);
298 /// @endcond
299 //--------------------------------------------------------------------------------------------------
300 /**
301  * Creates a new Legato thread of execution. After creating the thread, you have the opportunity
302  * to set attributes before it starts. It won't start until le_thread_Start() is called.
303  *
304  * @param[in] name Thread name (will be copied, so can be temporary).
305  * @param[in] mainFunc Thread's main function.
306  * @param[in] context Value to pass to mainFunc when it is called.
307  *
308  * @return A reference to the thread (doesn't return if fails).
309  */
310 //--------------------------------------------------------------------------------------------------
311 LE_DECLARE_INLINE le_thread_Ref_t le_thread_Create
312 (
313  const char* name,
314  le_thread_MainFunc_t mainFunc,
315  void* context
316 )
317 {
318  return _le_thread_Create(mainFunc, context);
319 }
320 #endif /* end LE_CONFIG_THREAD_NAMES_ENABLED */
321 
322 
323 //--------------------------------------------------------------------------------------------------
324 /**
325  * Sets the priority of a thread.
326  *
327  * @return
328  * - LE_OK if successful.
329  * - LE_OUT_OF_RANGE if the priority level requested is out of range.
330  */
331 //--------------------------------------------------------------------------------------------------
332 le_result_t le_thread_SetPriority
333 (
334  le_thread_Ref_t thread, ///< [IN]
335  le_thread_Priority_t priority ///< [IN]
336 );
337 
338 
339 //--------------------------------------------------------------------------------------------------
340 /**
341  * Sets the stack size of a thread.
342  *
343  * @note It's generally not necessary to set the stack size. Some reasons why you might are:
344  * - to increase it beyond the system's default stack size to prevent overflow
345  * for a thread that makes extremely heavy use of the stack;
346  * - to decrease it to save memory when:
347  * - running in a system that does not support virtual memory
348  * - the thread has very tight real-time constraints that require that the stack
349  * memory be locked into physical memory to avoid page faults.
350  *
351  * @return
352  * - LE_OK if successful.
353  * - LE_OVERFLOW if the stack size requested is too small.
354  * - LE_OUT_OF_RANGE if the stack size requested is too large.
355  */
356 //--------------------------------------------------------------------------------------------------
357 le_result_t le_thread_SetStackSize
358 (
359  le_thread_Ref_t thread, ///< [IN]
360  size_t size ///< [IN] Stack size, in bytes. May be rounded up to the
361  /// nearest virtual memory page size.
362 );
363 
364 
365 //--------------------------------------------------------------------------------------------------
366 /**
367  * Define a static thread stack region.
368  *
369  * @param name Stack variable name.
370  * @param bytes Number of bytes in the stack.
371  */
372 //--------------------------------------------------------------------------------------------------
373 #define LE_THREAD_DEFINE_STATIC_STACK(name, bytes) \
374  static uint8_t _thread_stack_##name[LE_THREAD_STACK_EXTRA_SIZE + \
375  ((bytes) < LE_THREAD_STACK_MIN_SIZE ? LE_THREAD_STACK_MIN_SIZE : (bytes))] \
376  __attribute__((aligned(LE_THREAD_STACK_ALIGNMENT)))
377 
378 
379 //--------------------------------------------------------------------------------------------------
380 /**
381  * Set a static stack for a thread.
382  *
383  * @see le_thread_SetStack() for details.
384  *
385  * @param thread Thread to set the stack for.
386  * @param name Stack variable name that was previously passed to
387  * LE_THREAD_DEFINE_STATIC_STACK().
388  *
389  * @return Return value of le_thread_SetStack().
390  */
391 //--------------------------------------------------------------------------------------------------
392 #define LE_THREAD_SET_STATIC_STACK(thread, name) \
393  le_thread_SetStack((thread), &_thread_stack_##name, sizeof(_thread_stack_##name))
394 
395 
396 //--------------------------------------------------------------------------------------------------
397 /**
398  * Sets the stack of a thread.
399  *
400  * Setting the stack explicitly allows the caller to control the memory allocation of the thread's
401  * stack and, in some cases, control data. This can be useful for allocating the space out of
402  * static memory, for example.
403  *
404  * The macro LE_THREAD_DEFINE_STATIC_STACK() may be used to create a statically allocated stack for
405  * use with this function, and LE_THREAD_SET_STATIC_STACK() may be used to call it properly.
406  *
407  * @attention In general, this function is only useful on embedded, RTOS based systems in order to
408  * perform up-front allocation of thread resources. On more capable systems it is
409  * safer to allow the operating system to set up the stack (which may optionally be
410  * sized using le_thread_SetStackSize()).
411  *
412  * @return
413  * - LE_OK if successful.
414  * - LE_BAD_PARAMETER if the size or stack is invalid (NULL or improperly aligned).
415  */
416 //--------------------------------------------------------------------------------------------------
417 le_result_t le_thread_SetStack
418 (
419  le_thread_Ref_t thread, ///< [IN] Thread instance.
420  void *stack, ///< [IN] Address of the lowest byte of the stack. This must be
421  /// appropriately aligned (LE_THREAD_DEFINE_STATIC_STACK()
422  /// will do this).
423  size_t size ///< [IN] Stack size, in bytes.
424 );
425 
426 
427 //--------------------------------------------------------------------------------------------------
428 /**
429  * Makes a thread "joinable", meaning that when it finishes, it will remain in existence until
430  * another thread "joins" with it by calling le_thread_Join(). By default, threads are not
431  * joinable and will be destroyed automatically when they finish.
432  */
433 //--------------------------------------------------------------------------------------------------
434 void le_thread_SetJoinable
435 (
436  le_thread_Ref_t thread ///< [IN]
437 );
438 
439 
440 //--------------------------------------------------------------------------------------------------
441 /**
442  * Starts a new Legato execution thread. After creating the thread, you have the opportunity
443  * to set attributes before it starts. It won't start until le_thread_Start() is called.
444  */
445 //--------------------------------------------------------------------------------------------------
446 void le_thread_Start
447 (
448  le_thread_Ref_t thread ///< [IN]
449 );
450 
451 
452 //--------------------------------------------------------------------------------------------------
453 /**
454  * "Joins" the calling thread with another thread. Blocks the calling thread until the other
455  * thread finishes.
456  *
457  * After a thread has been joined with, its thread reference is no longer valid and must never
458  * be used again.
459  *
460  * The other thread's result value (the value it returned from its main function or passed into
461  * le_thread_Exit()) can be obtained.
462  *
463  * @return
464  * - LE_OK if successful.
465  * - LE_DEADLOCK if a thread tries to join with itself or two threads try to join each other.
466  * - LE_NOT_FOUND if the other thread doesn't exist.
467  * - LE_NOT_POSSIBLE if the other thread can't be joined with.
468  * @deprecated the result code LE_NOT_POSSIBLE is scheduled to be removed before 15.04
469  *
470  * @warning The other thread must be "joinable". See le_thread_SetJoinable();
471  *
472  * @warning It's an error for two or more threads try to join with the same thread.
473  */
474 //--------------------------------------------------------------------------------------------------
475 le_result_t le_thread_Join
476 (
477  le_thread_Ref_t thread, ///< [IN]
478  void** resultValuePtr ///< [OUT] Ptr to where the finished thread's result value
479  /// will be stored. Can be NULL if the result is
480  /// not needed.
481 );
482 
483 
484 //--------------------------------------------------------------------------------------------------
485 /**
486  * Terminates the calling thread.
487  */
488 //--------------------------------------------------------------------------------------------------
489 void le_thread_Exit
490 (
491  void* resultValue ///< [IN] Result value. If this thread is joinable, this result
492  /// can be obtained by another thread calling le_thread_Join()
493  /// on this thread.
494 );
495 
496 
497 //--------------------------------------------------------------------------------------------------
498 /**
499  * Tells another thread to terminate. Returns immediately, but the termination of the
500  * thread happens asynchronously and is not guaranteed to occur when this function returns.
501  *
502  * @note This function is not available on RTOS.
503 
504  *
505  * @return
506  * - LE_OK if successful.
507  * - LE_NOT_FOUND if the thread doesn't exist.
508  */
509 //--------------------------------------------------------------------------------------------------
510 LE_FULL_API le_result_t le_thread_Cancel
511 (
512  le_thread_Ref_t threadToCancel ///< [IN] Thread to cancel.
513 );
514 
515 
516 //--------------------------------------------------------------------------------------------------
517 /**
518  * Gets the calling thread's thread reference.
519  *
520  * @return Calling thread's thread reference.
521  */
522 //--------------------------------------------------------------------------------------------------
523 le_thread_Ref_t le_thread_GetCurrent
524 (
525  void
526 );
527 
528 
529 //--------------------------------------------------------------------------------------------------
530 /**
531  * Gets the name of a given thread.
532  */
533 //--------------------------------------------------------------------------------------------------
534 void le_thread_GetName
535 (
536  le_thread_Ref_t threadRef, ///< [IN] Thread to get the name for.
537  char* buffPtr, ///< [OUT] Buffer to store the name of the thread.
538  size_t buffSize ///< [IN] Size of the buffer.
539 );
540 
541 
542 //--------------------------------------------------------------------------------------------------
543 /**
544  * Gets the name of the calling thread.
545  */
546 //--------------------------------------------------------------------------------------------------
547 const char* le_thread_GetMyName
548 (
549  void
550 );
551 
552 
553 //--------------------------------------------------------------------------------------------------
554 /**
555  * Destructor functions for threads must look like this:
556  *
557  * @param context [IN] Context parameter that was passed into le_thread_SetDestructor() when
558  * this destructor was registered.
559  */
560 //--------------------------------------------------------------------------------------------------
561 typedef void (* le_thread_Destructor_t)
562 (
563  void* context ///< [IN] Context parameter that was passed into le_thread_SetDestructor() when
564  /// this destructor was registered.
565 );
566 
567 
568 //--------------------------------------------------------------------------------------------------
569 /**
570  * Reference to a registered destructor function.
571  */
572 //--------------------------------------------------------------------------------------------------
573 typedef struct le_thread_Destructor* le_thread_DestructorRef_t;
574 
575 
576 //--------------------------------------------------------------------------------------------------
577 /**
578  * Registers a destructor function for the calling thread. The destructor will be called by that
579  * thread just before it terminates.
580  *
581  * A thread can register (or remove) its own destructor functions any time.
582  *
583  * @return Reference to the destructor that can be passed to le_thread_RemoveDestructor().
584  *
585  * See @ref threadDestructors for more information on destructors.
586  */
587 //--------------------------------------------------------------------------------------------------
588 le_thread_DestructorRef_t le_thread_AddDestructor
589 (
590  le_thread_Destructor_t destructor, ///< [IN] Function to be called.
591  void* context ///< [IN] Parameter to pass to the destructor.
592 );
593 
594 
595 //--------------------------------------------------------------------------------------------------
596 /**
597  * Registers a destructor function for a child thread. The destructor will be called by the
598  * child thread just before it terminates.
599  *
600  * This can only be done before the child thread is started. After that, only the child thread
601  * can add its own destructors.
602  *
603  * The reason for allowing another thread to register a destructor function is to
604  * avoid a race condition that can cause resource leakage when a parent thread passes dynamically
605  * allocated resources to threads that they create. This is only a problem if the child thread
606  * is expected to release the resources when they are finished with them, and the child thread
607  * may get cancelled at any time.
608  *
609  * For example, a thread @e T1 could allocate an object from a memory pool, create a thread @e T2,
610  * and pass that object to @e T2 for processing and release. @e T2 could register a destructor
611  * function to release the resource whenever it terminates, whether through cancellation or
612  * normal exit. But, if it's possible that @e T2 could get cancelled before it even has a
613  * chance to register a destructor function for itself, the memory pool object could never get
614  * released. So, we allow @e T1 to register a destructor function for @e T2 before starting @e T2.
615  *
616  * See @ref threadDestructors for more information on destructors.
617  */
618 //--------------------------------------------------------------------------------------------------
619 void le_thread_AddChildDestructor
620 (
621  le_thread_Ref_t thread, ///< [IN] Thread to attach the destructor to.
622  le_thread_Destructor_t destructor, ///< [IN] Function to be called.
623  void* context ///< [IN] Parameter to pass to the destructor.
624 );
625 
626 
627 //--------------------------------------------------------------------------------------------------
628 /**
629  * Removes a destructor function from the calling thread's list of destructors.
630  */
631 //--------------------------------------------------------------------------------------------------
632 void le_thread_RemoveDestructor
633 (
634  le_thread_DestructorRef_t destructor ///< [in] Reference to the destructor to remove.
635 );
636 
637 //--------------------------------------------------------------------------------------------------
638 /**
639  * Gets the calling thread's component instance data record.
640  */
641 //--------------------------------------------------------------------------------------------------
642 const _le_cdata_ThreadRec_t *_le_thread_GetCDataInstancePtr
643 (
644  void
645 );
646 
647 //--------------------------------------------------------------------------------------------------
648 /**
649  * Sets the calling thread's component instance data record.
650  */
651 //--------------------------------------------------------------------------------------------------
652 void _le_thread_SetCDataInstancePtr
653 (
654  const _le_cdata_ThreadRec_t *cdataPtr ///< CData instance for the thread.
655 );
656 
657 #if LE_CONFIG_THREAD_NAMES_ENABLED
658 //--------------------------------------------------------------------------------------------------
659 /**
660  * Initialize the thread-specific data needed by the Legato framework for the calling thread.
661  *
662  * This is used to turn a non-Legato thread (a thread that was created using a non-Legato API,
663  * such as pthread_create() ) into a Legato thread.
664  *
665  * @param[in] name A name for the thread (will be copied, so can be temporary).
666  *
667  * @note This is not needed if the thread was started using le_thread_Start().
668  **/
669 //--------------------------------------------------------------------------------------------------
670 void le_thread_InitLegatoThreadData
671 (
672  const char* name
673 );
674 #else /* if not LE_CONFIG_THREAD_NAMES_ENABLED */
675 /// @cond HIDDEN_IN_USER_DOCS
676 //--------------------------------------------------------------------------------------------------
677 /**
678  * Internal function used to implement le_thread_InitLegatoThreadData().
679  */
680 //--------------------------------------------------------------------------------------------------
681 void _le_thread_InitLegatoThreadData(void);
682 /// @endcond
683 //--------------------------------------------------------------------------------------------------
684 /**
685  * Initialize the thread-specific data needed by the Legato framework for the calling thread.
686  *
687  * This is used to turn a non-Legato thread (a thread that was created using a non-Legato API,
688  * such as pthread_create() ) into a Legato thread.
689  *
690  * @param[in] name A name for the thread (will be copied, so can be temporary).
691  *
692  * @note This is not needed if the thread was started using le_thread_Start().
693  **/
694 //--------------------------------------------------------------------------------------------------
695 LE_DECLARE_INLINE void le_thread_InitLegatoThreadData
696 (
697  const char* name
698 )
699 {
700  _le_thread_InitLegatoThreadData();
701 }
702 #endif /* end LE_CONFIG_THREAD_NAMES_ENABLED */
703 
704 
705 //--------------------------------------------------------------------------------------------------
706 /**
707  * Clean-up the thread-specific data that was initialized using le_thread_InitLegatoThreadData().
708  *
709  * To prevent memory leaks, this must be called by the thread when it dies (unless the whole
710  * process is dying).
711  *
712  * @note This is not needed if the thread was started using le_thread_Start().
713  **/
714 //--------------------------------------------------------------------------------------------------
715 void le_thread_CleanupLegatoThreadData
716 (
717  void
718 );
719 
720 
721 #endif // LEGATO_THREAD_INCLUDE_GUARD
Definition: le_cdata.h:57
le_result_t
Definition: le_basics.h:45
#define LE_FULL_API
Definition: le_apiFeatures.h:40
#define LE_DECLARE_INLINE
Definition: le_basics.h:317