Andy Ross | 73cb958 | 2017-05-09 10:42:39 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2017 Intel Corporation |
| 3 | * |
| 4 | * SPDX-License-Identifier: Apache-2.0 |
| 5 | */ |
| 6 | |
| 7 | #include <kernel.h> |
Andy Ross | 73cb958 | 2017-05-09 10:42:39 -0700 | [diff] [blame] | 8 | #include <string.h> |
Anas Nashif | 6ecadb0 | 2019-06-26 10:33:45 -0400 | [diff] [blame] | 9 | #include <sys/math_extras.h> |
Christopher Friedt | 135ffaf | 2020-11-26 08:19:10 -0500 | [diff] [blame] | 10 | #include <sys/util.h> |
Andy Ross | 73cb958 | 2017-05-09 10:42:39 -0700 | [diff] [blame] | 11 | |
Christopher Friedt | 135ffaf | 2020-11-26 08:19:10 -0500 | [diff] [blame] | 12 | static void *z_heap_aligned_alloc(struct k_heap *heap, size_t align, size_t size) |
Andrew Boie | a2480bd | 2018-04-12 16:59:02 -0700 | [diff] [blame] | 13 | { |
Nicolas Pitre | a2011d8 | 2021-01-15 22:39:02 -0500 | [diff] [blame] | 14 | void *mem; |
Christopher Friedt | 135ffaf | 2020-11-26 08:19:10 -0500 | [diff] [blame] | 15 | struct k_heap **heap_ref; |
Nicolas Pitre | a2011d8 | 2021-01-15 22:39:02 -0500 | [diff] [blame] | 16 | size_t __align; |
Christopher Friedt | 135ffaf | 2020-11-26 08:19:10 -0500 | [diff] [blame] | 17 | |
Andrew Boie | a2480bd | 2018-04-12 16:59:02 -0700 | [diff] [blame] | 18 | /* |
Nicolas Pitre | a2011d8 | 2021-01-15 22:39:02 -0500 | [diff] [blame] | 19 | * Adjust the size to make room for our heap reference. |
| 20 | * Merge a rewind bit with align value (see sys_heap_aligned_alloc()). |
| 21 | * This allows for storing the heap pointer right below the aligned |
| 22 | * boundary without wasting any memory. |
Andrew Boie | a2480bd | 2018-04-12 16:59:02 -0700 | [diff] [blame] | 23 | */ |
Nicolas Pitre | a2011d8 | 2021-01-15 22:39:02 -0500 | [diff] [blame] | 24 | if (size_add_overflow(size, sizeof(heap_ref), &size)) { |
Andrew Boie | a2480bd | 2018-04-12 16:59:02 -0700 | [diff] [blame] | 25 | return NULL; |
| 26 | } |
Nicolas Pitre | a2011d8 | 2021-01-15 22:39:02 -0500 | [diff] [blame] | 27 | __align = align | sizeof(heap_ref); |
Andy Ross | 9413922 | 2020-10-01 09:43:04 -0700 | [diff] [blame] | 28 | |
Nicolas Pitre | a2011d8 | 2021-01-15 22:39:02 -0500 | [diff] [blame] | 29 | mem = k_heap_aligned_alloc(heap, __align, size, K_NO_WAIT); |
Christopher Friedt | 135ffaf | 2020-11-26 08:19:10 -0500 | [diff] [blame] | 30 | if (mem == NULL) { |
Andrew Boie | a2480bd | 2018-04-12 16:59:02 -0700 | [diff] [blame] | 31 | return NULL; |
| 32 | } |
| 33 | |
Nicolas Pitre | a2011d8 | 2021-01-15 22:39:02 -0500 | [diff] [blame] | 34 | heap_ref = mem; |
Christopher Friedt | 135ffaf | 2020-11-26 08:19:10 -0500 | [diff] [blame] | 35 | *heap_ref = heap; |
Nicolas Pitre | a2011d8 | 2021-01-15 22:39:02 -0500 | [diff] [blame] | 36 | mem = ++heap_ref; |
| 37 | __ASSERT(align == 0 || ((uintptr_t)mem & (align - 1)) == 0, |
| 38 | "misaligned memory at %p (align = %zu)", mem, align); |
Andrew Boie | a2480bd | 2018-04-12 16:59:02 -0700 | [diff] [blame] | 39 | |
Nicolas Pitre | a2011d8 | 2021-01-15 22:39:02 -0500 | [diff] [blame] | 40 | return mem; |
Christopher Friedt | 135ffaf | 2020-11-26 08:19:10 -0500 | [diff] [blame] | 41 | } |
| 42 | |
Andrew Boie | a2480bd | 2018-04-12 16:59:02 -0700 | [diff] [blame] | 43 | void k_free(void *ptr) |
| 44 | { |
Christopher Friedt | 135ffaf | 2020-11-26 08:19:10 -0500 | [diff] [blame] | 45 | struct k_heap **heap_ref; |
Andrew Boie | a2480bd | 2018-04-12 16:59:02 -0700 | [diff] [blame] | 46 | |
Christopher Friedt | 135ffaf | 2020-11-26 08:19:10 -0500 | [diff] [blame] | 47 | if (ptr != NULL) { |
Nicolas Pitre | a2011d8 | 2021-01-15 22:39:02 -0500 | [diff] [blame] | 48 | heap_ref = ptr; |
| 49 | ptr = --heap_ref; |
Torbjörn Leksell | 80cd9da | 2021-03-26 13:42:25 +0100 | [diff] [blame] | 50 | |
| 51 | SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_heap_sys, k_free, *heap_ref); |
| 52 | |
Christopher Friedt | 135ffaf | 2020-11-26 08:19:10 -0500 | [diff] [blame] | 53 | k_heap_free(*heap_ref, ptr); |
Torbjörn Leksell | 80cd9da | 2021-03-26 13:42:25 +0100 | [diff] [blame] | 54 | |
| 55 | SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_heap_sys, k_free, *heap_ref); |
Andrew Boie | a2480bd | 2018-04-12 16:59:02 -0700 | [diff] [blame] | 56 | } |
| 57 | } |
| 58 | |
Andy Ross | 73cb958 | 2017-05-09 10:42:39 -0700 | [diff] [blame] | 59 | #if (CONFIG_HEAP_MEM_POOL_SIZE > 0) |
| 60 | |
Andy Ross | c770cab | 2020-10-02 08:22:03 -0700 | [diff] [blame] | 61 | K_HEAP_DEFINE(_system_heap, CONFIG_HEAP_MEM_POOL_SIZE); |
| 62 | #define _SYSTEM_HEAP (&_system_heap) |
Andy Ross | 73cb958 | 2017-05-09 10:42:39 -0700 | [diff] [blame] | 63 | |
Christopher Friedt | 135ffaf | 2020-11-26 08:19:10 -0500 | [diff] [blame] | 64 | void *k_aligned_alloc(size_t align, size_t size) |
Andy Ross | 73cb958 | 2017-05-09 10:42:39 -0700 | [diff] [blame] | 65 | { |
Christopher Friedt | 135ffaf | 2020-11-26 08:19:10 -0500 | [diff] [blame] | 66 | __ASSERT(align / sizeof(void *) >= 1 |
| 67 | && (align % sizeof(void *)) == 0, |
| 68 | "align must be a multiple of sizeof(void *)"); |
| 69 | |
| 70 | __ASSERT((align & (align - 1)) == 0, |
| 71 | "align must be a power of 2"); |
| 72 | |
Torbjörn Leksell | 80cd9da | 2021-03-26 13:42:25 +0100 | [diff] [blame] | 73 | SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_heap_sys, k_aligned_alloc, _SYSTEM_HEAP); |
| 74 | |
| 75 | void *ret = z_heap_aligned_alloc(_SYSTEM_HEAP, align, size); |
| 76 | |
| 77 | SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_heap_sys, k_aligned_alloc, _SYSTEM_HEAP, ret); |
| 78 | |
| 79 | return ret; |
| 80 | } |
| 81 | |
| 82 | void *k_malloc(size_t size) |
| 83 | { |
| 84 | SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_heap_sys, k_malloc, _SYSTEM_HEAP); |
| 85 | |
| 86 | void *ret = k_aligned_alloc(sizeof(void *), size); |
| 87 | |
| 88 | SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_heap_sys, k_malloc, _SYSTEM_HEAP, ret); |
| 89 | |
| 90 | return ret; |
Andy Ross | 73cb958 | 2017-05-09 10:42:39 -0700 | [diff] [blame] | 91 | } |
Andrew Boie | 7f95e83 | 2017-11-08 14:40:01 -0800 | [diff] [blame] | 92 | |
| 93 | void *k_calloc(size_t nmemb, size_t size) |
| 94 | { |
| 95 | void *ret; |
| 96 | size_t bounds; |
| 97 | |
Torbjörn Leksell | 80cd9da | 2021-03-26 13:42:25 +0100 | [diff] [blame] | 98 | SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_heap_sys, k_calloc, _SYSTEM_HEAP); |
| 99 | |
Jakob Olesen | c8708d9 | 2019-05-07 10:17:35 -0700 | [diff] [blame] | 100 | if (size_mul_overflow(nmemb, size, &bounds)) { |
Torbjörn Leksell | 80cd9da | 2021-03-26 13:42:25 +0100 | [diff] [blame] | 101 | SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_heap_sys, k_calloc, _SYSTEM_HEAP, NULL); |
| 102 | |
Leandro Pereira | 85dcc97 | 2018-04-12 12:53:57 -0700 | [diff] [blame] | 103 | return NULL; |
| 104 | } |
| 105 | |
Andrew Boie | 7f95e83 | 2017-11-08 14:40:01 -0800 | [diff] [blame] | 106 | ret = k_malloc(bounds); |
Flavio Ceolin | 4218d5f | 2018-09-17 09:39:51 -0700 | [diff] [blame] | 107 | if (ret != NULL) { |
Flavio Ceolin | da49f2e | 2018-09-11 19:09:03 -0700 | [diff] [blame] | 108 | (void)memset(ret, 0, bounds); |
Andrew Boie | 7f95e83 | 2017-11-08 14:40:01 -0800 | [diff] [blame] | 109 | } |
Torbjörn Leksell | 80cd9da | 2021-03-26 13:42:25 +0100 | [diff] [blame] | 110 | |
| 111 | SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_heap_sys, k_calloc, _SYSTEM_HEAP, ret); |
| 112 | |
Andrew Boie | 7f95e83 | 2017-11-08 14:40:01 -0800 | [diff] [blame] | 113 | return ret; |
| 114 | } |
Andrew Boie | 92e5bd7 | 2018-04-12 17:12:15 -0700 | [diff] [blame] | 115 | |
| 116 | void k_thread_system_pool_assign(struct k_thread *thread) |
| 117 | { |
Andy Ross | c770cab | 2020-10-02 08:22:03 -0700 | [diff] [blame] | 118 | thread->resource_pool = _SYSTEM_HEAP; |
Andrew Boie | 92e5bd7 | 2018-04-12 17:12:15 -0700 | [diff] [blame] | 119 | } |
Andrew Boie | 6f654bb | 2019-05-22 10:38:43 -0700 | [diff] [blame] | 120 | #else |
Andy Ross | c770cab | 2020-10-02 08:22:03 -0700 | [diff] [blame] | 121 | #define _SYSTEM_HEAP NULL |
Andy Ross | 73cb958 | 2017-05-09 10:42:39 -0700 | [diff] [blame] | 122 | #endif |
Andrew Boie | 92e5bd7 | 2018-04-12 17:12:15 -0700 | [diff] [blame] | 123 | |
Daniel Leung | 0c9f969 | 2020-12-15 13:37:11 -0800 | [diff] [blame] | 124 | void *z_thread_aligned_alloc(size_t align, size_t size) |
Andrew Boie | 92e5bd7 | 2018-04-12 17:12:15 -0700 | [diff] [blame] | 125 | { |
| 126 | void *ret; |
Andy Ross | c770cab | 2020-10-02 08:22:03 -0700 | [diff] [blame] | 127 | struct k_heap *heap; |
Andrew Boie | 92e5bd7 | 2018-04-12 17:12:15 -0700 | [diff] [blame] | 128 | |
Andrew Boie | 6f654bb | 2019-05-22 10:38:43 -0700 | [diff] [blame] | 129 | if (k_is_in_isr()) { |
Andy Ross | c770cab | 2020-10-02 08:22:03 -0700 | [diff] [blame] | 130 | heap = _SYSTEM_HEAP; |
Andrew Boie | 6f654bb | 2019-05-22 10:38:43 -0700 | [diff] [blame] | 131 | } else { |
Andy Ross | c770cab | 2020-10-02 08:22:03 -0700 | [diff] [blame] | 132 | heap = _current->resource_pool; |
Andrew Boie | 6f654bb | 2019-05-22 10:38:43 -0700 | [diff] [blame] | 133 | } |
| 134 | |
Anas Nashif | 3f4f3f6 | 2021-03-29 17:13:47 -0400 | [diff] [blame] | 135 | if (heap != NULL) { |
Daniel Leung | 0c9f969 | 2020-12-15 13:37:11 -0800 | [diff] [blame] | 136 | ret = z_heap_aligned_alloc(heap, align, size); |
Andrew Boie | 92e5bd7 | 2018-04-12 17:12:15 -0700 | [diff] [blame] | 137 | } else { |
| 138 | ret = NULL; |
| 139 | } |
| 140 | |
| 141 | return ret; |
| 142 | } |