le_thread.h File Reference

#include "le_cdata.h"

Go to the source code of this file.

Macros

#define LE_THREAD_PRIORITY_RT_LOWEST   LE_THREAD_PRIORITY_RT_1
 Lowest real-time priority.
 
#define LE_THREAD_PRIORITY_RT_HIGHEST   LE_THREAD_PRIORITY_RT_32
 Highest real-time priority.
 
#define LE_THREAD_DEFINE_STATIC_STACK(name, bytes)
 
#define LE_THREAD_SET_STATIC_STACK(thread, name)   le_thread_SetStack((thread), &_thread_stack_##name, sizeof(_thread_stack_##name))
 

Typedefs

typedef struct le_thread * le_thread_Ref_t
 
typedef void *(* le_thread_MainFunc_t) (void *context)
 
typedef void(* le_thread_Destructor_t) (void *context)
 
typedef struct le_thread_Destructor * le_thread_DestructorRef_t
 

Enumerations

enum  le_thread_Priority_t {
  LE_THREAD_PRIORITY_IDLE = 0, LE_THREAD_PRIORITY_LOW, LE_THREAD_PRIORITY_MEDIUM, LE_THREAD_PRIORITY_HIGH,
  LE_THREAD_PRIORITY_RT_1, LE_THREAD_PRIORITY_RT_2, LE_THREAD_PRIORITY_RT_3, LE_THREAD_PRIORITY_RT_4,
  LE_THREAD_PRIORITY_RT_5, LE_THREAD_PRIORITY_RT_6, LE_THREAD_PRIORITY_RT_7, LE_THREAD_PRIORITY_RT_8,
  LE_THREAD_PRIORITY_RT_9, LE_THREAD_PRIORITY_RT_10, LE_THREAD_PRIORITY_RT_11, LE_THREAD_PRIORITY_RT_12,
  LE_THREAD_PRIORITY_RT_13, LE_THREAD_PRIORITY_RT_14, LE_THREAD_PRIORITY_RT_15, LE_THREAD_PRIORITY_RT_16,
  LE_THREAD_PRIORITY_RT_17, LE_THREAD_PRIORITY_RT_18, LE_THREAD_PRIORITY_RT_19, LE_THREAD_PRIORITY_RT_20,
  LE_THREAD_PRIORITY_RT_21, LE_THREAD_PRIORITY_RT_22, LE_THREAD_PRIORITY_RT_23, LE_THREAD_PRIORITY_RT_24,
  LE_THREAD_PRIORITY_RT_25, LE_THREAD_PRIORITY_RT_26, LE_THREAD_PRIORITY_RT_27, LE_THREAD_PRIORITY_RT_28,
  LE_THREAD_PRIORITY_RT_29, LE_THREAD_PRIORITY_RT_30, LE_THREAD_PRIORITY_RT_31, LE_THREAD_PRIORITY_RT_32
}
 

Functions

le_thread_Ref_t le_thread_Create (const char *name, le_thread_MainFunc_t mainFunc, void *context)
 
le_result_t le_thread_SetPriority (le_thread_Ref_t thread, le_thread_Priority_t priority)
 
le_result_t le_thread_SetStackSize (le_thread_Ref_t thread, size_t size)
 
le_result_t le_thread_SetStack (le_thread_Ref_t thread, void *stack, size_t size)
 
void le_thread_SetJoinable (le_thread_Ref_t thread)
 
void le_thread_Start (le_thread_Ref_t thread)
 
le_result_t le_thread_Join (le_thread_Ref_t thread, void **resultValuePtr)
 
void le_thread_Exit (void *resultValue)
 
LE_FULL_API le_result_t le_thread_Cancel (le_thread_Ref_t threadToCancel)
 
int le_thread_Sleep (unsigned int seconds)
 
le_thread_Ref_t le_thread_GetCurrent (void)
 
void le_thread_GetName (le_thread_Ref_t threadRef, char *buffPtr, size_t buffSize)
 
const char * le_thread_GetMyName (void)
 
le_thread_DestructorRef_t le_thread_AddDestructor (le_thread_Destructor_t destructor, void *context)
 
void le_thread_AddChildDestructor (le_thread_Ref_t thread, le_thread_Destructor_t destructor, void *context)
 
void le_thread_RemoveDestructor (le_thread_DestructorRef_t destructor)
 
const _le_cdata_ThreadRec_t_le_thread_GetCDataInstancePtr (void)
 
void _le_thread_SetCDataInstancePtr (const _le_cdata_ThreadRec_t *cdataPtr)
 
void le_thread_InitLegatoThreadData (const char *name)
 
void le_thread_CleanupLegatoThreadData (void)
 

Detailed Description

Legato Thread Control API include file.

Macro Definition Documentation

◆ LE_THREAD_DEFINE_STATIC_STACK

#define LE_THREAD_DEFINE_STATIC_STACK (   name,
  bytes 
)
Value:
static uint8_t _thread_stack_##name[LE_THREAD_STACK_EXTRA_SIZE + \
((bytes) < LE_THREAD_STACK_MIN_SIZE ? LE_THREAD_STACK_MIN_SIZE : (bytes))] \
__attribute__((aligned(LE_THREAD_STACK_ALIGNMENT)))
char name[LIMIT_MAX_SAFE_REF_NAME_BYTES]
Descriptive name for debugging.
Definition: le_safeRef.h:234

Define a static thread stack region.

Parameters
nameStack variable name.
bytesNumber of bytes in the stack.

◆ LE_THREAD_SET_STATIC_STACK

#define LE_THREAD_SET_STATIC_STACK (   thread,
  name 
)    le_thread_SetStack((thread), &_thread_stack_##name, sizeof(_thread_stack_##name))

Set a static stack for a thread.

See also
le_thread_SetStack() for details.
Parameters
threadThread to set the stack for.
nameStack variable name that was previously passed to LE_THREAD_DEFINE_STATIC_STACK().
Returns
Return value of le_thread_SetStack().

Typedef Documentation

◆ le_thread_Destructor_t

typedef void(* le_thread_Destructor_t) (void *context)

Destructor functions for threads must look like this:

Parameters
context[IN] Context parameter that was passed into le_thread_SetDestructor() when this destructor was registered.

◆ le_thread_DestructorRef_t

typedef struct le_thread_Destructor* le_thread_DestructorRef_t

Reference to a registered destructor function.

◆ le_thread_MainFunc_t

typedef void*(* le_thread_MainFunc_t) (void *context)

Main functions for threads must look like this:

Parameters
context[IN] Context value that was passed to le_thread_Create().
Returns
Thread result value. If the thread is joinable, then this value can be obtained by another thread through a call to vt_thread_Join(). Otherwise, the return value is ignored.

◆ le_thread_Ref_t

typedef struct le_thread* le_thread_Ref_t

Reference to a thread of execution.

Note
NULL can be used as an invalid value.

Enumeration Type Documentation

◆ le_thread_Priority_t

Thread priority levels.

Real-time priority levels should be avoided unless absolutely necessary for the application. They are privileged levels and will therefore not be allowed unless the application is executed by an identity with the appropriate permissions. If a thread running at a real-time priority level does not block, no other thread at a lower priority level will run, so be careful with these.

Note
Higher numbers are higher priority.
Enumerator
LE_THREAD_PRIORITY_IDLE 

Lowest priority level. Only runs when nothing else to do.

LE_THREAD_PRIORITY_LOW 

Low, non-realtime priority level. Low, medium, high: intended for normal processes that contend for the CPU. Processes with these priorities don't preempt each other, but their priorities affect how they're inserted into the scheduling queue (high to low).

LE_THREAD_PRIORITY_MEDIUM 

Medium, non-real-time priority level. THIS IS THE DEFAULT.

LE_THREAD_PRIORITY_HIGH 

High, non-real-time priority level.

LE_THREAD_PRIORITY_RT_1 

Real-time priority level 1. The lowest realtime priority level.

LE_THREAD_PRIORITY_RT_2 

Real-time priority level 2.

LE_THREAD_PRIORITY_RT_3 

Real-time priority level 3.

LE_THREAD_PRIORITY_RT_4 

Real-time priority level 4.

LE_THREAD_PRIORITY_RT_5 

Real-time priority level 5.

LE_THREAD_PRIORITY_RT_6 

Real-time priority level 6.

LE_THREAD_PRIORITY_RT_7 

Real-time priority level 7.

LE_THREAD_PRIORITY_RT_8 

Real-time priority level 8.

LE_THREAD_PRIORITY_RT_9 

Real-time priority level 9.

LE_THREAD_PRIORITY_RT_10 

Real-time priority level 10.

LE_THREAD_PRIORITY_RT_11 

Real-time priority level 11.

LE_THREAD_PRIORITY_RT_12 

Real-time priority level 12.

LE_THREAD_PRIORITY_RT_13 

Real-time priority level 13.

LE_THREAD_PRIORITY_RT_14 

Real-time priority level 14.

LE_THREAD_PRIORITY_RT_15 

Real-time priority level 15.

LE_THREAD_PRIORITY_RT_16 

Real-time priority level 16.

LE_THREAD_PRIORITY_RT_17 

Real-time priority level 17.

LE_THREAD_PRIORITY_RT_18 

Real-time priority level 18.

LE_THREAD_PRIORITY_RT_19 

Real-time priority level 19.

LE_THREAD_PRIORITY_RT_20 

Real-time priority level 20.

LE_THREAD_PRIORITY_RT_21 

Real-time priority level 21.

LE_THREAD_PRIORITY_RT_22 

Real-time priority level 22.

LE_THREAD_PRIORITY_RT_23 

Real-time priority level 23.

LE_THREAD_PRIORITY_RT_24 

Real-time priority level 24.

LE_THREAD_PRIORITY_RT_25 

Real-time priority level 25.

LE_THREAD_PRIORITY_RT_26 

Real-time priority level 26.

LE_THREAD_PRIORITY_RT_27 

Real-time priority level 27.

LE_THREAD_PRIORITY_RT_28 

Real-time priority level 28.

LE_THREAD_PRIORITY_RT_29 

Real-time priority level 29.

LE_THREAD_PRIORITY_RT_30 

Real-time priority level 30.

LE_THREAD_PRIORITY_RT_31 

Real-time priority level 31.

LE_THREAD_PRIORITY_RT_32 

Real-time priority level 32.

Function Documentation

◆ _le_thread_GetCDataInstancePtr()

const _le_cdata_ThreadRec_t* _le_thread_GetCDataInstancePtr ( void  )

Gets the calling thread's component instance data record.

◆ _le_thread_SetCDataInstancePtr()

void _le_thread_SetCDataInstancePtr ( const _le_cdata_ThreadRec_t cdataPtr)

Sets the calling thread's component instance data record.

Parameters
cdataPtrCData instance for the thread.

◆ le_thread_AddChildDestructor()

void le_thread_AddChildDestructor ( le_thread_Ref_t  thread,
le_thread_Destructor_t  destructor,
void *  context 
)

Registers a destructor function for a child thread. The destructor will be called by the child thread just before it terminates.

This can only be done before the child thread is started. After that, only the child thread can add its own destructors.

The reason for allowing another thread to register a destructor function is to avoid a race condition that can cause resource leakage when a parent thread passes dynamically allocated resources to threads that they create. This is only a problem if the child thread is expected to release the resources when they are finished with them, and the child thread may get cancelled at any time.

For example, a thread T1 could allocate an object from a memory pool, create a thread T2, and pass that object to T2 for processing and release. T2 could register a destructor function to release the resource whenever it terminates, whether through cancellation or normal exit. But, if it's possible that T2 could get cancelled before it even has a chance to register a destructor function for itself, the memory pool object could never get released. So, we allow T1 to register a destructor function for T2 before starting T2.

See Thread Destructors for more information on destructors.

Parameters
[in]threadThread to attach the destructor to.
[in]destructorFunction to be called.
[in]contextParameter to pass to the destructor.

◆ le_thread_AddDestructor()

le_thread_DestructorRef_t le_thread_AddDestructor ( le_thread_Destructor_t  destructor,
void *  context 
)

Registers a destructor function for the calling thread. The destructor will be called by that thread just before it terminates.

A thread can register (or remove) its own destructor functions any time.

Returns
Reference to the destructor that can be passed to le_thread_RemoveDestructor().

See Thread Destructors for more information on destructors.

Parameters
[in]destructorFunction to be called.
[in]contextParameter to pass to the destructor.

◆ le_thread_Cancel()

LE_FULL_API le_result_t le_thread_Cancel ( le_thread_Ref_t  threadToCancel)

Tells another thread to terminate. Returns immediately, but the termination of the thread happens asynchronously and is not guaranteed to occur when this function returns.

Note
This function is not available on RTOS.
Returns
  • LE_OK if successful.
  • LE_NOT_FOUND if the thread doesn't exist.
Parameters
[in]threadToCancelThread to cancel.

◆ le_thread_CleanupLegatoThreadData()

void le_thread_CleanupLegatoThreadData ( void  )

Clean-up the thread-specific data that was initialized using le_thread_InitLegatoThreadData().

To prevent memory leaks, this must be called by the thread when it dies (unless the whole process is dying).

Note
This is not needed if the thread was started using le_thread_Start().

◆ le_thread_Create()

le_thread_Ref_t le_thread_Create ( const char *  name,
le_thread_MainFunc_t  mainFunc,
void *  context 
)

Creates a new Legato thread of execution. After creating the thread, you have the opportunity to set attributes before it starts. It won't start until le_thread_Start() is called.

Parameters
[in]nameThread name (will be copied, so can be temporary).
[in]mainFuncThread's main function.
[in]contextValue to pass to mainFunc when it is called.
Returns
A reference to the thread (doesn't return if fails).

◆ le_thread_Exit()

void le_thread_Exit ( void *  resultValue)

Terminates the calling thread.

Parameters
[in]resultValueResult value. If this thread is joinable, this result can be obtained by another thread calling le_thread_Join() on this thread.

◆ le_thread_GetCurrent()

le_thread_Ref_t le_thread_GetCurrent ( void  )

Gets the calling thread's thread reference.

Returns
Calling thread's thread reference.

◆ le_thread_GetMyName()

const char* le_thread_GetMyName ( void  )

Gets the name of the calling thread.

◆ le_thread_GetName()

void le_thread_GetName ( le_thread_Ref_t  threadRef,
char *  buffPtr,
size_t  buffSize 
)

Gets the name of a given thread.

Parameters
[in]threadRefThread to get the name for.
[out]buffPtrBuffer to store the name of the thread.
[in]buffSizeSize of the buffer.

◆ le_thread_InitLegatoThreadData()

void le_thread_InitLegatoThreadData ( const char *  name)

Initialize the thread-specific data needed by the Legato framework for the calling thread.

This is used to turn a non-Legato thread (a thread that was created using a non-Legato API, such as pthread_create() ) into a Legato thread.

Parameters
[in]nameA name for the thread (will be copied, so can be temporary).
Note
This is not needed if the thread was started using le_thread_Start().

◆ le_thread_Join()

le_result_t le_thread_Join ( le_thread_Ref_t  thread,
void **  resultValuePtr 
)

"Joins" the calling thread with another thread. Blocks the calling thread until the other thread finishes.

After a thread has been joined with, its thread reference is no longer valid and must never be used again.

The other thread's result value (the value it returned from its main function or passed into le_thread_Exit()) can be obtained.

Returns
  • LE_OK if successful.
  • LE_DEADLOCK if a thread tries to join with itself or two threads try to join each other.
  • LE_NOT_FOUND if the other thread doesn't exist.
  • LE_FAULT if the other thread can't be joined with.
Warning
The other thread must be "joinable". See le_thread_SetJoinable();
It's an error for two or more threads try to join with the same thread.
Parameters
[in]thread
[out]resultValuePtrPtr to where the finished thread's result value will be stored. Can be NULL if the result is not needed.

◆ le_thread_RemoveDestructor()

void le_thread_RemoveDestructor ( le_thread_DestructorRef_t  destructor)

Removes a destructor function from the calling thread's list of destructors.

Parameters
[in]destructorReference to the destructor to remove.

◆ le_thread_SetJoinable()

void le_thread_SetJoinable ( le_thread_Ref_t  thread)

Makes a thread "joinable", meaning that when it finishes, it will remain in existence until another thread "joins" with it by calling le_thread_Join(). By default, threads are not joinable and will be destroyed automatically when they finish.

Parameters
[in]thread

◆ le_thread_SetPriority()

le_result_t le_thread_SetPriority ( le_thread_Ref_t  thread,
le_thread_Priority_t  priority 
)

Sets the priority of a thread.

Returns
  • LE_OK if successful.
  • LE_OUT_OF_RANGE if the priority level requested is out of range.
Parameters
[in]thread
[in]priority

◆ le_thread_SetStack()

le_result_t le_thread_SetStack ( le_thread_Ref_t  thread,
void *  stack,
size_t  size 
)

Sets the stack of a thread.

Setting the stack explicitly allows the caller to control the memory allocation of the thread's stack and, in some cases, control data. This can be useful for allocating the space out of static memory, for example.

The macro LE_THREAD_DEFINE_STATIC_STACK() may be used to create a statically allocated stack for use with this function, and LE_THREAD_SET_STATIC_STACK() may be used to call it properly.

Attention
In general, this function is only useful on embedded, RTOS based systems in order to perform up-front allocation of thread resources. On more capable systems it is safer to allow the operating system to set up the stack (which may optionally be sized using le_thread_SetStackSize()).
Returns
  • LE_OK if successful.
  • LE_BAD_PARAMETER if the size or stack is invalid (NULL or improperly aligned).
Parameters
[in]threadThread instance.
[in]stackAddress of the lowest byte of the stack. This must be appropriately aligned (LE_THREAD_DEFINE_STATIC_STACK() will do this).
[in]sizeStack size, in bytes.

◆ le_thread_SetStackSize()

le_result_t le_thread_SetStackSize ( le_thread_Ref_t  thread,
size_t  size 
)

Sets the stack size of a thread.

Note
It's generally not necessary to set the stack size. Some reasons why you might are:
  • to increase it beyond the system's default stack size to prevent overflow for a thread that makes extremely heavy use of the stack;
  • to decrease it to save memory when:
    • running in a system that does not support virtual memory
    • the thread has very tight real-time constraints that require that the stack memory be locked into physical memory to avoid page faults.
Returns
  • LE_OK if successful.
  • LE_OVERFLOW if the stack size requested is too small.
  • LE_OUT_OF_RANGE if the stack size requested is too large.
Parameters
[in]thread
[in]sizeStack size, in bytes. May be rounded up to the nearest virtual memory page size.

◆ le_thread_Sleep()

int le_thread_Sleep ( unsigned int  seconds)

Causes the calling thread to sleep.

Returns
  • 0 if the sleep is successful.
  • -1 if the call is interrupted by a signal handler or encounters an error.
Note
This function is not a full equivalence of nanosleep() as the remaining sleep time will not be available to the caller if nanosleep() returns due to being interrupted by a signal.
Parameters
[in]secondsTime to sleep in seconds.

◆ le_thread_Start()

void le_thread_Start ( le_thread_Ref_t  thread)

Starts a new Legato execution thread. After creating the thread, you have the opportunity to set attributes before it starts. It won't start until le_thread_Start() is called.

Parameters
[in]thread