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