mirror of
				https://github.com/FreeRTOS/FreeRTOS-Kernel.git
				synced 2025-11-04 11:09:01 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			241 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			241 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * FreeRTOS Kernel <DEVELOPMENT BRANCH>
 | 
						|
 * Copyright (C) 2020 Synopsys, Inc. or its affiliates.  All Rights Reserved.
 | 
						|
 *
 | 
						|
 * SPDX-License-Identifier: MIT
 | 
						|
 *
 | 
						|
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 | 
						|
 * this software and associated documentation files (the "Software"), to deal in
 | 
						|
 * the Software without restriction, including without limitation the rights to
 | 
						|
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 | 
						|
 * the Software, and to permit persons to whom the Software is furnished to do so,
 | 
						|
 * subject to the following conditions:
 | 
						|
 *
 | 
						|
 * The above copyright notice and this permission notice shall be included in all
 | 
						|
 * copies or substantial portions of the Software.
 | 
						|
 *
 | 
						|
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
						|
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 | 
						|
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 | 
						|
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 | 
						|
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | 
						|
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
						|
 *
 | 
						|
 * https://www.FreeRTOS.org
 | 
						|
 * https://github.com/FreeRTOS
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
#if defined( __MW__ )
 | 
						|
 | 
						|
    #include <stdint.h>
 | 
						|
    #include <stdlib.h>
 | 
						|
    #include <string.h>
 | 
						|
 | 
						|
    #include "FreeRTOS.h"
 | 
						|
 | 
						|
    #include "queue.h"
 | 
						|
    #include "semphr.h"
 | 
						|
    #include "task.h"
 | 
						|
 | 
						|
    #include "arc/arc_exception.h"
 | 
						|
    #include "embARC_toolchain.h"
 | 
						|
    #include "embARC_debug.h"
 | 
						|
 | 
						|
    #ifdef ENABLE_FREERTOS_TLS_DEBUG
 | 
						|
        #define TLS_DEBUG( fmt, ... )    EMBARC_PRINTF( fmt, ## __VA_ARGS__ )
 | 
						|
    #else
 | 
						|
        #define TLS_DEBUG( fmt, ... )
 | 
						|
    #endif
 | 
						|
 | 
						|
/*
 | 
						|
 * Runtime routines to execute constructors and
 | 
						|
 * destructors for task local storage.
 | 
						|
 */
 | 
						|
    extern void __mw_run_tls_dtor();
 | 
						|
    extern void __mw_run_tls_ctor();
 | 
						|
 | 
						|
    extern uint32_t exc_nest_count;
 | 
						|
 | 
						|
/*
 | 
						|
 * Linker generated symbols to mark .tls section addresses
 | 
						|
 * first byte .. last byte
 | 
						|
 */
 | 
						|
    extern char _ftls[], _etls[];
 | 
						|
    #pragma weak _ftls
 | 
						|
    #pragma weak _etls
 | 
						|
 | 
						|
    void executable_requires_tls_section( void )
 | 
						|
    {
 | 
						|
        #if _ARC
 | 
						|
            for( ; ; )
 | 
						|
            {
 | 
						|
                _flag( 1 );
 | 
						|
                _nop();
 | 
						|
                _nop();
 | 
						|
                _nop();
 | 
						|
                _nop();
 | 
						|
                _nop();
 | 
						|
            }
 | 
						|
        #endif
 | 
						|
    }
 | 
						|
    #pragma off_inline(executable_requires_tls_section);
 | 
						|
    #pragma alias(executable_requires_tls_section, "executable_requires_.tls_section");
 | 
						|
 | 
						|
    static void * init_task_tls( void )
 | 
						|
    {
 | 
						|
        uint32_t len = ( uint32_t ) ( _etls - _ftls );
 | 
						|
        void * tls = NULL;
 | 
						|
 | 
						|
        #if FREERTOS_HEAP_SEL == 3
 | 
						|
        #warning "FreeRTOS TLS support is not compatible with heap 3 solution(FREERTOS_HEAP_SEL=3)!"
 | 
						|
        #warning "You can change FREERTOS_HEAP_SEL in freertos.mk to select other heap solution."
 | 
						|
        #else
 | 
						|
            tls = pvPortMalloc( len );
 | 
						|
        #endif
 | 
						|
 | 
						|
        if( tls )
 | 
						|
        {
 | 
						|
            TLS_DEBUG( "Malloc task tls:%dbytes\r\n", len );
 | 
						|
            memcpy( tls, _ftls, len );
 | 
						|
            __mw_run_tls_ctor(); /* Run constructors */
 | 
						|
        }
 | 
						|
 | 
						|
        return tls;
 | 
						|
    }
 | 
						|
 | 
						|
    static void free_task_tls( void * pxTCB )
 | 
						|
    {
 | 
						|
        TaskHandle_t task2free = ( TaskHandle_t ) pxTCB;
 | 
						|
 | 
						|
        if( task2free != NULL )
 | 
						|
        {
 | 
						|
            void * tls = pvTaskGetThreadLocalStoragePointer( task2free, 0 );
 | 
						|
 | 
						|
            if( tls )
 | 
						|
            {
 | 
						|
                TLS_DEBUG( "Free task tls\r\n" );
 | 
						|
                __mw_run_tls_dtor();
 | 
						|
                vPortFree( tls );
 | 
						|
                vTaskSetThreadLocalStoragePointer( task2free, 0, NULL );
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    void task_end_hook( void * pxTCB )
 | 
						|
    {
 | 
						|
        free_task_tls( pxTCB );
 | 
						|
    }
 | 
						|
 | 
						|
    static void * get_isr_tls( void )
 | 
						|
    {
 | 
						|
        /* In an ISR */
 | 
						|
        static int first = 1;
 | 
						|
 | 
						|
        if( _Rarely( first ) )
 | 
						|
        {
 | 
						|
            first = 0;
 | 
						|
            __mw_run_tls_ctor(); /* Run constructors */
 | 
						|
        }
 | 
						|
 | 
						|
        return ( void * ) _ftls;
 | 
						|
    }
 | 
						|
    #pragma off_inline(get_isr_tls)
 | 
						|
 | 
						|
    static void * get_task_tls( void )
 | 
						|
    {
 | 
						|
        TaskHandle_t cur_task;
 | 
						|
 | 
						|
        cur_task = xTaskGetCurrentTaskHandle();
 | 
						|
 | 
						|
        if( cur_task == NULL )
 | 
						|
        {
 | 
						|
            return get_isr_tls();
 | 
						|
        }
 | 
						|
 | 
						|
        void * tls = pvTaskGetThreadLocalStoragePointer( cur_task, 0 );
 | 
						|
 | 
						|
        if( tls == NULL )
 | 
						|
        {
 | 
						|
            tls = init_task_tls();
 | 
						|
 | 
						|
            if( tls )
 | 
						|
            {
 | 
						|
                vTaskSetThreadLocalStoragePointer( cur_task, 0, tls );
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                tls = get_isr_tls();
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        return tls;
 | 
						|
    }
 | 
						|
    #pragma off_inline(get_task_tls)
 | 
						|
 | 
						|
    #if _ARC /* for ARC XCALLs need to preserve flags */
 | 
						|
        extern void * _Preserve_flags _mwget_tls( void );
 | 
						|
    #endif
 | 
						|
 | 
						|
/*
 | 
						|
 * Back end gens calls to find local data for this task
 | 
						|
 */
 | 
						|
    void * _mwget_tls( void )
 | 
						|
    {
 | 
						|
        if( _ftls == ( char * ) 0 )
 | 
						|
        {
 | 
						|
            executable_requires_tls_section();
 | 
						|
        }
 | 
						|
 | 
						|
        if( exc_nest_count > 0 ) /* In ISR */
 | 
						|
        {
 | 
						|
            return get_isr_tls();
 | 
						|
        }
 | 
						|
        else /* In Task */
 | 
						|
        {
 | 
						|
            return get_task_tls();
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
/* simple interface of thread safe */
 | 
						|
    typedef xSemaphoreHandle _lock_t;
 | 
						|
    #if configUSE_RECURSIVE_MUTEXES != 1
 | 
						|
        #error "configUSE_RECURSIVE_MUTEXES in FreeRTOSConfig.h need to 1"
 | 
						|
    #endif
 | 
						|
 | 
						|
    void _mwmutex_create( _lock_t * mutex_ptr )
 | 
						|
    {
 | 
						|
        *mutex_ptr = xSemaphoreCreateRecursiveMutex();
 | 
						|
    }
 | 
						|
 | 
						|
    void _mwmutex_delete( _lock_t * mutex_ptr )
 | 
						|
    {
 | 
						|
        if( ( *mutex_ptr ) != NULL )
 | 
						|
        {
 | 
						|
            vSemaphoreDelete( *mutex_ptr );
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    void _mwmutex_lock( _lock_t mutex )
 | 
						|
    {
 | 
						|
        if( ( mutex ) != NULL )
 | 
						|
        {
 | 
						|
            while( xSemaphoreTakeRecursive( mutex, portMAX_DELAY ) != pdTRUE )
 | 
						|
            {
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    void _mwmutex_unlock( _lock_t mutex )
 | 
						|
    {
 | 
						|
        if( ( mutex ) != NULL )
 | 
						|
        {
 | 
						|
            xSemaphoreGiveRecursive( mutex );
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
#else /* if defined( __MW__ ) */
 | 
						|
 | 
						|
#endif /* __MW__ */
 |