Azure IoT / azure_c_shared_utility

Dependents:   STM32F746_iothub_client_sample_mqtt f767zi_mqtt iothub_client_sample_amqp iothub_client_sample_http ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers gballoc.c Source File

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