Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-os by
rtx_malloc_wrapper.c
00001 /* 00002 * Copyright (c) 2016, ARM Limited, All Rights Reserved 00003 * SPDX-License-Identifier: Apache-2.0 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); you may 00006 * not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 00013 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00018 #include "cmsis_os.h" 00019 #include "uvisor-lib/uvisor-lib.h" 00020 00021 #include <stdint.h> 00022 #include <stddef.h> 00023 #include <stdio.h> 00024 #include <reent.h> 00025 00026 #define OP_MALLOC 0 00027 #define OP_REALLOC 1 00028 #define OP_FREE 2 00029 00030 #define HEAP_ACTIVE 0 00031 #define HEAP_PROCESS 1 00032 00033 /* Use printf with caution inside malloc: printf may allocate memory itself, 00034 so using printf in malloc may lead to recursive calls! */ 00035 #define DPRINTF(...) {}; 00036 00037 extern RtxBoxIndex * const __uvisor_ps; 00038 00039 /** @retval 0 The kernel is not initialized. 00040 * @retval 1 The kernel is initialized.. */ 00041 static int is_kernel_initialized() 00042 { 00043 static uint8_t kernel_running = 0; 00044 if (kernel_running) { 00045 return 1; 00046 } 00047 if (osKernelRunning()) { 00048 kernel_running = 1; 00049 return 1; 00050 } 00051 return 0; 00052 } 00053 00054 static int init_allocator() 00055 { 00056 int ret = 0; 00057 if (__uvisor_ps == NULL) { 00058 #if defined(UVISOR_PRESENT) && (UVISOR_PRESENT == 1) 00059 return -1; 00060 #else 00061 extern void secure_malloc_init(void); 00062 secure_malloc_init(); 00063 #endif 00064 } 00065 00066 if ((__uvisor_ps->mutex_id == NULL) && is_kernel_initialized()) { 00067 /* Point the mutex pointer to the data. */ 00068 __uvisor_ps->mutex.mutex = &(__uvisor_ps->mutex_data); 00069 /* Create mutex if not already done. */ 00070 __uvisor_ps->mutex_id = osMutexCreate(&(__uvisor_ps->mutex)); 00071 /* Mutex failed to be created. */ 00072 if (__uvisor_ps->mutex_id == NULL) { 00073 return -1; 00074 } 00075 } 00076 00077 if (__uvisor_ps->index.active_heap == NULL) { 00078 /* We need to initialize the process heap. */ 00079 if (__uvisor_ps->index.box_heap != NULL) { 00080 /* Lock the mutex during initialization. */ 00081 int kernel_initialized = is_kernel_initialized(); 00082 if (kernel_initialized) { 00083 osMutexWait(__uvisor_ps->mutex_id, osWaitForever); 00084 } 00085 /* Initialize the process heap. */ 00086 SecureAllocator allocator = secure_allocator_create_with_pool( 00087 __uvisor_ps->index.box_heap, 00088 __uvisor_ps->index.box_heap_size); 00089 /* Set the allocator. */ 00090 ret = allocator ? 0 : -1; 00091 __uvisor_ps->index.active_heap = allocator; 00092 /* Release the mutex. */ 00093 if (kernel_initialized) { 00094 osMutexRelease(__uvisor_ps->mutex_id); 00095 } 00096 } 00097 else { 00098 DPRINTF("uvisor_allocator: No process heap available!\n"); 00099 ret = -1; 00100 } 00101 } 00102 return ret; 00103 } 00104 00105 static void * memory(void * ptr, size_t size, int heap, int operation) 00106 { 00107 /* Buffer the return value. */ 00108 void * ret = NULL; 00109 /* Initialize allocator. */ 00110 if (init_allocator()) { 00111 return NULL; 00112 } 00113 /* Check if we need to aquire the mutex. */ 00114 int mutexed = is_kernel_initialized() && 00115 ((heap == HEAP_PROCESS) || __uvisor_ps->index.box_heap == __uvisor_ps->index.active_heap); 00116 void * allocator = (heap == HEAP_PROCESS) ? 00117 (__uvisor_ps->index.box_heap) : 00118 (__uvisor_ps->index.active_heap); 00119 00120 /* Aquire the mutex if required. 00121 * TODO: Mutex use is very coarse here. It may be sufficient to guard 00122 * the `rt_alloc_mem` and `rt_free_mem` functions in `uvisor_allocator.c`. 00123 * However, it is simpler to do it here for now. */ 00124 if (mutexed) { 00125 osMutexWait(__uvisor_ps->mutex_id, osWaitForever); 00126 } 00127 /* Perform the required operation. */ 00128 switch(operation) 00129 { 00130 case OP_MALLOC: 00131 ret = secure_malloc(allocator, size); 00132 break; 00133 case OP_REALLOC: 00134 ret = secure_realloc(allocator, ptr, size); 00135 break; 00136 case OP_FREE: 00137 secure_free(allocator, ptr); 00138 break; 00139 default: 00140 break; 00141 } 00142 /* Release the mutex if required. */ 00143 if (mutexed) { 00144 osMutexRelease(__uvisor_ps->mutex_id); 00145 } 00146 return ret; 00147 } 00148 00149 /* Wrapped memory management functions. */ 00150 #if defined (__CC_ARM) 00151 void * $Sub$$_malloc_r(struct _reent * r, size_t size) { 00152 return memory(r, size, HEAP_ACTIVE, OP_MALLOC); 00153 } 00154 void * $Sub$$_realloc_r(struct _reent * r, void * ptr, size_t size) { 00155 (void)r; 00156 return memory(ptr, size, HEAP_ACTIVE, OP_REALLOC); 00157 } 00158 void $Sub$$_free_r(struct _reent * r, void * ptr) { 00159 (void)r; 00160 memory(ptr, 0, HEAP_ACTIVE, OP_FREE); 00161 } 00162 #elif defined (__GNUC__) 00163 void * __wrap__malloc_r(struct _reent * r, size_t size) { 00164 return memory(r, size, HEAP_ACTIVE, OP_MALLOC); 00165 } 00166 void * __wrap__realloc_r(struct _reent * r, void * ptr, size_t size) { 00167 (void)r; 00168 return memory(ptr, size, HEAP_ACTIVE, OP_REALLOC); 00169 } 00170 void __wrap__free_r(struct _reent * r, void * ptr) { 00171 (void)r; 00172 memory(ptr, 0, HEAP_ACTIVE, OP_FREE); 00173 } 00174 #elif defined (__ICCARM__) 00175 /* TODO: Find out how to do function wrapping for IARCC. */ 00176 /* TODO: newlib allocator is not thread-safe! */ 00177 # warning "Using uVisor allocator is not available for IARCC. Falling back to newlib allocator." 00178 #endif 00179 00180 void * malloc_p(size_t size) { 00181 return memory(NULL, size, HEAP_PROCESS, OP_MALLOC); 00182 } 00183 void * realloc_p(void * ptr, size_t size) { 00184 return memory(ptr, size, HEAP_PROCESS, OP_REALLOC); 00185 } 00186 void free_p(void * ptr) { 00187 memory(ptr, 0, HEAP_PROCESS, OP_FREE); 00188 }
Generated on Tue Jul 12 2022 13:16:04 by
