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.
Dependents: STM32F746_iothub_client_sample_mqtt f767zi_mqtt iothub_client_sample_amqp iothub_client_sample_http ... more
gballoc.c
00001 // Copyright (c) Microsoft. All rights reserved. 00002 // Licensed under the MIT license. See LICENSE file in the project root for full license information. 00003 00004 00005 #include <stdlib.h> 00006 #include <stdint.h> 00007 #include <stddef.h> 00008 #include "azure_c_shared_utility/lock.h" 00009 #include "azure_c_shared_utility/optimize_size.h" 00010 #include "azure_c_shared_utility/xlogging.h" 00011 00012 #ifndef GB_USE_CUSTOM_HEAP 00013 00014 #ifndef SIZE_MAX 00015 #define SIZE_MAX ((size_t)~(size_t)0) 00016 #endif 00017 00018 typedef struct ALLOCATION_TAG 00019 { 00020 size_t size; 00021 void* ptr; 00022 void* next; 00023 } ALLOCATION; 00024 00025 typedef enum GBALLOC_STATE_TAG 00026 { 00027 GBALLOC_STATE_INIT, 00028 GBALLOC_STATE_NOT_INIT 00029 } GBALLOC_STATE; 00030 00031 static ALLOCATION* head = NULL; 00032 static size_t totalSize = 0; 00033 static size_t maxSize = 0; 00034 static size_t g_allocations = 0; 00035 static GBALLOC_STATE gballocState = GBALLOC_STATE_NOT_INIT; 00036 00037 static LOCK_HANDLE gballocThreadSafeLock = NULL; 00038 00039 int gballoc_init(void) 00040 { 00041 int result; 00042 00043 if (gballocState != GBALLOC_STATE_NOT_INIT) 00044 { 00045 /* Codes_SRS_GBALLOC_01_025: [Init after Init shall fail and return a non-zero value.] */ 00046 result = __FAILURE__; 00047 } 00048 /* Codes_SRS_GBALLOC_01_026: [gballoc_Init shall create a lock handle that will be used to make the other gballoc APIs thread-safe.] */ 00049 else if ((gballocThreadSafeLock = Lock_Init()) == NULL) 00050 { 00051 /* Codes_SRS_GBALLOC_01_027: [If the Lock creation fails, gballoc_init shall return a non-zero value.]*/ 00052 result = __FAILURE__; 00053 } 00054 else 00055 { 00056 gballocState = GBALLOC_STATE_INIT; 00057 00058 /* 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.] */ 00059 totalSize = 0; 00060 maxSize = 0; 00061 g_allocations = 0; 00062 00063 /* Codes_SRS_GBALLOC_01_024: [gballoc_init shall initialize the gballoc module and return 0 upon success.] */ 00064 result = 0; 00065 } 00066 00067 return result; 00068 } 00069 00070 void gballoc_deinit(void) 00071 { 00072 if (gballocState == GBALLOC_STATE_INIT) 00073 { 00074 /* Codes_SRS_GBALLOC_01_028: [gballoc_deinit shall free all resources allocated by gballoc_init.] */ 00075 (void)Lock_Deinit(gballocThreadSafeLock); 00076 } 00077 00078 gballocState = GBALLOC_STATE_NOT_INIT; 00079 } 00080 00081 void* gballoc_malloc(size_t size) 00082 { 00083 void* result; 00084 00085 if (gballocState != GBALLOC_STATE_INIT) 00086 { 00087 /* Codes_SRS_GBALLOC_01_039: [If gballoc was not initialized gballoc_malloc shall simply call malloc without any memory tracking being performed.] */ 00088 result = malloc(size); 00089 } 00090 /* Codes_SRS_GBALLOC_01_030: [gballoc_malloc shall ensure thread safety by using the lock created by gballoc_Init.] */ 00091 else if (LOCK_OK != Lock(gballocThreadSafeLock)) 00092 { 00093 /* Codes_SRS_GBALLOC_01_048: [If acquiring the lock fails, gballoc_malloc shall return NULL.] */ 00094 LogError("Failed to get the Lock."); 00095 result = NULL; 00096 } 00097 else 00098 { 00099 ALLOCATION* allocation = (ALLOCATION*)malloc(sizeof(ALLOCATION)); 00100 if (allocation == NULL) 00101 { 00102 result = NULL; 00103 } 00104 else 00105 { 00106 /* Codes_SRS_GBALLOC_01_003: [gb_malloc shall call the C99 malloc function and return its result.] */ 00107 result = malloc(size); 00108 if (result == NULL) 00109 { 00110 /* 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.] */ 00111 free(allocation); 00112 } 00113 else 00114 { 00115 /* 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.] */ 00116 allocation->ptr = result; 00117 allocation->size = size; 00118 allocation->next = head; 00119 head = allocation; 00120 00121 g_allocations++; 00122 totalSize += size; 00123 /* Codes_SRS_GBALLOC_01_011: [The maximum total memory used shall be the maximum of the total memory used at any point.] */ 00124 if (maxSize < totalSize) 00125 { 00126 maxSize = totalSize; 00127 } 00128 } 00129 } 00130 00131 (void)Unlock(gballocThreadSafeLock); 00132 } 00133 00134 return result; 00135 } 00136 00137 void* gballoc_calloc(size_t nmemb, size_t size) 00138 { 00139 void* result; 00140 00141 if (gballocState != GBALLOC_STATE_INIT) 00142 { 00143 /* Codes_SRS_GBALLOC_01_040: [If gballoc was not initialized gballoc_calloc shall simply call calloc without any memory tracking being performed.] */ 00144 result = calloc(nmemb, size); 00145 } 00146 /* Codes_SRS_GBALLOC_01_031: [gballoc_calloc shall ensure thread safety by using the lock created by gballoc_Init] */ 00147 else if (LOCK_OK != Lock(gballocThreadSafeLock)) 00148 { 00149 /* Codes_SRS_GBALLOC_01_046: [If acquiring the lock fails, gballoc_calloc shall return NULL.] */ 00150 LogError("Failed to get the Lock."); 00151 result = NULL; 00152 } 00153 else 00154 { 00155 ALLOCATION* allocation = (ALLOCATION*)malloc(sizeof(ALLOCATION)); 00156 if (allocation == NULL) 00157 { 00158 result = NULL; 00159 } 00160 else 00161 { 00162 /* Codes_SRS_GBALLOC_01_020: [gballoc_calloc shall call the C99 calloc function and return its result.] */ 00163 result = calloc(nmemb, size); 00164 if (result == NULL) 00165 { 00166 /* 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.] */ 00167 free(allocation); 00168 } 00169 else 00170 { 00171 /* Codes_SRS_GBALLOC_01_021: [If the underlying calloc call is successful, gballoc_calloc shall increment the total memory used with nmemb*size.] */ 00172 allocation->ptr = result; 00173 allocation->size = nmemb * size; 00174 allocation->next = head; 00175 head = allocation; 00176 g_allocations++; 00177 00178 totalSize += allocation->size; 00179 /* Codes_SRS_GBALLOC_01_011: [The maximum total memory used shall be the maximum of the total memory used at any point.] */ 00180 if (maxSize < totalSize) 00181 { 00182 maxSize = totalSize; 00183 } 00184 } 00185 } 00186 00187 (void)Unlock(gballocThreadSafeLock); 00188 } 00189 00190 return result; 00191 } 00192 00193 void* gballoc_realloc(void* ptr, size_t size) 00194 { 00195 ALLOCATION* curr; 00196 void* result; 00197 ALLOCATION* allocation = NULL; 00198 00199 if (gballocState != GBALLOC_STATE_INIT) 00200 { 00201 /* Codes_SRS_GBALLOC_01_041: [If gballoc was not initialized gballoc_realloc shall shall simply call realloc without any memory tracking being performed.] */ 00202 result = realloc(ptr, size); 00203 } 00204 /* Codes_SRS_GBALLOC_01_032: [gballoc_realloc shall ensure thread safety by using the lock created by gballoc_Init.] */ 00205 else if (LOCK_OK != Lock(gballocThreadSafeLock)) 00206 { 00207 /* Codes_SRS_GBALLOC_01_047: [If acquiring the lock fails, gballoc_realloc shall return NULL.] */ 00208 LogError("Failed to get the Lock."); 00209 result = NULL; 00210 } 00211 else 00212 { 00213 if (ptr == NULL) 00214 { 00215 /* 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.] */ 00216 allocation = (ALLOCATION*)malloc(sizeof(ALLOCATION)); 00217 } 00218 else 00219 { 00220 curr = head; 00221 while (curr != NULL) 00222 { 00223 if (curr->ptr == ptr) 00224 { 00225 allocation = curr; 00226 break; 00227 } 00228 else 00229 { 00230 curr = (ALLOCATION*)curr->next; 00231 } 00232 } 00233 } 00234 00235 if (allocation == NULL) 00236 { 00237 /* 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.] */ 00238 /* 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.] */ 00239 result = NULL; 00240 } 00241 else 00242 { 00243 result = realloc(ptr, size); 00244 if (result == NULL) 00245 { 00246 /* 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.] */ 00247 if (ptr == NULL) 00248 { 00249 free(allocation); 00250 } 00251 } 00252 else 00253 { 00254 if (ptr != NULL) 00255 { 00256 /* 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.] */ 00257 allocation->ptr = result; 00258 totalSize -= allocation->size; 00259 allocation->size = size; 00260 } 00261 else 00262 { 00263 /* add block */ 00264 allocation->ptr = result; 00265 allocation->size = size; 00266 allocation->next = head; 00267 head = allocation; 00268 } 00269 00270 /* Codes_SRS_GBALLOC_01_007: [If realloc is successful, gballoc_realloc shall also increment the total memory used value tracked by this module.] */ 00271 totalSize += size; 00272 g_allocations++; 00273 00274 /* Codes_SRS_GBALLOC_01_011: [The maximum total memory used shall be the maximum of the total memory used at any point.] */ 00275 if (maxSize < totalSize) 00276 { 00277 maxSize = totalSize; 00278 } 00279 } 00280 } 00281 00282 (void)Unlock(gballocThreadSafeLock); 00283 } 00284 00285 return result; 00286 } 00287 00288 void gballoc_free(void* ptr) 00289 { 00290 ALLOCATION* curr = head; 00291 ALLOCATION* prev = NULL; 00292 00293 if (gballocState != GBALLOC_STATE_INIT) 00294 { 00295 /* Codes_SRS_GBALLOC_01_042: [If gballoc was not initialized gballoc_free shall shall simply call free.] */ 00296 free(ptr); 00297 } 00298 /* Codes_SRS_GBALLOC_01_033: [gballoc_free shall ensure thread safety by using the lock created by gballoc_Init.] */ 00299 else if (LOCK_OK != Lock(gballocThreadSafeLock)) 00300 { 00301 /* Codes_SRS_GBALLOC_01_049: [If acquiring the lock fails, gballoc_free shall do nothing.] */ 00302 LogError("Failed to get the Lock."); 00303 } 00304 else 00305 { 00306 /* 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.] */ 00307 while (curr != NULL) 00308 { 00309 if (curr->ptr == ptr) 00310 { 00311 /* Codes_SRS_GBALLOC_01_008: [gballoc_free shall call the C99 free function.] */ 00312 free(ptr); 00313 totalSize -= curr->size; 00314 if (prev != NULL) 00315 { 00316 prev->next = curr->next; 00317 } 00318 else 00319 { 00320 head = (ALLOCATION*)curr->next; 00321 } 00322 00323 free(curr); 00324 break; 00325 } 00326 00327 prev = curr; 00328 curr = (ALLOCATION*)curr->next; 00329 } 00330 00331 if ((curr == NULL) && (ptr != NULL)) 00332 { 00333 /* 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.] */ 00334 00335 /* could not find the allocation */ 00336 LogError("Could not free allocation for address %p (not found)", ptr); 00337 } 00338 (void)Unlock(gballocThreadSafeLock); 00339 } 00340 } 00341 00342 size_t gballoc_getMaximumMemoryUsed(void) 00343 { 00344 size_t result; 00345 00346 /* Codes_SRS_GBALLOC_01_038: [If gballoc was not initialized gballoc_getMaximumMemoryUsed shall return MAX_INT_SIZE.] */ 00347 if (gballocState != GBALLOC_STATE_INIT) 00348 { 00349 LogError("gballoc is not initialized."); 00350 result = SIZE_MAX; 00351 } 00352 /* Codes_SRS_GBALLOC_01_034: [gballoc_getMaximumMemoryUsed shall ensure thread safety by using the lock created by gballoc_Init.] */ 00353 else if (LOCK_OK != Lock(gballocThreadSafeLock)) 00354 { 00355 /* Codes_SRS_GBALLOC_01_050: [If the lock cannot be acquired, gballoc_getMaximumMemoryUsed shall return SIZE_MAX.] */ 00356 LogError("Failed to get the Lock."); 00357 result = SIZE_MAX; 00358 } 00359 else 00360 { 00361 /* Codes_SRS_GBALLOC_01_010: [gballoc_getMaximumMemoryUsed shall return the maximum amount of total memory used recorded since the module initialization.] */ 00362 result = maxSize; 00363 (void)Unlock(gballocThreadSafeLock); 00364 } 00365 00366 return result; 00367 } 00368 00369 size_t gballoc_getCurrentMemoryUsed(void) 00370 { 00371 size_t result; 00372 00373 /* Codes_SRS_GBALLOC_01_044: [If gballoc was not initialized gballoc_getCurrentMemoryUsed shall return SIZE_MAX.] */ 00374 if (gballocState != GBALLOC_STATE_INIT) 00375 { 00376 LogError("gballoc is not initialized."); 00377 result = SIZE_MAX; 00378 } 00379 /* Codes_SRS_GBALLOC_01_036: [gballoc_getCurrentMemoryUsed shall ensure thread safety by using the lock created by gballoc_Init.]*/ 00380 else if (LOCK_OK != Lock(gballocThreadSafeLock)) 00381 { 00382 /* Codes_SRS_GBALLOC_01_051: [If the lock cannot be acquired, gballoc_getCurrentMemoryUsed shall return SIZE_MAX.] */ 00383 LogError("Failed to get the Lock."); 00384 result = SIZE_MAX; 00385 } 00386 else 00387 { 00388 /*Codes_SRS_GBALLOC_02_001: [gballoc_getCurrentMemoryUsed shall return the currently used memory size.] */ 00389 result = totalSize; 00390 (void)Unlock(gballocThreadSafeLock); 00391 } 00392 00393 return result; 00394 } 00395 00396 size_t gballoc_getAllocationCount(void) 00397 { 00398 size_t result; 00399 00400 /* Codes_SRS_GBALLOC_07_001: [ If gballoc was not initialized gballoc_getAllocationCount shall return 0. ] */ 00401 if (gballocState != GBALLOC_STATE_INIT) 00402 { 00403 LogError("gballoc is not initialized."); 00404 result = 0; 00405 } 00406 /* Codes_SRS_GBALLOC_07_002: [ gballoc_getAllocationCount shall ensure thread safety by using the lock created by gballoc_Init ] */ 00407 else if (LOCK_OK != Lock(gballocThreadSafeLock)) 00408 { 00409 /* Codes_SRS_GBALLOC_07_003: [ If the lock cannot be acquired, gballoc_getAllocationCount shall return 0. ] */ 00410 LogError("Failed to get the Lock."); 00411 result = 0; 00412 } 00413 else 00414 { 00415 /* Codes_SRS_GBALLOC_07_004: [ gballoc_getAllocationCount shall return the currently number of allocations. ] */ 00416 result = g_allocations; 00417 (void)Unlock(gballocThreadSafeLock); 00418 } 00419 00420 return result; 00421 } 00422 00423 void gballoc_resetMetrics() 00424 { 00425 /* Codes_SRS_GBALLOC_07_005: [ If gballoc was not initialized gballoc_reset Metrics shall do nothing.] */ 00426 if (gballocState != GBALLOC_STATE_INIT) 00427 { 00428 LogError("gballoc is not initialized."); 00429 } 00430 /* Codes_SRS_GBALLOC_07_006: [ gballoc_resetMetrics shall ensure thread safety by using the lock created by gballoc_Init ]*/ 00431 else if (LOCK_OK != Lock(gballocThreadSafeLock)) 00432 { 00433 /* Codes_SRS_GBALLOC_07_007: [ If the lock cannot be acquired, gballoc_reset Metrics shall do nothing.] */ 00434 LogError("Failed to get the Lock."); 00435 } 00436 else 00437 { 00438 /* Codes_SRS_GBALLOC_07_008: [ gballoc_resetMetrics shall reset the total allocation size, max allocation size and number of allocation to zero. ] */ 00439 totalSize = 0; 00440 maxSize = 0; 00441 g_allocations = 0; 00442 (void)Unlock(gballocThreadSafeLock); 00443 } 00444 } 00445 00446 #endif // GB_USE_CUSTOM_HEAP
Generated on Wed Jul 13 2022 23:38:02 by
1.7.2
