Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / libvpx / source / libvpx / vpx_mem / vpx_mem.c
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 #define __VPX_MEM_C__
13
14 #include "vpx_mem.h"
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include "include/vpx_mem_intrnl.h"
19 #include "vpx/vpx_integer.h"
20
21 #if CONFIG_MEM_TRACKER
22 #ifndef VPX_NO_GLOBALS
23 static unsigned long g_alloc_count = 0;
24 #else
25 #include "vpx_global_handling.h"
26 #define g_alloc_count vpxglobalm(vpxmem,g_alloc_count)
27 #endif
28 #endif
29
30 #if CONFIG_MEM_MANAGER
31 # include "heapmm.h"
32 # include "hmm_intrnl.h"
33
34 # define SHIFT_HMM_ADDR_ALIGN_UNIT 5
35 # define TOTAL_MEMORY_TO_ALLOCATE  20971520 /* 20 * 1024 * 1024 */
36
37 # define MM_DYNAMIC_MEMORY 1
38 # if MM_DYNAMIC_MEMORY
39 static unsigned char *g_p_mng_memory_raw = NULL;
40 static unsigned char *g_p_mng_memory     = NULL;
41 # else
42 static unsigned char g_p_mng_memory[TOTAL_MEMORY_TO_ALLOCATE];
43 # endif
44
45 static size_t g_mm_memory_size = TOTAL_MEMORY_TO_ALLOCATE;
46
47 static hmm_descriptor hmm_d;
48 static int g_mng_memory_allocated = 0;
49
50 static int vpx_mm_create_heap_memory();
51 static void *vpx_mm_realloc(void *memblk, size_t size);
52 #endif /*CONFIG_MEM_MANAGER*/
53
54 #if USE_GLOBAL_FUNCTION_POINTERS
55 struct GLOBAL_FUNC_POINTERS {
56   g_malloc_func g_malloc;
57   g_calloc_func g_calloc;
58   g_realloc_func g_realloc;
59   g_free_func g_free;
60   g_memcpy_func g_memcpy;
61   g_memset_func g_memset;
62   g_memmove_func g_memmove;
63 } *g_func = NULL;
64
65 # define VPX_MALLOC_L  g_func->g_malloc
66 # define VPX_REALLOC_L g_func->g_realloc
67 # define VPX_FREE_L    g_func->g_free
68 # define VPX_MEMCPY_L  g_func->g_memcpy
69 # define VPX_MEMSET_L  g_func->g_memset
70 # define VPX_MEMMOVE_L g_func->g_memmove
71 #else
72 # define VPX_MALLOC_L  malloc
73 # define VPX_REALLOC_L realloc
74 # define VPX_FREE_L    free
75 # define VPX_MEMCPY_L  memcpy
76 # define VPX_MEMSET_L  memset
77 # define VPX_MEMMOVE_L memmove
78 #endif /* USE_GLOBAL_FUNCTION_POINTERS */
79
80 unsigned int vpx_mem_get_version() {
81   unsigned int ver = ((unsigned int)(unsigned char)VPX_MEM_VERSION_CHIEF << 24 |
82                       (unsigned int)(unsigned char)VPX_MEM_VERSION_MAJOR << 16 |
83                       (unsigned int)(unsigned char)VPX_MEM_VERSION_MINOR << 8  |
84                       (unsigned int)(unsigned char)VPX_MEM_VERSION_PATCH);
85   return ver;
86 }
87
88 int vpx_mem_set_heap_size(size_t size) {
89   int ret = -1;
90
91 #if CONFIG_MEM_MANAGER
92 #if MM_DYNAMIC_MEMORY
93
94   if (!g_mng_memory_allocated && size) {
95     g_mm_memory_size = size;
96     ret = 0;
97   } else
98     ret = -3;
99
100 #else
101   ret = -2;
102 #endif
103 #else
104   (void)size;
105 #endif
106
107   return ret;
108 }
109
110 void *vpx_memalign(size_t align, size_t size) {
111   void *addr,
112        * x = NULL;
113
114 #if CONFIG_MEM_MANAGER
115   int number_aau;
116
117   if (vpx_mm_create_heap_memory() < 0) {
118     _P(printf("[vpx][mm] ERROR vpx_memalign() Couldn't create memory for Heap.\n");)
119   }
120
121   number_aau = ((size + align - 1 + ADDRESS_STORAGE_SIZE) >>
122                 SHIFT_HMM_ADDR_ALIGN_UNIT) + 1;
123
124   addr = hmm_alloc(&hmm_d, number_aau);
125 #else
126   addr = VPX_MALLOC_L(size + align - 1 + ADDRESS_STORAGE_SIZE);
127 #endif /*CONFIG_MEM_MANAGER*/
128
129   if (addr) {
130     x = align_addr((unsigned char *)addr + ADDRESS_STORAGE_SIZE, (int)align);
131     /* save the actual malloc address */
132     ((size_t *)x)[-1] = (size_t)addr;
133   }
134
135   return x;
136 }
137
138 void *vpx_malloc(size_t size) {
139   return vpx_memalign(DEFAULT_ALIGNMENT, size);
140 }
141
142 void *vpx_calloc(size_t num, size_t size) {
143   void *x;
144
145   x = vpx_memalign(DEFAULT_ALIGNMENT, num * size);
146
147   if (x)
148     VPX_MEMSET_L(x, 0, num * size);
149
150   return x;
151 }
152
153 void *vpx_realloc(void *memblk, size_t size) {
154   void *addr,
155        * new_addr = NULL;
156   int align = DEFAULT_ALIGNMENT;
157
158   /*
159   The realloc() function changes the size of the object pointed to by
160   ptr to the size specified by size, and returns a pointer to the
161   possibly moved block. The contents are unchanged up to the lesser
162   of the new and old sizes. If ptr is null, realloc() behaves like
163   malloc() for the specified size. If size is zero (0) and ptr is
164   not a null pointer, the object pointed to is freed.
165   */
166   if (!memblk)
167     new_addr = vpx_malloc(size);
168   else if (!size)
169     vpx_free(memblk);
170   else {
171     addr   = (void *)(((size_t *)memblk)[-1]);
172     memblk = NULL;
173
174 #if CONFIG_MEM_MANAGER
175     new_addr = vpx_mm_realloc(addr, size + align + ADDRESS_STORAGE_SIZE);
176 #else
177     new_addr = VPX_REALLOC_L(addr, size + align + ADDRESS_STORAGE_SIZE);
178 #endif
179
180     if (new_addr) {
181       addr = new_addr;
182       new_addr = (void *)(((size_t)
183                            ((unsigned char *)new_addr + ADDRESS_STORAGE_SIZE) + (align - 1)) &
184                           (size_t) - align);
185       /* save the actual malloc address */
186       ((size_t *)new_addr)[-1] = (size_t)addr;
187     }
188   }
189
190   return new_addr;
191 }
192
193 void vpx_free(void *memblk) {
194   if (memblk) {
195     void *addr = (void *)(((size_t *)memblk)[-1]);
196 #if CONFIG_MEM_MANAGER
197     hmm_free(&hmm_d, addr);
198 #else
199     VPX_FREE_L(addr);
200 #endif
201   }
202 }
203
204 #if CONFIG_MEM_TRACKER
205 void *xvpx_memalign(size_t align, size_t size, char *file, int line) {
206 #if TRY_BOUNDS_CHECK
207   unsigned char *x_bounds;
208 #endif
209
210   void *x;
211
212   if (g_alloc_count == 0) {
213 #if TRY_BOUNDS_CHECK
214     int i_rv = vpx_memory_tracker_init(BOUNDS_CHECK_PAD_SIZE, BOUNDS_CHECK_VALUE);
215 #else
216     int i_rv = vpx_memory_tracker_init(0, 0);
217 #endif
218
219     if (i_rv < 0) {
220       _P(printf("ERROR xvpx_malloc MEM_TRACK_USAGE error vpx_memory_tracker_init().\n");)
221     }
222   }
223
224 #if TRY_BOUNDS_CHECK
225   {
226     int i;
227     unsigned int tempme = BOUNDS_CHECK_VALUE;
228
229     x_bounds = vpx_memalign(align, size + (BOUNDS_CHECK_PAD_SIZE * 2));
230
231     if (x_bounds) {
232       /*we're aligning the address twice here but to keep things
233         consistent we want to have the padding come before the stored
234         address so no matter what free function gets called we will
235         attempt to free the correct address*/
236       x_bounds = (unsigned char *)(((size_t *)x_bounds)[-1]);
237       x = align_addr(x_bounds + BOUNDS_CHECK_PAD_SIZE + ADDRESS_STORAGE_SIZE,
238                      (int)align);
239       /* save the actual malloc address */
240       ((size_t *)x)[-1] = (size_t)x_bounds;
241
242       for (i = 0; i < BOUNDS_CHECK_PAD_SIZE; i += sizeof(unsigned int)) {
243         VPX_MEMCPY_L(x_bounds + i, &tempme, sizeof(unsigned int));
244         VPX_MEMCPY_L((unsigned char *)x + size + i,
245                      &tempme, sizeof(unsigned int));
246       }
247     } else
248       x = NULL;
249   }
250 #else
251   x = vpx_memalign(align, size);
252 #endif /*TRY_BOUNDS_CHECK*/
253
254   g_alloc_count++;
255
256   vpx_memory_tracker_add((size_t)x, (unsigned int)size, file, line, 1);
257
258   return x;
259 }
260
261 void *xvpx_malloc(size_t size, char *file, int line) {
262   return xvpx_memalign(DEFAULT_ALIGNMENT, size, file, line);
263 }
264
265 void *xvpx_calloc(size_t num, size_t size, char *file, int line) {
266   void *x = xvpx_memalign(DEFAULT_ALIGNMENT, num * size, file, line);
267
268   if (x)
269     VPX_MEMSET_L(x, 0, num * size);
270
271   return x;
272 }
273
274 void *xvpx_realloc(void *memblk, size_t size, char *file, int line) {
275   struct mem_block *p = NULL;
276   int orig_size = 0,
277       orig_line = 0;
278   char *orig_file = NULL;
279
280 #if TRY_BOUNDS_CHECK
281   unsigned char *x_bounds = memblk ?
282                             (unsigned char *)(((size_t *)memblk)[-1]) :
283                             NULL;
284 #endif
285
286   void *x;
287
288   if (g_alloc_count == 0) {
289 #if TRY_BOUNDS_CHECK
290
291     if (!vpx_memory_tracker_init(BOUNDS_CHECK_PAD_SIZE, BOUNDS_CHECK_VALUE))
292 #else
293     if (!vpx_memory_tracker_init(0, 0))
294 #endif
295     {
296       _P(printf("ERROR xvpx_malloc MEM_TRACK_USAGE error vpx_memory_tracker_init().\n");)
297     }
298   }
299
300   if ((p = vpx_memory_tracker_find((size_t)memblk))) {
301     orig_size = p->size;
302     orig_file = p->file;
303     orig_line = p->line;
304   }
305
306 #if TRY_BOUNDS_CHECK_ON_FREE
307   vpx_memory_tracker_check_integrity(file, line);
308 #endif
309
310   /* have to do this regardless of success, because
311    * the memory that does get realloc'd may change
312    * the bounds values of this block
313    */
314   vpx_memory_tracker_remove((size_t)memblk);
315
316 #if TRY_BOUNDS_CHECK
317   {
318     int i;
319     unsigned int tempme = BOUNDS_CHECK_VALUE;
320
321     x_bounds = vpx_realloc(memblk, size + (BOUNDS_CHECK_PAD_SIZE * 2));
322
323     if (x_bounds) {
324       x_bounds = (unsigned char *)(((size_t *)x_bounds)[-1]);
325       x = align_addr(x_bounds + BOUNDS_CHECK_PAD_SIZE + ADDRESS_STORAGE_SIZE,
326                      (int)DEFAULT_ALIGNMENT);
327       /* save the actual malloc address */
328       ((size_t *)x)[-1] = (size_t)x_bounds;
329
330       for (i = 0; i < BOUNDS_CHECK_PAD_SIZE; i += sizeof(unsigned int)) {
331         VPX_MEMCPY_L(x_bounds + i, &tempme, sizeof(unsigned int));
332         VPX_MEMCPY_L((unsigned char *)x + size + i,
333                      &tempme, sizeof(unsigned int));
334       }
335     } else
336       x = NULL;
337   }
338 #else
339   x = vpx_realloc(memblk, size);
340 #endif /*TRY_BOUNDS_CHECK*/
341
342   if (!memblk) ++g_alloc_count;
343
344   if (x)
345     vpx_memory_tracker_add((size_t)x, (unsigned int)size, file, line, 1);
346   else
347     vpx_memory_tracker_add((size_t)memblk, orig_size, orig_file, orig_line, 1);
348
349   return x;
350 }
351
352 void xvpx_free(void *p_address, char *file, int line) {
353 #if TRY_BOUNDS_CHECK
354   unsigned char *p_bounds_address = (unsigned char *)p_address;
355   /*p_bounds_address -= BOUNDS_CHECK_PAD_SIZE;*/
356 #endif
357
358 #if !TRY_BOUNDS_CHECK_ON_FREE
359   (void)file;
360   (void)line;
361 #endif
362
363   if (p_address) {
364 #if TRY_BOUNDS_CHECK_ON_FREE
365     vpx_memory_tracker_check_integrity(file, line);
366 #endif
367
368     /* if the addr isn't found in the list, assume it was allocated via
369      * vpx_ calls not xvpx_, therefore it does not contain any padding
370      */
371     if (vpx_memory_tracker_remove((size_t)p_address) == -2) {
372       p_bounds_address = p_address;
373       _P(fprintf(stderr, "[vpx_mem][xvpx_free] addr: %p not found in"
374                  " list; freed from file:%s"
375                  " line:%d\n", p_address, file, line));
376     } else
377       --g_alloc_count;
378
379 #if TRY_BOUNDS_CHECK
380     vpx_free(p_bounds_address);
381 #else
382     vpx_free(p_address);
383 #endif
384
385     if (!g_alloc_count)
386       vpx_memory_tracker_destroy();
387   }
388 }
389
390 #endif /*CONFIG_MEM_TRACKER*/
391
392 #if CONFIG_MEM_CHECKS
393 #if defined(VXWORKS)
394 #include <task_lib.h> /*for task_delay()*/
395 /* This function is only used to get a stack trace of the player
396 object so we can se where we are having a problem. */
397 static int get_my_tt(int task) {
398   tt(task);
399
400   return 0;
401 }
402
403 static void vx_sleep(int msec) {
404   int ticks_to_sleep = 0;
405
406   if (msec) {
407     int msec_per_tick = 1000 / sys_clk_rate_get();
408
409     if (msec < msec_per_tick)
410       ticks_to_sleep++;
411     else
412       ticks_to_sleep = msec / msec_per_tick;
413   }
414
415   task_delay(ticks_to_sleep);
416 }
417 #endif
418 #endif
419
420 void *vpx_memcpy(void *dest, const void *source, size_t length) {
421 #if CONFIG_MEM_CHECKS
422
423   if (((int)dest < 0x4000) || ((int)source < 0x4000)) {
424     _P(printf("WARNING: vpx_memcpy dest:0x%x source:0x%x len:%d\n", (int)dest, (int)source, length);)
425
426 #if defined(VXWORKS)
427     sp(get_my_tt, task_id_self(), 0, 0, 0, 0, 0, 0, 0, 0);
428
429     vx_sleep(10000);
430 #endif
431   }
432
433 #endif
434
435   return VPX_MEMCPY_L(dest, source, length);
436 }
437
438 void *vpx_memset(void *dest, int val, size_t length) {
439 #if CONFIG_MEM_CHECKS
440
441   if ((int)dest < 0x4000) {
442     _P(printf("WARNING: vpx_memset dest:0x%x val:%d len:%d\n", (int)dest, val, length);)
443
444 #if defined(VXWORKS)
445     sp(get_my_tt, task_id_self(), 0, 0, 0, 0, 0, 0, 0, 0);
446
447     vx_sleep(10000);
448 #endif
449   }
450
451 #endif
452
453   return VPX_MEMSET_L(dest, val, length);
454 }
455
456 #if CONFIG_VP9 && CONFIG_VP9_HIGHBITDEPTH
457 void *vpx_memset16(void *dest, int val, size_t length) {
458 #if CONFIG_MEM_CHECKS
459   if ((int)dest < 0x4000) {
460     _P(printf("WARNING: vpx_memset dest:0x%x val:%d len:%d\n",
461               (int)dest, val, length);)
462
463 #if defined(VXWORKS)
464     sp(get_my_tt, task_id_self(), 0, 0, 0, 0, 0, 0, 0, 0);
465
466     vx_sleep(10000);
467 #endif
468   }
469 #endif
470   int i;
471   void *orig = dest;
472   uint16_t *dest16 = dest;
473   for (i = 0; i < length; i++)
474     *dest16++ = val;
475   return orig;
476 }
477 #endif  // CONFIG_VP9 && CONFIG_VP9_HIGHBITDEPTH
478
479 void *vpx_memmove(void *dest, const void *src, size_t count) {
480 #if CONFIG_MEM_CHECKS
481
482   if (((int)dest < 0x4000) || ((int)src < 0x4000)) {
483     _P(printf("WARNING: vpx_memmove dest:0x%x src:0x%x count:%d\n", (int)dest, (int)src, count);)
484
485 #if defined(VXWORKS)
486     sp(get_my_tt, task_id_self(), 0, 0, 0, 0, 0, 0, 0, 0);
487
488     vx_sleep(10000);
489 #endif
490   }
491
492 #endif
493
494   return VPX_MEMMOVE_L(dest, src, count);
495 }
496
497 #if CONFIG_MEM_MANAGER
498
499 static int vpx_mm_create_heap_memory() {
500   int i_rv = 0;
501
502   if (!g_mng_memory_allocated) {
503 #if MM_DYNAMIC_MEMORY
504     g_p_mng_memory_raw =
505       (unsigned char *)malloc(g_mm_memory_size + HMM_ADDR_ALIGN_UNIT);
506
507     if (g_p_mng_memory_raw) {
508       g_p_mng_memory = (unsigned char *)((((unsigned int)g_p_mng_memory_raw) +
509                                           HMM_ADDR_ALIGN_UNIT - 1) &
510                                          -(int)HMM_ADDR_ALIGN_UNIT);
511
512       _P(printf("[vpx][mm] total memory size:%d g_p_mng_memory_raw:0x%x g_p_mng_memory:0x%x\n"
513 , g_mm_memory_size + HMM_ADDR_ALIGN_UNIT
514 , (unsigned int)g_p_mng_memory_raw
515 , (unsigned int)g_p_mng_memory);)
516     } else {
517       _P(printf("[vpx][mm] Couldn't allocate memory:%d for vpx memory manager.\n"
518 , g_mm_memory_size);)
519
520       i_rv = -1;
521     }
522
523     if (g_p_mng_memory)
524 #endif
525     {
526       int chunk_size = 0;
527
528       g_mng_memory_allocated = 1;
529
530       hmm_init(&hmm_d);
531
532       chunk_size = g_mm_memory_size >> SHIFT_HMM_ADDR_ALIGN_UNIT;
533
534       chunk_size -= DUMMY_END_BLOCK_BAUS;
535
536       _P(printf("[vpx][mm] memory size:%d for vpx memory manager. g_p_mng_memory:0x%x  chunk_size:%d\n"
537 , g_mm_memory_size
538 , (unsigned int)g_p_mng_memory
539 , chunk_size);)
540
541       hmm_new_chunk(&hmm_d, (void *)g_p_mng_memory, chunk_size);
542     }
543
544 #if MM_DYNAMIC_MEMORY
545     else {
546       _P(printf("[vpx][mm] Couldn't allocate memory:%d for vpx memory manager.\n"
547 , g_mm_memory_size);)
548
549       i_rv = -1;
550     }
551
552 #endif
553   }
554
555   return i_rv;
556 }
557
558 static void *vpx_mm_realloc(void *memblk, size_t size) {
559   void *p_ret = NULL;
560
561   if (vpx_mm_create_heap_memory() < 0) {
562     _P(printf("[vpx][mm] ERROR vpx_mm_realloc() Couldn't create memory for Heap.\n");)
563   } else {
564     int i_rv = 0;
565     int old_num_aaus;
566     int new_num_aaus;
567
568     old_num_aaus = hmm_true_size(memblk);
569     new_num_aaus = (size >> SHIFT_HMM_ADDR_ALIGN_UNIT) + 1;
570
571     if (old_num_aaus == new_num_aaus) {
572       p_ret = memblk;
573     } else {
574       i_rv = hmm_resize(&hmm_d, memblk, new_num_aaus);
575
576       if (i_rv == 0) {
577         p_ret = memblk;
578       } else {
579         /* Error. Try to malloc and then copy data. */
580         void *p_from_malloc;
581
582         new_num_aaus = (size >> SHIFT_HMM_ADDR_ALIGN_UNIT) + 1;
583         p_from_malloc  = hmm_alloc(&hmm_d, new_num_aaus);
584
585         if (p_from_malloc) {
586           vpx_memcpy(p_from_malloc, memblk, size);
587           hmm_free(&hmm_d, memblk);
588
589           p_ret = p_from_malloc;
590         }
591       }
592     }
593   }
594
595   return p_ret;
596 }
597 #endif /*CONFIG_MEM_MANAGER*/
598
599 #if USE_GLOBAL_FUNCTION_POINTERS
600 # if CONFIG_MEM_TRACKER
601 extern int vpx_memory_tracker_set_functions(g_malloc_func g_malloc_l
602 , g_calloc_func g_calloc_l
603 , g_realloc_func g_realloc_l
604 , g_free_func g_free_l
605 , g_memcpy_func g_memcpy_l
606 , g_memset_func g_memset_l
607 , g_memmove_func g_memmove_l);
608 # endif
609 #endif /*USE_GLOBAL_FUNCTION_POINTERS*/
610 int vpx_mem_set_functions(g_malloc_func g_malloc_l
611 , g_calloc_func g_calloc_l
612 , g_realloc_func g_realloc_l
613 , g_free_func g_free_l
614 , g_memcpy_func g_memcpy_l
615 , g_memset_func g_memset_l
616 , g_memmove_func g_memmove_l) {
617 #if USE_GLOBAL_FUNCTION_POINTERS
618
619   /* If use global functions is turned on then the
620   application must set the global functions before
621   it does anything else or vpx_mem will have
622   unpredictable results. */
623   if (!g_func) {
624     g_func = (struct GLOBAL_FUNC_POINTERS *)
625              g_malloc_l(sizeof(struct GLOBAL_FUNC_POINTERS));
626
627     if (!g_func) {
628       return -1;
629     }
630   }
631
632 #if CONFIG_MEM_TRACKER
633   {
634     int rv = 0;
635     rv = vpx_memory_tracker_set_functions(g_malloc_l
636 , g_calloc_l
637 , g_realloc_l
638 , g_free_l
639 , g_memcpy_l
640 , g_memset_l
641 , g_memmove_l);
642
643     if (rv < 0) {
644       return rv;
645     }
646   }
647 #endif
648
649   g_func->g_malloc  = g_malloc_l;
650   g_func->g_calloc  = g_calloc_l;
651   g_func->g_realloc = g_realloc_l;
652   g_func->g_free    = g_free_l;
653   g_func->g_memcpy  = g_memcpy_l;
654   g_func->g_memset  = g_memset_l;
655   g_func->g_memmove = g_memmove_l;
656
657   return 0;
658 #else
659   (void)g_malloc_l;
660   (void)g_calloc_l;
661   (void)g_realloc_l;
662   (void)g_free_l;
663   (void)g_memcpy_l;
664   (void)g_memset_l;
665   (void)g_memmove_l;
666   return -1;
667 #endif
668 }
669
670 int vpx_mem_unset_functions() {
671 #if USE_GLOBAL_FUNCTION_POINTERS
672
673   if (g_func) {
674     g_free_func temp_free = g_func->g_free;
675     temp_free(g_func);
676     g_func = NULL;
677   }
678
679 #endif
680   return 0;
681 }