Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

When OS_TLS_TBL_SIZE is set to 1 or greater, each task’s OS_TCB will contain a new array called .OSTCBTLSTbl[] as shown below. Each array element is of type OS_TLS which is actually a pointer to void. This allows an OS_TCB to be extended so that it can have as many TLS areas as needed.

 

Anchor
Figure - Each OS_TCB contains an array of OS_TLS when OS_TLS_TBL_SIZE is greater than 0 in os_cfg.h
Figure - Each OS_TCB contains an array of OS_TLS when OS_TLS_TBL_SIZE is greater than 0 in os_cfg.h

Panel
borderWidth0
titleFigure - Each OS_TCB contains an array of OS_TLS when OS_TLS_TBL_SIZE is greater than 0 in os_cfg.h

Each OS_TCB contains an array of OS_TLS when OS_TLS_TBL_SIZE is greater than 0 in os_cfg.hImage Added


The number of entries (i.e., the value to set OS_TLS_TBL_SIZE to) depends on the compiler being supported as well as whether TLS storage is needed for other purposes.

...

Finally, each .OSTCBTLSTbl[] entry can have a ‘destructor’ associated with it. A destructor is a function that is called when the task is deleted. Destructors are common to all tasks. This means that if a destructor is assigned for a TLS ID, the same destructor will be called for all the tasks for that entry. Also, when a task is deleted, the destructor for all of the TLS IDs will be called – assuming, of course, that a destructor was assigned to the corresponding TLS ID. You set a destructor function by calling OS_TLS_SetDestruct() and specify the TLS ID associated with the destructor as well as a pointer to the function that will be called. Note that a destructor function must be declared as follows:


Code Block
languagecpp
void MyDestructFunction (OS_TCB    *p_tcb,
                         OS_TLS_ID  id,
                         OS_TLS     value);


The drawing below shows the global destructor table. Note that not all implementations of os_tls.c will have destructors for the TLS.

...

OS_TLS_TaskCreate() should check that TLS is a feature enabled for the task being created. This is done by examining the OS_TCB’s option field (i.e., p_tcb->Opt) as follows:


Code Block
languagecpp
void OS_TLS_TaskCreate (OS_TCB *p_tcb)
{
    OS_TLS p_tls;


    if ((p_tcb->Opt & OS_OPT_TASK_NO_TLS) == OS_OPT_NONE) {
        p_tls                    = /* Allocate storage for TLS */
        p_tcb->TLS_Tbl[MyTLS_ID] = p_tls;
    }
}


void OS_TLS_TaskDel (OS_TCB *p_tcb)

...

The code below shows how OS_TLS_TaskDel() can be implemented.


Code Block
languagecpp
void OS_TLS_TaskDel (OS_TCB *p_tcb)
{
    OS_TLS_ID            id;
    OS_TLS_DESTRUCT_PTR *p_tbl;


    for (id = 0; id < OS_TLS_NextAvailID; id++) {
        p_tbl = &OS_TLS_DestructPtrTbl[id];
        if (*p_tbl != (OS_TLS_DESTRUCT_PTR)0) {
           (*p_tbl)(p_tcb, id, p_tcb->TLS_Tbl[id]);
        }
    }
}


OS_TLS_TaskDel() should actually check that TLS was used by the task being deleted. This is done by examining the OS_TCB’s option field (i.e., p_tcb->Opt) as follows:


Code Block
languagecpp
void OS_TLS_TaskDel (OS_TCB *p_tcb)
{
    OS_TLS_ID            id;
    OS_TLS_DESTRUCT_PTR *p_tbl;


    for (id = 0; id < OS_TLS_NextAvailID; id++) {
        p_tbl = &OS_TLS_DestructPtrTbl[id];
        if (*p_tbl != (OS_TLS_DESTRUCT_PTR)0) {
           (*p_tbl)(p_tcb, id, p_tcb->TLS_Tbl[id]);
        }
    }
}


An alternate implementation is shown below where OS_TLS_TaskDel() needs to deallocate storage for the task is shown below.

...

OS_TLS_TaskSw() should check that TLS is desired for the task being switched in. This is done by examining the OS_TCB’s option field (i.e. p_tcb->Opt) as follows:


Code Block
languagecpp
if ((p_tcb->Opt & OS_OPT_TASK_NO_TLS) == OS_OPT_NONE) {
    /* TLS option enabled for this task */
}


Compiler-Specific Lock APIs

As previously mentioned, some compilers may already have declared API functions that are called to ensure exclusive access to shared resources. For example, APIs such as _mutex_lock_file_system() and _mutex_unlock_file_system() could be required by the compiler to ensure exclusive access to the file system. os_tls.c might then implement these using µC/OS-III as shown below. Note that we also included the code to initialize the mutex in OS_TLS_Init().


Code Block
languagecpp
OS_EVENT *OS_TLS_FS_Sem;   /* Needed to ensure exclusive access to the FS */


void OS_TLS_Init (INT8U *p_err)
{
    OS_TLS_NextAvailID = 0u;
    OS_TLS_NewLibID    = OS_TLS_GetID(p_err);
    if (*p_err != OS_ERR_NONE) {
        return;
    }
    OS_TLS_FS_Sem = OSSemCreate(1);
}


void _mutex_lock_file_system (void)
{
    INT8U  os_err;


    if (OSRunning == 0) {
        return;
    }
    OSSemPend((OS_EVENT *)OS_TLS_FS_Sem,
              (INT32U    )0u,
              (INT8U    *)&os_err);
}


void _mutex_unlock_file_system (void)
{
    INT8U err;


    if (OSRunning == 0) {
        return;
    }
    OSSemPost((OS_SEM *)OS_TLS_FS_Sem);
}


The compiler may require the implementation of many such API functions to ensure exclusive access to the heap, environment variables, etc. These would all be found in os_tls.c.

...