Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
c-utility/src/gballoc.c@0:f7f1f0d76dd6, 2018-08-23 (annotated)
- Committer:
- XinZhangMS
- Date:
- Thu Aug 23 06:52:14 2018 +0000
- Revision:
- 0:f7f1f0d76dd6
azure-c-sdk for mbed os supporting NUCLEO_F767ZI
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
XinZhangMS | 0:f7f1f0d76dd6 | 1 | // Copyright (c) Microsoft. All rights reserved. |
XinZhangMS | 0:f7f1f0d76dd6 | 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. |
XinZhangMS | 0:f7f1f0d76dd6 | 3 | |
XinZhangMS | 0:f7f1f0d76dd6 | 4 | |
XinZhangMS | 0:f7f1f0d76dd6 | 5 | #include <stdlib.h> |
XinZhangMS | 0:f7f1f0d76dd6 | 6 | #include <stdint.h> |
XinZhangMS | 0:f7f1f0d76dd6 | 7 | #include <stddef.h> |
XinZhangMS | 0:f7f1f0d76dd6 | 8 | #include "azure_c_shared_utility/lock.h" |
XinZhangMS | 0:f7f1f0d76dd6 | 9 | #include "azure_c_shared_utility/optimize_size.h" |
XinZhangMS | 0:f7f1f0d76dd6 | 10 | #include "azure_c_shared_utility/xlogging.h" |
XinZhangMS | 0:f7f1f0d76dd6 | 11 | |
XinZhangMS | 0:f7f1f0d76dd6 | 12 | #ifndef GB_USE_CUSTOM_HEAP |
XinZhangMS | 0:f7f1f0d76dd6 | 13 | |
XinZhangMS | 0:f7f1f0d76dd6 | 14 | #ifndef SIZE_MAX |
XinZhangMS | 0:f7f1f0d76dd6 | 15 | #define SIZE_MAX ((size_t)~(size_t)0) |
XinZhangMS | 0:f7f1f0d76dd6 | 16 | #endif |
XinZhangMS | 0:f7f1f0d76dd6 | 17 | |
XinZhangMS | 0:f7f1f0d76dd6 | 18 | typedef struct ALLOCATION_TAG |
XinZhangMS | 0:f7f1f0d76dd6 | 19 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 20 | size_t size; |
XinZhangMS | 0:f7f1f0d76dd6 | 21 | void* ptr; |
XinZhangMS | 0:f7f1f0d76dd6 | 22 | void* next; |
XinZhangMS | 0:f7f1f0d76dd6 | 23 | } ALLOCATION; |
XinZhangMS | 0:f7f1f0d76dd6 | 24 | |
XinZhangMS | 0:f7f1f0d76dd6 | 25 | typedef enum GBALLOC_STATE_TAG |
XinZhangMS | 0:f7f1f0d76dd6 | 26 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 27 | GBALLOC_STATE_INIT, |
XinZhangMS | 0:f7f1f0d76dd6 | 28 | GBALLOC_STATE_NOT_INIT |
XinZhangMS | 0:f7f1f0d76dd6 | 29 | } GBALLOC_STATE; |
XinZhangMS | 0:f7f1f0d76dd6 | 30 | |
XinZhangMS | 0:f7f1f0d76dd6 | 31 | static ALLOCATION* head = NULL; |
XinZhangMS | 0:f7f1f0d76dd6 | 32 | static size_t totalSize = 0; |
XinZhangMS | 0:f7f1f0d76dd6 | 33 | static size_t maxSize = 0; |
XinZhangMS | 0:f7f1f0d76dd6 | 34 | static size_t g_allocations = 0; |
XinZhangMS | 0:f7f1f0d76dd6 | 35 | static GBALLOC_STATE gballocState = GBALLOC_STATE_NOT_INIT; |
XinZhangMS | 0:f7f1f0d76dd6 | 36 | |
XinZhangMS | 0:f7f1f0d76dd6 | 37 | static LOCK_HANDLE gballocThreadSafeLock = NULL; |
XinZhangMS | 0:f7f1f0d76dd6 | 38 | |
XinZhangMS | 0:f7f1f0d76dd6 | 39 | int gballoc_init(void) |
XinZhangMS | 0:f7f1f0d76dd6 | 40 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 41 | int result; |
XinZhangMS | 0:f7f1f0d76dd6 | 42 | |
XinZhangMS | 0:f7f1f0d76dd6 | 43 | if (gballocState != GBALLOC_STATE_NOT_INIT) |
XinZhangMS | 0:f7f1f0d76dd6 | 44 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 45 | /* Codes_SRS_GBALLOC_01_025: [Init after Init shall fail and return a non-zero value.] */ |
XinZhangMS | 0:f7f1f0d76dd6 | 46 | result = __FAILURE__; |
XinZhangMS | 0:f7f1f0d76dd6 | 47 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 48 | /* Codes_SRS_GBALLOC_01_026: [gballoc_Init shall create a lock handle that will be used to make the other gballoc APIs thread-safe.] */ |
XinZhangMS | 0:f7f1f0d76dd6 | 49 | else if ((gballocThreadSafeLock = Lock_Init()) == NULL) |
XinZhangMS | 0:f7f1f0d76dd6 | 50 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 51 | /* Codes_SRS_GBALLOC_01_027: [If the Lock creation fails, gballoc_init shall return a non-zero value.]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 52 | result = __FAILURE__; |
XinZhangMS | 0:f7f1f0d76dd6 | 53 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 54 | else |
XinZhangMS | 0:f7f1f0d76dd6 | 55 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 56 | gballocState = GBALLOC_STATE_INIT; |
XinZhangMS | 0:f7f1f0d76dd6 | 57 | |
XinZhangMS | 0:f7f1f0d76dd6 | 58 | /* Codes_ SRS_GBALLOC_01_002: [Upon initialization the total memory used and maximum total memory used tracked by the module shall be set to 0.] */ |
XinZhangMS | 0:f7f1f0d76dd6 | 59 | totalSize = 0; |
XinZhangMS | 0:f7f1f0d76dd6 | 60 | maxSize = 0; |
XinZhangMS | 0:f7f1f0d76dd6 | 61 | g_allocations = 0; |
XinZhangMS | 0:f7f1f0d76dd6 | 62 | |
XinZhangMS | 0:f7f1f0d76dd6 | 63 | /* Codes_SRS_GBALLOC_01_024: [gballoc_init shall initialize the gballoc module and return 0 upon success.] */ |
XinZhangMS | 0:f7f1f0d76dd6 | 64 | result = 0; |
XinZhangMS | 0:f7f1f0d76dd6 | 65 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 66 | |
XinZhangMS | 0:f7f1f0d76dd6 | 67 | return result; |
XinZhangMS | 0:f7f1f0d76dd6 | 68 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 69 | |
XinZhangMS | 0:f7f1f0d76dd6 | 70 | void gballoc_deinit(void) |
XinZhangMS | 0:f7f1f0d76dd6 | 71 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 72 | if (gballocState == GBALLOC_STATE_INIT) |
XinZhangMS | 0:f7f1f0d76dd6 | 73 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 74 | /* Codes_SRS_GBALLOC_01_028: [gballoc_deinit shall free all resources allocated by gballoc_init.] */ |
XinZhangMS | 0:f7f1f0d76dd6 | 75 | (void)Lock_Deinit(gballocThreadSafeLock); |
XinZhangMS | 0:f7f1f0d76dd6 | 76 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 77 | |
XinZhangMS | 0:f7f1f0d76dd6 | 78 | gballocState = GBALLOC_STATE_NOT_INIT; |
XinZhangMS | 0:f7f1f0d76dd6 | 79 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 80 | |
XinZhangMS | 0:f7f1f0d76dd6 | 81 | void* gballoc_malloc(size_t size) |
XinZhangMS | 0:f7f1f0d76dd6 | 82 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 83 | void* result; |
XinZhangMS | 0:f7f1f0d76dd6 | 84 | |
XinZhangMS | 0:f7f1f0d76dd6 | 85 | if (gballocState != GBALLOC_STATE_INIT) |
XinZhangMS | 0:f7f1f0d76dd6 | 86 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 87 | /* Codes_SRS_GBALLOC_01_039: [If gballoc was not initialized gballoc_malloc shall simply call malloc without any memory tracking being performed.] */ |
XinZhangMS | 0:f7f1f0d76dd6 | 88 | result = malloc(size); |
XinZhangMS | 0:f7f1f0d76dd6 | 89 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 90 | /* Codes_SRS_GBALLOC_01_030: [gballoc_malloc shall ensure thread safety by using the lock created by gballoc_Init.] */ |
XinZhangMS | 0:f7f1f0d76dd6 | 91 | else if (LOCK_OK != Lock(gballocThreadSafeLock)) |
XinZhangMS | 0:f7f1f0d76dd6 | 92 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 93 | /* Codes_SRS_GBALLOC_01_048: [If acquiring the lock fails, gballoc_malloc shall return NULL.] */ |
XinZhangMS | 0:f7f1f0d76dd6 | 94 | LogError("Failed to get the Lock."); |
XinZhangMS | 0:f7f1f0d76dd6 | 95 | result = NULL; |
XinZhangMS | 0:f7f1f0d76dd6 | 96 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 97 | else |
XinZhangMS | 0:f7f1f0d76dd6 | 98 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 99 | ALLOCATION* allocation = (ALLOCATION*)malloc(sizeof(ALLOCATION)); |
XinZhangMS | 0:f7f1f0d76dd6 | 100 | if (allocation == NULL) |
XinZhangMS | 0:f7f1f0d76dd6 | 101 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 102 | result = NULL; |
XinZhangMS | 0:f7f1f0d76dd6 | 103 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 104 | else |
XinZhangMS | 0:f7f1f0d76dd6 | 105 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 106 | /* Codes_SRS_GBALLOC_01_003: [gb_malloc shall call the C99 malloc function and return its result.] */ |
XinZhangMS | 0:f7f1f0d76dd6 | 107 | result = malloc(size); |
XinZhangMS | 0:f7f1f0d76dd6 | 108 | if (result == NULL) |
XinZhangMS | 0:f7f1f0d76dd6 | 109 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 110 | /* Codes_SRS_GBALLOC_01_012: [When the underlying malloc call fails, gballoc_malloc shall return NULL and size should not be counted towards total memory used.] */ |
XinZhangMS | 0:f7f1f0d76dd6 | 111 | free(allocation); |
XinZhangMS | 0:f7f1f0d76dd6 | 112 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 113 | else |
XinZhangMS | 0:f7f1f0d76dd6 | 114 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 115 | /* Codes_SRS_GBALLOC_01_004: [If the underlying malloc call is successful, gb_malloc shall increment the total memory used with the amount indicated by size.] */ |
XinZhangMS | 0:f7f1f0d76dd6 | 116 | allocation->ptr = result; |
XinZhangMS | 0:f7f1f0d76dd6 | 117 | allocation->size = size; |
XinZhangMS | 0:f7f1f0d76dd6 | 118 | allocation->next = head; |
XinZhangMS | 0:f7f1f0d76dd6 | 119 | head = allocation; |
XinZhangMS | 0:f7f1f0d76dd6 | 120 | |
XinZhangMS | 0:f7f1f0d76dd6 | 121 | g_allocations++; |
XinZhangMS | 0:f7f1f0d76dd6 | 122 | totalSize += size; |
XinZhangMS | 0:f7f1f0d76dd6 | 123 | /* Codes_SRS_GBALLOC_01_011: [The maximum total memory used shall be the maximum of the total memory used at any point.] */ |
XinZhangMS | 0:f7f1f0d76dd6 | 124 | if (maxSize < totalSize) |
XinZhangMS | 0:f7f1f0d76dd6 | 125 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 126 | maxSize = totalSize; |
XinZhangMS | 0:f7f1f0d76dd6 | 127 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 128 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 129 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 130 | |
XinZhangMS | 0:f7f1f0d76dd6 | 131 | (void)Unlock(gballocThreadSafeLock); |
XinZhangMS | 0:f7f1f0d76dd6 | 132 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 133 | |
XinZhangMS | 0:f7f1f0d76dd6 | 134 | return result; |
XinZhangMS | 0:f7f1f0d76dd6 | 135 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 136 | |
XinZhangMS | 0:f7f1f0d76dd6 | 137 | void* gballoc_calloc(size_t nmemb, size_t size) |
XinZhangMS | 0:f7f1f0d76dd6 | 138 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 139 | void* result; |
XinZhangMS | 0:f7f1f0d76dd6 | 140 | |
XinZhangMS | 0:f7f1f0d76dd6 | 141 | if (gballocState != GBALLOC_STATE_INIT) |
XinZhangMS | 0:f7f1f0d76dd6 | 142 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 143 | /* Codes_SRS_GBALLOC_01_040: [If gballoc was not initialized gballoc_calloc shall simply call calloc without any memory tracking being performed.] */ |
XinZhangMS | 0:f7f1f0d76dd6 | 144 | result = calloc(nmemb, size); |
XinZhangMS | 0:f7f1f0d76dd6 | 145 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 146 | /* Codes_SRS_GBALLOC_01_031: [gballoc_calloc shall ensure thread safety by using the lock created by gballoc_Init] */ |
XinZhangMS | 0:f7f1f0d76dd6 | 147 | else if (LOCK_OK != Lock(gballocThreadSafeLock)) |
XinZhangMS | 0:f7f1f0d76dd6 | 148 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 149 | /* Codes_SRS_GBALLOC_01_046: [If acquiring the lock fails, gballoc_calloc shall return NULL.] */ |
XinZhangMS | 0:f7f1f0d76dd6 | 150 | LogError("Failed to get the Lock."); |
XinZhangMS | 0:f7f1f0d76dd6 | 151 | result = NULL; |
XinZhangMS | 0:f7f1f0d76dd6 | 152 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 153 | else |
XinZhangMS | 0:f7f1f0d76dd6 | 154 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 155 | ALLOCATION* allocation = (ALLOCATION*)malloc(sizeof(ALLOCATION)); |
XinZhangMS | 0:f7f1f0d76dd6 | 156 | if (allocation == NULL) |
XinZhangMS | 0:f7f1f0d76dd6 | 157 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 158 | result = NULL; |
XinZhangMS | 0:f7f1f0d76dd6 | 159 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 160 | else |
XinZhangMS | 0:f7f1f0d76dd6 | 161 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 162 | /* Codes_SRS_GBALLOC_01_020: [gballoc_calloc shall call the C99 calloc function and return its result.] */ |
XinZhangMS | 0:f7f1f0d76dd6 | 163 | result = calloc(nmemb, size); |
XinZhangMS | 0:f7f1f0d76dd6 | 164 | if (result == NULL) |
XinZhangMS | 0:f7f1f0d76dd6 | 165 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 166 | /* Codes_SRS_GBALLOC_01_022: [When the underlying calloc call fails, gballoc_calloc shall return NULL and size should not be counted towards total memory used.] */ |
XinZhangMS | 0:f7f1f0d76dd6 | 167 | free(allocation); |
XinZhangMS | 0:f7f1f0d76dd6 | 168 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 169 | else |
XinZhangMS | 0:f7f1f0d76dd6 | 170 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 171 | /* Codes_SRS_GBALLOC_01_021: [If the underlying calloc call is successful, gballoc_calloc shall increment the total memory used with nmemb*size.] */ |
XinZhangMS | 0:f7f1f0d76dd6 | 172 | allocation->ptr = result; |
XinZhangMS | 0:f7f1f0d76dd6 | 173 | allocation->size = nmemb * size; |
XinZhangMS | 0:f7f1f0d76dd6 | 174 | allocation->next = head; |
XinZhangMS | 0:f7f1f0d76dd6 | 175 | head = allocation; |
XinZhangMS | 0:f7f1f0d76dd6 | 176 | g_allocations++; |
XinZhangMS | 0:f7f1f0d76dd6 | 177 | |
XinZhangMS | 0:f7f1f0d76dd6 | 178 | totalSize += allocation->size; |
XinZhangMS | 0:f7f1f0d76dd6 | 179 | /* Codes_SRS_GBALLOC_01_011: [The maximum total memory used shall be the maximum of the total memory used at any point.] */ |
XinZhangMS | 0:f7f1f0d76dd6 | 180 | if (maxSize < totalSize) |
XinZhangMS | 0:f7f1f0d76dd6 | 181 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 182 | maxSize = totalSize; |
XinZhangMS | 0:f7f1f0d76dd6 | 183 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 184 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 185 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 186 | |
XinZhangMS | 0:f7f1f0d76dd6 | 187 | (void)Unlock(gballocThreadSafeLock); |
XinZhangMS | 0:f7f1f0d76dd6 | 188 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 189 | |
XinZhangMS | 0:f7f1f0d76dd6 | 190 | return result; |
XinZhangMS | 0:f7f1f0d76dd6 | 191 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 192 | |
XinZhangMS | 0:f7f1f0d76dd6 | 193 | void* gballoc_realloc(void* ptr, size_t size) |
XinZhangMS | 0:f7f1f0d76dd6 | 194 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 195 | ALLOCATION* curr; |
XinZhangMS | 0:f7f1f0d76dd6 | 196 | void* result; |
XinZhangMS | 0:f7f1f0d76dd6 | 197 | ALLOCATION* allocation = NULL; |
XinZhangMS | 0:f7f1f0d76dd6 | 198 | |
XinZhangMS | 0:f7f1f0d76dd6 | 199 | if (gballocState != GBALLOC_STATE_INIT) |
XinZhangMS | 0:f7f1f0d76dd6 | 200 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 201 | /* Codes_SRS_GBALLOC_01_041: [If gballoc was not initialized gballoc_realloc shall shall simply call realloc without any memory tracking being performed.] */ |
XinZhangMS | 0:f7f1f0d76dd6 | 202 | result = realloc(ptr, size); |
XinZhangMS | 0:f7f1f0d76dd6 | 203 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 204 | /* Codes_SRS_GBALLOC_01_032: [gballoc_realloc shall ensure thread safety by using the lock created by gballoc_Init.] */ |
XinZhangMS | 0:f7f1f0d76dd6 | 205 | else if (LOCK_OK != Lock(gballocThreadSafeLock)) |
XinZhangMS | 0:f7f1f0d76dd6 | 206 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 207 | /* Codes_SRS_GBALLOC_01_047: [If acquiring the lock fails, gballoc_realloc shall return NULL.] */ |
XinZhangMS | 0:f7f1f0d76dd6 | 208 | LogError("Failed to get the Lock."); |
XinZhangMS | 0:f7f1f0d76dd6 | 209 | result = NULL; |
XinZhangMS | 0:f7f1f0d76dd6 | 210 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 211 | else |
XinZhangMS | 0:f7f1f0d76dd6 | 212 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 213 | if (ptr == NULL) |
XinZhangMS | 0:f7f1f0d76dd6 | 214 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 215 | /* Codes_SRS_GBALLOC_01_017: [When ptr is NULL, gballoc_realloc shall call the underlying realloc with ptr being NULL and the realloc result shall be tracked by gballoc.] */ |
XinZhangMS | 0:f7f1f0d76dd6 | 216 | allocation = (ALLOCATION*)malloc(sizeof(ALLOCATION)); |
XinZhangMS | 0:f7f1f0d76dd6 | 217 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 218 | else |
XinZhangMS | 0:f7f1f0d76dd6 | 219 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 220 | curr = head; |
XinZhangMS | 0:f7f1f0d76dd6 | 221 | while (curr != NULL) |
XinZhangMS | 0:f7f1f0d76dd6 | 222 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 223 | if (curr->ptr == ptr) |
XinZhangMS | 0:f7f1f0d76dd6 | 224 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 225 | allocation = curr; |
XinZhangMS | 0:f7f1f0d76dd6 | 226 | break; |
XinZhangMS | 0:f7f1f0d76dd6 | 227 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 228 | else |
XinZhangMS | 0:f7f1f0d76dd6 | 229 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 230 | curr = (ALLOCATION*)curr->next; |
XinZhangMS | 0:f7f1f0d76dd6 | 231 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 232 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 233 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 234 | |
XinZhangMS | 0:f7f1f0d76dd6 | 235 | if (allocation == NULL) |
XinZhangMS | 0:f7f1f0d76dd6 | 236 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 237 | /* Codes_SRS_GBALLOC_01_015: [When allocating memory used for tracking by gballoc_realloc fails, gballoc_realloc shall return NULL and no change should be made to the counted total memory usage.] */ |
XinZhangMS | 0:f7f1f0d76dd6 | 238 | /* Codes_SRS_GBALLOC_01_016: [When the ptr pointer cannot be found in the pointers tracked by gballoc, gballoc_realloc shall return NULL and the underlying realloc shall not be called.] */ |
XinZhangMS | 0:f7f1f0d76dd6 | 239 | result = NULL; |
XinZhangMS | 0:f7f1f0d76dd6 | 240 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 241 | else |
XinZhangMS | 0:f7f1f0d76dd6 | 242 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 243 | result = realloc(ptr, size); |
XinZhangMS | 0:f7f1f0d76dd6 | 244 | if (result == NULL) |
XinZhangMS | 0:f7f1f0d76dd6 | 245 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 246 | /* Codes_SRS_GBALLOC_01_014: [When the underlying realloc call fails, gballoc_realloc shall return NULL and no change should be made to the counted total memory usage.] */ |
XinZhangMS | 0:f7f1f0d76dd6 | 247 | if (ptr == NULL) |
XinZhangMS | 0:f7f1f0d76dd6 | 248 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 249 | free(allocation); |
XinZhangMS | 0:f7f1f0d76dd6 | 250 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 251 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 252 | else |
XinZhangMS | 0:f7f1f0d76dd6 | 253 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 254 | if (ptr != NULL) |
XinZhangMS | 0:f7f1f0d76dd6 | 255 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 256 | /* Codes_SRS_GBALLOC_01_006: [If the underlying realloc call is successful, gballoc_realloc shall look up the size associated with the pointer ptr and decrease the total memory used with that size.] */ |
XinZhangMS | 0:f7f1f0d76dd6 | 257 | allocation->ptr = result; |
XinZhangMS | 0:f7f1f0d76dd6 | 258 | totalSize -= allocation->size; |
XinZhangMS | 0:f7f1f0d76dd6 | 259 | allocation->size = size; |
XinZhangMS | 0:f7f1f0d76dd6 | 260 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 261 | else |
XinZhangMS | 0:f7f1f0d76dd6 | 262 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 263 | /* add block */ |
XinZhangMS | 0:f7f1f0d76dd6 | 264 | allocation->ptr = result; |
XinZhangMS | 0:f7f1f0d76dd6 | 265 | allocation->size = size; |
XinZhangMS | 0:f7f1f0d76dd6 | 266 | allocation->next = head; |
XinZhangMS | 0:f7f1f0d76dd6 | 267 | head = allocation; |
XinZhangMS | 0:f7f1f0d76dd6 | 268 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 269 | |
XinZhangMS | 0:f7f1f0d76dd6 | 270 | /* Codes_SRS_GBALLOC_01_007: [If realloc is successful, gballoc_realloc shall also increment the total memory used value tracked by this module.] */ |
XinZhangMS | 0:f7f1f0d76dd6 | 271 | totalSize += size; |
XinZhangMS | 0:f7f1f0d76dd6 | 272 | g_allocations++; |
XinZhangMS | 0:f7f1f0d76dd6 | 273 | |
XinZhangMS | 0:f7f1f0d76dd6 | 274 | /* Codes_SRS_GBALLOC_01_011: [The maximum total memory used shall be the maximum of the total memory used at any point.] */ |
XinZhangMS | 0:f7f1f0d76dd6 | 275 | if (maxSize < totalSize) |
XinZhangMS | 0:f7f1f0d76dd6 | 276 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 277 | maxSize = totalSize; |
XinZhangMS | 0:f7f1f0d76dd6 | 278 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 279 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 280 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 281 | |
XinZhangMS | 0:f7f1f0d76dd6 | 282 | (void)Unlock(gballocThreadSafeLock); |
XinZhangMS | 0:f7f1f0d76dd6 | 283 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 284 | |
XinZhangMS | 0:f7f1f0d76dd6 | 285 | return result; |
XinZhangMS | 0:f7f1f0d76dd6 | 286 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 287 | |
XinZhangMS | 0:f7f1f0d76dd6 | 288 | void gballoc_free(void* ptr) |
XinZhangMS | 0:f7f1f0d76dd6 | 289 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 290 | ALLOCATION* curr = head; |
XinZhangMS | 0:f7f1f0d76dd6 | 291 | ALLOCATION* prev = NULL; |
XinZhangMS | 0:f7f1f0d76dd6 | 292 | |
XinZhangMS | 0:f7f1f0d76dd6 | 293 | if (gballocState != GBALLOC_STATE_INIT) |
XinZhangMS | 0:f7f1f0d76dd6 | 294 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 295 | /* Codes_SRS_GBALLOC_01_042: [If gballoc was not initialized gballoc_free shall shall simply call free.] */ |
XinZhangMS | 0:f7f1f0d76dd6 | 296 | free(ptr); |
XinZhangMS | 0:f7f1f0d76dd6 | 297 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 298 | /* Codes_SRS_GBALLOC_01_033: [gballoc_free shall ensure thread safety by using the lock created by gballoc_Init.] */ |
XinZhangMS | 0:f7f1f0d76dd6 | 299 | else if (LOCK_OK != Lock(gballocThreadSafeLock)) |
XinZhangMS | 0:f7f1f0d76dd6 | 300 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 301 | /* Codes_SRS_GBALLOC_01_049: [If acquiring the lock fails, gballoc_free shall do nothing.] */ |
XinZhangMS | 0:f7f1f0d76dd6 | 302 | LogError("Failed to get the Lock."); |
XinZhangMS | 0:f7f1f0d76dd6 | 303 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 304 | else |
XinZhangMS | 0:f7f1f0d76dd6 | 305 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 306 | /* Codes_SRS_GBALLOC_01_009: [gballoc_free shall also look up the size associated with the ptr pointer and decrease the total memory used with the associated size amount.] */ |
XinZhangMS | 0:f7f1f0d76dd6 | 307 | while (curr != NULL) |
XinZhangMS | 0:f7f1f0d76dd6 | 308 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 309 | if (curr->ptr == ptr) |
XinZhangMS | 0:f7f1f0d76dd6 | 310 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 311 | /* Codes_SRS_GBALLOC_01_008: [gballoc_free shall call the C99 free function.] */ |
XinZhangMS | 0:f7f1f0d76dd6 | 312 | free(ptr); |
XinZhangMS | 0:f7f1f0d76dd6 | 313 | totalSize -= curr->size; |
XinZhangMS | 0:f7f1f0d76dd6 | 314 | if (prev != NULL) |
XinZhangMS | 0:f7f1f0d76dd6 | 315 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 316 | prev->next = curr->next; |
XinZhangMS | 0:f7f1f0d76dd6 | 317 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 318 | else |
XinZhangMS | 0:f7f1f0d76dd6 | 319 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 320 | head = (ALLOCATION*)curr->next; |
XinZhangMS | 0:f7f1f0d76dd6 | 321 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 322 | |
XinZhangMS | 0:f7f1f0d76dd6 | 323 | free(curr); |
XinZhangMS | 0:f7f1f0d76dd6 | 324 | break; |
XinZhangMS | 0:f7f1f0d76dd6 | 325 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 326 | |
XinZhangMS | 0:f7f1f0d76dd6 | 327 | prev = curr; |
XinZhangMS | 0:f7f1f0d76dd6 | 328 | curr = (ALLOCATION*)curr->next; |
XinZhangMS | 0:f7f1f0d76dd6 | 329 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 330 | |
XinZhangMS | 0:f7f1f0d76dd6 | 331 | if ((curr == NULL) && (ptr != NULL)) |
XinZhangMS | 0:f7f1f0d76dd6 | 332 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 333 | /* Codes_SRS_GBALLOC_01_019: [When the ptr pointer cannot be found in the pointers tracked by gballoc, gballoc_free shall not free any memory.] */ |
XinZhangMS | 0:f7f1f0d76dd6 | 334 | |
XinZhangMS | 0:f7f1f0d76dd6 | 335 | /* could not find the allocation */ |
XinZhangMS | 0:f7f1f0d76dd6 | 336 | LogError("Could not free allocation for address %p (not found)", ptr); |
XinZhangMS | 0:f7f1f0d76dd6 | 337 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 338 | (void)Unlock(gballocThreadSafeLock); |
XinZhangMS | 0:f7f1f0d76dd6 | 339 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 340 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 341 | |
XinZhangMS | 0:f7f1f0d76dd6 | 342 | size_t gballoc_getMaximumMemoryUsed(void) |
XinZhangMS | 0:f7f1f0d76dd6 | 343 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 344 | size_t result; |
XinZhangMS | 0:f7f1f0d76dd6 | 345 | |
XinZhangMS | 0:f7f1f0d76dd6 | 346 | /* Codes_SRS_GBALLOC_01_038: [If gballoc was not initialized gballoc_getMaximumMemoryUsed shall return MAX_INT_SIZE.] */ |
XinZhangMS | 0:f7f1f0d76dd6 | 347 | if (gballocState != GBALLOC_STATE_INIT) |
XinZhangMS | 0:f7f1f0d76dd6 | 348 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 349 | LogError("gballoc is not initialized."); |
XinZhangMS | 0:f7f1f0d76dd6 | 350 | result = SIZE_MAX; |
XinZhangMS | 0:f7f1f0d76dd6 | 351 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 352 | /* Codes_SRS_GBALLOC_01_034: [gballoc_getMaximumMemoryUsed shall ensure thread safety by using the lock created by gballoc_Init.] */ |
XinZhangMS | 0:f7f1f0d76dd6 | 353 | else if (LOCK_OK != Lock(gballocThreadSafeLock)) |
XinZhangMS | 0:f7f1f0d76dd6 | 354 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 355 | /* Codes_SRS_GBALLOC_01_050: [If the lock cannot be acquired, gballoc_getMaximumMemoryUsed shall return SIZE_MAX.] */ |
XinZhangMS | 0:f7f1f0d76dd6 | 356 | LogError("Failed to get the Lock."); |
XinZhangMS | 0:f7f1f0d76dd6 | 357 | result = SIZE_MAX; |
XinZhangMS | 0:f7f1f0d76dd6 | 358 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 359 | else |
XinZhangMS | 0:f7f1f0d76dd6 | 360 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 361 | /* Codes_SRS_GBALLOC_01_010: [gballoc_getMaximumMemoryUsed shall return the maximum amount of total memory used recorded since the module initialization.] */ |
XinZhangMS | 0:f7f1f0d76dd6 | 362 | result = maxSize; |
XinZhangMS | 0:f7f1f0d76dd6 | 363 | (void)Unlock(gballocThreadSafeLock); |
XinZhangMS | 0:f7f1f0d76dd6 | 364 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 365 | |
XinZhangMS | 0:f7f1f0d76dd6 | 366 | return result; |
XinZhangMS | 0:f7f1f0d76dd6 | 367 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 368 | |
XinZhangMS | 0:f7f1f0d76dd6 | 369 | size_t gballoc_getCurrentMemoryUsed(void) |
XinZhangMS | 0:f7f1f0d76dd6 | 370 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 371 | size_t result; |
XinZhangMS | 0:f7f1f0d76dd6 | 372 | |
XinZhangMS | 0:f7f1f0d76dd6 | 373 | /* Codes_SRS_GBALLOC_01_044: [If gballoc was not initialized gballoc_getCurrentMemoryUsed shall return SIZE_MAX.] */ |
XinZhangMS | 0:f7f1f0d76dd6 | 374 | if (gballocState != GBALLOC_STATE_INIT) |
XinZhangMS | 0:f7f1f0d76dd6 | 375 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 376 | LogError("gballoc is not initialized."); |
XinZhangMS | 0:f7f1f0d76dd6 | 377 | result = SIZE_MAX; |
XinZhangMS | 0:f7f1f0d76dd6 | 378 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 379 | /* Codes_SRS_GBALLOC_01_036: [gballoc_getCurrentMemoryUsed shall ensure thread safety by using the lock created by gballoc_Init.]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 380 | else if (LOCK_OK != Lock(gballocThreadSafeLock)) |
XinZhangMS | 0:f7f1f0d76dd6 | 381 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 382 | /* Codes_SRS_GBALLOC_01_051: [If the lock cannot be acquired, gballoc_getCurrentMemoryUsed shall return SIZE_MAX.] */ |
XinZhangMS | 0:f7f1f0d76dd6 | 383 | LogError("Failed to get the Lock."); |
XinZhangMS | 0:f7f1f0d76dd6 | 384 | result = SIZE_MAX; |
XinZhangMS | 0:f7f1f0d76dd6 | 385 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 386 | else |
XinZhangMS | 0:f7f1f0d76dd6 | 387 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 388 | /*Codes_SRS_GBALLOC_02_001: [gballoc_getCurrentMemoryUsed shall return the currently used memory size.] */ |
XinZhangMS | 0:f7f1f0d76dd6 | 389 | result = totalSize; |
XinZhangMS | 0:f7f1f0d76dd6 | 390 | (void)Unlock(gballocThreadSafeLock); |
XinZhangMS | 0:f7f1f0d76dd6 | 391 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 392 | |
XinZhangMS | 0:f7f1f0d76dd6 | 393 | return result; |
XinZhangMS | 0:f7f1f0d76dd6 | 394 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 395 | |
XinZhangMS | 0:f7f1f0d76dd6 | 396 | size_t gballoc_getAllocationCount(void) |
XinZhangMS | 0:f7f1f0d76dd6 | 397 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 398 | size_t result; |
XinZhangMS | 0:f7f1f0d76dd6 | 399 | |
XinZhangMS | 0:f7f1f0d76dd6 | 400 | /* Codes_SRS_GBALLOC_07_001: [ If gballoc was not initialized gballoc_getAllocationCount shall return 0. ] */ |
XinZhangMS | 0:f7f1f0d76dd6 | 401 | if (gballocState != GBALLOC_STATE_INIT) |
XinZhangMS | 0:f7f1f0d76dd6 | 402 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 403 | LogError("gballoc is not initialized."); |
XinZhangMS | 0:f7f1f0d76dd6 | 404 | result = 0; |
XinZhangMS | 0:f7f1f0d76dd6 | 405 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 406 | /* Codes_SRS_GBALLOC_07_002: [ gballoc_getAllocationCount shall ensure thread safety by using the lock created by gballoc_Init ] */ |
XinZhangMS | 0:f7f1f0d76dd6 | 407 | else if (LOCK_OK != Lock(gballocThreadSafeLock)) |
XinZhangMS | 0:f7f1f0d76dd6 | 408 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 409 | /* Codes_SRS_GBALLOC_07_003: [ If the lock cannot be acquired, gballoc_getAllocationCount shall return 0. ] */ |
XinZhangMS | 0:f7f1f0d76dd6 | 410 | LogError("Failed to get the Lock."); |
XinZhangMS | 0:f7f1f0d76dd6 | 411 | result = 0; |
XinZhangMS | 0:f7f1f0d76dd6 | 412 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 413 | else |
XinZhangMS | 0:f7f1f0d76dd6 | 414 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 415 | /* Codes_SRS_GBALLOC_07_004: [ gballoc_getAllocationCount shall return the currently number of allocations. ] */ |
XinZhangMS | 0:f7f1f0d76dd6 | 416 | result = g_allocations; |
XinZhangMS | 0:f7f1f0d76dd6 | 417 | (void)Unlock(gballocThreadSafeLock); |
XinZhangMS | 0:f7f1f0d76dd6 | 418 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 419 | |
XinZhangMS | 0:f7f1f0d76dd6 | 420 | return result; |
XinZhangMS | 0:f7f1f0d76dd6 | 421 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 422 | |
XinZhangMS | 0:f7f1f0d76dd6 | 423 | void gballoc_resetMetrics() |
XinZhangMS | 0:f7f1f0d76dd6 | 424 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 425 | /* Codes_SRS_GBALLOC_07_005: [ If gballoc was not initialized gballoc_reset Metrics shall do nothing.] */ |
XinZhangMS | 0:f7f1f0d76dd6 | 426 | if (gballocState != GBALLOC_STATE_INIT) |
XinZhangMS | 0:f7f1f0d76dd6 | 427 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 428 | LogError("gballoc is not initialized."); |
XinZhangMS | 0:f7f1f0d76dd6 | 429 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 430 | /* Codes_SRS_GBALLOC_07_006: [ gballoc_resetMetrics shall ensure thread safety by using the lock created by gballoc_Init ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 431 | else if (LOCK_OK != Lock(gballocThreadSafeLock)) |
XinZhangMS | 0:f7f1f0d76dd6 | 432 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 433 | /* Codes_SRS_GBALLOC_07_007: [ If the lock cannot be acquired, gballoc_reset Metrics shall do nothing.] */ |
XinZhangMS | 0:f7f1f0d76dd6 | 434 | LogError("Failed to get the Lock."); |
XinZhangMS | 0:f7f1f0d76dd6 | 435 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 436 | else |
XinZhangMS | 0:f7f1f0d76dd6 | 437 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 438 | /* Codes_SRS_GBALLOC_07_008: [ gballoc_resetMetrics shall reset the total allocation size, max allocation size and number of allocation to zero. ] */ |
XinZhangMS | 0:f7f1f0d76dd6 | 439 | totalSize = 0; |
XinZhangMS | 0:f7f1f0d76dd6 | 440 | maxSize = 0; |
XinZhangMS | 0:f7f1f0d76dd6 | 441 | g_allocations = 0; |
XinZhangMS | 0:f7f1f0d76dd6 | 442 | (void)Unlock(gballocThreadSafeLock); |
XinZhangMS | 0:f7f1f0d76dd6 | 443 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 444 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 445 | |
XinZhangMS | 0:f7f1f0d76dd6 | 446 | #endif // GB_USE_CUSTOM_HEAP |