• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 
12 /*
13   vpx_mem_tracker.c
14 
15   jwz 2003-09-30:
16    Stores a list of addreses, their size, and file and line they came from.
17    All exposed lib functions are prefaced by vpx_ and allow the global list
18    to be thread safe.
19    Current supported platforms are:
20     Linux, Win32, win_ce and vx_works
21    Further support can be added by defining the platform specific mutex
22    in the memory_tracker struct as well as calls to create/destroy/lock/unlock
23    the mutex in vpx_memory_tracker_init/Destroy and memory_tracker_lock_mutex/unlock_mutex
24 */
25 #include "vpx_ports/config.h"
26 
27 #if defined(__uClinux__)
28 # include <lddk.h>
29 #endif
30 
31 #if HAVE_PTHREAD_H
32 # include <pthread.h>
33 #elif defined(WIN32) || defined(_WIN32_WCE)
34 # define WIN32_LEAN_AND_MEAN
35 # include <windows.h>
36 # include <winbase.h>
37 #elif defined(VXWORKS)
38 # include <sem_lib.h>
39 #elif defined(NDS_NITRO)
40 # include <nitro.h>
41 # include <nitro/os.h>
42 #endif
43 
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <string.h> //VXWORKS doesn't have a malloc/memory.h file,
47 //this should pull in malloc,free,etc.
48 #include <stdarg.h>
49 
50 #include "include/vpx_mem_tracker.h"
51 
52 #undef vpx_malloc   //undefine any vpx_mem macros that may affect calls to
53 #undef vpx_free     //memory functions in this file
54 #undef vpx_memcpy
55 #undef vpx_memset
56 
57 
58 #ifndef USE_GLOBAL_FUNCTION_POINTERS
59 # define USE_GLOBAL_FUNCTION_POINTERS   0  //use function pointers instead of compiled functions.
60 #endif
61 
62 #if USE_GLOBAL_FUNCTION_POINTERS
63 static mem_track_malloc_func g_malloc   = malloc;
64 static mem_track_calloc_func g_calloc   = calloc;
65 static mem_track_realloc_func g_realloc = realloc;
66 static mem_track_free_func g_free       = free;
67 static mem_track_memcpy_func g_memcpy   = memcpy;
68 static mem_track_memset_func g_memset   = memset;
69 static mem_track_memmove_func g_memmove = memmove;
70 # define MEM_TRACK_MALLOC g_malloc
71 # define MEM_TRACK_FREE   g_free
72 # define MEM_TRACK_MEMCPY g_memcpy
73 # define MEM_TRACK_MEMSET g_memset
74 #else
75 # define MEM_TRACK_MALLOC vpx_malloc
76 # define MEM_TRACK_FREE   vpx_free
77 # define MEM_TRACK_MEMCPY vpx_memcpy
78 # define MEM_TRACK_MEMSET vpx_memset
79 #endif // USE_GLOBAL_FUNCTION_POINTERS
80 
81 /* prototypes for internal library functions */
82 static void memtrack_log(const char *fmt, ...);
83 static void memory_tracker_dump();
84 static void memory_tracker_check_integrity(char *file, unsigned int line);
85 static void memory_tracker_add(size_t addr, unsigned int size,
86                                char *file, unsigned int line,
87                                int padded);
88 static int memory_tracker_remove(size_t addr);
89 static struct mem_block *memory_tracker_find(size_t addr);
90 
91 #if defined(NO_MUTEX)
92 # define memory_tracker_lock_mutex() (!g_b_mem_tracker_inited)
93 # define memory_tracker_unlock_mutex()
94 #else
95 static int memory_tracker_lock_mutex();
96 static int memory_tracker_unlock_mutex();
97 #endif
98 
99 #ifndef VPX_NO_GLOBALS
100 struct memory_tracker
101 {
102     struct mem_block *head,
103             * tail;
104     int len,
105         totalsize;
106     unsigned int current_allocated,
107              max_allocated;
108 
109 #if HAVE_PTHREAD_H
110     pthread_mutex_t mutex;
111 #elif defined(WIN32) || defined(_WIN32_WCE)
112     HANDLE mutex;
113 #elif defined(VXWORKS)
114     SEM_ID mutex;
115 #elif defined(NDS_NITRO)
116     OSMutex mutex;
117 #elif defined(NO_MUTEX)
118 #else
119 #error "No mutex type defined for this platform!"
120 #endif
121 
122     int padding_size,
123         pad_value;
124 };
125 
126 static struct memory_tracker memtrack;   //our global memory allocation list
127 static int g_b_mem_tracker_inited = 0;     //indicates whether the global list has
128 //been initialized (1:yes/0:no)
129 static struct
130 {
131     FILE *file;
132     int type;
133     void (*func)(void *userdata, const char *fmt, va_list args);
134     void *userdata;
135 } g_logging = {NULL, 0, NULL, NULL};
136 #else
137 # include "vpx_global_handling.h"
138 #define g_b_mem_tracker_inited vpxglobalm(vpxmem,g_b_mem_tracker_inited)
139 #define g_logging vpxglobalm(vpxmem,g_logging)
140 #define memtrack vpxglobalm(vpxmem,memtrack)
141 #endif // #ifndef VPX_NO_GLOBALS
142 
143 extern void *vpx_malloc(size_t size);
144 extern void vpx_free(void *memblk);
145 extern void *vpx_memcpy(void *dest, const void *src, size_t length);
146 extern void *vpx_memset(void *dest, int val, size_t length);
147 
148 /*
149  *
150  * Exposed library functions
151  *
152 */
153 
154 /*
155     vpx_memory_tracker_init(int padding_size, int pad_value)
156       padding_size - the size of the padding before and after each mem addr.
157                      Values > 0 indicate that integrity checks can be performed
158                      by inspecting these areas.
159       pad_value - the initial value within the padding area before and after
160                   each mem addr.
161 
162     Initializes global memory tracker structure
163     Allocates the head of the list
164 */
vpx_memory_tracker_init(int padding_size,int pad_value)165 int vpx_memory_tracker_init(int padding_size, int pad_value)
166 {
167     if (!g_b_mem_tracker_inited)
168     {
169         if ((memtrack.head = (struct mem_block *)
170                              MEM_TRACK_MALLOC(sizeof(struct mem_block))))
171         {
172             int ret;
173 
174             MEM_TRACK_MEMSET(memtrack.head, 0, sizeof(struct mem_block));
175 
176             memtrack.tail = memtrack.head;
177 
178             memtrack.current_allocated = 0;
179             memtrack.max_allocated     = 0;
180 
181             memtrack.padding_size = padding_size;
182             memtrack.pad_value    = pad_value;
183 
184 #if HAVE_PTHREAD_H
185             ret = pthread_mutex_init(&memtrack.mutex,
186                                      NULL);            /*mutex attributes (NULL=default)*/
187 #elif defined(WIN32) || defined(_WIN32_WCE)
188             memtrack.mutex = CreateMutex(NULL,   /*security attributes*/
189                                           FALSE,  /*we don't want initial ownership*/
190                                           NULL);  /*mutex name*/
191             ret = !memtrack.mutex;
192 #elif defined(VXWORKS)
193             memtrack.mutex = sem_bcreate(SEM_Q_FIFO, /*SEM_Q_FIFO non-priority based mutex*/
194                                          SEM_FULL);  /*SEM_FULL initial state is unlocked*/
195             ret = !memtrack.mutex;
196 #elif defined(NDS_NITRO)
197             os_init_mutex(&memtrack.mutex);
198             ret = 0;
199 #elif defined(NO_MUTEX)
200             ret = 0;
201 #endif
202 
203             if (ret)
204             {
205                 memtrack_log("vpx_memory_tracker_init: Error creating mutex!\n");
206 
207                 MEM_TRACK_FREE(memtrack.head);
208                 memtrack.head = NULL;
209             }
210             else
211             {
212                 memtrack_log("Memory Tracker init'd, v."vpx_mem_tracker_version" pad_size:%d pad_val:0x%x %d\n"
213                              , padding_size
214                              , pad_value
215                              , pad_value);
216                 g_b_mem_tracker_inited = 1;
217             }
218         }
219     }
220 
221     return g_b_mem_tracker_inited;
222 }
223 
224 /*
225     vpx_memory_tracker_destroy()
226     If our global struct was initialized zeros out all its members,
227     frees memory and destroys it's mutex
228 */
vpx_memory_tracker_destroy()229 void vpx_memory_tracker_destroy()
230 {
231     if (!memory_tracker_lock_mutex())
232     {
233         struct mem_block *p  = memtrack.head,
234                                   * p2 = memtrack.head;
235 
236         memory_tracker_dump();
237 
238         while (p)
239     {
240             p2 = p;
241             p  = p->next;
242 
243             MEM_TRACK_FREE(p2);
244         }
245 
246         memtrack.head              = NULL;
247         memtrack.tail              = NULL;
248         memtrack.len               = 0;
249         memtrack.current_allocated = 0;
250         memtrack.max_allocated     = 0;
251 
252         if (!g_logging.type && g_logging.file && g_logging.file != stderr)
253         {
254 #if !defined(NDS_NITRO)
255             fclose(g_logging.file);
256 #endif
257             g_logging.file = NULL;
258         }
259 
260         memory_tracker_unlock_mutex();
261 
262         g_b_mem_tracker_inited = 0;
263     }
264 }
265 
266 /*
267     vpx_memory_tracker_add(size_t addr, unsigned int size,
268                          char * file, unsigned int line)
269       addr - memory address to be added to list
270       size - size of addr
271       file - the file addr was referenced from
272       line - the line in file addr was referenced from
273     Adds memory address addr, it's size, file and line it came from
274     to the global list via the thread safe internal library function
275 */
vpx_memory_tracker_add(size_t addr,unsigned int size,char * file,unsigned int line,int padded)276 void vpx_memory_tracker_add(size_t addr, unsigned int size,
277                             char *file, unsigned int line,
278                             int padded)
279 {
280     memory_tracker_add(addr, size, file, line, padded);
281 }
282 
283 /*
284     vpx_memory_tracker_remove(size_t addr)
285       addr - memory address to be removed from list
286     Removes addr from the global list via the thread safe
287     internal remove function
288     Return:
289       Same as described for memory_tracker_remove
290 */
vpx_memory_tracker_remove(size_t addr)291 int vpx_memory_tracker_remove(size_t addr)
292 {
293     return memory_tracker_remove(addr);
294 }
295 
296 /*
297     vpx_memory_tracker_find(size_t addr)
298       addr - address to be found in list
299     Return:
300         If found, pointer to the memory block that matches addr
301         NULL otherwise
302 */
vpx_memory_tracker_find(size_t addr)303 struct mem_block *vpx_memory_tracker_find(size_t addr)
304 {
305     struct mem_block *p = NULL;
306 
307     if (!memory_tracker_lock_mutex())
308     {
309         p = memory_tracker_find(addr);
310         memory_tracker_unlock_mutex();
311     }
312 
313     return p;
314 }
315 
316 /*
317     vpx_memory_tracker_dump()
318     Locks the memory tracker's mutex and calls the internal
319     library function to dump the current contents of the
320     global memory allocation list
321 */
vpx_memory_tracker_dump()322 void vpx_memory_tracker_dump()
323 {
324     if (!memory_tracker_lock_mutex())
325     {
326         memory_tracker_dump();
327         memory_tracker_unlock_mutex();
328     }
329 }
330 
331 /*
332     vpx_memory_tracker_check_integrity(char* file, unsigned int line)
333       file - The file name where the check was placed
334       line - The line in file where the check was placed
335     Locks the memory tracker's mutex and calls the internal
336     integrity check function to inspect every address in the global
337     memory allocation list
338 */
vpx_memory_tracker_check_integrity(char * file,unsigned int line)339 void vpx_memory_tracker_check_integrity(char *file, unsigned int line)
340 {
341     if (!memory_tracker_lock_mutex())
342     {
343         memory_tracker_check_integrity(file, line);
344         memory_tracker_unlock_mutex();
345     }
346 }
347 
348 /*
349     vpx_memory_tracker_set_log_type
350     Sets the logging type for the memory tracker. Based on the value it will
351     direct its output to the appropriate place.
352     Return:
353       0: on success
354       -1: if the logging type could not be set, because the value was invalid
355           or because a file could not be opened
356 */
vpx_memory_tracker_set_log_type(int type,char * option)357 int vpx_memory_tracker_set_log_type(int type, char *option)
358 {
359     int ret = -1;
360 
361     switch (type)
362     {
363     case 0:
364         g_logging.type = 0;
365 
366         if (!option)
367         {
368             g_logging.file = stderr;
369             ret = 0;
370         }
371 
372 #if !defined(NDS_NITRO)
373         else
374         {
375             if ((g_logging.file = fopen((char *)option, "w")))
376                 ret = 0;
377         }
378 
379 #endif
380         break;
381 #if defined(WIN32) && !defined(_WIN32_WCE)
382     case 1:
383         g_logging.type = type;
384         ret = 0;
385         break;
386 #endif
387     default:
388         break;
389     }
390 
391     //output the version to the new logging destination
392     if (!ret)
393         memtrack_log("Memory Tracker logging initialized, "
394                      "Memory Tracker v."vpx_mem_tracker_version"\n");
395 
396     return ret;
397 }
398 
399 /*
400     vpx_memory_tracker_set_log_func
401     Sets a logging function to be used by the memory tracker.
402     Return:
403       0: on success
404       -1: if the logging type could not be set because logfunc was NULL
405 */
vpx_memory_tracker_set_log_func(void * userdata,void (* logfunc)(void * userdata,const char * fmt,va_list args))406 int vpx_memory_tracker_set_log_func(void *userdata,
407                                     void(*logfunc)(void *userdata,
408                                             const char *fmt, va_list args))
409 {
410     int ret = -1;
411 
412     if (logfunc)
413     {
414         g_logging.type     = -1;
415         g_logging.userdata = userdata;
416         g_logging.func     = logfunc;
417         ret = 0;
418     }
419 
420     //output the version to the new logging destination
421     if (!ret)
422         memtrack_log("Memory Tracker logging initialized, "
423                      "Memory Tracker v."vpx_mem_tracker_version"\n");
424 
425     return ret;
426 }
427 
428 /*
429  *
430  * END - Exposed library functions
431  *
432 */
433 
434 
435 /*
436  *
437  * Internal library functions
438  *
439 */
440 
memtrack_log(const char * fmt,...)441 static void memtrack_log(const char *fmt, ...)
442 {
443     va_list list;
444 
445     va_start(list, fmt);
446 
447     switch (g_logging.type)
448     {
449     case -1:
450 
451         if (g_logging.func)
452             g_logging.func(g_logging.userdata, fmt, list);
453 
454         break;
455     case 0:
456 
457         if (g_logging.file)
458         {
459             vfprintf(g_logging.file, fmt, list);
460             fflush(g_logging.file);
461         }
462 
463         break;
464 #if defined(WIN32) && !defined(_WIN32_WCE)
465     case 1:
466     {
467         char temp[1024];
468         _vsnprintf(temp, sizeof(temp) / sizeof(char) - 1, fmt, list);
469         OutputDebugString(temp);
470     }
471     break;
472 #endif
473     default:
474         break;
475     }
476 
477     va_end(list);
478 }
479 
480 /*
481     memory_tracker_dump()
482     Dumps the current contents of the global memory allocation list
483 */
memory_tracker_dump()484 static void memory_tracker_dump()
485 {
486     int i = 0;
487     struct mem_block *p = (memtrack.head ? memtrack.head->next : NULL);
488 
489     memtrack_log("\n_currently Allocated= %d; Max allocated= %d\n",
490                  memtrack.current_allocated, memtrack.max_allocated);
491 
492     while (p)
493     {
494 #if defined(WIN32) && !defined(_WIN32_WCE)
495 
496         /*when using outputdebugstring, output filenames so they
497           can be clicked to be opened in visual studio*/
498         if (g_logging.type == 1)
499             memtrack_log("memblocks[%d].addr= 0x%.8x, memblocks[%d].size= %d, file:\n"
500                          "  %s(%d):\n", i,
501                          p->addr, i, p->size,
502                          p->file, p->line);
503         else
504 #endif
505             memtrack_log("memblocks[%d].addr= 0x%.8x, memblocks[%d].size= %d, file: %s, line: %d\n", i,
506                          p->addr, i, p->size,
507                          p->file, p->line);
508 
509 #ifdef NDS_NITRO
510 
511         if (!(i % 20)) os_sleep(500);
512 
513 #endif
514 
515         p = p->next;
516         ++i;
517     }
518 
519     memtrack_log("\n");
520 }
521 
522 /*
523     memory_tracker_check_integrity(char* file, unsigned int file)
524       file - the file name where the check was placed
525       line - the line in file where the check was placed
526     If a padding_size was supplied to vpx_memory_tracker_init()
527     this function will check ea. addr in the list verifying that
528     addr-padding_size and addr+padding_size is filled with pad_value
529 */
memory_tracker_check_integrity(char * file,unsigned int line)530 static void memory_tracker_check_integrity(char *file, unsigned int line)
531 {
532     if (memtrack.padding_size)
533     {
534         int i,
535             index = 0;
536         unsigned char *p_show_me,
537                  * p_show_me2;
538         unsigned int tempme = memtrack.pad_value,
539                      dead1,
540                      dead2;
541         unsigned char *x_bounds;
542         struct mem_block *p = memtrack.head->next;
543 
544         while (p)
545         {
546             //x_bounds = (unsigned char*)p->addr;
547             //back up VPX_BYTE_ALIGNMENT
548             //x_bounds -= memtrack.padding_size;
549 
550             if (p->padded)   // can the bounds be checked?
551             {
552                 /*yes, move to the address that was actually allocated
553                 by the vpx_* calls*/
554                 x_bounds = (unsigned char *)(((size_t *)p->addr)[-1]);
555 
556                 for (i = 0; i < memtrack.padding_size; i += sizeof(unsigned int))
557                 {
558                     p_show_me = (x_bounds + i);
559                     p_show_me2 = (unsigned char *)(p->addr + p->size + i);
560 
561                     MEM_TRACK_MEMCPY(&dead1, p_show_me, sizeof(unsigned int));
562                     MEM_TRACK_MEMCPY(&dead2, p_show_me2, sizeof(unsigned int));
563 
564                     if ((dead1 != tempme) || (dead2 != tempme))
565                     {
566                         memtrack_log("\n[vpx_mem integrity check failed]:\n"
567                                      "    index[%d,%d] {%s:%d} addr=0x%x, size=%d,"
568                                      " file: %s, line: %d c0:0x%x c1:0x%x\n",
569                                      index, i, file, line, p->addr, p->size, p->file,
570                                      p->line, dead1, dead2);
571                     }
572                 }
573             }
574 
575             ++index;
576             p = p->next;
577         }
578     }
579 }
580 
581 /*
582     memory_tracker_add(size_t addr, unsigned int size,
583                      char * file, unsigned int line)
584     Adds an address (addr), it's size, file and line number to our list.
585     Adjusts the total bytes allocated and max bytes allocated if necessary.
586     If memory cannot be allocated the list will be destroyed.
587 */
memory_tracker_add(size_t addr,unsigned int size,char * file,unsigned int line,int padded)588 void memory_tracker_add(size_t addr, unsigned int size,
589                         char *file, unsigned int line,
590                         int padded)
591 {
592     if (!memory_tracker_lock_mutex())
593     {
594         struct mem_block *p;
595 
596         p = MEM_TRACK_MALLOC(sizeof(struct mem_block));
597 
598         if (p)
599         {
600             p->prev       = memtrack.tail;
601             p->prev->next = p;
602             p->addr       = addr;
603             p->size       = size;
604             p->line       = line;
605             p->file       = file;
606             p->padded     = padded;
607             p->next       = NULL;
608 
609             memtrack.tail = p;
610 
611             memtrack.current_allocated += size;
612 
613             if (memtrack.current_allocated > memtrack.max_allocated)
614                 memtrack.max_allocated = memtrack.current_allocated;
615 
616             //memtrack_log("memory_tracker_add: added addr=0x%.8x\n", addr);
617 
618             memory_tracker_unlock_mutex();
619         }
620         else
621         {
622             memtrack_log("memory_tracker_add: error allocating memory!\n");
623             memory_tracker_unlock_mutex();
624             vpx_memory_tracker_destroy();
625         }
626     }
627 }
628 
629 /*
630     memory_tracker_remove(size_t addr)
631     Removes an address and its corresponding size (if they exist)
632     from the memory tracker list and adjusts the current number
633     of bytes allocated.
634     Return:
635       0: on success
636       -1: if the mutex could not be locked
637       -2: if the addr was not found in the list
638 */
memory_tracker_remove(size_t addr)639 int memory_tracker_remove(size_t addr)
640 {
641     int ret = -1;
642 
643     if (!memory_tracker_lock_mutex())
644     {
645         struct mem_block *p;
646 
647         if ((p = memory_tracker_find(addr)))
648         {
649             memtrack.current_allocated -= p->size;
650 
651             p->prev->next = p->next;
652 
653             if (p->next)
654                 p->next->prev = p->prev;
655             else
656                 memtrack.tail = p->prev;
657 
658             ret = 0;
659             MEM_TRACK_FREE(p);
660         }
661         else
662         {
663             if (addr)
664                 memtrack_log("memory_tracker_remove(): addr not found in list,"
665                              " 0x%.8x\n", addr);
666 
667             ret = -2;
668         }
669 
670         memory_tracker_unlock_mutex();
671     }
672 
673     return ret;
674 }
675 
676 /*
677     memory_tracker_find(size_t addr)
678     Finds an address in our addrs list
679     NOTE: the mutex MUST be locked in the other internal
680           functions before calling this one. This avoids
681           the need for repeated locking and unlocking as in Remove
682     Returns: pointer to the mem block if found, NULL otherwise
683 */
memory_tracker_find(size_t addr)684 static struct mem_block *memory_tracker_find(size_t addr)
685 {
686     struct mem_block *p = NULL;
687 
688     if (memtrack.head)
689     {
690         p = memtrack.head->next;
691 
692         while (p && (p->addr != addr))
693             p = p->next;
694     }
695 
696     return p;
697 }
698 
699 
700 #if !defined(NO_MUTEX)
701 /*
702     memory_tracker_lock_mutex()
703     Locks the memory tracker mutex with a platform specific call
704     Returns:
705         0: Success
706        <0: Failure, either the mutex was not initialized
707            or the call to lock the mutex failed
708 */
memory_tracker_lock_mutex()709 static int memory_tracker_lock_mutex()
710 {
711     int ret = -1;
712 
713     if (g_b_mem_tracker_inited)
714     {
715 
716 #if HAVE_PTHREAD_H
717         ret = pthread_mutex_lock(&memtrack.mutex);
718 #elif defined(WIN32) || defined(_WIN32_WCE)
719         ret = WaitForSingleObject(memtrack.mutex, INFINITE);
720 #elif defined(VXWORKS)
721         ret = sem_take(memtrack.mutex, WAIT_FOREVER);
722 #elif defined(NDS_NITRO)
723         os_lock_mutex(&memtrack.mutex);
724         ret = 0;
725 #endif
726 
727         if (ret)
728         {
729             memtrack_log("memory_tracker_lock_mutex: mutex lock failed\n");
730         }
731     }
732 
733     return ret;
734 }
735 
736 /*
737     memory_tracker_unlock_mutex()
738     Unlocks the memory tracker mutex with a platform specific call
739     Returns:
740         0: Success
741        <0: Failure, either the mutex was not initialized
742            or the call to unlock the mutex failed
743 */
memory_tracker_unlock_mutex()744 static int memory_tracker_unlock_mutex()
745 {
746     int ret = -1;
747 
748     if (g_b_mem_tracker_inited)
749     {
750 
751 #if HAVE_PTHREAD_H
752         ret = pthread_mutex_unlock(&memtrack.mutex);
753 #elif defined(WIN32) || defined(_WIN32_WCE)
754         ret = !ReleaseMutex(memtrack.mutex);
755 #elif defined(VXWORKS)
756         ret = sem_give(memtrack.mutex);
757 #elif defined(NDS_NITRO)
758         os_unlock_mutex(&memtrack.mutex);
759         ret = 0;
760 #endif
761 
762         if (ret)
763         {
764             memtrack_log("memory_tracker_unlock_mutex: mutex unlock failed\n");
765         }
766     }
767 
768     return ret;
769 }
770 #endif
771 
772 /*
773     vpx_memory_tracker_set_functions
774 
775     Sets the function pointers for the standard library functions.
776 
777     Return:
778       0: on success
779       -1: if the use global function pointers is not set.
780 */
vpx_memory_tracker_set_functions(mem_track_malloc_func g_malloc_l,mem_track_calloc_func g_calloc_l,mem_track_realloc_func g_realloc_l,mem_track_free_func g_free_l,mem_track_memcpy_func g_memcpy_l,mem_track_memset_func g_memset_l,mem_track_memmove_func g_memmove_l)781 int vpx_memory_tracker_set_functions(mem_track_malloc_func g_malloc_l
782                                      , mem_track_calloc_func g_calloc_l
783                                      , mem_track_realloc_func g_realloc_l
784                                      , mem_track_free_func g_free_l
785                                      , mem_track_memcpy_func g_memcpy_l
786                                      , mem_track_memset_func g_memset_l
787                                      , mem_track_memmove_func g_memmove_l)
788 {
789 #if USE_GLOBAL_FUNCTION_POINTERS
790 
791     if (g_malloc_l)
792         g_malloc = g_malloc_l;
793 
794     if (g_calloc_l)
795         g_calloc = g_calloc_l;
796 
797     if (g_realloc_l)
798         g_realloc = g_realloc_l;
799 
800     if (g_free_l)
801         g_free = g_free_l;
802 
803     if (g_memcpy_l)
804         g_memcpy = g_memcpy_l;
805 
806     if (g_memset_l)
807         g_memset = g_memset_l;
808 
809     if (g_memmove_l)
810         g_memmove = g_memmove_l;
811 
812     return 0;
813 #else
814     (void)g_malloc_l;
815     (void)g_calloc_l;
816     (void)g_realloc_l;
817     (void)g_free_l;
818     (void)g_memcpy_l;
819     (void)g_memset_l;
820     (void)g_memmove_l;
821     return -1;
822 #endif
823 }
824