VisualStudio projects: asm tool updates
[profile/ivi/libvpx.git] / vpx_mem / vpx_mem_tracker.c
1 /*
2  *  Copyright (c) 2010 The VP8 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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 }