Deallocate the given small/medium memory block from the given heap
| 976 | |
| 977 | //! Deallocate the given small/medium memory block from the given heap |
| 978 | static void |
| 979 | _memory_deallocate_to_heap(heap_t* heap, span_t* span, void* p) { |
| 980 | //Check if span is the currently active span in order to operate |
| 981 | //on the correct bookkeeping data |
| 982 | const count_t class_idx = span->size_class; |
| 983 | size_class_t* size_class = _memory_size_class + class_idx; |
| 984 | int is_active = (heap->active_span[class_idx] == span); |
| 985 | span_block_t* block_data = is_active ? |
| 986 | heap->active_block + class_idx : |
| 987 | &span->data.block; |
| 988 | |
| 989 | #if ENABLE_STATISTICS |
| 990 | heap->allocated -= size_class->size; |
| 991 | heap->requested -= *(size_t*)pointer_offset(p, size_class->size - sizeof(size_t)); |
| 992 | #endif |
| 993 | |
| 994 | //Check if the span will become completely free |
| 995 | if (block_data->free_count == ((count_t)size_class->block_count - 1)) { |
| 996 | //Track counters |
| 997 | size_t span_class_idx = _span_class_from_page_count(size_class->page_count); |
| 998 | assert(heap->span_counter[span_class_idx].current_allocations > 0); |
| 999 | --heap->span_counter[span_class_idx].current_allocations; |
| 1000 | |
| 1001 | //If it was active, reset counter. Otherwise, if not active, remove from |
| 1002 | //partial free list if we had a previous free block (guard for classes with only 1 block) |
| 1003 | if (is_active) |
| 1004 | block_data->free_count = 0; |
| 1005 | else if (block_data->free_count > 0) |
| 1006 | _memory_list_remove(&heap->size_cache[class_idx], span); |
| 1007 | |
| 1008 | //Add to span cache |
| 1009 | _memory_heap_cache_insert(heap, span, size_class->page_count); |
| 1010 | return; |
| 1011 | } |
| 1012 | |
| 1013 | //Check if first free block for this span (previously fully allocated) |
| 1014 | if (block_data->free_count == 0) { |
| 1015 | //add to free list and disable autolink |
| 1016 | _memory_list_add(&heap->size_cache[class_idx], span); |
| 1017 | block_data->first_autolink = (uint16_t)size_class->block_count; |
| 1018 | } |
| 1019 | ++block_data->free_count; |
| 1020 | //Span is not yet completely free, so add block to the linked list of free blocks |
| 1021 | void* blocks_start = pointer_offset(span, SPAN_HEADER_SIZE); |
| 1022 | count_t block_offset = (count_t)pointer_diff(p, blocks_start); |
| 1023 | count_t block_idx = block_offset / (count_t)size_class->size; |
| 1024 | uint32_t* block = pointer_offset(blocks_start, block_idx * size_class->size); |
| 1025 | *block = block_data->free_list; |
| 1026 | block_data->free_list = (uint16_t)block_idx; |
| 1027 | } |
| 1028 | |
| 1029 | //! Deallocate the given large memory block from the given heap |
| 1030 | static void |
no test coverage detected