Toyomasa Watarai / simple-mbed-cloud-client

Dependents:  

Committer:
MACRUM
Date:
Mon Jul 02 06:30:39 2018 +0000
Revision:
0:276e7a263c35
Initial commit

Who changed what in which revision?

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