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  LE_UNUSED(name);
312  return _le_thread_Create(mainFunc, context);
313 }
314 #endif /* end LE_CONFIG_THREAD_NAMES_ENABLED */
315 
316 
317 //--------------------------------------------------------------------------------------------------
318 /**
319  * Sets the priority of a thread.
320  *
321  * @return
322  * - LE_OK if successful.
323  * - LE_OUT_OF_RANGE if the priority level requested is out of range.
324  */
325 //--------------------------------------------------------------------------------------------------
327 (
328  le_thread_Ref_t thread, ///< [IN]
329  le_thread_Priority_t priority ///< [IN]
330 );
331 
332 
333 //--------------------------------------------------------------------------------------------------
334 /**
335  * Sets the stack size of a thread.
336  *
337  * @note It's generally not necessary to set the stack size. Some reasons why you might are:
338  * - to increase it beyond the system's default stack size to prevent overflow
339  * for a thread that makes extremely heavy use of the stack;
340  * - to decrease it to save memory when:
341  * - running in a system that does not support virtual memory
342  * - the thread has very tight real-time constraints that require that the stack
343  * memory be locked into physical memory to avoid page faults.
344  *
345  * @return
346  * - LE_OK if successful.
347  * - LE_OVERFLOW if the stack size requested is too small.
348  * - LE_OUT_OF_RANGE if the stack size requested is too large.
349  */
350 //--------------------------------------------------------------------------------------------------
352 (
353  le_thread_Ref_t thread, ///< [IN]
354  size_t size ///< [IN] Stack size, in bytes. May be rounded up to the
355  /// nearest virtual memory page size.
356 );
357 
358 
359 //--------------------------------------------------------------------------------------------------
360 /**
361  * Define a static thread stack region.
362  *
363  * @param name Stack variable name.
364  * @param bytes Number of bytes in the stack.
365  */
366 //--------------------------------------------------------------------------------------------------
367 #define LE_THREAD_DEFINE_STATIC_STACK(name, bytes) \
368  static uint8_t _thread_stack_##name[LE_THREAD_STACK_EXTRA_SIZE + \
369  ((bytes) < LE_THREAD_STACK_MIN_SIZE ? LE_THREAD_STACK_MIN_SIZE : (bytes))] \
370  __attribute__((aligned(LE_THREAD_STACK_ALIGNMENT)))
371 
372 
373 //--------------------------------------------------------------------------------------------------
374 /**
375  * Set a static stack for a thread.
376  *
377  * @see le_thread_SetStack() for details.
378  *
379  * @param thread Thread to set the stack for.
380  * @param name Stack variable name that was previously passed to
381  * LE_THREAD_DEFINE_STATIC_STACK().
382  *
383  * @return Return value of le_thread_SetStack().
384  */
385 //--------------------------------------------------------------------------------------------------
386 #define LE_THREAD_SET_STATIC_STACK(thread, name) \
387  le_thread_SetStack((thread), &_thread_stack_##name, sizeof(_thread_stack_##name))
388 
389 
390 //--------------------------------------------------------------------------------------------------
391 /**
392  * Sets the stack of a thread.
393  *
394  * Setting the stack explicitly allows the caller to control the memory allocation of the thread's
395  * stack and, in some cases, control data. This can be useful for allocating the space out of
396  * static memory, for example.
397  *
398  * The macro LE_THREAD_DEFINE_STATIC_STACK() may be used to create a statically allocated stack for
399  * use with this function, and LE_THREAD_SET_STATIC_STACK() may be used to call it properly.
400  *
401  * @attention In general, this function is only useful on embedded, RTOS based systems in order to
402  * perform up-front allocation of thread resources. On more capable systems it is
403  * safer to allow the operating system to set up the stack (which may optionally be
404  * sized using le_thread_SetStackSize()).
405  *
406  * @return
407  * - LE_OK if successful.
408  * - LE_BAD_PARAMETER if the size or stack is invalid (NULL or improperly aligned).
409  */
410 //--------------------------------------------------------------------------------------------------
412 (
413  le_thread_Ref_t thread, ///< [IN] Thread instance.
414  void *stack, ///< [IN] Address of the lowest byte of the stack. This must be
415  /// appropriately aligned (LE_THREAD_DEFINE_STATIC_STACK()
416  /// will do this).
417  size_t size ///< [IN] Stack size, in bytes.
418 );
419 
420 
421 //--------------------------------------------------------------------------------------------------
422 /**
423  * Makes a thread "joinable", meaning that when it finishes, it will remain in existence until
424  * another thread "joins" with it by calling le_thread_Join(). By default, threads are not
425  * joinable and will be destroyed automatically when they finish.
426  */
427 //--------------------------------------------------------------------------------------------------
429 (
430  le_thread_Ref_t thread ///< [IN]
431 );
432 
433 
434 //--------------------------------------------------------------------------------------------------
435 /**
436  * Starts a new Legato execution thread. After creating the thread, you have the opportunity
437  * to set attributes before it starts. It won't start until le_thread_Start() is called.
438  */
439 //--------------------------------------------------------------------------------------------------
440 void le_thread_Start
441 (
442  le_thread_Ref_t thread ///< [IN]
443 );
444 
445 
446 //--------------------------------------------------------------------------------------------------
447 /**
448  * "Joins" the calling thread with another thread. Blocks the calling thread until the other
449  * thread finishes.
450  *
451  * After a thread has been joined with, its thread reference is no longer valid and must never
452  * be used again.
453  *
454  * The other thread's result value (the value it returned from its main function or passed into
455  * le_thread_Exit()) can be obtained.
456  *
457  * @return
458  * - LE_OK if successful.
459  * - LE_DEADLOCK if a thread tries to join with itself or two threads try to join each other.
460  * - LE_NOT_FOUND if the other thread doesn't exist.
461  * - LE_FAULT if the other thread can't be joined with.
462  *
463  * @warning The other thread must be "joinable". See le_thread_SetJoinable();
464  *
465  * @warning It's an error for two or more threads try to join with the same thread.
466  */
467 //--------------------------------------------------------------------------------------------------
469 (
470  le_thread_Ref_t thread, ///< [IN]
471  void** resultValuePtr ///< [OUT] Ptr to where the finished thread's result value
472  /// will be stored. Can be NULL if the result is
473  /// not needed.
474 );
475 
476 
477 //--------------------------------------------------------------------------------------------------
478 /**
479  * Terminates the calling thread.
480  */
481 //--------------------------------------------------------------------------------------------------
482 void le_thread_Exit
483 (
484  void* resultValue ///< [IN] Result value. If this thread is joinable, this result
485  /// can be obtained by another thread calling le_thread_Join()
486  /// on this thread.
487 );
488 
489 
490 //--------------------------------------------------------------------------------------------------
491 /**
492  * Tells another thread to terminate. Returns immediately, but the termination of the
493  * thread happens asynchronously and is not guaranteed to occur when this function returns.
494  *
495  * @note This function is not available on RTOS.
496 
497  *
498  * @return
499  * - LE_OK if successful.
500  * - LE_NOT_FOUND if the thread doesn't exist.
501  */
502 //--------------------------------------------------------------------------------------------------
504 (
505  le_thread_Ref_t threadToCancel ///< [IN] Thread to cancel.
506 );
507 
508 
509 //--------------------------------------------------------------------------------------------------
510 /**
511  * Causes the calling thread to sleep.
512  *
513  * @return
514  * - 0 if the sleep is successful.
515  * - -1 if the call is interrupted by a signal handler or encounters an error.
516  *
517  * @note This function is not a full equivalence of nanosleep() as the remaining sleep time will not
518  * be available to the caller if nanosleep() returns due to being interrupted by a signal.
519  */
520 //--------------------------------------------------------------------------------------------------
521 int le_thread_Sleep
522 (
523  unsigned int seconds ///< [IN] Time to sleep in seconds.
524 );
525 
526 
527 //--------------------------------------------------------------------------------------------------
528 /**
529  * Gets the calling thread's thread reference.
530  *
531  * @return Calling thread's thread reference.
532  */
533 //--------------------------------------------------------------------------------------------------
535 (
536  void
537 );
538 
539 
540 //--------------------------------------------------------------------------------------------------
541 /**
542  * Gets the name of a given thread.
543  */
544 //--------------------------------------------------------------------------------------------------
546 (
547  le_thread_Ref_t threadRef, ///< [IN] Thread to get the name for.
548  char* buffPtr, ///< [OUT] Buffer to store the name of the thread.
549  size_t buffSize ///< [IN] Size of the buffer.
550 );
551 
552 
553 //--------------------------------------------------------------------------------------------------
554 /**
555  * Gets the name of the calling thread.
556  */
557 //--------------------------------------------------------------------------------------------------
558 const char* le_thread_GetMyName
559 (
560  void
561 );
562 
563 
564 //--------------------------------------------------------------------------------------------------
565 /**
566  * Destructor functions for threads must look like this:
567  *
568  * @param context [IN] Context parameter that was passed into le_thread_SetDestructor() when
569  * this destructor was registered.
570  */
571 //--------------------------------------------------------------------------------------------------
572 typedef void (* le_thread_Destructor_t)
573 (
574  void* context ///< [IN] Context parameter that was passed into le_thread_SetDestructor() when
575  /// this destructor was registered.
576 );
577 
578 
579 //--------------------------------------------------------------------------------------------------
580 /**
581  * Reference to a registered destructor function.
582  */
583 //--------------------------------------------------------------------------------------------------
584 typedef struct le_thread_Destructor* le_thread_DestructorRef_t;
585 
586 
587 //--------------------------------------------------------------------------------------------------
588 /**
589  * Registers a destructor function for the calling thread. The destructor will be called by that
590  * thread just before it terminates.
591  *
592  * A thread can register (or remove) its own destructor functions any time.
593  *
594  * @return Reference to the destructor that can be passed to le_thread_RemoveDestructor().
595  *
596  * See @ref threadDestructors for more information on destructors.
597  */
598 //--------------------------------------------------------------------------------------------------
600 (
601  le_thread_Destructor_t destructor, ///< [IN] Function to be called.
602  void* context ///< [IN] Parameter to pass to the destructor.
603 );
604 
605 
606 //--------------------------------------------------------------------------------------------------
607 /**
608  * Registers a destructor function for a child thread. The destructor will be called by the
609  * child thread just before it terminates.
610  *
611  * This can only be done before the child thread is started. After that, only the child thread
612  * can add its own destructors.
613  *
614  * The reason for allowing another thread to register a destructor function is to
615  * avoid a race condition that can cause resource leakage when a parent thread passes dynamically
616  * allocated resources to threads that they create. This is only a problem if the child thread
617  * is expected to release the resources when they are finished with them, and the child thread
618  * may get cancelled at any time.
619  *
620  * For example, a thread @e T1 could allocate an object from a memory pool, create a thread @e T2,
621  * and pass that object to @e T2 for processing and release. @e T2 could register a destructor
622  * function to release the resource whenever it terminates, whether through cancellation or
623  * normal exit. But, if it's possible that @e T2 could get cancelled before it even has a
624  * chance to register a destructor function for itself, the memory pool object could never get
625  * released. So, we allow @e T1 to register a destructor function for @e T2 before starting @e T2.
626  *
627  * See @ref threadDestructors for more information on destructors.
628  */
629 //--------------------------------------------------------------------------------------------------
631 (
632  le_thread_Ref_t thread, ///< [IN] Thread to attach the destructor to.
633  le_thread_Destructor_t destructor, ///< [IN] Function to be called.
634  void* context ///< [IN] Parameter to pass to the destructor.
635 );
636 
637 
638 //--------------------------------------------------------------------------------------------------
639 /**
640  * Removes a destructor function from the calling thread's list of destructors.
641  */
642 //--------------------------------------------------------------------------------------------------
644 (
645  le_thread_DestructorRef_t destructor ///< [in] Reference to the destructor to remove.
646 );
647 
648 //--------------------------------------------------------------------------------------------------
649 /**
650  * Gets the calling thread's component instance data record.
651  */
652 //--------------------------------------------------------------------------------------------------
654 (
655  void
656 );
657 
658 //--------------------------------------------------------------------------------------------------
659 /**
660  * Sets the calling thread's component instance data record.
661  */
662 //--------------------------------------------------------------------------------------------------
664 (
665  const _le_cdata_ThreadRec_t *cdataPtr ///< CData instance for the thread.
666 );
667 
668 #if LE_CONFIG_THREAD_NAMES_ENABLED
669 //--------------------------------------------------------------------------------------------------
670 /**
671  * Initialize the thread-specific data needed by the Legato framework for the calling thread.
672  *
673  * This is used to turn a non-Legato thread (a thread that was created using a non-Legato API,
674  * such as pthread_create() ) into a Legato thread.
675  *
676  * @param[in] name A name for the thread (will be copied, so can be temporary).
677  *
678  * @note This is not needed if the thread was started using le_thread_Start().
679  **/
680 //--------------------------------------------------------------------------------------------------
682 (
683  const char* name
684 );
685 #else /* if not LE_CONFIG_THREAD_NAMES_ENABLED */
686 /// @cond HIDDEN_IN_USER_DOCS
687 //--------------------------------------------------------------------------------------------------
688 /**
689  * Internal function used to implement le_thread_InitLegatoThreadData().
690  */
691 //--------------------------------------------------------------------------------------------------
692 void _le_thread_InitLegatoThreadData(void);
693 /// @endcond
694 //--------------------------------------------------------------------------------------------------
695 /**
696  * Initialize the thread-specific data needed by the Legato framework for the calling thread.
697  *
698  * This is used to turn a non-Legato thread (a thread that was created using a non-Legato API,
699  * such as pthread_create() ) into a Legato thread.
700  *
701  * @param[in] name A name for the thread (will be copied, so can be temporary).
702  *
703  * @note This is not needed if the thread was started using le_thread_Start().
704  **/
705 //--------------------------------------------------------------------------------------------------
707 (
708  const char* name
709 )
710 {
711  LE_UNUSED(name);
712  _le_thread_InitLegatoThreadData();
713 }
714 #endif /* end LE_CONFIG_THREAD_NAMES_ENABLED */
715 
716 
717 //--------------------------------------------------------------------------------------------------
718 /**
719  * Clean-up the thread-specific data that was initialized using le_thread_InitLegatoThreadData().
720  *
721  * To prevent memory leaks, this must be called by the thread when it dies (unless the whole
722  * process is dying).
723  *
724  * @note This is not needed if the thread was started using le_thread_Start().
725  **/
726 //--------------------------------------------------------------------------------------------------
728 (
729  void
730 );
731 
732 
733 #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)
#define LE_UNUSED(v)
Definition: le_basics.h:369
struct le_thread_Destructor * le_thread_DestructorRef_t
Definition: le_thread.h:584
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:573
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:320