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