Marco Zecchini
/
Example_RTOS
Rtos API example
Embed:
(wiki syntax)
Show/hide line numbers
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_os2.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 /* 00027 * These are the C standard memory functions: 00028 * - void *calloc(size_t nmemb, size_t size); 00029 * - void free(void *ptr); 00030 * - void *malloc(size_t size); 00031 * - void *realloc(void *ptr, size_t size); 00032 */ 00033 00034 /* Use printf with caution inside malloc: printf may allocate memory itself, 00035 so using printf in malloc may lead to recursive calls! */ 00036 #define DPRINTF(...) {}; 00037 00038 extern RtxBoxIndex * const __uvisor_ps; 00039 00040 /** @retval 0 The kernel is not initialized. 00041 * @retval 1 The kernel is initialized.. */ 00042 static int is_kernel_initialized() 00043 { 00044 /* TODO: Bare-bone boxes must not call any RTX2 functions for now. 00045 * Each box should instead provide `heap_lock` and `heap_unlock` functions 00046 * as part of the box context. These would just be empty for boxes without 00047 * the need for heap locking. */ 00048 if (__uvisor_ps->index.box_id_self != 0) { 00049 return 0; 00050 } 00051 00052 static uint8_t kernel_running = 0; 00053 if (kernel_running) { 00054 return 1; 00055 } 00056 if (osKernelGetState() == osKernelRunning) { 00057 kernel_running = 1; 00058 return 1; 00059 } 00060 return 0; 00061 } 00062 00063 static int init_allocator() 00064 { 00065 int ret = 0; 00066 if (__uvisor_ps == NULL) { 00067 #if defined(UVISOR_PRESENT) && (UVISOR_PRESENT == 1) 00068 return -1; 00069 #else 00070 extern void secure_malloc_init(void); 00071 secure_malloc_init(); 00072 #endif 00073 } 00074 00075 if ((__uvisor_ps->mutex_id == NULL) && is_kernel_initialized()) { 00076 /* Point the mutex attr to the data. */ 00077 __uvisor_ps->mutex_attr.name = "uvisor_malloc_mutex"; 00078 __uvisor_ps->mutex_attr.attr_bits = 0; /* Non-recursive */ 00079 __uvisor_ps->mutex_attr.cb_mem = &__uvisor_ps->mutex_data; 00080 __uvisor_ps->mutex_attr.cb_size = sizeof(__uvisor_ps->mutex_data); 00081 00082 /* Create mutex if not already done. */ 00083 __uvisor_ps->mutex_id = osMutexNew(&__uvisor_ps->mutex_attr); 00084 /* Mutex failed to be created. */ 00085 if (__uvisor_ps->mutex_id == NULL) { 00086 return -1; 00087 } 00088 } 00089 00090 if (__uvisor_ps->index.active_heap == NULL) { 00091 /* We need to initialize the process heap. */ 00092 if ((void *) __uvisor_ps->index.bss.address_of.heap != NULL) { 00093 /* Lock the mutex during initialization. */ 00094 int kernel_initialized = is_kernel_initialized(); 00095 if (kernel_initialized) { 00096 osMutexAcquire(__uvisor_ps->mutex_id, osWaitForever); 00097 } 00098 /* Initialize the process heap. */ 00099 SecureAllocator allocator = secure_allocator_create_with_pool( 00100 (void *) __uvisor_ps->index.bss.address_of.heap, 00101 __uvisor_ps->index.box_heap_size); 00102 /* Set the allocator. */ 00103 ret = allocator ? 0 : -1; 00104 __uvisor_ps->index.active_heap = allocator; 00105 /* Release the mutex. */ 00106 if (kernel_initialized) { 00107 osMutexRelease(__uvisor_ps->mutex_id); 00108 } 00109 } 00110 else { 00111 DPRINTF("uvisor_allocator: No process heap available!\n"); 00112 ret = -1; 00113 } 00114 } 00115 return ret; 00116 } 00117 00118 typedef enum { 00119 MEMOP_MALLOC, 00120 MEMOP_MEMALIGN, 00121 MEMOP_CALLOC, 00122 MEMOP_REALLOC, 00123 MEMOP_FREE 00124 } MemoryOperation; 00125 00126 00127 static void * memory(MemoryOperation operation, uint32_t * args) 00128 { 00129 /* Buffer the return value. */ 00130 void * ret = NULL; 00131 /* Initialize allocator. */ 00132 if (init_allocator()) { 00133 return NULL; 00134 } 00135 /* Check if we need to aquire the mutex. */ 00136 int mutexed = is_kernel_initialized(); 00137 void * allocator = __uvisor_ps->index.active_heap; 00138 00139 /* Aquire the mutex if required. 00140 * TODO: Mutex use is very coarse here. It may be sufficient to guard 00141 * the `rt_alloc_mem` and `rt_free_mem` functions in `uvisor_allocator.c`. 00142 * However, it is simpler to do it here for now. */ 00143 if (mutexed) { 00144 osMutexAcquire(__uvisor_ps->mutex_id, osWaitForever); 00145 } 00146 /* Perform the required operation. */ 00147 switch(operation) 00148 { 00149 case MEMOP_MALLOC: 00150 ret = secure_malloc(allocator, (size_t) args[0]); 00151 break; 00152 case MEMOP_MEMALIGN: 00153 ret = secure_aligned_alloc(allocator, (size_t) args[0], (size_t) args[1]); 00154 break; 00155 case MEMOP_CALLOC: 00156 ret = secure_calloc(allocator, (size_t) args[0], (size_t) args[1]); 00157 break; 00158 case MEMOP_REALLOC: 00159 ret = secure_realloc(allocator, (void *) args[0], (size_t) args[1]); 00160 break; 00161 case MEMOP_FREE: 00162 secure_free(allocator, (void *) args[0]); 00163 break; 00164 default: 00165 break; 00166 } 00167 /* Release the mutex if required. */ 00168 if (mutexed) { 00169 osMutexRelease(__uvisor_ps->mutex_id); 00170 } 00171 return ret; 00172 } 00173 00174 /* Wrapped memory management functions. */ 00175 #if defined (__GNUC__) 00176 00177 void * __wrap__malloc_r(struct _reent * r, size_t size) { 00178 (void) r; 00179 return memory(MEMOP_MALLOC, (uint32_t *) &size); 00180 } 00181 void * __wrap__memalign_r(struct _reent * r, size_t alignment, size_t bytes) { 00182 (void) r; 00183 uint32_t args[2] = {(uint32_t) alignment, (uint32_t) bytes}; 00184 return memory(MEMOP_MEMALIGN, args); 00185 } 00186 void * __wrap__calloc_r(struct _reent * r, size_t nmemb, size_t size) { 00187 (void) r; 00188 uint32_t args[2] = {(uint32_t) nmemb, (uint32_t) size}; 00189 return memory(MEMOP_CALLOC, args); 00190 } 00191 void * __wrap__realloc_r(struct _reent * r, void * ptr, size_t size) { 00192 (void) r; 00193 uint32_t args[2] = {(uint32_t) ptr, (uint32_t) size}; 00194 return memory(MEMOP_REALLOC, args); 00195 } 00196 void __wrap__free_r(struct _reent * r, void * ptr) { 00197 (void) r; 00198 memory(MEMOP_FREE, (uint32_t *) &ptr); 00199 } 00200 00201 #elif defined (__CC_ARM) 00202 /* TODO: Find out how to do function wrapping for ARMCC. See microlib libc. */ 00203 # warning "Using uVisor allocator is not available for ARMCC. Falling back to default allocator." 00204 #elif defined (__ICCARM__) 00205 /* TODO: Find out how to do function wrapping for IARCC. */ 00206 # warning "Using uVisor allocator is not available for IARCC. Falling back to default allocator." 00207 #endif
Generated on Sun Jul 17 2022 08:25:29 by 1.7.2