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