/* * Copyright (c) 2021 Carlo Caione, * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #include #include static struct sys_multi_heap shared_multi_heap; static struct { struct sys_heap heap_pool[MAX_MULTI_HEAPS]; unsigned int heap_cnt; } smh_data[MAX_SHARED_MULTI_HEAP_ATTR]; static void *smh_choice(struct sys_multi_heap *mheap, void *cfg, size_t align, size_t size) { struct sys_heap *h; enum shared_multi_heap_attr attr; void *block; attr = (enum shared_multi_heap_attr)(long) cfg; if (attr >= MAX_SHARED_MULTI_HEAP_ATTR || size == 0) { return NULL; } /* Set in case the user requested a non-existing attr */ block = NULL; for (size_t hdx = 0; hdx < smh_data[attr].heap_cnt; hdx++) { h = &smh_data[attr].heap_pool[hdx]; if (h->heap == NULL) { return NULL; } block = sys_heap_aligned_alloc(h, align, size); if (block != NULL) { break; } } return block; } int shared_multi_heap_add(struct shared_multi_heap_region *region, void *user_data) { enum shared_multi_heap_attr attr; struct sys_heap *h; unsigned int slot; attr = region->attr; if (attr >= MAX_SHARED_MULTI_HEAP_ATTR) { return -EINVAL; } /* No more heaps available */ if (smh_data[attr].heap_cnt >= MAX_MULTI_HEAPS) { return -ENOMEM; } slot = smh_data[attr].heap_cnt; h = &smh_data[attr].heap_pool[slot]; sys_heap_init(h, (void *) region->addr, region->size); sys_multi_heap_add_heap(&shared_multi_heap, h, user_data); smh_data[attr].heap_cnt++; return 0; } void shared_multi_heap_free(void *block) { sys_multi_heap_free(&shared_multi_heap, block); } void *shared_multi_heap_alloc(enum shared_multi_heap_attr attr, size_t bytes) { if (attr >= MAX_SHARED_MULTI_HEAP_ATTR) { return NULL; } return sys_multi_heap_alloc(&shared_multi_heap, (void *)(long) attr, bytes); } void *shared_multi_heap_aligned_alloc(enum shared_multi_heap_attr attr, size_t align, size_t bytes) { if (attr >= MAX_SHARED_MULTI_HEAP_ATTR) { return NULL; } return sys_multi_heap_aligned_alloc(&shared_multi_heap, (void *)(long) attr, align, bytes); } int shared_multi_heap_pool_init(void) { static atomic_t state; if (!atomic_cas(&state, 0, 1)) { return -EALREADY; } sys_multi_heap_init(&shared_multi_heap, smh_choice); atomic_set(&state, 1); return 0; }