erkin yucel / mbed-os

Dependents:   BLE_file_test BLE_Blink ExternalEncoder

Committer:
elessair
Date:
Sun Oct 23 15:10:02 2016 +0000
Revision:
0:f269e3021894
Initial commit

Who changed what in which revision?

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