Merge "Update armv7 loopfilter to new interface"
[libvpx.git] / vpx_mem / vpx_mem.c
blobeade43222ab52184b26aa3027e884e6cff43d001
1 /*
2 * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
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 */
12 #define __VPX_MEM_C__
14 #include "vpx_mem.h"
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include "include/vpx_mem_intrnl.h"
20 #if CONFIG_MEM_TRACKER
21 #ifndef VPX_NO_GLOBALS
22 static unsigned long g_alloc_count = 0;
23 #else
24 #include "vpx_global_handling.h"
25 #define g_alloc_count vpxglobalm(vpxmem,g_alloc_count)
26 #endif
27 #endif
29 #if CONFIG_MEM_MANAGER
30 # include "heapmm.h"
31 # include "hmm_intrnl.h"
33 # define SHIFT_HMM_ADDR_ALIGN_UNIT 5
34 # define TOTAL_MEMORY_TO_ALLOCATE 20971520 /* 20 * 1024 * 1024 */
36 # define MM_DYNAMIC_MEMORY 1
37 # if MM_DYNAMIC_MEMORY
38 static unsigned char *g_p_mng_memory_raw = NULL;
39 static unsigned char *g_p_mng_memory = NULL;
40 # else
41 static unsigned char g_p_mng_memory[TOTAL_MEMORY_TO_ALLOCATE];
42 # endif
44 static size_t g_mm_memory_size = TOTAL_MEMORY_TO_ALLOCATE;
46 static hmm_descriptor hmm_d;
47 static int g_mng_memory_allocated = 0;
49 static int vpx_mm_create_heap_memory();
50 static void *vpx_mm_realloc(void *memblk, size_t size);
51 #endif /*CONFIG_MEM_MANAGER*/
53 #if USE_GLOBAL_FUNCTION_POINTERS
54 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;
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 */
80 unsigned int vpx_mem_get_version()
82 unsigned int ver = ((unsigned int)(unsigned char)VPX_MEM_VERSION_CHIEF << 24 |
83 (unsigned int)(unsigned char)VPX_MEM_VERSION_MAJOR << 16 |
84 (unsigned int)(unsigned char)VPX_MEM_VERSION_MINOR << 8 |
85 (unsigned int)(unsigned char)VPX_MEM_VERSION_PATCH);
86 return ver;
89 int vpx_mem_set_heap_size(size_t size)
91 int ret = -1;
93 #if CONFIG_MEM_MANAGER
94 #if MM_DYNAMIC_MEMORY
96 if (!g_mng_memory_allocated && size)
98 g_mm_memory_size = size;
99 ret = 0;
101 else
102 ret = -3;
104 #else
105 ret = -2;
106 #endif
107 #else
108 (void)size;
109 #endif
111 return ret;
114 void *vpx_memalign(size_t align, size_t size)
116 void *addr,
117 * x = NULL;
119 #if CONFIG_MEM_MANAGER
120 int number_aau;
122 if (vpx_mm_create_heap_memory() < 0)
124 _P(printf("[vpx][mm] ERROR vpx_memalign() Couldn't create memory for Heap.\n");)
127 number_aau = ((size + align - 1 + ADDRESS_STORAGE_SIZE) >>
128 SHIFT_HMM_ADDR_ALIGN_UNIT) + 1;
130 addr = hmm_alloc(&hmm_d, number_aau);
131 #else
132 addr = VPX_MALLOC_L(size + align - 1 + ADDRESS_STORAGE_SIZE);
133 #endif /*CONFIG_MEM_MANAGER*/
135 if (addr)
137 x = align_addr((unsigned char *)addr + ADDRESS_STORAGE_SIZE, (int)align);
138 /* save the actual malloc address */
139 ((size_t *)x)[-1] = (size_t)addr;
142 return x;
145 void *vpx_malloc(size_t size)
147 return vpx_memalign(DEFAULT_ALIGNMENT, size);
150 void *vpx_calloc(size_t num, size_t size)
152 void *x;
154 x = vpx_memalign(DEFAULT_ALIGNMENT, num * size);
156 if (x)
157 VPX_MEMSET_L(x, 0, num * size);
159 return x;
162 void *vpx_realloc(void *memblk, size_t size)
164 void *addr,
165 * new_addr = NULL;
166 int align = DEFAULT_ALIGNMENT;
169 The realloc() function changes the size of the object pointed to by
170 ptr to the size specified by size, and returns a pointer to the
171 possibly moved block. The contents are unchanged up to the lesser
172 of the new and old sizes. If ptr is null, realloc() behaves like
173 malloc() for the specified size. If size is zero (0) and ptr is
174 not a null pointer, the object pointed to is freed.
176 if (!memblk)
177 new_addr = vpx_malloc(size);
178 else if (!size)
179 vpx_free(memblk);
180 else
182 addr = (void *)(((size_t *)memblk)[-1]);
183 memblk = NULL;
185 #if CONFIG_MEM_MANAGER
186 new_addr = vpx_mm_realloc(addr, size + align + ADDRESS_STORAGE_SIZE);
187 #else
188 new_addr = VPX_REALLOC_L(addr, size + align + ADDRESS_STORAGE_SIZE);
189 #endif
191 if (new_addr)
193 addr = new_addr;
194 new_addr = (void *)(((size_t)
195 ((unsigned char *)new_addr + ADDRESS_STORAGE_SIZE) + (align - 1)) &
196 (size_t) - align);
197 /* save the actual malloc address */
198 ((size_t *)new_addr)[-1] = (size_t)addr;
202 return new_addr;
205 void vpx_free(void *memblk)
207 if (memblk)
209 void *addr = (void *)(((size_t *)memblk)[-1]);
210 #if CONFIG_MEM_MANAGER
211 hmm_free(&hmm_d, addr);
212 #else
213 VPX_FREE_L(addr);
214 #endif
218 #if CONFIG_MEM_TRACKER
219 void *xvpx_memalign(size_t align, size_t size, char *file, int line)
221 #if TRY_BOUNDS_CHECK
222 unsigned char *x_bounds;
223 #endif
225 void *x;
227 if (g_alloc_count == 0)
229 #if TRY_BOUNDS_CHECK
230 int i_rv = vpx_memory_tracker_init(BOUNDS_CHECK_PAD_SIZE, BOUNDS_CHECK_VALUE);
231 #else
232 int i_rv = vpx_memory_tracker_init(0, 0);
233 #endif
235 if (i_rv < 0)
237 _P(printf("ERROR xvpx_malloc MEM_TRACK_USAGE error vpx_memory_tracker_init().\n");)
241 #if TRY_BOUNDS_CHECK
243 int i;
244 unsigned int tempme = BOUNDS_CHECK_VALUE;
246 x_bounds = vpx_memalign(align, size + (BOUNDS_CHECK_PAD_SIZE * 2));
248 if (x_bounds)
250 /*we're aligning the address twice here but to keep things
251 consistent we want to have the padding come before the stored
252 address so no matter what free function gets called we will
253 attempt to free the correct address*/
254 x_bounds = (unsigned char *)(((size_t *)x_bounds)[-1]);
255 x = align_addr(x_bounds + BOUNDS_CHECK_PAD_SIZE + ADDRESS_STORAGE_SIZE,
256 (int)align);
257 /* save the actual malloc address */
258 ((size_t *)x)[-1] = (size_t)x_bounds;
260 for (i = 0; i < BOUNDS_CHECK_PAD_SIZE; i += sizeof(unsigned int))
262 VPX_MEMCPY_L(x_bounds + i, &tempme, sizeof(unsigned int));
263 VPX_MEMCPY_L((unsigned char *)x + size + i,
264 &tempme, sizeof(unsigned int));
267 else
268 x = NULL;
270 #else
271 x = vpx_memalign(align, size);
272 #endif /*TRY_BOUNDS_CHECK*/
274 g_alloc_count++;
276 vpx_memory_tracker_add((size_t)x, (unsigned int)size, file, line, 1);
278 return x;
281 void *xvpx_malloc(size_t size, char *file, int line)
283 return xvpx_memalign(DEFAULT_ALIGNMENT, size, file, line);
286 void *xvpx_calloc(size_t num, size_t size, char *file, int line)
288 void *x = xvpx_memalign(DEFAULT_ALIGNMENT, num * size, file, line);
290 if (x)
291 VPX_MEMSET_L(x, 0, num * size);
293 return x;
296 void *xvpx_realloc(void *memblk, size_t size, char *file, int line)
298 struct mem_block *p = NULL;
299 int orig_size = 0,
300 orig_line = 0;
301 char *orig_file = NULL;
303 #if TRY_BOUNDS_CHECK
304 unsigned char *x_bounds = memblk ?
305 (unsigned char *)(((size_t *)memblk)[-1]) :
306 NULL;
307 #endif
309 void *x;
311 if (g_alloc_count == 0)
313 #if TRY_BOUNDS_CHECK
315 if (!vpx_memory_tracker_init(BOUNDS_CHECK_PAD_SIZE, BOUNDS_CHECK_VALUE))
316 #else
317 if (!vpx_memory_tracker_init(0, 0))
318 #endif
320 _P(printf("ERROR xvpx_malloc MEM_TRACK_USAGE error vpx_memory_tracker_init().\n");)
324 if ((p = vpx_memory_tracker_find((size_t)memblk)))
326 orig_size = p->size;
327 orig_file = p->file;
328 orig_line = p->line;
331 #if TRY_BOUNDS_CHECK_ON_FREE
332 vpx_memory_tracker_check_integrity(file, line);
333 #endif
335 /* have to do this regardless of success, because
336 * the memory that does get realloc'd may change
337 * the bounds values of this block
339 vpx_memory_tracker_remove((size_t)memblk);
341 #if TRY_BOUNDS_CHECK
343 int i;
344 unsigned int tempme = BOUNDS_CHECK_VALUE;
346 x_bounds = vpx_realloc(memblk, size + (BOUNDS_CHECK_PAD_SIZE * 2));
348 if (x_bounds)
350 x_bounds = (unsigned char *)(((size_t *)x_bounds)[-1]);
351 x = align_addr(x_bounds + BOUNDS_CHECK_PAD_SIZE + ADDRESS_STORAGE_SIZE,
352 (int)DEFAULT_ALIGNMENT);
353 /* save the actual malloc address */
354 ((size_t *)x)[-1] = (size_t)x_bounds;
356 for (i = 0; i < BOUNDS_CHECK_PAD_SIZE; i += sizeof(unsigned int))
358 VPX_MEMCPY_L(x_bounds + i, &tempme, sizeof(unsigned int));
359 VPX_MEMCPY_L((unsigned char *)x + size + i,
360 &tempme, sizeof(unsigned int));
363 else
364 x = NULL;
366 #else
367 x = vpx_realloc(memblk, size);
368 #endif /*TRY_BOUNDS_CHECK*/
370 if (!memblk) ++g_alloc_count;
372 if (x)
373 vpx_memory_tracker_add((size_t)x, (unsigned int)size, file, line, 1);
374 else
375 vpx_memory_tracker_add((size_t)memblk, orig_size, orig_file, orig_line, 1);
377 return x;
380 void xvpx_free(void *p_address, char *file, int line)
382 #if TRY_BOUNDS_CHECK
383 unsigned char *p_bounds_address = (unsigned char *)p_address;
384 /*p_bounds_address -= BOUNDS_CHECK_PAD_SIZE;*/
385 #endif
387 #if !TRY_BOUNDS_CHECK_ON_FREE
388 (void)file;
389 (void)line;
390 #endif
392 if (p_address)
394 #if TRY_BOUNDS_CHECK_ON_FREE
395 vpx_memory_tracker_check_integrity(file, line);
396 #endif
398 /* if the addr isn't found in the list, assume it was allocated via
399 * vpx_ calls not xvpx_, therefore it does not contain any padding
401 if (vpx_memory_tracker_remove((size_t)p_address) == -2)
403 p_bounds_address = p_address;
404 _P(fprintf(stderr, "[vpx_mem][xvpx_free] addr: %p not found in"
405 " list; freed from file:%s"
406 " line:%d\n", p_address, file, line));
408 else
409 --g_alloc_count;
411 #if TRY_BOUNDS_CHECK
412 vpx_free(p_bounds_address);
413 #else
414 vpx_free(p_address);
415 #endif
417 if (!g_alloc_count)
418 vpx_memory_tracker_destroy();
422 #endif /*CONFIG_MEM_TRACKER*/
424 #if CONFIG_MEM_CHECKS
425 #if defined(VXWORKS)
426 #include <task_lib.h> /*for task_delay()*/
427 /* This function is only used to get a stack trace of the player
428 object so we can se where we are having a problem. */
429 static int get_my_tt(int task)
431 tt(task);
433 return 0;
436 static void vx_sleep(int msec)
438 int ticks_to_sleep = 0;
440 if (msec)
442 int msec_per_tick = 1000 / sys_clk_rate_get();
444 if (msec < msec_per_tick)
445 ticks_to_sleep++;
446 else
447 ticks_to_sleep = msec / msec_per_tick;
450 task_delay(ticks_to_sleep);
452 #endif
453 #endif
455 void *vpx_memcpy(void *dest, const void *source, size_t length)
457 #if CONFIG_MEM_CHECKS
459 if (((int)dest < 0x4000) || ((int)source < 0x4000))
461 _P(printf("WARNING: vpx_memcpy dest:0x%x source:0x%x len:%d\n", (int)dest, (int)source, length);)
463 #if defined(VXWORKS)
464 sp(get_my_tt, task_id_self(), 0, 0, 0, 0, 0, 0, 0, 0);
466 vx_sleep(10000);
467 #endif
470 #endif
472 return VPX_MEMCPY_L(dest, source, length);
475 void *vpx_memset(void *dest, int val, size_t length)
477 #if CONFIG_MEM_CHECKS
479 if ((int)dest < 0x4000)
481 _P(printf("WARNING: vpx_memset dest:0x%x val:%d len:%d\n", (int)dest, val, length);)
483 #if defined(VXWORKS)
484 sp(get_my_tt, task_id_self(), 0, 0, 0, 0, 0, 0, 0, 0);
486 vx_sleep(10000);
487 #endif
490 #endif
492 return VPX_MEMSET_L(dest, val, length);
495 void *vpx_memmove(void *dest, const void *src, size_t count)
497 #if CONFIG_MEM_CHECKS
499 if (((int)dest < 0x4000) || ((int)src < 0x4000))
501 _P(printf("WARNING: vpx_memmove dest:0x%x src:0x%x count:%d\n", (int)dest, (int)src, count);)
503 #if defined(VXWORKS)
504 sp(get_my_tt, task_id_self(), 0, 0, 0, 0, 0, 0, 0, 0);
506 vx_sleep(10000);
507 #endif
510 #endif
512 return VPX_MEMMOVE_L(dest, src, count);
515 #if CONFIG_MEM_MANAGER
517 static int vpx_mm_create_heap_memory()
519 int i_rv = 0;
521 if (!g_mng_memory_allocated)
523 #if MM_DYNAMIC_MEMORY
524 g_p_mng_memory_raw =
525 (unsigned char *)malloc(g_mm_memory_size + HMM_ADDR_ALIGN_UNIT);
527 if (g_p_mng_memory_raw)
529 g_p_mng_memory = (unsigned char *)((((unsigned int)g_p_mng_memory_raw) +
530 HMM_ADDR_ALIGN_UNIT - 1) &
531 -(int)HMM_ADDR_ALIGN_UNIT);
533 _P(printf("[vpx][mm] total memory size:%d g_p_mng_memory_raw:0x%x g_p_mng_memory:0x%x\n"
534 , g_mm_memory_size + HMM_ADDR_ALIGN_UNIT
535 , (unsigned int)g_p_mng_memory_raw
536 , (unsigned int)g_p_mng_memory);)
538 else
540 _P(printf("[vpx][mm] Couldn't allocate memory:%d for vpx memory manager.\n"
541 , g_mm_memory_size);)
543 i_rv = -1;
546 if (g_p_mng_memory)
547 #endif
549 int chunk_size = 0;
551 g_mng_memory_allocated = 1;
553 hmm_init(&hmm_d);
555 chunk_size = g_mm_memory_size >> SHIFT_HMM_ADDR_ALIGN_UNIT;
557 chunk_size -= DUMMY_END_BLOCK_BAUS;
559 _P(printf("[vpx][mm] memory size:%d for vpx memory manager. g_p_mng_memory:0x%x chunk_size:%d\n"
560 , g_mm_memory_size
561 , (unsigned int)g_p_mng_memory
562 , chunk_size);)
564 hmm_new_chunk(&hmm_d, (void *)g_p_mng_memory, chunk_size);
567 #if MM_DYNAMIC_MEMORY
568 else
570 _P(printf("[vpx][mm] Couldn't allocate memory:%d for vpx memory manager.\n"
571 , g_mm_memory_size);)
573 i_rv = -1;
576 #endif
579 return i_rv;
582 static void *vpx_mm_realloc(void *memblk, size_t size)
584 void *p_ret = NULL;
586 if (vpx_mm_create_heap_memory() < 0)
588 _P(printf("[vpx][mm] ERROR vpx_mm_realloc() Couldn't create memory for Heap.\n");)
590 else
592 int i_rv = 0;
593 int old_num_aaus;
594 int new_num_aaus;
596 old_num_aaus = hmm_true_size(memblk);
597 new_num_aaus = (size >> SHIFT_HMM_ADDR_ALIGN_UNIT) + 1;
599 if (old_num_aaus == new_num_aaus)
601 p_ret = memblk;
603 else
605 i_rv = hmm_resize(&hmm_d, memblk, new_num_aaus);
607 if (i_rv == 0)
609 p_ret = memblk;
611 else
613 /* Error. Try to malloc and then copy data. */
614 void *p_from_malloc;
616 new_num_aaus = (size >> SHIFT_HMM_ADDR_ALIGN_UNIT) + 1;
617 p_from_malloc = hmm_alloc(&hmm_d, new_num_aaus);
619 if (p_from_malloc)
621 vpx_memcpy(p_from_malloc, memblk, size);
622 hmm_free(&hmm_d, memblk);
624 p_ret = p_from_malloc;
630 return p_ret;
632 #endif /*CONFIG_MEM_MANAGER*/
634 #if USE_GLOBAL_FUNCTION_POINTERS
635 # if CONFIG_MEM_TRACKER
636 extern int vpx_memory_tracker_set_functions(g_malloc_func g_malloc_l
637 , g_calloc_func g_calloc_l
638 , g_realloc_func g_realloc_l
639 , g_free_func g_free_l
640 , g_memcpy_func g_memcpy_l
641 , g_memset_func g_memset_l
642 , g_memmove_func g_memmove_l);
643 # endif
644 #endif /*USE_GLOBAL_FUNCTION_POINTERS*/
645 int vpx_mem_set_functions(g_malloc_func g_malloc_l
646 , g_calloc_func g_calloc_l
647 , g_realloc_func g_realloc_l
648 , g_free_func g_free_l
649 , g_memcpy_func g_memcpy_l
650 , g_memset_func g_memset_l
651 , g_memmove_func g_memmove_l)
653 #if USE_GLOBAL_FUNCTION_POINTERS
655 /* If use global functions is turned on then the
656 application must set the global functions before
657 it does anything else or vpx_mem will have
658 unpredictable results. */
659 if (!g_func)
661 g_func = (struct GLOBAL_FUNC_POINTERS *)
662 g_malloc_l(sizeof(struct GLOBAL_FUNC_POINTERS));
664 if (!g_func)
666 return -1;
670 #if CONFIG_MEM_TRACKER
672 int rv = 0;
673 rv = vpx_memory_tracker_set_functions(g_malloc_l
674 , g_calloc_l
675 , g_realloc_l
676 , g_free_l
677 , g_memcpy_l
678 , g_memset_l
679 , g_memmove_l);
681 if (rv < 0)
683 return rv;
686 #endif
688 g_func->g_malloc = g_malloc_l;
689 g_func->g_calloc = g_calloc_l;
690 g_func->g_realloc = g_realloc_l;
691 g_func->g_free = g_free_l;
692 g_func->g_memcpy = g_memcpy_l;
693 g_func->g_memset = g_memset_l;
694 g_func->g_memmove = g_memmove_l;
696 return 0;
697 #else
698 (void)g_malloc_l;
699 (void)g_calloc_l;
700 (void)g_realloc_l;
701 (void)g_free_l;
702 (void)g_memcpy_l;
703 (void)g_memset_l;
704 (void)g_memmove_l;
705 return -1;
706 #endif
709 int vpx_mem_unset_functions()
711 #if USE_GLOBAL_FUNCTION_POINTERS
713 if (g_func)
715 g_free_func temp_free = g_func->g_free;
716 temp_free(g_func);
717 g_func = NULL;
720 #endif
721 return 0;