1 /*
2 * FreeRTOS Kernel V10.6.2
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 //-----------------------------------------------------------------------------
52 void
_Mtxinit(_Rmtx * mtx)53 _Mtxinit(_Rmtx * mtx)
54 {
55 *mtx = xSemaphoreCreateRecursiveMutex();
56 }
57
58 //-----------------------------------------------------------------------------
59 // Destroy lock.
60 //-----------------------------------------------------------------------------
61 void
_Mtxdst(_Rmtx * mtx)62 _Mtxdst(_Rmtx * mtx)
63 {
64 if ((mtx != NULL) && (*mtx != NULL)) {
65 vSemaphoreDelete(*mtx);
66 }
67 }
68
69 //-----------------------------------------------------------------------------
70 // Lock.
71 //-----------------------------------------------------------------------------
72 void
_Mtxlock(_Rmtx * mtx)73 _Mtxlock(_Rmtx * mtx)
74 {
75 if ((mtx != NULL) && (*mtx != NULL)) {
76 xSemaphoreTakeRecursive(*mtx, portMAX_DELAY);
77 }
78 }
79
80 //-----------------------------------------------------------------------------
81 // Unlock.
82 //-----------------------------------------------------------------------------
83 void
_Mtxunlock(_Rmtx * mtx)84 _Mtxunlock(_Rmtx * mtx)
85 {
86 if ((mtx != NULL) && (*mtx != NULL)) {
87 xSemaphoreGiveRecursive(*mtx);
88 }
89 }
90
91 //-----------------------------------------------------------------------------
92 // Called by malloc() to allocate blocks of memory from the heap.
93 //-----------------------------------------------------------------------------
94 void *
_sbrk_r(struct _reent * reent,int32_t incr)95 _sbrk_r (struct _reent * reent, int32_t incr)
96 {
97 extern char _end;
98 extern char _heap_sentry;
99 static char * _heap_sentry_ptr = &_heap_sentry;
100 static char * heap_ptr;
101 char * base;
102
103 if (!heap_ptr)
104 heap_ptr = (char *) &_end;
105
106 base = heap_ptr;
107 if (heap_ptr + incr >= _heap_sentry_ptr) {
108 reent->_errno = ENOMEM;
109 return (char *) -1;
110 }
111
112 heap_ptr += incr;
113 return base;
114 }
115
116 //-----------------------------------------------------------------------------
117 // Global initialization for C library.
118 //-----------------------------------------------------------------------------
119 void
vPortClibInit(void)120 vPortClibInit(void)
121 {
122 }
123
124 //-----------------------------------------------------------------------------
125 // Per-thread cleanup stub provided for linking, does nothing.
126 //-----------------------------------------------------------------------------
127 void
_reclaim_reent(void * ptr)128 _reclaim_reent(void * ptr)
129 {
130 }
131
132 #endif /* XSHAL_CLIB == XTHAL_CLIB_XCLIB */
133
134 #if XSHAL_CLIB == XTHAL_CLIB_NEWLIB
135
136 #include <errno.h>
137 #include <malloc.h>
138 #include <stdio.h>
139 #include <stdlib.h>
140 #include <string.h>
141
142 #include "semphr.h"
143
144 static SemaphoreHandle_t xClibMutex;
145 static uint32_t ulClibInitDone = 0;
146
147 //-----------------------------------------------------------------------------
148 // Get C library lock.
149 //-----------------------------------------------------------------------------
150 void
__malloc_lock(struct _reent * ptr)151 __malloc_lock(struct _reent * ptr)
152 {
153 if (!ulClibInitDone)
154 return;
155
156 xSemaphoreTakeRecursive(xClibMutex, portMAX_DELAY);
157 }
158
159 //-----------------------------------------------------------------------------
160 // Release C library lock.
161 //-----------------------------------------------------------------------------
162 void
__malloc_unlock(struct _reent * ptr)163 __malloc_unlock(struct _reent * ptr)
164 {
165 if (!ulClibInitDone)
166 return;
167
168 xSemaphoreGiveRecursive(xClibMutex);
169 }
170
171 //-----------------------------------------------------------------------------
172 // Lock for environment. Since we have only one global lock we can just call
173 // the malloc() lock function.
174 //-----------------------------------------------------------------------------
175 void
__env_lock(struct _reent * ptr)176 __env_lock(struct _reent * ptr)
177 {
178 __malloc_lock(ptr);
179 }
180
181
182 //-----------------------------------------------------------------------------
183 // Unlock environment.
184 //-----------------------------------------------------------------------------
185 void
__env_unlock(struct _reent * ptr)186 __env_unlock(struct _reent * ptr)
187 {
188 __malloc_unlock(ptr);
189 }
190
191 //-----------------------------------------------------------------------------
192 // Called by malloc() to allocate blocks of memory from the heap.
193 //-----------------------------------------------------------------------------
194 void *
_sbrk_r(struct _reent * reent,int32_t incr)195 _sbrk_r (struct _reent * reent, int32_t incr)
196 {
197 extern char _end;
198 extern char _heap_sentry;
199 static char * _heap_sentry_ptr = &_heap_sentry;
200 static char * heap_ptr;
201 char * base;
202
203 if (!heap_ptr)
204 heap_ptr = (char *) &_end;
205
206 base = heap_ptr;
207 if (heap_ptr + incr >= _heap_sentry_ptr) {
208 reent->_errno = ENOMEM;
209 return (char *) -1;
210 }
211
212 heap_ptr += incr;
213 return base;
214 }
215
216 //-----------------------------------------------------------------------------
217 // Global initialization for C library.
218 //-----------------------------------------------------------------------------
219 void
vPortClibInit(void)220 vPortClibInit(void)
221 {
222 configASSERT(!ulClibInitDone);
223
224 xClibMutex = xSemaphoreCreateRecursiveMutex();
225 ulClibInitDone = 1;
226 }
227
228 #endif /* XSHAL_CLIB == XTHAL_CLIB_NEWLIB */
229
230 #endif /* XT_USE_THREAD_SAFE_CLIB */
231