void OS_TLS_Init (OS_ERR *p_err) { CPU_INT16U ix; OS_TLS_LOCK *p_lock; CPU_SR_ALLOC(); OS_TLS_NextAvailID = 0u; OS_TLS_LibID = OS_TLS_GetID(p_err); CPU_CRITICAL_ENTER(); /* Create the link list of OS_TLS_LOCK objects. */ for (ix = 0u; ix < (OS_TLS_LOCK_MAX - 1u); ix++) { p_lock = &OS_TLS_LockPoolTbl[ix]; p_lock->NextPtr = &OS_TLS_LockPoolTbl[ix + 1u]; } p_lock = &OS_TLS_LockPoolTbl[OS_TLS_LOCK_MAX - 1u]; p_lock->NextPtr = (OS_TLS_LOCK *)0; /* Last node points to 'NULL' */ OS_TLS_LockPoolListPtr = &OS_TLS_LockPoolTbl[0]; /* Initialize the list head pointer. */ CPU_CRITICAL_EXIT(); }
/*! **************************************************************************** @brief Allocates a thread slot and returns the slot number This function allocates the slot (i.e memory location of a word size ) from the thread local storage buffer and returns the slot number. @param[out] pnThreadSlotKey - Pointer to return the slot number if a free slot is found. Must be populated with ADI_OSAL_TLS_UNALLOCATED. If a valid slot is already present in the supplied address this API returns success. @param[in] pTerminateCallbackFunc - Pointer to a function that gets called when the slot is freed. Can be NULL if the callback function is not required. @return ADI_OSAL_SUCCESS - If the function successfully allocated the slot. @return ADI_OSAL_FAILED - If the function failed to allocate the slot. @return ADI_OSAL_CALLER_ERROR - If the function is invoked from an invalid location (i.e an ISR) Note: "pnThreadSlotKey" will be set to ADI_OSAL_INVALID_THREAD_SLOT if there are no free slots. @ingroup thread local storage *****************************************************************************/ ADI_OSAL_STATUS adi_osal_ThreadSlotAcquire(ADI_OSAL_TLS_SLOT_KEY *pnThreadSlotKey, ADI_OSAL_TLS_CALLBACK_PTR pTerminateCallbackFunc) { OS_TLS_ID nSlotIndex; uint32_t nSlotBit; INT8U nErr; ADI_OSAL_STATUS eRetStatus = ADI_OSAL_FAILED; /*! @internal @var _adi_osal_gTLSUsedSlots Word used in the management of allocated TLS slots. Bits are used to represent the status of the slot. Bit 0 corresponds to slot number 0 and slot number 30 corresponds bit number 30. A slot is free if the corresponding bit is clear and a slot is acquired if the corresponding bit is set. Initially all the slot bits are clear. @endinternal */ static uint32_t _adi_osal_gTLSUsedSlots = 0u; #ifdef OSAL_DEBUG if (CALLED_FROM_AN_ISR) { return (ADI_OSAL_CALLER_ERROR); } #endif /* OSAL_DEBUG */ /* Lock the scheduler - as a task may be deleted while a callback is being * installed. */ OSSchedLock(); /* If the passed-in slot number has already been allocated, then we return * successfully. We check that - * - It has the correct TLS signature * - The slot has been (and is still) allocated. */ if(IsValidTLSKey(*pnThreadSlotKey)) { /* Extract the slot number from the TLS key, and convert to a bit * position */ nSlotBit = 1ul << (*pnThreadSlotKey & TLS_MASK_NUM); if(0u != (_adi_osal_gTLSUsedSlots & nSlotBit)) { /* The slot has previously been allocated using the supplied * address */ OSSchedUnlock(); return(ADI_OSAL_SUCCESS); } } /* Before we allocate a slot, the address to be written-to must have * an "unallocated" key. */ if(*pnThreadSlotKey != ADI_OSAL_TLS_UNALLOCATED) { OSSchedUnlock(); *pnThreadSlotKey = ADI_OSAL_INVALID_THREAD_SLOT; return(eRetStatus); } nSlotIndex = OS_TLS_GetID(&nErr); /* If the callback is NULL we don't put anything in the slot to save us * from calling the OSAL function */ if ((nErr == OS_ERR_NONE) && (NULL != pTerminateCallbackFunc)) { OS_TLS_SetDestruct(nSlotIndex, _adi_osal_TLSCallback, &nErr); } /* there was an error either allocating the slot or installing the * callback */ if (nErr != OS_ERR_NONE) { *pnThreadSlotKey = ADI_OSAL_INVALID_THREAD_SLOT; OSSchedUnlock(); return(eRetStatus); } /* everything went well so we record the used slot and we finish */ _adi_osal_gaTLSCallbacks[nSlotIndex] = pTerminateCallbackFunc; nSlotBit = ((uint32_t) 1 << (nSlotIndex)); /* * Set the context switch-sensitive globals * before breaking and releasing the scheduler lock : * - set the bit in the TLS available slot word. * - set the callback function, NULL pointers will not be called. */ _adi_osal_gTLSUsedSlots |= nSlotBit; OSSchedUnlock(); *pnThreadSlotKey = (nSlotIndex | TLS_SIGNATURE); return (ADI_OSAL_SUCCESS); }