mkernel 0.0.2
Micro-kernel framework, everything as a module
memtrack.c
Go to the documentation of this file.
1
19#include "memtrack.h"
20#include <string.h> /* strdup */
21#include <stdio.h> /* fprintf */
22
23static struct MemBlock *Head;
24static struct MemBlock *Tail;
25static uint64_t NbBlocks;
26static uint64_t RAMSize;
28/* Early definition, documented in the implementation below */
29static unsigned int memtrack_init();
30
31/* Early definition, documented in the implementation below */
32static unsigned int memtrack_addblock_preinit(const void *p_Ptr,
33 const size_t p_Size,
34 const char *p_File,
35 const int p_Line,
36 const char *p_CompilDate,
37 const char *p_CompilTime,
38 const char *p_Function);
39
40/* Early definition, documented in the implementation below */
41static unsigned int memtrack_delblock_preinit(const void *p_Ptr,
42 const char *p_File,
43 const int p_Line,
44 const char *p_CompilDate,
45 const char *p_CompilTime,
46 const char *p_Function);
47
48/* Early definition, documented in the implementation below */
49static uint64_t memtrack_dumpblocks_preinit();
50
51/* Early definition, documented in the implementation below */
52static uint64_t memtrack_getallocatedblocks_preinit();
53
54/* Early definition, documented in the implementation below */
55static uint64_t memtrack_getallocatedRAM_preinit();
56
57/* Early definition, documented in the implementation below */
58static size_t memtrack_getblocksize_preinit(const void *p_Ptr);
59
60/* Early definition, documented in the implementation below */
61static unsigned int memtrack_addblock_postinit(const void *p_Ptr,
62 const size_t p_Size,
63 const char *p_File,
64 const int p_Line,
65 const char *p_CompilDate,
66 const char *p_CompilTime,
67 const char *p_Function);
68
69/* Early definition, documented in the implementation below */
70static unsigned int memtrack_delblock_postinit(const void *p_Ptr,
71 const char *p_File,
72 const int p_Line,
73 const char *p_CompilDate,
74 const char *p_CompilTime,
75 const char *p_Function);
76
77/* Early definition, documented in the implementation below */
78static uint64_t memtrack_dumpblocks_postinit();
79
80/* Early definition, documented in the implementation below */
81static uint64_t memtrack_getallocatedblocks_postinit();
82
83/* Early definition, documented in the implementation below */
84static uint64_t memtrack_getallocatedRAM_postinit();
85
86/* Early definition, documented in the implementation below */
87static size_t memtrack_getblocksize_postinit(const void *p_Ptr);
88
89/*******************/
90/* Implementations */
91/*******************/
92
100{
101 /* Ne réinitialise que si nécessaire */
102 if ( memtrack_addblock == memtrack_addblock_preinit)
103 return;
104
105 /* Déconfiguration des foncteurs */
106 memtrack_addblock = memtrack_addblock_preinit;
107 memtrack_delblock = memtrack_delblock_preinit;
108 memtrack_dumpblocks = memtrack_dumpblocks_preinit;
109 memtrack_getallocatedblocks = memtrack_getallocatedblocks_preinit;
110 memtrack_getallocatedRAM = memtrack_getallocatedRAM_preinit;
111 memtrack_getblocksize = memtrack_getblocksize_preinit;
112
113 /* Purge de la liste */
114 while (Tail!=Head->Next) {
115 memtrack_delblock_postinit(Head->Next->Ptr,NULL,0,NULL,NULL,NULL);
116 }
117
118 /* Réinitialization des pointeurs */
119 free(Head);
120 free(Tail);
121 Head=NULL;
122 Tail=NULL;
123}
124
141static unsigned int memtrack_init()
142{
143 Head = (TMemBlock *) malloc(sizeof(TMemBlock));
144 Tail = (TMemBlock *) malloc(sizeof(TMemBlock));
145
146 if ((NULL==Head)||(NULL==Tail)) {
147 fprintf(stderr,"%s:%d Not enough memory to initialize memtracker\n",
148 __FILE__,__LINE__);
149 return 1;
150 }
151 Head->Prev = (TMemBlock *) NULL;
152 Head->Next = Tail;
153 Tail->Next = (TMemBlock *) NULL;
154 Tail->Prev = Head;
155 Tail->Ptr = Head->Ptr = (void *)NULL;
156 Tail->Size = Head->Size = 0;
157 Tail->File = Head->File = (char *)NULL;
158 Tail->Line = Head->Line = 0;
159 Tail->CompilDate = Head->CompilDate = (char *)NULL;
160 Tail->CompilTime = Head->CompilTime = (char *)NULL;
161 Tail->Function = Head->Function = (char *)NULL;
162
163 /* Initialisation des compteurs */
164 NbBlocks=0;
165 RAMSize=0;
166
167 /* Modification des foncteurs pour utiliser les fonctions définitives */
168 memtrack_addblock = memtrack_addblock_postinit;
169 memtrack_delblock = memtrack_delblock_postinit;
170 memtrack_dumpblocks = memtrack_dumpblocks_postinit;
171 memtrack_getallocatedblocks = memtrack_getallocatedblocks_postinit;
172 memtrack_getallocatedRAM = memtrack_getallocatedRAM_postinit;
173 memtrack_getblocksize = memtrack_getblocksize_postinit;
174
175 return 0;
176}
177
178
190static unsigned int memtrack_addblock_preinit(const void *p_Ptr,
191 const size_t p_Size,
192 const char *p_File,
193 const int p_Line,
194 const char *p_CompilDate,
195 const char *p_CompilTime,
196 const char *p_Function)
197{
198 /* Initialisation de la liste */
199 if (0!=memtrack_init()) {
200 fprintf(stderr,"%s:%d Not enough memory to initialize memtracker\n",
201 __FILE__,__LINE__);
202 /* OOM */
203 return 1;
204 }
205
206 /* Appel de la fonction réelle */
207 return memtrack_addblock(p_Ptr, p_Size, p_File, p_Line, p_CompilDate,
208 p_CompilTime, p_Function);
209}
210
222static unsigned int memtrack_delblock_preinit(const void *p_Ptr,
223 const char *p_File,
224 const int p_Line,
225 const char *p_CompilDate,
226 const char *p_CompilTime,
227 const char *p_Function)
228{
229 /* Initialisation de la liste */
230 if (0!=memtrack_init()) {
231 fprintf(stderr,"%s:%d Not enough memory to initialize memtracker\n",
232 __FILE__,__LINE__);
233 /* OOM */
234 return 1;
235 }
236
237 /* Appel de la fonction réelle */
238 return memtrack_delblock(p_Ptr, p_File, p_Line, p_CompilDate,
239 p_CompilTime, p_Function);
240}
241
253static uint64_t memtrack_dumpblocks_preinit()
254{
255 /* Initialisation de la liste */
256 if (0!=memtrack_init()) {
257 fprintf(stderr,"%s:%d Not enough memory to initialize memtracker\n",
258 __FILE__,__LINE__);
259 /* OOM */
260 return 0;
261 }
262
263 /* Appel de la fonction réelle */
264 return memtrack_dumpblocks();
265}
266
278static uint64_t memtrack_getallocatedblocks_preinit()
279{
280 /* Initialisation de la liste */
281 if (0!=memtrack_init()) {
282 fprintf(stderr,"%s:%d Not enough memory to initialize memtracker\n",
283 __FILE__,__LINE__);
284 /* OOM */
285 return 0;
286 }
287
288 /* Appel de la fonction réelle */
290}
291
303static uint64_t memtrack_getallocatedRAM_preinit()
304{
305 /* Initialisation de la liste */
306 if (0!=memtrack_init()) {
307 fprintf(stderr,"%s:%d Not enough memory to initialize memtracker\n",
308 __FILE__,__LINE__);
309 /* OOM */
310 return 0;
311 }
312
313 /* Appel de la fonction réelle */
315}
316
328static size_t memtrack_getblocksize_preinit(const void *p_Ptr)
329{
330 /* Initialisation de la liste */
331 if (0!=memtrack_init()) {
332 fprintf(stderr,"%s:%d Not enough memory to initialize memtracker\n",
333 __FILE__,__LINE__);
334 /* OOM */
335 return 0;
336 }
337
338 /* Appel de la fonction réelle */
339 return memtrack_getblocksize(p_Ptr);
340}
341
350static unsigned int memtrack_addblock_postinit(const void *p_Ptr,
351 const size_t p_Size,
352 const char *p_File,
353 const int p_Line,
354 const char *p_CompilDate,
355 const char *p_CompilTime,
356 const char *p_Function)
357{
358 TMemBlock *l_tmp;
359
360 /* Test de validité des données à enregistrer */
361 /* Meme si malloc permet Size=0, ce n'est pas portable */
362 if ((NULL==p_Ptr)||
363 (0==p_Size)||
364 (NULL==p_File)||
365 (0==p_File[0])||
366 (0==p_Line)||
367 (NULL==p_CompilDate)||
368 (0==p_CompilDate[0])||
369 (NULL==p_CompilTime)||
370 (0==p_CompilTime[0])||
371 (NULL==p_Function)||
372 (0==p_Function[0])) {
373 fprintf(stderr,"%s:%d Null or empty parameters\n",__FILE__, __LINE__);
374 return 1;
375 }
376
377 /* On ne peut pas dupliquer un pointeur. Pour le modifier, il faut le
378 * supprimer et le recréer, ce n'est pas le rôle de ces fonctions de
379 * bas-niveau */
380
381 /* Recherche du pointeur */
382 l_tmp = Head->Next;
383 while ((l_tmp->Ptr != p_Ptr) && (l_tmp != Tail))
384 l_tmp = l_tmp->Next;
385
386 /* Le bloc ne doit pas avoir été trouvé */
387 if (l_tmp != Tail) {
388 fprintf(stderr,"%s:%d Memory bloc already registered\n",__FILE__, __LINE__);
389 return 1;
390 }
391
392 /* Allocation d'un nouveau descripteur de bloc */
393 l_tmp = (TMemBlock *) malloc(sizeof(TMemBlock));
394
395 /* Allocation réussie ? */
396 if (NULL == l_tmp) {
397 return 1;
398 }
399
400 /* Remplissage du descripteur */
401 l_tmp->Ptr = (void *)p_Ptr;
402 l_tmp->Size = p_Size;
403 if (NULL==(l_tmp->File = strdup(p_File?p_File:""))) {
404 free(l_tmp);
405 return 1;
406 };
407 l_tmp->Line = p_Line;
408 if (NULL==(l_tmp->CompilDate = strdup(p_CompilDate?p_CompilDate:""))) {
409 free(l_tmp->File);
410 free(l_tmp);
411 return 1;
412 };
413 if (NULL==(l_tmp->CompilTime = strdup(p_CompilTime?p_CompilTime:""))) {
414 free(l_tmp->CompilDate);
415 free(l_tmp->File);
416 free(l_tmp);
417 return 1;
418 };
419 if (NULL==(l_tmp->Function = strdup(p_Function?p_Function:""))) {
420 free(l_tmp->CompilTime);
421 free(l_tmp->CompilDate);
422 free(l_tmp->File);
423 free(l_tmp);
424 return 1;
425 };
426
427 /* Ajout de la description dans la liste (Section critique) */
428 l_tmp->Prev = Tail->Prev;
429 l_tmp->Next = Tail;
430 l_tmp->Prev->Next = l_tmp->Next->Prev = l_tmp;
431
432 /* Mise à jour des compteurs */
433 NbBlocks++;
434 RAMSize += p_Size;
435
436 return 0;
437}
438
447static unsigned int memtrack_delblock_postinit(const void *p_Ptr,
448 const char *p_File,
449 const int p_Line,
450 const char *p_CompilDate,
451 const char *p_CompilTime,
452 const char *p_Function)
453{
454 TMemBlock *l_tmp;
455 (void) p_File;
456 (void) p_Line;
457 (void) p_CompilDate;
458 (void) p_CompilTime;
459 (void) p_Function;
460
461 /* Recherche de la description */
462 l_tmp = Head->Next;
463 while ((l_tmp->Ptr != p_Ptr) && (l_tmp != Tail))
464 l_tmp = l_tmp->Next;
465
466 /* Le bloc doit avoir été trouvé */
467 if (l_tmp == Tail) {
468 fprintf(stderr,"%s:%d Block not found for deletion\n",__FILE__, __LINE__);
469 return 1;
470 }
471
472 /* Libération des ressources acquises */
473 /* On ne libère pas le bloc mémoire lui-même */
474 free(l_tmp->File);
475 free(l_tmp->CompilDate);
476 free(l_tmp->CompilTime);
477 free(l_tmp->Function);
478
479 /* Retrait de la description de la liste (Section critique) */
480 l_tmp->Next->Prev = l_tmp->Prev;
481 l_tmp->Prev->Next = l_tmp->Next;
482
483 /* Mise à jour des compteurs */
484 NbBlocks--;
485 RAMSize -= l_tmp->Size;
486
487 /* Libération de la description */
488 free(l_tmp);
489
490 return 0;
491}
492
501static uint64_t memtrack_dumpblocks_postinit()
502{
503 TMemBlock *l_tmp;
504 uint64_t l_NbBlocks = 0;;
505
506 if (Head->Next != Tail) {
507 size_t l_BlockSize;
508 fprintf(stderr,
509 "+----------------------------------------------------------------------------------------------------------+\n");
510 fprintf(stderr, "| %-104s |\n", "Memory Tracker Report");
511 fprintf(stderr,
512 "+----------------------+----------------------+------+-----------------+----------+------------------------+\n");
513 fprintf(stderr,
514 "| %-20s | %-20s | %-4s | %-15s | %-8s | %-22s |\n",
515 "Function", "File", "Line", "Address", "Bytes",
516 "Compiled");
517 fprintf(stderr,
518 "+----------------------+----------------------+------+-----------------+----------+------------------------+\n");
519
520 l_tmp = Head->Next;
521 l_BlockSize = 0;
522 while (l_tmp != Tail) {
523 fprintf(stderr,
524 "| %-20s | %-20s | %4d | %15p | %8lu | %11s @ %8s |\n",
525 l_tmp->Function, l_tmp->File, l_tmp->Line,
526 l_tmp->Ptr, (unsigned long)l_tmp->Size, l_tmp->CompilDate,
527 l_tmp->CompilTime);
528 l_NbBlocks++;
529 l_BlockSize += l_tmp->Size;
530 l_tmp = l_tmp->Next;
531 }
532 fprintf(stderr,
533 "+----------------------+----------------------+------+-----------------+----------+------------------------+\n");
534 fprintf(stderr,
535 "| %9lu bytes in %6lu blocks. %70s |\n", (unsigned long)l_BlockSize,
536 l_NbBlocks, "");
537 fprintf(stderr,
538 "+----------------------------------------------------------------------------------------------------------+\n");
539 }
540 /* Add ASSERT or assert (l_NbBlocks==NbBlocks) */
541 return l_NbBlocks;
542}
543
552static uint64_t memtrack_getallocatedblocks_postinit()
553{
554 return NbBlocks;
555}
556
565static uint64_t memtrack_getallocatedRAM_postinit()
566{
567 return RAMSize;
568}
569
578static size_t memtrack_getblocksize_postinit(const void *p_Ptr)
579{
580 /* Recherche de la description */
581 TMemBlock *l_tmp = Head->Next;
582 while ((l_tmp->Ptr != p_Ptr) && (l_tmp != Tail))
583 l_tmp = l_tmp->Next;
584
585 /* Le bloc doit avoir été trouvé */
586 if (l_tmp == Tail)
587 return 0;
588 else
589 return l_tmp->Size;
590}
591
592/* Documented in header file */
593unsigned int (*memtrack_addblock) (const void *p_Ptr,
594 const size_t p_Size,
595 const char *p_File,
596 const int p_Line,
597 const char *p_CompilDate,
598 const char *p_CompilTime,
599 const char *p_Function) =
600 memtrack_addblock_preinit;
601
602/* Documented in header file */
603unsigned int (*memtrack_delblock) (const void *p_Ptr,
604 const char *p_File,
605 const int p_Line,
606 const char *p_CompilDate,
607 const char *p_CompilTime,
608 const char *p_Function) =
609 memtrack_delblock_preinit;
610
611/* Documented in header file */
612uint64_t (*memtrack_dumpblocks) () = memtrack_dumpblocks_preinit;
613
614/* Documented in header file */
615uint64_t (*memtrack_getallocatedblocks) () = memtrack_getallocatedblocks_preinit;
616
617/* Documented in header file */
618uint64_t (*memtrack_getallocatedRAM) () = memtrack_getallocatedRAM_preinit;
619
620/* Documented in header file */
621size_t(*memtrack_getblocksize) (const void *p_Ptr) = memtrack_getblocksize_preinit;
#define malloc(size)
Same syntaxt and same behavior than regular malloc function, with memory leaks tracking.
Definition: memory.h:32
#define strdup(chaine)
Same syntaxt and same behavior than regular strdup function, with memory leaks tracking.
Definition: memory.h:44
#define free(ptr)
Same syntaxt and same behavior than regular free function, with memory leaks tracking.
Definition: memory.h:41
size_t(* memtrack_getblocksize)(const void *p_Ptr)
Functor to get size of a specific memory block.
Definition: memtrack.c:621
void memtrack_reset()
Memory block metadata list reset.
Definition: memtrack.c:99
uint64_t(* memtrack_getallocatedblocks)()
Functor to get the number of allocated blocks.
Definition: memtrack.c:615
uint64_t(* memtrack_getallocatedRAM)()
Functor to get the total RAM size allocated.
Definition: memtrack.c:618
unsigned int(* memtrack_delblock)(const void *p_Ptr, const char *p_File, const int p_Line, const char *p_CompilDate, const char *p_CompilTime, const char *p_Function)
Functor to unregister an allocated memory block metadata.
Definition: memtrack.c:603
uint64_t(* memtrack_dumpblocks)()
Functor to list allocated memory blocks metadata.
Definition: memtrack.c:612
unsigned int(* memtrack_addblock)(const void *p_Ptr, const size_t p_Size, const char *p_File, const int p_Line, const char *p_CompilDate, const char *p_CompilTime, const char *p_Function)
Functor to register an allocated memory block metadata.
Definition: memtrack.c:593
Memory block metadata tracking headers.
#define NULL
Definition: mkernel-opt.c:64
Memory block metadata list item.
Definition: memtrack.h:37
size_t Size
Allocated memory block size.
Definition: memtrack.h:41
struct MemBlock * Prev
Previous item pointer.
Definition: memtrack.h:38
struct MemBlock * Next
Next item pointer.
Definition: memtrack.h:39
char * CompilDate
Source file compilation date.
Definition: memtrack.h:44
char * CompilTime
Source file compilation time.
Definition: memtrack.h:45
char * File
Source file which asked the allocation.
Definition: memtrack.h:42
char * Function
Fonction name which asked the allocation.
Definition: memtrack.h:46
void * Ptr
Allocated memory block pointer.
Definition: memtrack.h:40
int Line
Source line number ch asked the allocation.
Definition: memtrack.h:43