Пример #1
0
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);
}