Merge "Fixed an encoder debug/relese mismatch in x86_64-win64-vs8"
[libvpx.git] / vpx_mem / vpx_mem.c
blobf6b1a355001411f8a63d1649e63deb5b7ca3b3f1
1 /*
2 * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
4 * Use of this source code is governed by a BSD-style license and patent
5 * grant that can be found in the LICENSE file in the root of the source
6 * tree. All contributing project authors may be found in the AUTHORS
7 * file in the root of the source tree.
8 */
11 #define __VPX_MEM_C__
13 #include "vpx_mem.h"
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include "include/vpx_mem_intrnl.h"
19 #if CONFIG_MEM_TRACKER
20 #ifndef VPX_NO_GLOBALS
21 static unsigned long g_alloc_count = 0;
22 #else
23 #include "vpx_global_handling.h"
24 #define g_alloc_count vpxglobalm(vpxmem,g_alloc_count)
25 #endif
26 #endif
28 #if CONFIG_MEM_MANAGER
29 # include "heapmm.h"
30 # include "hmm_intrnl.h"
32 # define SHIFT_HMM_ADDR_ALIGN_UNIT 5
33 # define TOTAL_MEMORY_TO_ALLOCATE 20971520 // 20 * 1024 * 1024
35 # define MM_DYNAMIC_MEMORY 1
36 # if MM_DYNAMIC_MEMORY
37 static unsigned char *g_p_mng_memory_raw = NULL;
38 static unsigned char *g_p_mng_memory = NULL;
39 # else
40 static unsigned char g_p_mng_memory[TOTAL_MEMORY_TO_ALLOCATE];
41 # endif
43 static size_t g_mm_memory_size = TOTAL_MEMORY_TO_ALLOCATE;
45 static hmm_descriptor hmm_d;
46 static int g_mng_memory_allocated = 0;
48 static int vpx_mm_create_heap_memory();
49 static void *vpx_mm_realloc(void *memblk, size_t size);
50 #endif //CONFIG_MEM_MANAGER
52 #if USE_GLOBAL_FUNCTION_POINTERS
53 struct GLOBAL_FUNC_POINTERS
55 g_malloc_func g_malloc;
56 g_calloc_func g_calloc;
57 g_realloc_func g_realloc;
58 g_free_func g_free;
59 g_memcpy_func g_memcpy;
60 g_memset_func g_memset;
61 g_memmove_func g_memmove;
62 } *g_func = NULL;
64 # define VPX_MALLOC_L g_func->g_malloc
65 # define VPX_REALLOC_L g_func->g_realloc
66 # define VPX_FREE_L g_func->g_free
67 # define VPX_MEMCPY_L g_func->g_memcpy
68 # define VPX_MEMSET_L g_func->g_memset
69 # define VPX_MEMMOVE_L g_func->g_memmove
70 #else
71 # define VPX_MALLOC_L malloc
72 # define VPX_REALLOC_L realloc
73 # define VPX_FREE_L free
74 # define VPX_MEMCPY_L memcpy
75 # define VPX_MEMSET_L memset
76 # define VPX_MEMMOVE_L memmove
77 #endif // USE_GLOBAL_FUNCTION_POINTERS
79 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;
88 int vpx_mem_set_heap_size(size_t size)
90 int ret = -1;
92 #if CONFIG_MEM_MANAGER
93 #if MM_DYNAMIC_MEMORY
95 if (!g_mng_memory_allocated && size)
97 g_mm_memory_size = size;
98 ret = 0;
100 else
101 ret = -3;
103 #else
104 ret = -2;
105 #endif
106 #else
107 (void)size;
108 #endif
110 return ret;
113 void *vpx_memalign(size_t align, size_t size)
115 void *addr,
116 * x = NULL;
118 #if CONFIG_MEM_MANAGER
119 int number_aau;
121 if (vpx_mm_create_heap_memory() < 0)
123 _P(printf("[vpx][mm] ERROR vpx_memalign() Couldn't create memory for Heap.\n");)
126 number_aau = ((size + align - 1 + ADDRESS_STORAGE_SIZE) >>
127 SHIFT_HMM_ADDR_ALIGN_UNIT) + 1;
129 addr = hmm_alloc(&hmm_d, number_aau);
130 #else
131 addr = VPX_MALLOC_L(size + align - 1 + ADDRESS_STORAGE_SIZE);
132 #endif //CONFIG_MEM_MANAGER
134 if (addr)
136 x = align_addr((unsigned char *)addr + ADDRESS_STORAGE_SIZE, (int)align);
137 /* save the actual malloc address */
138 ((size_t *)x)[-1] = (size_t)addr;
141 return x;
144 void *vpx_malloc(size_t size)
146 return vpx_memalign(DEFAULT_ALIGNMENT, size);
149 void *vpx_calloc(size_t num, size_t size)
151 void *x;
153 x = vpx_memalign(DEFAULT_ALIGNMENT, num * size);
155 if (x)
156 VPX_MEMSET_L(x, 0, num * size);
158 return x;
161 void *vpx_realloc(void *memblk, size_t size)
163 void *addr,
164 * new_addr = NULL;
165 int align = DEFAULT_ALIGNMENT;
168 The realloc() function changes the size of the object pointed to by
169 ptr to the size specified by size, and returns a pointer to the
170 possibly moved block. The contents are unchanged up to the lesser
171 of the new and old sizes. If ptr is null, realloc() behaves like
172 malloc() for the specified size. If size is zero (0) and ptr is
173 not a null pointer, the object pointed to is freed.
175 if (!memblk)
176 new_addr = vpx_malloc(size);
177 else if (!size)
178 vpx_free(memblk);
179 else
181 addr = (void *)(((size_t *)memblk)[-1]);
182 memblk = NULL;
184 #if CONFIG_MEM_MANAGER
185 new_addr = vpx_mm_realloc(addr, size + align + ADDRESS_STORAGE_SIZE);
186 #else
187 new_addr = VPX_REALLOC_L(addr, size + align + ADDRESS_STORAGE_SIZE);
188 #endif
190 if (new_addr)
192 addr = new_addr;
193 new_addr = (void *)(((size_t)
194 ((unsigned char *)new_addr + ADDRESS_STORAGE_SIZE) + (align - 1)) &
195 (size_t) - align);
196 /* save the actual malloc address */
197 ((size_t *)new_addr)[-1] = (size_t)addr;
201 return new_addr;
204 void vpx_free(void *memblk)
206 if (memblk)
208 void *addr = (void *)(((size_t *)memblk)[-1]);
209 #if CONFIG_MEM_MANAGER
210 hmm_free(&hmm_d, addr);
211 #else
212 VPX_FREE_L(addr);
213 #endif
217 #if CONFIG_MEM_TRACKER
218 void *xvpx_memalign(size_t align, size_t size, char *file, int line)
220 #if TRY_BOUNDS_CHECK
221 unsigned char *x_bounds;
222 #endif
224 void *x;
226 if (g_alloc_count == 0)
228 #if TRY_BOUNDS_CHECK
229 int i_rv = vpx_memory_tracker_init(BOUNDS_CHECK_PAD_SIZE, BOUNDS_CHECK_VALUE);
230 #else
231 int i_rv = vpx_memory_tracker_init(0, 0);
232 #endif
234 if (i_rv < 0)
236 _P(printf("ERROR xvpx_malloc MEM_TRACK_USAGE error vpx_memory_tracker_init().\n");)
240 #if TRY_BOUNDS_CHECK
242 int i;
243 unsigned int tempme = BOUNDS_CHECK_VALUE;
245 x_bounds = vpx_memalign(align, size + (BOUNDS_CHECK_PAD_SIZE * 2));
247 if (x_bounds)
249 /*we're aligning the address twice here but to keep things
250 consistent we want to have the padding come before the stored
251 address so no matter what free function gets called we will
252 attempt to free the correct address*/
253 x_bounds = (unsigned char *)(((size_t *)x_bounds)[-1]);
254 x = align_addr(x_bounds + BOUNDS_CHECK_PAD_SIZE + ADDRESS_STORAGE_SIZE,
255 (int)align);
256 /* save the actual malloc address */
257 ((size_t *)x)[-1] = (size_t)x_bounds;
259 for (i = 0; i < BOUNDS_CHECK_PAD_SIZE; i += sizeof(unsigned int))
261 VPX_MEMCPY_L(x_bounds + i, &tempme, sizeof(unsigned int));
262 VPX_MEMCPY_L((unsigned char *)x + size + i,
263 &tempme, sizeof(unsigned int));
266 else
267 x = NULL;
269 #else
270 x = vpx_memalign(align, size);
271 #endif //TRY_BOUNDS_CHECK
273 g_alloc_count++;
275 vpx_memory_tracker_add((size_t)x, (unsigned int)size, file, line, 1);
277 return x;
280 void *xvpx_malloc(size_t size, char *file, int line)
282 return xvpx_memalign(DEFAULT_ALIGNMENT, size, file, line);
285 void *xvpx_calloc(size_t num, size_t size, char *file, int line)
287 void *x = xvpx_memalign(DEFAULT_ALIGNMENT, num * size, file, line);
289 if (x)
290 VPX_MEMSET_L(x, 0, num * size);
292 return x;
295 void *xvpx_realloc(void *memblk, size_t size, char *file, int line)
297 struct mem_block *p = NULL;
298 int orig_size = 0,
299 orig_line = 0;
300 char *orig_file = NULL;
302 #if TRY_BOUNDS_CHECK
303 unsigned char *x_bounds = memblk ?
304 (unsigned char *)(((size_t *)memblk)[-1]) :
305 NULL;
306 #endif
308 void *x;
310 if (g_alloc_count == 0)
312 #if TRY_BOUNDS_CHECK
314 if (!vpx_memory_tracker_init(BOUNDS_CHECK_PAD_SIZE, BOUNDS_CHECK_VALUE))
315 #else
316 if (!vpx_memory_tracker_init(0, 0))
317 #endif
319 _P(printf("ERROR xvpx_malloc MEM_TRACK_USAGE error vpx_memory_tracker_init().\n");)
323 if ((p = vpx_memory_tracker_find((size_t)memblk)))
325 orig_size = p->size;
326 orig_file = p->file;
327 orig_line = p->line;
330 #if TRY_BOUNDS_CHECK_ON_FREE
331 vpx_memory_tracker_check_integrity(file, line);
332 #endif
334 //have to do this regardless of success, because
335 //the memory that does get realloc'd may change
336 //the bounds values of this block
337 vpx_memory_tracker_remove((size_t)memblk);
339 #if TRY_BOUNDS_CHECK
341 int i;
342 unsigned int tempme = BOUNDS_CHECK_VALUE;
344 x_bounds = vpx_realloc(memblk, size + (BOUNDS_CHECK_PAD_SIZE * 2));
346 if (x_bounds)
348 x_bounds = (unsigned char *)(((size_t *)x_bounds)[-1]);
349 x = align_addr(x_bounds + BOUNDS_CHECK_PAD_SIZE + ADDRESS_STORAGE_SIZE,
350 (int)DEFAULT_ALIGNMENT);
351 /* save the actual malloc address */
352 ((size_t *)x)[-1] = (size_t)x_bounds;
354 for (i = 0; i < BOUNDS_CHECK_PAD_SIZE; i += sizeof(unsigned int))
356 VPX_MEMCPY_L(x_bounds + i, &tempme, sizeof(unsigned int));
357 VPX_MEMCPY_L((unsigned char *)x + size + i,
358 &tempme, sizeof(unsigned int));
361 else
362 x = NULL;
364 #else
365 x = vpx_realloc(memblk, size);
366 #endif //TRY_BOUNDS_CHECK
368 if (!memblk) ++g_alloc_count;
370 if (x)
371 vpx_memory_tracker_add((size_t)x, (unsigned int)size, file, line, 1);
372 else
373 vpx_memory_tracker_add((size_t)memblk, orig_size, orig_file, orig_line, 1);
375 return x;
378 void xvpx_free(void *p_address, char *file, int line)
380 #if TRY_BOUNDS_CHECK
381 unsigned char *p_bounds_address = (unsigned char *)p_address;
382 //p_bounds_address -= BOUNDS_CHECK_PAD_SIZE;
383 #endif
385 #if !TRY_BOUNDS_CHECK_ON_FREE
386 (void)file;
387 (void)line;
388 #endif
390 if (p_address)
392 #if TRY_BOUNDS_CHECK_ON_FREE
393 vpx_memory_tracker_check_integrity(file, line);
394 #endif
396 //if the addr isn't found in the list, assume it was allocated via
397 //vpx_ calls not xvpx_, therefore it does not contain any padding
398 if (vpx_memory_tracker_remove((size_t)p_address) == -2)
400 p_bounds_address = p_address;
401 _P(fprintf(stderr, "[vpx_mem][xvpx_free] addr: %p not found in"
402 " list; freed from file:%s"
403 " line:%d\n", p_address, file, line));
405 else
406 --g_alloc_count;
408 #if TRY_BOUNDS_CHECK
409 vpx_free(p_bounds_address);
410 #else
411 vpx_free(p_address);
412 #endif
414 if (!g_alloc_count)
415 vpx_memory_tracker_destroy();
419 #endif /*CONFIG_MEM_TRACKER*/
421 #if CONFIG_MEM_CHECKS
422 #if defined(VXWORKS)
423 #include <task_lib.h> //for task_delay()
424 /* This function is only used to get a stack trace of the player
425 object so we can se where we are having a problem. */
426 static int get_my_tt(int task)
428 tt(task);
430 return 0;
433 static void vx_sleep(int msec)
435 int ticks_to_sleep = 0;
437 if (msec)
439 int msec_per_tick = 1000 / sys_clk_rate_get();
441 if (msec < msec_per_tick)
442 ticks_to_sleep++;
443 else
444 ticks_to_sleep = msec / msec_per_tick;
447 task_delay(ticks_to_sleep);
449 #endif
450 #endif
452 void *vpx_memcpy(void *dest, const void *source, size_t length)
454 #if CONFIG_MEM_CHECKS
456 if (((int)dest < 0x4000) || ((int)source < 0x4000))
458 _P(printf("WARNING: vpx_memcpy dest:0x%x source:0x%x len:%d\n", (int)dest, (int)source, length);)
460 #if defined(VXWORKS)
461 sp(get_my_tt, task_id_self(), 0, 0, 0, 0, 0, 0, 0, 0);
463 vx_sleep(10000);
464 #endif
467 #endif
469 return VPX_MEMCPY_L(dest, source, length);
472 void *vpx_memset(void *dest, int val, size_t length)
474 #if CONFIG_MEM_CHECKS
476 if ((int)dest < 0x4000)
478 _P(printf("WARNING: vpx_memset dest:0x%x val:%d len:%d\n", (int)dest, val, length);)
480 #if defined(VXWORKS)
481 sp(get_my_tt, task_id_self(), 0, 0, 0, 0, 0, 0, 0, 0);
483 vx_sleep(10000);
484 #endif
487 #endif
489 return VPX_MEMSET_L(dest, val, length);
492 void *vpx_memmove(void *dest, const void *src, size_t count)
494 #if CONFIG_MEM_CHECKS
496 if (((int)dest < 0x4000) || ((int)src < 0x4000))
498 _P(printf("WARNING: vpx_memmove dest:0x%x src:0x%x count:%d\n", (int)dest, (int)src, count);)
500 #if defined(VXWORKS)
501 sp(get_my_tt, task_id_self(), 0, 0, 0, 0, 0, 0, 0, 0);
503 vx_sleep(10000);
504 #endif
507 #endif
509 return VPX_MEMMOVE_L(dest, src, count);
512 #if CONFIG_MEM_MANAGER
514 static int vpx_mm_create_heap_memory()
516 int i_rv = 0;
518 if (!g_mng_memory_allocated)
520 #if MM_DYNAMIC_MEMORY
521 g_p_mng_memory_raw =
522 (unsigned char *)malloc(g_mm_memory_size + HMM_ADDR_ALIGN_UNIT);
524 if (g_p_mng_memory_raw)
526 g_p_mng_memory = (unsigned char *)((((unsigned int)g_p_mng_memory_raw) +
527 HMM_ADDR_ALIGN_UNIT - 1) &
528 -(int)HMM_ADDR_ALIGN_UNIT);
530 _P(printf("[vpx][mm] total memory size:%d g_p_mng_memory_raw:0x%x g_p_mng_memory:0x%x\n"
531 , g_mm_memory_size + HMM_ADDR_ALIGN_UNIT
532 , (unsigned int)g_p_mng_memory_raw
533 , (unsigned int)g_p_mng_memory);)
535 else
537 _P(printf("[vpx][mm] Couldn't allocate memory:%d for vpx memory manager.\n"
538 , g_mm_memory_size);)
540 i_rv = -1;
543 if (g_p_mng_memory)
544 #endif
546 int chunk_size = 0;
548 g_mng_memory_allocated = 1;
550 hmm_init(&hmm_d);
552 chunk_size = g_mm_memory_size >> SHIFT_HMM_ADDR_ALIGN_UNIT;
554 chunk_size -= DUMMY_END_BLOCK_BAUS;
556 _P(printf("[vpx][mm] memory size:%d for vpx memory manager. g_p_mng_memory:0x%x chunk_size:%d\n"
557 , g_mm_memory_size
558 , (unsigned int)g_p_mng_memory
559 , chunk_size);)
561 hmm_new_chunk(&hmm_d, (void *)g_p_mng_memory, chunk_size);
564 #if MM_DYNAMIC_MEMORY
565 else
567 _P(printf("[vpx][mm] Couldn't allocate memory:%d for vpx memory manager.\n"
568 , g_mm_memory_size);)
570 i_rv = -1;
573 #endif
576 return i_rv;
579 static void *vpx_mm_realloc(void *memblk, size_t size)
581 void *p_ret = NULL;
583 if (vpx_mm_create_heap_memory() < 0)
585 _P(printf("[vpx][mm] ERROR vpx_mm_realloc() Couldn't create memory for Heap.\n");)
587 else
589 int i_rv = 0;
590 int old_num_aaus;
591 int new_num_aaus;
593 old_num_aaus = hmm_true_size(memblk);
594 new_num_aaus = (size >> SHIFT_HMM_ADDR_ALIGN_UNIT) + 1;
596 if (old_num_aaus == new_num_aaus)
598 p_ret = memblk;
600 else
602 i_rv = hmm_resize(&hmm_d, memblk, new_num_aaus);
604 if (i_rv == 0)
606 p_ret = memblk;
608 else
610 /* Error. Try to malloc and then copy data. */
611 void *p_from_malloc;
613 new_num_aaus = (size >> SHIFT_HMM_ADDR_ALIGN_UNIT) + 1;
614 p_from_malloc = hmm_alloc(&hmm_d, new_num_aaus);
616 if (p_from_malloc)
618 vpx_memcpy(p_from_malloc, memblk, size);
619 hmm_free(&hmm_d, memblk);
621 p_ret = p_from_malloc;
627 return p_ret;
629 #endif //CONFIG_MEM_MANAGER
631 #if USE_GLOBAL_FUNCTION_POINTERS
632 # if CONFIG_MEM_TRACKER
633 extern int vpx_memory_tracker_set_functions(g_malloc_func g_malloc_l
634 , g_calloc_func g_calloc_l
635 , g_realloc_func g_realloc_l
636 , g_free_func g_free_l
637 , g_memcpy_func g_memcpy_l
638 , g_memset_func g_memset_l
639 , g_memmove_func g_memmove_l);
640 # endif
641 #endif //USE_GLOBAL_FUNCTION_POINTERS
642 int vpx_mem_set_functions(g_malloc_func g_malloc_l
643 , g_calloc_func g_calloc_l
644 , g_realloc_func g_realloc_l
645 , g_free_func g_free_l
646 , g_memcpy_func g_memcpy_l
647 , g_memset_func g_memset_l
648 , g_memmove_func g_memmove_l)
650 #if USE_GLOBAL_FUNCTION_POINTERS
652 /* If use global functions is turned on then the
653 application must set the global functions before
654 it does anything else or vpx_mem will have
655 unpredictable results. */
656 if (!g_func)
658 g_func = (struct GLOBAL_FUNC_POINTERS *)
659 g_malloc_l(sizeof(struct GLOBAL_FUNC_POINTERS));
661 if (!g_func)
663 return -1;
667 #if CONFIG_MEM_TRACKER
669 int rv = 0;
670 rv = vpx_memory_tracker_set_functions(g_malloc_l
671 , g_calloc_l
672 , g_realloc_l
673 , g_free_l
674 , g_memcpy_l
675 , g_memset_l
676 , g_memmove_l);
678 if (rv < 0)
680 return rv;
683 #endif
685 g_func->g_malloc = g_malloc_l;
686 g_func->g_calloc = g_calloc_l;
687 g_func->g_realloc = g_realloc_l;
688 g_func->g_free = g_free_l;
689 g_func->g_memcpy = g_memcpy_l;
690 g_func->g_memset = g_memset_l;
691 g_func->g_memmove = g_memmove_l;
693 return 0;
694 #else
695 (void)g_malloc_l;
696 (void)g_calloc_l;
697 (void)g_realloc_l;
698 (void)g_free_l;
699 (void)g_memcpy_l;
700 (void)g_memset_l;
701 (void)g_memmove_l;
702 return -1;
703 #endif
706 int vpx_mem_unset_functions()
708 #if USE_GLOBAL_FUNCTION_POINTERS
710 if (g_func)
712 g_free_func temp_free = g_func->g_free;
713 temp_free(g_func);
714 g_func = NULL;
717 #endif
718 return 0;