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