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.
simple-mbed-cloud-client/mbed-cloud-client/nanostack-libservice/source/nsdynmemLIB/nsdynmemLIB.c@0:8f0bb79ddd48, 2021-05-04 (annotated)
- Committer:
- leothedragon
- Date:
- Tue May 04 08:55:12 2021 +0000
- Revision:
- 0:8f0bb79ddd48
nmn
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
leothedragon | 0:8f0bb79ddd48 | 1 | /* |
leothedragon | 0:8f0bb79ddd48 | 2 | * Copyright (c) 2014-2018 ARM Limited. All rights reserved. |
leothedragon | 0:8f0bb79ddd48 | 3 | * SPDX-License-Identifier: Apache-2.0 |
leothedragon | 0:8f0bb79ddd48 | 4 | * Licensed under the Apache License, Version 2.0 (the License); you may |
leothedragon | 0:8f0bb79ddd48 | 5 | * not use this file except in compliance with the License. |
leothedragon | 0:8f0bb79ddd48 | 6 | * You may obtain a copy of the License at |
leothedragon | 0:8f0bb79ddd48 | 7 | * |
leothedragon | 0:8f0bb79ddd48 | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
leothedragon | 0:8f0bb79ddd48 | 9 | * |
leothedragon | 0:8f0bb79ddd48 | 10 | * Unless required by applicable law or agreed to in writing, software |
leothedragon | 0:8f0bb79ddd48 | 11 | * distributed under the License is distributed on an AS IS BASIS, WITHOUT |
leothedragon | 0:8f0bb79ddd48 | 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
leothedragon | 0:8f0bb79ddd48 | 13 | * See the License for the specific language governing permissions and |
leothedragon | 0:8f0bb79ddd48 | 14 | * limitations under the License. |
leothedragon | 0:8f0bb79ddd48 | 15 | */ |
leothedragon | 0:8f0bb79ddd48 | 16 | #include <stdint.h> |
leothedragon | 0:8f0bb79ddd48 | 17 | #include <string.h> |
leothedragon | 0:8f0bb79ddd48 | 18 | #include "nsdynmemLIB.h" |
leothedragon | 0:8f0bb79ddd48 | 19 | #include "platform/arm_hal_interrupt.h" |
leothedragon | 0:8f0bb79ddd48 | 20 | #include <stdlib.h> |
leothedragon | 0:8f0bb79ddd48 | 21 | #include "ns_list.h" |
leothedragon | 0:8f0bb79ddd48 | 22 | |
leothedragon | 0:8f0bb79ddd48 | 23 | #ifndef STANDARD_MALLOC |
leothedragon | 0:8f0bb79ddd48 | 24 | typedef enum mem_stat_update_t { |
leothedragon | 0:8f0bb79ddd48 | 25 | DEV_HEAP_ALLOC_OK, |
leothedragon | 0:8f0bb79ddd48 | 26 | DEV_HEAP_ALLOC_FAIL, |
leothedragon | 0:8f0bb79ddd48 | 27 | DEV_HEAP_FREE, |
leothedragon | 0:8f0bb79ddd48 | 28 | } mem_stat_update_t; |
leothedragon | 0:8f0bb79ddd48 | 29 | |
leothedragon | 0:8f0bb79ddd48 | 30 | typedef struct { |
leothedragon | 0:8f0bb79ddd48 | 31 | ns_list_link_t link; |
leothedragon | 0:8f0bb79ddd48 | 32 | } hole_t; |
leothedragon | 0:8f0bb79ddd48 | 33 | |
leothedragon | 0:8f0bb79ddd48 | 34 | typedef int ns_mem_word_size_t; // internal signed heap block size type |
leothedragon | 0:8f0bb79ddd48 | 35 | |
leothedragon | 0:8f0bb79ddd48 | 36 | /* struct for book keeping variables */ |
leothedragon | 0:8f0bb79ddd48 | 37 | struct ns_mem_book { |
leothedragon | 0:8f0bb79ddd48 | 38 | ns_mem_word_size_t *heap_main; |
leothedragon | 0:8f0bb79ddd48 | 39 | ns_mem_word_size_t *heap_main_end; |
leothedragon | 0:8f0bb79ddd48 | 40 | mem_stat_t *mem_stat_info_ptr; |
leothedragon | 0:8f0bb79ddd48 | 41 | void (*heap_failure_callback)(heap_fail_t); |
leothedragon | 0:8f0bb79ddd48 | 42 | NS_LIST_HEAD(hole_t, link) holes_list; |
leothedragon | 0:8f0bb79ddd48 | 43 | ns_mem_heap_size_t heap_size; |
leothedragon | 0:8f0bb79ddd48 | 44 | ns_mem_heap_size_t temporary_alloc_heap_limit; /* Amount of reserved heap temporary alloc can't exceed */ |
leothedragon | 0:8f0bb79ddd48 | 45 | }; |
leothedragon | 0:8f0bb79ddd48 | 46 | |
leothedragon | 0:8f0bb79ddd48 | 47 | static ns_mem_book_t *default_book; // heap pointer for original "ns_" API use |
leothedragon | 0:8f0bb79ddd48 | 48 | |
leothedragon | 0:8f0bb79ddd48 | 49 | // size of a hole_t in our word units |
leothedragon | 0:8f0bb79ddd48 | 50 | #define HOLE_T_SIZE ((ns_mem_word_size_t) ((sizeof(hole_t) + sizeof(ns_mem_word_size_t) - 1) / sizeof(ns_mem_word_size_t))) |
leothedragon | 0:8f0bb79ddd48 | 51 | |
leothedragon | 0:8f0bb79ddd48 | 52 | #define TEMPORARY_ALLOC_FREE_HEAP_THRESHOLD 5 /* temporary allocations must leave 5% of the heap free */ |
leothedragon | 0:8f0bb79ddd48 | 53 | |
leothedragon | 0:8f0bb79ddd48 | 54 | static NS_INLINE hole_t *hole_from_block_start(ns_mem_word_size_t *start) |
leothedragon | 0:8f0bb79ddd48 | 55 | { |
leothedragon | 0:8f0bb79ddd48 | 56 | return (hole_t *)(start + 1); |
leothedragon | 0:8f0bb79ddd48 | 57 | } |
leothedragon | 0:8f0bb79ddd48 | 58 | |
leothedragon | 0:8f0bb79ddd48 | 59 | static NS_INLINE ns_mem_word_size_t *block_start_from_hole(hole_t *start) |
leothedragon | 0:8f0bb79ddd48 | 60 | { |
leothedragon | 0:8f0bb79ddd48 | 61 | return ((ns_mem_word_size_t *)start) - 1; |
leothedragon | 0:8f0bb79ddd48 | 62 | } |
leothedragon | 0:8f0bb79ddd48 | 63 | |
leothedragon | 0:8f0bb79ddd48 | 64 | static void heap_failure(ns_mem_book_t *book, heap_fail_t reason) |
leothedragon | 0:8f0bb79ddd48 | 65 | { |
leothedragon | 0:8f0bb79ddd48 | 66 | if (book->heap_failure_callback) { |
leothedragon | 0:8f0bb79ddd48 | 67 | book->heap_failure_callback(reason); |
leothedragon | 0:8f0bb79ddd48 | 68 | } |
leothedragon | 0:8f0bb79ddd48 | 69 | } |
leothedragon | 0:8f0bb79ddd48 | 70 | |
leothedragon | 0:8f0bb79ddd48 | 71 | #endif |
leothedragon | 0:8f0bb79ddd48 | 72 | |
leothedragon | 0:8f0bb79ddd48 | 73 | void ns_dyn_mem_init(void *heap, ns_mem_heap_size_t h_size, |
leothedragon | 0:8f0bb79ddd48 | 74 | void (*passed_fptr)(heap_fail_t), mem_stat_t *info_ptr) |
leothedragon | 0:8f0bb79ddd48 | 75 | { |
leothedragon | 0:8f0bb79ddd48 | 76 | default_book = ns_mem_init(heap, h_size, passed_fptr, info_ptr); |
leothedragon | 0:8f0bb79ddd48 | 77 | } |
leothedragon | 0:8f0bb79ddd48 | 78 | |
leothedragon | 0:8f0bb79ddd48 | 79 | const mem_stat_t *ns_dyn_mem_get_mem_stat(void) |
leothedragon | 0:8f0bb79ddd48 | 80 | { |
leothedragon | 0:8f0bb79ddd48 | 81 | #ifndef STANDARD_MALLOC |
leothedragon | 0:8f0bb79ddd48 | 82 | return ns_mem_get_mem_stat(default_book); |
leothedragon | 0:8f0bb79ddd48 | 83 | #else |
leothedragon | 0:8f0bb79ddd48 | 84 | return NULL; |
leothedragon | 0:8f0bb79ddd48 | 85 | #endif |
leothedragon | 0:8f0bb79ddd48 | 86 | } |
leothedragon | 0:8f0bb79ddd48 | 87 | |
leothedragon | 0:8f0bb79ddd48 | 88 | |
leothedragon | 0:8f0bb79ddd48 | 89 | ns_mem_book_t *ns_mem_init(void *heap, ns_mem_heap_size_t h_size, |
leothedragon | 0:8f0bb79ddd48 | 90 | void (*passed_fptr)(heap_fail_t), |
leothedragon | 0:8f0bb79ddd48 | 91 | mem_stat_t *info_ptr) |
leothedragon | 0:8f0bb79ddd48 | 92 | { |
leothedragon | 0:8f0bb79ddd48 | 93 | #ifndef STANDARD_MALLOC |
leothedragon | 0:8f0bb79ddd48 | 94 | ns_mem_book_t *book; |
leothedragon | 0:8f0bb79ddd48 | 95 | |
leothedragon | 0:8f0bb79ddd48 | 96 | ns_mem_word_size_t *ptr; |
leothedragon | 0:8f0bb79ddd48 | 97 | ns_mem_word_size_t temp_int; |
leothedragon | 0:8f0bb79ddd48 | 98 | /* Do memory alignment */ |
leothedragon | 0:8f0bb79ddd48 | 99 | temp_int = ((uintptr_t)heap % sizeof(ns_mem_word_size_t)); |
leothedragon | 0:8f0bb79ddd48 | 100 | if (temp_int) { |
leothedragon | 0:8f0bb79ddd48 | 101 | heap = (uint8_t *) heap + (sizeof(ns_mem_word_size_t) - temp_int); |
leothedragon | 0:8f0bb79ddd48 | 102 | h_size -= (sizeof(ns_mem_word_size_t) - temp_int); |
leothedragon | 0:8f0bb79ddd48 | 103 | } |
leothedragon | 0:8f0bb79ddd48 | 104 | |
leothedragon | 0:8f0bb79ddd48 | 105 | /* Make correction for total length also */ |
leothedragon | 0:8f0bb79ddd48 | 106 | temp_int = (h_size % sizeof(ns_mem_word_size_t)); |
leothedragon | 0:8f0bb79ddd48 | 107 | if (temp_int) { |
leothedragon | 0:8f0bb79ddd48 | 108 | h_size -= (sizeof(ns_mem_word_size_t) - temp_int); |
leothedragon | 0:8f0bb79ddd48 | 109 | } |
leothedragon | 0:8f0bb79ddd48 | 110 | book = heap; |
leothedragon | 0:8f0bb79ddd48 | 111 | book->heap_main = (ns_mem_word_size_t *) & (book[1]); // SET Heap Pointer |
leothedragon | 0:8f0bb79ddd48 | 112 | book->heap_size = h_size - sizeof(ns_mem_book_t); //Set Heap Size |
leothedragon | 0:8f0bb79ddd48 | 113 | temp_int = (book->heap_size / sizeof(ns_mem_word_size_t)); |
leothedragon | 0:8f0bb79ddd48 | 114 | temp_int -= 2; |
leothedragon | 0:8f0bb79ddd48 | 115 | ptr = book->heap_main; |
leothedragon | 0:8f0bb79ddd48 | 116 | *ptr = -(temp_int); |
leothedragon | 0:8f0bb79ddd48 | 117 | ptr += (temp_int + 1); |
leothedragon | 0:8f0bb79ddd48 | 118 | *ptr = -(temp_int); |
leothedragon | 0:8f0bb79ddd48 | 119 | book->heap_main_end = ptr; |
leothedragon | 0:8f0bb79ddd48 | 120 | |
leothedragon | 0:8f0bb79ddd48 | 121 | ns_list_init(&book->holes_list); |
leothedragon | 0:8f0bb79ddd48 | 122 | ns_list_add_to_start(&book->holes_list, hole_from_block_start(book->heap_main)); |
leothedragon | 0:8f0bb79ddd48 | 123 | |
leothedragon | 0:8f0bb79ddd48 | 124 | book->mem_stat_info_ptr = info_ptr; |
leothedragon | 0:8f0bb79ddd48 | 125 | //RESET Memory by Hea Len |
leothedragon | 0:8f0bb79ddd48 | 126 | if (info_ptr) { |
leothedragon | 0:8f0bb79ddd48 | 127 | memset(book->mem_stat_info_ptr, 0, sizeof(mem_stat_t)); |
leothedragon | 0:8f0bb79ddd48 | 128 | book->mem_stat_info_ptr->heap_sector_size = book->heap_size; |
leothedragon | 0:8f0bb79ddd48 | 129 | } |
leothedragon | 0:8f0bb79ddd48 | 130 | book->temporary_alloc_heap_limit = book->heap_size / 100 * (100 - TEMPORARY_ALLOC_FREE_HEAP_THRESHOLD); |
leothedragon | 0:8f0bb79ddd48 | 131 | #endif |
leothedragon | 0:8f0bb79ddd48 | 132 | //There really is no support to standard malloc in this library anymore |
leothedragon | 0:8f0bb79ddd48 | 133 | book->heap_failure_callback = passed_fptr; |
leothedragon | 0:8f0bb79ddd48 | 134 | |
leothedragon | 0:8f0bb79ddd48 | 135 | return book; |
leothedragon | 0:8f0bb79ddd48 | 136 | } |
leothedragon | 0:8f0bb79ddd48 | 137 | |
leothedragon | 0:8f0bb79ddd48 | 138 | const mem_stat_t *ns_mem_get_mem_stat(ns_mem_book_t *heap) |
leothedragon | 0:8f0bb79ddd48 | 139 | { |
leothedragon | 0:8f0bb79ddd48 | 140 | #ifndef STANDARD_MALLOC |
leothedragon | 0:8f0bb79ddd48 | 141 | return heap->mem_stat_info_ptr; |
leothedragon | 0:8f0bb79ddd48 | 142 | #else |
leothedragon | 0:8f0bb79ddd48 | 143 | return NULL; |
leothedragon | 0:8f0bb79ddd48 | 144 | #endif |
leothedragon | 0:8f0bb79ddd48 | 145 | } |
leothedragon | 0:8f0bb79ddd48 | 146 | |
leothedragon | 0:8f0bb79ddd48 | 147 | int ns_mem_set_temporary_alloc_free_heap_threshold(ns_mem_book_t *book, uint8_t free_heap_percentage, ns_mem_heap_size_t free_heap_amount) |
leothedragon | 0:8f0bb79ddd48 | 148 | { |
leothedragon | 0:8f0bb79ddd48 | 149 | #ifndef STANDARD_MALLOC |
leothedragon | 0:8f0bb79ddd48 | 150 | ns_mem_heap_size_t heap_limit = 0; |
leothedragon | 0:8f0bb79ddd48 | 151 | |
leothedragon | 0:8f0bb79ddd48 | 152 | if (!book || !book->mem_stat_info_ptr) { |
leothedragon | 0:8f0bb79ddd48 | 153 | // no book or mem_stats |
leothedragon | 0:8f0bb79ddd48 | 154 | return -1; |
leothedragon | 0:8f0bb79ddd48 | 155 | } |
leothedragon | 0:8f0bb79ddd48 | 156 | |
leothedragon | 0:8f0bb79ddd48 | 157 | if (free_heap_amount && free_heap_amount < book->heap_size / 2) { |
leothedragon | 0:8f0bb79ddd48 | 158 | heap_limit = book->heap_size - free_heap_amount; |
leothedragon | 0:8f0bb79ddd48 | 159 | } |
leothedragon | 0:8f0bb79ddd48 | 160 | |
leothedragon | 0:8f0bb79ddd48 | 161 | if (!free_heap_amount && free_heap_percentage && free_heap_percentage < 50) { |
leothedragon | 0:8f0bb79ddd48 | 162 | heap_limit = book->heap_size / 100 * (100 - free_heap_percentage); |
leothedragon | 0:8f0bb79ddd48 | 163 | } |
leothedragon | 0:8f0bb79ddd48 | 164 | |
leothedragon | 0:8f0bb79ddd48 | 165 | if (free_heap_amount == 0 && free_heap_percentage == 0) { |
leothedragon | 0:8f0bb79ddd48 | 166 | // feature disabled, allow whole heap to be reserved by temporary allo |
leothedragon | 0:8f0bb79ddd48 | 167 | heap_limit = book->heap_size; |
leothedragon | 0:8f0bb79ddd48 | 168 | } |
leothedragon | 0:8f0bb79ddd48 | 169 | |
leothedragon | 0:8f0bb79ddd48 | 170 | if (heap_limit == 0) { |
leothedragon | 0:8f0bb79ddd48 | 171 | // illegal heap parameters |
leothedragon | 0:8f0bb79ddd48 | 172 | return -2; |
leothedragon | 0:8f0bb79ddd48 | 173 | } |
leothedragon | 0:8f0bb79ddd48 | 174 | |
leothedragon | 0:8f0bb79ddd48 | 175 | book->temporary_alloc_heap_limit = heap_limit; |
leothedragon | 0:8f0bb79ddd48 | 176 | |
leothedragon | 0:8f0bb79ddd48 | 177 | return 0; |
leothedragon | 0:8f0bb79ddd48 | 178 | #else |
leothedragon | 0:8f0bb79ddd48 | 179 | return -3; |
leothedragon | 0:8f0bb79ddd48 | 180 | #endif |
leothedragon | 0:8f0bb79ddd48 | 181 | } |
leothedragon | 0:8f0bb79ddd48 | 182 | |
leothedragon | 0:8f0bb79ddd48 | 183 | extern int ns_dyn_mem_set_temporary_alloc_free_heap_threshold(uint8_t free_heap_percentage, ns_mem_heap_size_t free_heap_amount) |
leothedragon | 0:8f0bb79ddd48 | 184 | { |
leothedragon | 0:8f0bb79ddd48 | 185 | return ns_mem_set_temporary_alloc_free_heap_threshold(default_book, free_heap_percentage, free_heap_amount); |
leothedragon | 0:8f0bb79ddd48 | 186 | } |
leothedragon | 0:8f0bb79ddd48 | 187 | |
leothedragon | 0:8f0bb79ddd48 | 188 | #ifndef STANDARD_MALLOC |
leothedragon | 0:8f0bb79ddd48 | 189 | static void dev_stat_update(mem_stat_t *mem_stat_info_ptr, mem_stat_update_t type, ns_mem_block_size_t size) |
leothedragon | 0:8f0bb79ddd48 | 190 | { |
leothedragon | 0:8f0bb79ddd48 | 191 | if (mem_stat_info_ptr) { |
leothedragon | 0:8f0bb79ddd48 | 192 | switch (type) { |
leothedragon | 0:8f0bb79ddd48 | 193 | case DEV_HEAP_ALLOC_OK: |
leothedragon | 0:8f0bb79ddd48 | 194 | mem_stat_info_ptr->heap_sector_alloc_cnt++; |
leothedragon | 0:8f0bb79ddd48 | 195 | mem_stat_info_ptr->heap_sector_allocated_bytes += size; |
leothedragon | 0:8f0bb79ddd48 | 196 | if (mem_stat_info_ptr->heap_sector_allocated_bytes_max < mem_stat_info_ptr->heap_sector_allocated_bytes) { |
leothedragon | 0:8f0bb79ddd48 | 197 | mem_stat_info_ptr->heap_sector_allocated_bytes_max = mem_stat_info_ptr->heap_sector_allocated_bytes; |
leothedragon | 0:8f0bb79ddd48 | 198 | } |
leothedragon | 0:8f0bb79ddd48 | 199 | mem_stat_info_ptr->heap_alloc_total_bytes += size; |
leothedragon | 0:8f0bb79ddd48 | 200 | break; |
leothedragon | 0:8f0bb79ddd48 | 201 | case DEV_HEAP_ALLOC_FAIL: |
leothedragon | 0:8f0bb79ddd48 | 202 | mem_stat_info_ptr->heap_alloc_fail_cnt++; |
leothedragon | 0:8f0bb79ddd48 | 203 | break; |
leothedragon | 0:8f0bb79ddd48 | 204 | case DEV_HEAP_FREE: |
leothedragon | 0:8f0bb79ddd48 | 205 | mem_stat_info_ptr->heap_sector_alloc_cnt--; |
leothedragon | 0:8f0bb79ddd48 | 206 | mem_stat_info_ptr->heap_sector_allocated_bytes -= size; |
leothedragon | 0:8f0bb79ddd48 | 207 | break; |
leothedragon | 0:8f0bb79ddd48 | 208 | } |
leothedragon | 0:8f0bb79ddd48 | 209 | } |
leothedragon | 0:8f0bb79ddd48 | 210 | } |
leothedragon | 0:8f0bb79ddd48 | 211 | |
leothedragon | 0:8f0bb79ddd48 | 212 | static ns_mem_word_size_t convert_allocation_size(ns_mem_book_t *book, ns_mem_block_size_t requested_bytes) |
leothedragon | 0:8f0bb79ddd48 | 213 | { |
leothedragon | 0:8f0bb79ddd48 | 214 | if (book->heap_main == 0) { |
leothedragon | 0:8f0bb79ddd48 | 215 | heap_failure(book, NS_DYN_MEM_HEAP_SECTOR_UNITIALIZED); |
leothedragon | 0:8f0bb79ddd48 | 216 | } else if (requested_bytes < 1) { |
leothedragon | 0:8f0bb79ddd48 | 217 | heap_failure(book, NS_DYN_MEM_ALLOCATE_SIZE_NOT_VALID); |
leothedragon | 0:8f0bb79ddd48 | 218 | } else if (requested_bytes > (book->heap_size - 2 * sizeof(ns_mem_word_size_t))) { |
leothedragon | 0:8f0bb79ddd48 | 219 | heap_failure(book, NS_DYN_MEM_ALLOCATE_SIZE_NOT_VALID); |
leothedragon | 0:8f0bb79ddd48 | 220 | } |
leothedragon | 0:8f0bb79ddd48 | 221 | return (requested_bytes + sizeof(ns_mem_word_size_t) - 1) / sizeof(ns_mem_word_size_t); |
leothedragon | 0:8f0bb79ddd48 | 222 | } |
leothedragon | 0:8f0bb79ddd48 | 223 | |
leothedragon | 0:8f0bb79ddd48 | 224 | // Checks that block length indicators are valid |
leothedragon | 0:8f0bb79ddd48 | 225 | // Block has format: Size of data area [1 word] | data area [abs(size) words]| Size of data area [1 word] |
leothedragon | 0:8f0bb79ddd48 | 226 | // If Size is negative it means area is unallocated |
leothedragon | 0:8f0bb79ddd48 | 227 | static int8_t ns_mem_block_validate(ns_mem_word_size_t *block_start) |
leothedragon | 0:8f0bb79ddd48 | 228 | { |
leothedragon | 0:8f0bb79ddd48 | 229 | int8_t ret_val = -1; |
leothedragon | 0:8f0bb79ddd48 | 230 | ns_mem_word_size_t *end = block_start; |
leothedragon | 0:8f0bb79ddd48 | 231 | ns_mem_word_size_t size_start = *end; |
leothedragon | 0:8f0bb79ddd48 | 232 | end += (1 + abs(size_start)); |
leothedragon | 0:8f0bb79ddd48 | 233 | if (size_start != 0 && size_start == *end) { |
leothedragon | 0:8f0bb79ddd48 | 234 | ret_val = 0; |
leothedragon | 0:8f0bb79ddd48 | 235 | } |
leothedragon | 0:8f0bb79ddd48 | 236 | return ret_val; |
leothedragon | 0:8f0bb79ddd48 | 237 | } |
leothedragon | 0:8f0bb79ddd48 | 238 | #endif |
leothedragon | 0:8f0bb79ddd48 | 239 | |
leothedragon | 0:8f0bb79ddd48 | 240 | // For direction, use 1 for direction up and -1 for down |
leothedragon | 0:8f0bb79ddd48 | 241 | static void *ns_mem_internal_alloc(ns_mem_book_t *book, const ns_mem_block_size_t alloc_size, int direction) |
leothedragon | 0:8f0bb79ddd48 | 242 | { |
leothedragon | 0:8f0bb79ddd48 | 243 | #ifndef STANDARD_MALLOC |
leothedragon | 0:8f0bb79ddd48 | 244 | if (!book) { |
leothedragon | 0:8f0bb79ddd48 | 245 | /* We can not do anything except return NULL because we can't find book |
leothedragon | 0:8f0bb79ddd48 | 246 | keeping block */ |
leothedragon | 0:8f0bb79ddd48 | 247 | return NULL; |
leothedragon | 0:8f0bb79ddd48 | 248 | } |
leothedragon | 0:8f0bb79ddd48 | 249 | |
leothedragon | 0:8f0bb79ddd48 | 250 | if (book->mem_stat_info_ptr && direction == 1) { |
leothedragon | 0:8f0bb79ddd48 | 251 | if (book->mem_stat_info_ptr->heap_sector_allocated_bytes > book->temporary_alloc_heap_limit) { |
leothedragon | 0:8f0bb79ddd48 | 252 | /* Not enough heap for temporary memory allocation */ |
leothedragon | 0:8f0bb79ddd48 | 253 | dev_stat_update(book->mem_stat_info_ptr, DEV_HEAP_ALLOC_FAIL, 0); |
leothedragon | 0:8f0bb79ddd48 | 254 | return NULL; |
leothedragon | 0:8f0bb79ddd48 | 255 | } |
leothedragon | 0:8f0bb79ddd48 | 256 | } |
leothedragon | 0:8f0bb79ddd48 | 257 | |
leothedragon | 0:8f0bb79ddd48 | 258 | ns_mem_word_size_t *block_ptr = NULL; |
leothedragon | 0:8f0bb79ddd48 | 259 | |
leothedragon | 0:8f0bb79ddd48 | 260 | platform_enter_critical(); |
leothedragon | 0:8f0bb79ddd48 | 261 | |
leothedragon | 0:8f0bb79ddd48 | 262 | ns_mem_word_size_t data_size = convert_allocation_size(book, alloc_size); |
leothedragon | 0:8f0bb79ddd48 | 263 | if (!data_size) { |
leothedragon | 0:8f0bb79ddd48 | 264 | goto done; |
leothedragon | 0:8f0bb79ddd48 | 265 | } |
leothedragon | 0:8f0bb79ddd48 | 266 | |
leothedragon | 0:8f0bb79ddd48 | 267 | // ns_list_foreach, either forwards or backwards, result to ptr |
leothedragon | 0:8f0bb79ddd48 | 268 | for (hole_t *cur_hole = direction > 0 ? ns_list_get_first(&book->holes_list) |
leothedragon | 0:8f0bb79ddd48 | 269 | : ns_list_get_last(&book->holes_list); |
leothedragon | 0:8f0bb79ddd48 | 270 | cur_hole; |
leothedragon | 0:8f0bb79ddd48 | 271 | cur_hole = direction > 0 ? ns_list_get_next(&book->holes_list, cur_hole) |
leothedragon | 0:8f0bb79ddd48 | 272 | : ns_list_get_previous(&book->holes_list, cur_hole) |
leothedragon | 0:8f0bb79ddd48 | 273 | ) { |
leothedragon | 0:8f0bb79ddd48 | 274 | ns_mem_word_size_t *p = block_start_from_hole(cur_hole); |
leothedragon | 0:8f0bb79ddd48 | 275 | if (ns_mem_block_validate(p) != 0 || *p >= 0) { |
leothedragon | 0:8f0bb79ddd48 | 276 | //Validation failed, or this supposed hole has positive (allocated) size |
leothedragon | 0:8f0bb79ddd48 | 277 | heap_failure(book, NS_DYN_MEM_HEAP_SECTOR_CORRUPTED); |
leothedragon | 0:8f0bb79ddd48 | 278 | break; |
leothedragon | 0:8f0bb79ddd48 | 279 | } |
leothedragon | 0:8f0bb79ddd48 | 280 | if (-*p >= data_size) { |
leothedragon | 0:8f0bb79ddd48 | 281 | // Found a big enough block |
leothedragon | 0:8f0bb79ddd48 | 282 | block_ptr = p; |
leothedragon | 0:8f0bb79ddd48 | 283 | break; |
leothedragon | 0:8f0bb79ddd48 | 284 | } |
leothedragon | 0:8f0bb79ddd48 | 285 | } |
leothedragon | 0:8f0bb79ddd48 | 286 | |
leothedragon | 0:8f0bb79ddd48 | 287 | if (!block_ptr) { |
leothedragon | 0:8f0bb79ddd48 | 288 | goto done; |
leothedragon | 0:8f0bb79ddd48 | 289 | } |
leothedragon | 0:8f0bb79ddd48 | 290 | |
leothedragon | 0:8f0bb79ddd48 | 291 | // Separate declaration from initialization to keep IAR happy as the gotos skip this block. |
leothedragon | 0:8f0bb79ddd48 | 292 | ns_mem_word_size_t block_data_size; |
leothedragon | 0:8f0bb79ddd48 | 293 | block_data_size = -*block_ptr; |
leothedragon | 0:8f0bb79ddd48 | 294 | if (block_data_size >= (data_size + 2 + HOLE_T_SIZE)) { |
leothedragon | 0:8f0bb79ddd48 | 295 | ns_mem_word_size_t hole_size = block_data_size - data_size - 2; |
leothedragon | 0:8f0bb79ddd48 | 296 | ns_mem_word_size_t *hole_ptr; |
leothedragon | 0:8f0bb79ddd48 | 297 | //There is enough room for a new hole so create it first |
leothedragon | 0:8f0bb79ddd48 | 298 | if (direction > 0) { |
leothedragon | 0:8f0bb79ddd48 | 299 | hole_ptr = block_ptr + 1 + data_size + 1; |
leothedragon | 0:8f0bb79ddd48 | 300 | // Hole will be left at end of area. |
leothedragon | 0:8f0bb79ddd48 | 301 | // Would like to just replace this block_ptr with new descriptor, but |
leothedragon | 0:8f0bb79ddd48 | 302 | // they could overlap, so ns_list_replace might fail |
leothedragon | 0:8f0bb79ddd48 | 303 | //ns_list_replace(&holes_list, block_ptr, hole_from_block_start(hole_ptr)); |
leothedragon | 0:8f0bb79ddd48 | 304 | hole_t *before = ns_list_get_previous(&book->holes_list, hole_from_block_start(block_ptr)); |
leothedragon | 0:8f0bb79ddd48 | 305 | ns_list_remove(&book->holes_list, hole_from_block_start(block_ptr)); |
leothedragon | 0:8f0bb79ddd48 | 306 | if (before) { |
leothedragon | 0:8f0bb79ddd48 | 307 | ns_list_add_after(&book->holes_list, before, hole_from_block_start(hole_ptr)); |
leothedragon | 0:8f0bb79ddd48 | 308 | } else { |
leothedragon | 0:8f0bb79ddd48 | 309 | ns_list_add_to_start(&book->holes_list, hole_from_block_start(hole_ptr)); |
leothedragon | 0:8f0bb79ddd48 | 310 | } |
leothedragon | 0:8f0bb79ddd48 | 311 | } else { |
leothedragon | 0:8f0bb79ddd48 | 312 | hole_ptr = block_ptr; |
leothedragon | 0:8f0bb79ddd48 | 313 | // Hole remains at start of area - keep existing descriptor in place. |
leothedragon | 0:8f0bb79ddd48 | 314 | block_ptr += 1 + hole_size + 1; |
leothedragon | 0:8f0bb79ddd48 | 315 | } |
leothedragon | 0:8f0bb79ddd48 | 316 | |
leothedragon | 0:8f0bb79ddd48 | 317 | hole_ptr[0] = -hole_size; |
leothedragon | 0:8f0bb79ddd48 | 318 | hole_ptr[1 + hole_size] = -hole_size; |
leothedragon | 0:8f0bb79ddd48 | 319 | } else { |
leothedragon | 0:8f0bb79ddd48 | 320 | // Not enough room for a left-over hole, so use the whole block |
leothedragon | 0:8f0bb79ddd48 | 321 | data_size = block_data_size; |
leothedragon | 0:8f0bb79ddd48 | 322 | ns_list_remove(&book->holes_list, hole_from_block_start(block_ptr)); |
leothedragon | 0:8f0bb79ddd48 | 323 | } |
leothedragon | 0:8f0bb79ddd48 | 324 | block_ptr[0] = data_size; |
leothedragon | 0:8f0bb79ddd48 | 325 | block_ptr[1 + data_size] = data_size; |
leothedragon | 0:8f0bb79ddd48 | 326 | |
leothedragon | 0:8f0bb79ddd48 | 327 | done: |
leothedragon | 0:8f0bb79ddd48 | 328 | if (book->mem_stat_info_ptr) { |
leothedragon | 0:8f0bb79ddd48 | 329 | if (block_ptr) { |
leothedragon | 0:8f0bb79ddd48 | 330 | //Update Allocate OK |
leothedragon | 0:8f0bb79ddd48 | 331 | dev_stat_update(book->mem_stat_info_ptr, DEV_HEAP_ALLOC_OK, (data_size + 2) * sizeof(ns_mem_word_size_t)); |
leothedragon | 0:8f0bb79ddd48 | 332 | |
leothedragon | 0:8f0bb79ddd48 | 333 | } else { |
leothedragon | 0:8f0bb79ddd48 | 334 | //Update Allocate Fail, second parameter is used for stats |
leothedragon | 0:8f0bb79ddd48 | 335 | dev_stat_update(book->mem_stat_info_ptr, DEV_HEAP_ALLOC_FAIL, 0); |
leothedragon | 0:8f0bb79ddd48 | 336 | } |
leothedragon | 0:8f0bb79ddd48 | 337 | } |
leothedragon | 0:8f0bb79ddd48 | 338 | platform_exit_critical(); |
leothedragon | 0:8f0bb79ddd48 | 339 | |
leothedragon | 0:8f0bb79ddd48 | 340 | return block_ptr ? block_ptr + 1 : NULL; |
leothedragon | 0:8f0bb79ddd48 | 341 | #else |
leothedragon | 0:8f0bb79ddd48 | 342 | void *retval = NULL; |
leothedragon | 0:8f0bb79ddd48 | 343 | if (alloc_size) { |
leothedragon | 0:8f0bb79ddd48 | 344 | platform_enter_critical(); |
leothedragon | 0:8f0bb79ddd48 | 345 | retval = malloc(alloc_size); |
leothedragon | 0:8f0bb79ddd48 | 346 | platform_exit_critical(); |
leothedragon | 0:8f0bb79ddd48 | 347 | } |
leothedragon | 0:8f0bb79ddd48 | 348 | return retval; |
leothedragon | 0:8f0bb79ddd48 | 349 | #endif |
leothedragon | 0:8f0bb79ddd48 | 350 | } |
leothedragon | 0:8f0bb79ddd48 | 351 | |
leothedragon | 0:8f0bb79ddd48 | 352 | void *ns_mem_alloc(ns_mem_book_t *heap, ns_mem_block_size_t alloc_size) |
leothedragon | 0:8f0bb79ddd48 | 353 | { |
leothedragon | 0:8f0bb79ddd48 | 354 | return ns_mem_internal_alloc(heap, alloc_size, -1); |
leothedragon | 0:8f0bb79ddd48 | 355 | } |
leothedragon | 0:8f0bb79ddd48 | 356 | |
leothedragon | 0:8f0bb79ddd48 | 357 | void *ns_mem_temporary_alloc(ns_mem_book_t *heap, ns_mem_block_size_t alloc_size) |
leothedragon | 0:8f0bb79ddd48 | 358 | { |
leothedragon | 0:8f0bb79ddd48 | 359 | return ns_mem_internal_alloc(heap, alloc_size, 1); |
leothedragon | 0:8f0bb79ddd48 | 360 | } |
leothedragon | 0:8f0bb79ddd48 | 361 | |
leothedragon | 0:8f0bb79ddd48 | 362 | void *ns_dyn_mem_alloc(ns_mem_block_size_t alloc_size) |
leothedragon | 0:8f0bb79ddd48 | 363 | { |
leothedragon | 0:8f0bb79ddd48 | 364 | return ns_mem_alloc(default_book, alloc_size); |
leothedragon | 0:8f0bb79ddd48 | 365 | } |
leothedragon | 0:8f0bb79ddd48 | 366 | |
leothedragon | 0:8f0bb79ddd48 | 367 | void *ns_dyn_mem_temporary_alloc(ns_mem_block_size_t alloc_size) |
leothedragon | 0:8f0bb79ddd48 | 368 | { |
leothedragon | 0:8f0bb79ddd48 | 369 | return ns_mem_temporary_alloc(default_book, alloc_size); |
leothedragon | 0:8f0bb79ddd48 | 370 | } |
leothedragon | 0:8f0bb79ddd48 | 371 | |
leothedragon | 0:8f0bb79ddd48 | 372 | #ifndef STANDARD_MALLOC |
leothedragon | 0:8f0bb79ddd48 | 373 | static void ns_mem_free_and_merge_with_adjacent_blocks(ns_mem_book_t *book, ns_mem_word_size_t *cur_block, ns_mem_word_size_t data_size) |
leothedragon | 0:8f0bb79ddd48 | 374 | { |
leothedragon | 0:8f0bb79ddd48 | 375 | // Theory of operation: Block is always in form | Len | Data | Len | |
leothedragon | 0:8f0bb79ddd48 | 376 | // So we need to check length of previous (if current not heap start) |
leothedragon | 0:8f0bb79ddd48 | 377 | // and next (if current not heap end) blocks. Negative length means |
leothedragon | 0:8f0bb79ddd48 | 378 | // free memory so we can merge freed block with those. |
leothedragon | 0:8f0bb79ddd48 | 379 | |
leothedragon | 0:8f0bb79ddd48 | 380 | hole_t *existing_start = NULL; |
leothedragon | 0:8f0bb79ddd48 | 381 | hole_t *existing_end = NULL; |
leothedragon | 0:8f0bb79ddd48 | 382 | ns_mem_word_size_t *start = cur_block; |
leothedragon | 0:8f0bb79ddd48 | 383 | ns_mem_word_size_t *end = cur_block + data_size + 1; |
leothedragon | 0:8f0bb79ddd48 | 384 | //invalidate current block |
leothedragon | 0:8f0bb79ddd48 | 385 | *start = -data_size; |
leothedragon | 0:8f0bb79ddd48 | 386 | *end = -data_size; |
leothedragon | 0:8f0bb79ddd48 | 387 | ns_mem_word_size_t merged_data_size = data_size; |
leothedragon | 0:8f0bb79ddd48 | 388 | |
leothedragon | 0:8f0bb79ddd48 | 389 | if (start != book->heap_main) { |
leothedragon | 0:8f0bb79ddd48 | 390 | if (*(start - 1) < 0) { |
leothedragon | 0:8f0bb79ddd48 | 391 | ns_mem_word_size_t *block_end = start - 1; |
leothedragon | 0:8f0bb79ddd48 | 392 | ns_mem_word_size_t block_size = 1 + (-*block_end) + 1; |
leothedragon | 0:8f0bb79ddd48 | 393 | merged_data_size += block_size; |
leothedragon | 0:8f0bb79ddd48 | 394 | start -= block_size; |
leothedragon | 0:8f0bb79ddd48 | 395 | if (*start != *block_end) { |
leothedragon | 0:8f0bb79ddd48 | 396 | heap_failure(book, NS_DYN_MEM_HEAP_SECTOR_CORRUPTED); |
leothedragon | 0:8f0bb79ddd48 | 397 | } |
leothedragon | 0:8f0bb79ddd48 | 398 | if (block_size >= 1 + HOLE_T_SIZE + 1) { |
leothedragon | 0:8f0bb79ddd48 | 399 | existing_start = hole_from_block_start(start); |
leothedragon | 0:8f0bb79ddd48 | 400 | } |
leothedragon | 0:8f0bb79ddd48 | 401 | } |
leothedragon | 0:8f0bb79ddd48 | 402 | } |
leothedragon | 0:8f0bb79ddd48 | 403 | |
leothedragon | 0:8f0bb79ddd48 | 404 | if (end != book->heap_main_end) { |
leothedragon | 0:8f0bb79ddd48 | 405 | if (*(end + 1) < 0) { |
leothedragon | 0:8f0bb79ddd48 | 406 | ns_mem_word_size_t *block_start = end + 1; |
leothedragon | 0:8f0bb79ddd48 | 407 | ns_mem_word_size_t block_size = 1 + (-*block_start) + 1; |
leothedragon | 0:8f0bb79ddd48 | 408 | merged_data_size += block_size; |
leothedragon | 0:8f0bb79ddd48 | 409 | end += block_size; |
leothedragon | 0:8f0bb79ddd48 | 410 | if (*end != *block_start) { |
leothedragon | 0:8f0bb79ddd48 | 411 | heap_failure(book, NS_DYN_MEM_HEAP_SECTOR_CORRUPTED); |
leothedragon | 0:8f0bb79ddd48 | 412 | } |
leothedragon | 0:8f0bb79ddd48 | 413 | if (block_size >= 1 + HOLE_T_SIZE + 1) { |
leothedragon | 0:8f0bb79ddd48 | 414 | existing_end = hole_from_block_start(block_start); |
leothedragon | 0:8f0bb79ddd48 | 415 | } |
leothedragon | 0:8f0bb79ddd48 | 416 | } |
leothedragon | 0:8f0bb79ddd48 | 417 | } |
leothedragon | 0:8f0bb79ddd48 | 418 | |
leothedragon | 0:8f0bb79ddd48 | 419 | hole_t *to_add = hole_from_block_start(start); |
leothedragon | 0:8f0bb79ddd48 | 420 | hole_t *before = NULL; |
leothedragon | 0:8f0bb79ddd48 | 421 | if (existing_end) { |
leothedragon | 0:8f0bb79ddd48 | 422 | // Extending hole described by "existing_end" downwards. |
leothedragon | 0:8f0bb79ddd48 | 423 | // Will replace with descriptor at bottom of merged block. |
leothedragon | 0:8f0bb79ddd48 | 424 | // (Can't use ns_list_replace, because of danger of overlap) |
leothedragon | 0:8f0bb79ddd48 | 425 | // Optimisation - note our position for insertion below. |
leothedragon | 0:8f0bb79ddd48 | 426 | before = ns_list_get_next(&book->holes_list, existing_end); |
leothedragon | 0:8f0bb79ddd48 | 427 | ns_list_remove(&book->holes_list, existing_end); |
leothedragon | 0:8f0bb79ddd48 | 428 | } |
leothedragon | 0:8f0bb79ddd48 | 429 | if (existing_start) { |
leothedragon | 0:8f0bb79ddd48 | 430 | // Extending hole described by "existing_start" upwards. |
leothedragon | 0:8f0bb79ddd48 | 431 | // No need to modify that descriptor - it remains at the bottom |
leothedragon | 0:8f0bb79ddd48 | 432 | // of the merged block to describe it. |
leothedragon | 0:8f0bb79ddd48 | 433 | } else { |
leothedragon | 0:8f0bb79ddd48 | 434 | // Didn't find adjacent descriptors, but may still |
leothedragon | 0:8f0bb79ddd48 | 435 | // be merging with small blocks without descriptors. |
leothedragon | 0:8f0bb79ddd48 | 436 | if (merged_data_size >= HOLE_T_SIZE) { |
leothedragon | 0:8f0bb79ddd48 | 437 | // Locate hole position in list, if we don't already know |
leothedragon | 0:8f0bb79ddd48 | 438 | // from merging with the block above. |
leothedragon | 0:8f0bb79ddd48 | 439 | if (!existing_end) { |
leothedragon | 0:8f0bb79ddd48 | 440 | ns_list_foreach(hole_t, ptr, &book->holes_list) { |
leothedragon | 0:8f0bb79ddd48 | 441 | if (ptr > to_add) { |
leothedragon | 0:8f0bb79ddd48 | 442 | before = ptr; |
leothedragon | 0:8f0bb79ddd48 | 443 | break; |
leothedragon | 0:8f0bb79ddd48 | 444 | } |
leothedragon | 0:8f0bb79ddd48 | 445 | } |
leothedragon | 0:8f0bb79ddd48 | 446 | } |
leothedragon | 0:8f0bb79ddd48 | 447 | if (before) { |
leothedragon | 0:8f0bb79ddd48 | 448 | ns_list_add_before(&book->holes_list, before, to_add); |
leothedragon | 0:8f0bb79ddd48 | 449 | } else { |
leothedragon | 0:8f0bb79ddd48 | 450 | ns_list_add_to_end(&book->holes_list, to_add); |
leothedragon | 0:8f0bb79ddd48 | 451 | } |
leothedragon | 0:8f0bb79ddd48 | 452 | |
leothedragon | 0:8f0bb79ddd48 | 453 | } |
leothedragon | 0:8f0bb79ddd48 | 454 | } |
leothedragon | 0:8f0bb79ddd48 | 455 | *start = -merged_data_size; |
leothedragon | 0:8f0bb79ddd48 | 456 | *end = -merged_data_size; |
leothedragon | 0:8f0bb79ddd48 | 457 | } |
leothedragon | 0:8f0bb79ddd48 | 458 | #endif |
leothedragon | 0:8f0bb79ddd48 | 459 | |
leothedragon | 0:8f0bb79ddd48 | 460 | void ns_mem_free(ns_mem_book_t *book, void *block) |
leothedragon | 0:8f0bb79ddd48 | 461 | { |
leothedragon | 0:8f0bb79ddd48 | 462 | #ifndef STANDARD_MALLOC |
leothedragon | 0:8f0bb79ddd48 | 463 | |
leothedragon | 0:8f0bb79ddd48 | 464 | if (!block) { |
leothedragon | 0:8f0bb79ddd48 | 465 | return; |
leothedragon | 0:8f0bb79ddd48 | 466 | } |
leothedragon | 0:8f0bb79ddd48 | 467 | |
leothedragon | 0:8f0bb79ddd48 | 468 | ns_mem_word_size_t *ptr = block; |
leothedragon | 0:8f0bb79ddd48 | 469 | ns_mem_word_size_t size; |
leothedragon | 0:8f0bb79ddd48 | 470 | |
leothedragon | 0:8f0bb79ddd48 | 471 | platform_enter_critical(); |
leothedragon | 0:8f0bb79ddd48 | 472 | ptr --; |
leothedragon | 0:8f0bb79ddd48 | 473 | //Read Current Size |
leothedragon | 0:8f0bb79ddd48 | 474 | size = *ptr; |
leothedragon | 0:8f0bb79ddd48 | 475 | if (ptr < book->heap_main || ptr >= book->heap_main_end) { |
leothedragon | 0:8f0bb79ddd48 | 476 | heap_failure(book, NS_DYN_MEM_POINTER_NOT_VALID); |
leothedragon | 0:8f0bb79ddd48 | 477 | } else if ((ptr + size) >= book->heap_main_end) { |
leothedragon | 0:8f0bb79ddd48 | 478 | heap_failure(book, NS_DYN_MEM_POINTER_NOT_VALID); |
leothedragon | 0:8f0bb79ddd48 | 479 | } else if (size < 0) { |
leothedragon | 0:8f0bb79ddd48 | 480 | heap_failure(book, NS_DYN_MEM_DOUBLE_FREE); |
leothedragon | 0:8f0bb79ddd48 | 481 | } else { |
leothedragon | 0:8f0bb79ddd48 | 482 | if (ns_mem_block_validate(ptr) != 0) { |
leothedragon | 0:8f0bb79ddd48 | 483 | heap_failure(book, NS_DYN_MEM_HEAP_SECTOR_CORRUPTED); |
leothedragon | 0:8f0bb79ddd48 | 484 | } else { |
leothedragon | 0:8f0bb79ddd48 | 485 | ns_mem_free_and_merge_with_adjacent_blocks(book, ptr, size); |
leothedragon | 0:8f0bb79ddd48 | 486 | if (book->mem_stat_info_ptr) { |
leothedragon | 0:8f0bb79ddd48 | 487 | //Update Free Counter |
leothedragon | 0:8f0bb79ddd48 | 488 | dev_stat_update(book->mem_stat_info_ptr, DEV_HEAP_FREE, (size + 2) * sizeof(ns_mem_word_size_t)); |
leothedragon | 0:8f0bb79ddd48 | 489 | } |
leothedragon | 0:8f0bb79ddd48 | 490 | } |
leothedragon | 0:8f0bb79ddd48 | 491 | } |
leothedragon | 0:8f0bb79ddd48 | 492 | platform_exit_critical(); |
leothedragon | 0:8f0bb79ddd48 | 493 | #else |
leothedragon | 0:8f0bb79ddd48 | 494 | platform_enter_critical(); |
leothedragon | 0:8f0bb79ddd48 | 495 | free(block); |
leothedragon | 0:8f0bb79ddd48 | 496 | platform_exit_critical(); |
leothedragon | 0:8f0bb79ddd48 | 497 | #endif |
leothedragon | 0:8f0bb79ddd48 | 498 | } |
leothedragon | 0:8f0bb79ddd48 | 499 | |
leothedragon | 0:8f0bb79ddd48 | 500 | void ns_dyn_mem_free(void *block) |
leothedragon | 0:8f0bb79ddd48 | 501 | { |
leothedragon | 0:8f0bb79ddd48 | 502 | ns_mem_free(default_book, block); |
leothedragon | 0:8f0bb79ddd48 | 503 | } |