joey shelton / LED_Demo

Dependencies:   MAX44000 PWM_Tone_Library nexpaq_mdk

Fork of LED_Demo by Maxim nexpaq

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers rtx_malloc_wrapper.c Source File

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 }