source: azure_iot_hub/trunk/azure_iothub/c-utility/src/gballoc.c@ 389

Last change on this file since 389 was 389, checked in by coas-nagasima, 5 years ago

ビルドが通るよう更新

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