1 /* 2 * FreeRTOS Kernel V11.1.0 3 * Copyright (C) 2020 Synopsys, Inc. or its affiliates. All Rights Reserved. 4 * 5 * SPDX-License-Identifier: MIT 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 * this software and associated documentation files (the "Software"), to deal in 9 * the Software without restriction, including without limitation the rights to 10 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 * the Software, and to permit persons to whom the Software is furnished to do so, 12 * subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included in all 15 * copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 * 24 * https://www.FreeRTOS.org 25 * https://github.com/FreeRTOS 26 * 27 */ 28 29 #if defined( __MW__ ) 30 31 #include <stdint.h> 32 #include <stdlib.h> 33 #include <string.h> 34 35 #include "FreeRTOS.h" 36 37 #include "queue.h" 38 #include "semphr.h" 39 #include "task.h" 40 41 #include "arc/arc_exception.h" 42 #include "embARC_toolchain.h" 43 #include "embARC_debug.h" 44 45 #ifdef ENABLE_FREERTOS_TLS_DEBUG 46 #define TLS_DEBUG( fmt, ... ) EMBARC_PRINTF( fmt, ## __VA_ARGS__ ) 47 #else 48 #define TLS_DEBUG( fmt, ... ) 49 #endif 50 51 /* 52 * Runtime routines to execute constructors and 53 * destructors for task local storage. 54 */ 55 extern void __mw_run_tls_dtor(); 56 extern void __mw_run_tls_ctor(); 57 58 extern uint32_t exc_nest_count; 59 60 /* 61 * Linker generated symbols to mark .tls section addresses 62 * first byte .. last byte 63 */ 64 extern char _ftls[], _etls[]; 65 #pragma weak _ftls 66 #pragma weak _etls 67 executable_requires_tls_section(void)68 void executable_requires_tls_section( void ) 69 { 70 #if _ARC 71 for( ; ; ) 72 { 73 _flag( 1 ); 74 _nop(); 75 _nop(); 76 _nop(); 77 _nop(); 78 _nop(); 79 } 80 #endif 81 } 82 #pragma off_inline(executable_requires_tls_section); 83 #pragma alias(executable_requires_tls_section, "executable_requires_.tls_section"); 84 init_task_tls(void)85 static void * init_task_tls( void ) 86 { 87 uint32_t len = ( uint32_t ) ( _etls - _ftls ); 88 void * tls = NULL; 89 90 #if FREERTOS_HEAP_SEL == 3 91 #warning "FreeRTOS TLS support is not compatible with heap 3 solution(FREERTOS_HEAP_SEL=3)!" 92 #warning "You can change FREERTOS_HEAP_SEL in freertos.mk to select other heap solution." 93 #else 94 tls = pvPortMalloc( len ); 95 #endif 96 97 if( tls ) 98 { 99 TLS_DEBUG( "Malloc task tls:%dbytes\r\n", len ); 100 memcpy( tls, _ftls, len ); 101 __mw_run_tls_ctor(); /* Run constructors */ 102 } 103 104 return tls; 105 } 106 free_task_tls(void * pxTCB)107 static void free_task_tls( void * pxTCB ) 108 { 109 TaskHandle_t task2free = ( TaskHandle_t ) pxTCB; 110 111 if( task2free != NULL ) 112 { 113 void * tls = pvTaskGetThreadLocalStoragePointer( task2free, 0 ); 114 115 if( tls ) 116 { 117 TLS_DEBUG( "Free task tls\r\n" ); 118 __mw_run_tls_dtor(); 119 vPortFree( tls ); 120 vTaskSetThreadLocalStoragePointer( task2free, 0, NULL ); 121 } 122 } 123 } 124 task_end_hook(void * pxTCB)125 void task_end_hook( void * pxTCB ) 126 { 127 free_task_tls( pxTCB ); 128 } 129 get_isr_tls(void)130 static void * get_isr_tls( void ) 131 { 132 /* In an ISR */ 133 static int first = 1; 134 135 if( _Rarely( first ) ) 136 { 137 first = 0; 138 __mw_run_tls_ctor(); /* Run constructors */ 139 } 140 141 return ( void * ) _ftls; 142 } 143 #pragma off_inline(get_isr_tls) 144 get_task_tls(void)145 static void * get_task_tls( void ) 146 { 147 TaskHandle_t cur_task; 148 149 cur_task = xTaskGetCurrentTaskHandle(); 150 151 if( cur_task == NULL ) 152 { 153 return get_isr_tls(); 154 } 155 156 void * tls = pvTaskGetThreadLocalStoragePointer( cur_task, 0 ); 157 158 if( tls == NULL ) 159 { 160 tls = init_task_tls(); 161 162 if( tls ) 163 { 164 vTaskSetThreadLocalStoragePointer( cur_task, 0, tls ); 165 } 166 else 167 { 168 tls = get_isr_tls(); 169 } 170 } 171 172 return tls; 173 } 174 #pragma off_inline(get_task_tls) 175 176 #if _ARC /* for ARC XCALLs need to preserve flags */ 177 extern void * _Preserve_flags _mwget_tls( void ); 178 #endif 179 180 /* 181 * Back end gens calls to find local data for this task 182 */ _mwget_tls(void)183 void * _mwget_tls( void ) 184 { 185 if( _ftls == ( char * ) 0 ) 186 { 187 executable_requires_tls_section(); 188 } 189 190 if( exc_nest_count > 0 ) /* In ISR */ 191 { 192 return get_isr_tls(); 193 } 194 else /* In Task */ 195 { 196 return get_task_tls(); 197 } 198 } 199 200 201 /* simple interface of thread safe */ 202 typedef xSemaphoreHandle _lock_t; 203 #if configUSE_RECURSIVE_MUTEXES != 1 204 #error "configUSE_RECURSIVE_MUTEXES in FreeRTOSConfig.h need to 1" 205 #endif 206 _mwmutex_create(_lock_t * mutex_ptr)207 void _mwmutex_create( _lock_t * mutex_ptr ) 208 { 209 *mutex_ptr = xSemaphoreCreateRecursiveMutex(); 210 } 211 _mwmutex_delete(_lock_t * mutex_ptr)212 void _mwmutex_delete( _lock_t * mutex_ptr ) 213 { 214 if( ( *mutex_ptr ) != NULL ) 215 { 216 vSemaphoreDelete( *mutex_ptr ); 217 } 218 } 219 _mwmutex_lock(_lock_t mutex)220 void _mwmutex_lock( _lock_t mutex ) 221 { 222 if( ( mutex ) != NULL ) 223 { 224 while( xSemaphoreTakeRecursive( mutex, portMAX_DELAY ) != pdTRUE ) 225 { 226 } 227 } 228 } 229 _mwmutex_unlock(_lock_t mutex)230 void _mwmutex_unlock( _lock_t mutex ) 231 { 232 if( ( mutex ) != NULL ) 233 { 234 xSemaphoreGiveRecursive( mutex ); 235 } 236 } 237 238 #else /* if defined( __MW__ ) */ 239 240 #endif /* __MW__ */ 241