1 /*
2  * FreeRTOS Kernel V11.0.1
3  * Copyright (C) 2015-2019 Cadence Design Systems, Inc.
4  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
5  *
6  * SPDX-License-Identifier: MIT
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a copy of
9  * this software and associated documentation files (the "Software"), to deal in
10  * the Software without restriction, including without limitation the rights to
11  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
12  * the Software, and to permit persons to whom the Software is furnished to do so,
13  * subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included in all
16  * copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
20  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
21  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
22  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  *
25  * https://www.FreeRTOS.org
26  * https://github.com/FreeRTOS
27  *
28  */
29 
30 #include "FreeRTOS.h"
31 
32 #if XT_USE_THREAD_SAFE_CLIB
33 
34     #if XSHAL_CLIB == XTHAL_CLIB_XCLIB
35 
36         #include <errno.h>
37         #include <sys/reent.h>
38 
39         #include "semphr.h"
40 
41         typedef SemaphoreHandle_t _Rmtx;
42 
43 /*----------------------------------------------------------------------------- */
44 /*  Override this and set to nonzero to enable locking. */
45 /*----------------------------------------------------------------------------- */
46         int32_t _xclib_use_mt = 1;
47 
48 
49 /*----------------------------------------------------------------------------- */
50 /*  Init lock. */
51 /*----------------------------------------------------------------------------- */
_Mtxinit(_Rmtx * mtx)52         void _Mtxinit( _Rmtx * mtx )
53         {
54             *mtx = xSemaphoreCreateRecursiveMutex();
55         }
56 
57 /*----------------------------------------------------------------------------- */
58 /*  Destroy lock. */
59 /*----------------------------------------------------------------------------- */
_Mtxdst(_Rmtx * mtx)60         void _Mtxdst( _Rmtx * mtx )
61         {
62             if( ( mtx != NULL ) && ( *mtx != NULL ) )
63             {
64                 vSemaphoreDelete( *mtx );
65             }
66         }
67 
68 /*----------------------------------------------------------------------------- */
69 /*  Lock. */
70 /*----------------------------------------------------------------------------- */
_Mtxlock(_Rmtx * mtx)71         void _Mtxlock( _Rmtx * mtx )
72         {
73             if( ( mtx != NULL ) && ( *mtx != NULL ) )
74             {
75                 xSemaphoreTakeRecursive( *mtx, portMAX_DELAY );
76             }
77         }
78 
79 /*----------------------------------------------------------------------------- */
80 /*  Unlock. */
81 /*----------------------------------------------------------------------------- */
_Mtxunlock(_Rmtx * mtx)82         void _Mtxunlock( _Rmtx * mtx )
83         {
84             if( ( mtx != NULL ) && ( *mtx != NULL ) )
85             {
86                 xSemaphoreGiveRecursive( *mtx );
87             }
88         }
89 
90 /*----------------------------------------------------------------------------- */
91 /*  Called by malloc() to allocate blocks of memory from the heap. */
92 /*----------------------------------------------------------------------------- */
_sbrk_r(struct _reent * reent,int32_t incr)93         void * _sbrk_r( struct _reent * reent,
94                         int32_t incr )
95         {
96             extern char _end;
97             extern char _heap_sentry;
98             static char * _heap_sentry_ptr = &_heap_sentry;
99             static char * heap_ptr;
100             char * base;
101 
102             if( !heap_ptr )
103             {
104                 heap_ptr = ( char * ) &_end;
105             }
106 
107             base = heap_ptr;
108 
109             if( heap_ptr + incr >= _heap_sentry_ptr )
110             {
111                 reent->_errno = ENOMEM;
112                 return ( char * ) -1;
113             }
114 
115             heap_ptr += incr;
116             return base;
117         }
118 
119 /*----------------------------------------------------------------------------- */
120 /*  Global initialization for C library. */
121 /*----------------------------------------------------------------------------- */
vPortClibInit(void)122         void vPortClibInit( void )
123         {
124         }
125 
126 /*----------------------------------------------------------------------------- */
127 /*  Per-thread cleanup stub provided for linking, does nothing. */
128 /*----------------------------------------------------------------------------- */
_reclaim_reent(void * ptr)129         void _reclaim_reent( void * ptr )
130         {
131         }
132 
133     #endif /* XSHAL_CLIB == XTHAL_CLIB_XCLIB */
134 
135     #if XSHAL_CLIB == XTHAL_CLIB_NEWLIB
136 
137         #include <errno.h>
138         #include <malloc.h>
139         #include <stdio.h>
140         #include <stdlib.h>
141         #include <string.h>
142 
143         #include "semphr.h"
144 
145         static SemaphoreHandle_t xClibMutex;
146         static uint32_t ulClibInitDone = 0;
147 
148 /*----------------------------------------------------------------------------- */
149 /*  Get C library lock. */
150 /*----------------------------------------------------------------------------- */
__malloc_lock(struct _reent * ptr)151         void __malloc_lock( struct _reent * ptr )
152         {
153             if( !ulClibInitDone )
154             {
155                 return;
156             }
157 
158             xSemaphoreTakeRecursive( xClibMutex, portMAX_DELAY );
159         }
160 
161 /*----------------------------------------------------------------------------- */
162 /*  Release C library lock. */
163 /*----------------------------------------------------------------------------- */
__malloc_unlock(struct _reent * ptr)164         void __malloc_unlock( struct _reent * ptr )
165         {
166             if( !ulClibInitDone )
167             {
168                 return;
169             }
170 
171             xSemaphoreGiveRecursive( xClibMutex );
172         }
173 
174 /*----------------------------------------------------------------------------- */
175 /*  Lock for environment. Since we have only one global lock we can just call */
176 /*  the malloc() lock function. */
177 /*----------------------------------------------------------------------------- */
__env_lock(struct _reent * ptr)178         void __env_lock( struct _reent * ptr )
179         {
180             __malloc_lock( ptr );
181         }
182 
183 
184 /*----------------------------------------------------------------------------- */
185 /*  Unlock environment. */
186 /*----------------------------------------------------------------------------- */
__env_unlock(struct _reent * ptr)187         void __env_unlock( struct _reent * ptr )
188         {
189             __malloc_unlock( ptr );
190         }
191 
192 /*----------------------------------------------------------------------------- */
193 /*  Called by malloc() to allocate blocks of memory from the heap. */
194 /*----------------------------------------------------------------------------- */
_sbrk_r(struct _reent * reent,int32_t incr)195         void * _sbrk_r( struct _reent * reent,
196                         int32_t incr )
197         {
198             extern char _end;
199             extern char _heap_sentry;
200             static char * _heap_sentry_ptr = &_heap_sentry;
201             static char * heap_ptr;
202             char * base;
203 
204             if( !heap_ptr )
205             {
206                 heap_ptr = ( char * ) &_end;
207             }
208 
209             base = heap_ptr;
210 
211             if( heap_ptr + incr >= _heap_sentry_ptr )
212             {
213                 reent->_errno = ENOMEM;
214                 return ( char * ) -1;
215             }
216 
217             heap_ptr += incr;
218             return base;
219         }
220 
221 /*----------------------------------------------------------------------------- */
222 /*  Global initialization for C library. */
223 /*----------------------------------------------------------------------------- */
vPortClibInit(void)224         void vPortClibInit( void )
225         {
226             configASSERT( !ulClibInitDone );
227 
228             xClibMutex = xSemaphoreCreateRecursiveMutex();
229             ulClibInitDone = 1;
230         }
231 
232     #endif /* XSHAL_CLIB == XTHAL_CLIB_NEWLIB */
233 
234 #endif /* XT_USE_THREAD_SAFE_CLIB */
235