summaryrefslogtreecommitdiff
path: root/vpx_mem/vpx_mem.c
diff options
context:
space:
mode:
Diffstat (limited to 'vpx_mem/vpx_mem.c')
-rw-r--r--vpx_mem/vpx_mem.c719
1 files changed, 719 insertions, 0 deletions
diff --git a/vpx_mem/vpx_mem.c b/vpx_mem/vpx_mem.c
new file mode 100644
index 000000000..f6b1a3550
--- /dev/null
+++ b/vpx_mem/vpx_mem.c
@@ -0,0 +1,719 @@
+/*
+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license and patent
+ * grant that can be found in the LICENSE file in the root of the source
+ * tree. All contributing project authors may be found in the AUTHORS
+ * file in the root of the source tree.
+ */
+
+
+#define __VPX_MEM_C__
+
+#include "vpx_mem.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "include/vpx_mem_intrnl.h"
+
+#if CONFIG_MEM_TRACKER
+#ifndef VPX_NO_GLOBALS
+static unsigned long g_alloc_count = 0;
+#else
+#include "vpx_global_handling.h"
+#define g_alloc_count vpxglobalm(vpxmem,g_alloc_count)
+#endif
+#endif
+
+#if CONFIG_MEM_MANAGER
+# include "heapmm.h"
+# include "hmm_intrnl.h"
+
+# define SHIFT_HMM_ADDR_ALIGN_UNIT 5
+# define TOTAL_MEMORY_TO_ALLOCATE 20971520 // 20 * 1024 * 1024
+
+# define MM_DYNAMIC_MEMORY 1
+# if MM_DYNAMIC_MEMORY
+static unsigned char *g_p_mng_memory_raw = NULL;
+static unsigned char *g_p_mng_memory = NULL;
+# else
+static unsigned char g_p_mng_memory[TOTAL_MEMORY_TO_ALLOCATE];
+# endif
+
+static size_t g_mm_memory_size = TOTAL_MEMORY_TO_ALLOCATE;
+
+static hmm_descriptor hmm_d;
+static int g_mng_memory_allocated = 0;
+
+static int vpx_mm_create_heap_memory();
+static void *vpx_mm_realloc(void *memblk, size_t size);
+#endif //CONFIG_MEM_MANAGER
+
+#if USE_GLOBAL_FUNCTION_POINTERS
+struct GLOBAL_FUNC_POINTERS
+{
+ g_malloc_func g_malloc;
+ g_calloc_func g_calloc;
+ g_realloc_func g_realloc;
+ g_free_func g_free;
+ g_memcpy_func g_memcpy;
+ g_memset_func g_memset;
+ g_memmove_func g_memmove;
+} *g_func = NULL;
+
+# define VPX_MALLOC_L g_func->g_malloc
+# define VPX_REALLOC_L g_func->g_realloc
+# define VPX_FREE_L g_func->g_free
+# define VPX_MEMCPY_L g_func->g_memcpy
+# define VPX_MEMSET_L g_func->g_memset
+# define VPX_MEMMOVE_L g_func->g_memmove
+#else
+# define VPX_MALLOC_L malloc
+# define VPX_REALLOC_L realloc
+# define VPX_FREE_L free
+# define VPX_MEMCPY_L memcpy
+# define VPX_MEMSET_L memset
+# define VPX_MEMMOVE_L memmove
+#endif // USE_GLOBAL_FUNCTION_POINTERS
+
+unsigned int vpx_mem_get_version()
+{
+ unsigned int ver = ((unsigned int)(unsigned char)VPX_MEM_VERSION_CHIEF << 24 |
+ (unsigned int)(unsigned char)VPX_MEM_VERSION_MAJOR << 16 |
+ (unsigned int)(unsigned char)VPX_MEM_VERSION_MINOR << 8 |
+ (unsigned int)(unsigned char)VPX_MEM_VERSION_PATCH);
+ return ver;
+}
+
+int vpx_mem_set_heap_size(size_t size)
+{
+ int ret = -1;
+
+#if CONFIG_MEM_MANAGER
+#if MM_DYNAMIC_MEMORY
+
+ if (!g_mng_memory_allocated && size)
+ {
+ g_mm_memory_size = size;
+ ret = 0;
+ }
+ else
+ ret = -3;
+
+#else
+ ret = -2;
+#endif
+#else
+ (void)size;
+#endif
+
+ return ret;
+}
+
+void *vpx_memalign(size_t align, size_t size)
+{
+ void *addr,
+ * x = NULL;
+
+#if CONFIG_MEM_MANAGER
+ int number_aau;
+
+ if (vpx_mm_create_heap_memory() < 0)
+ {
+ _P(printf("[vpx][mm] ERROR vpx_memalign() Couldn't create memory for Heap.\n");)
+ }
+
+ number_aau = ((size + align - 1 + ADDRESS_STORAGE_SIZE) >>
+ SHIFT_HMM_ADDR_ALIGN_UNIT) + 1;
+
+ addr = hmm_alloc(&hmm_d, number_aau);
+#else
+ addr = VPX_MALLOC_L(size + align - 1 + ADDRESS_STORAGE_SIZE);
+#endif //CONFIG_MEM_MANAGER
+
+ if (addr)
+ {
+ x = align_addr((unsigned char *)addr + ADDRESS_STORAGE_SIZE, (int)align);
+ /* save the actual malloc address */
+ ((size_t *)x)[-1] = (size_t)addr;
+ }
+
+ return x;
+}
+
+void *vpx_malloc(size_t size)
+{
+ return vpx_memalign(DEFAULT_ALIGNMENT, size);
+}
+
+void *vpx_calloc(size_t num, size_t size)
+{
+ void *x;
+
+ x = vpx_memalign(DEFAULT_ALIGNMENT, num * size);
+
+ if (x)
+ VPX_MEMSET_L(x, 0, num * size);
+
+ return x;
+}
+
+void *vpx_realloc(void *memblk, size_t size)
+{
+ void *addr,
+ * new_addr = NULL;
+ int align = DEFAULT_ALIGNMENT;
+
+ /*
+ The realloc() function changes the size of the object pointed to by
+ ptr to the size specified by size, and returns a pointer to the
+ possibly moved block. The contents are unchanged up to the lesser
+ of the new and old sizes. If ptr is null, realloc() behaves like
+ malloc() for the specified size. If size is zero (0) and ptr is
+ not a null pointer, the object pointed to is freed.
+ */
+ if (!memblk)
+ new_addr = vpx_malloc(size);
+ else if (!size)
+ vpx_free(memblk);
+ else
+ {
+ addr = (void *)(((size_t *)memblk)[-1]);
+ memblk = NULL;
+
+#if CONFIG_MEM_MANAGER
+ new_addr = vpx_mm_realloc(addr, size + align + ADDRESS_STORAGE_SIZE);
+#else
+ new_addr = VPX_REALLOC_L(addr, size + align + ADDRESS_STORAGE_SIZE);
+#endif
+
+ if (new_addr)
+ {
+ addr = new_addr;
+ new_addr = (void *)(((size_t)
+ ((unsigned char *)new_addr + ADDRESS_STORAGE_SIZE) + (align - 1)) &
+ (size_t) - align);
+ /* save the actual malloc address */
+ ((size_t *)new_addr)[-1] = (size_t)addr;
+ }
+ }
+
+ return new_addr;
+}
+
+void vpx_free(void *memblk)
+{
+ if (memblk)
+ {
+ void *addr = (void *)(((size_t *)memblk)[-1]);
+#if CONFIG_MEM_MANAGER
+ hmm_free(&hmm_d, addr);
+#else
+ VPX_FREE_L(addr);
+#endif
+ }
+}
+
+#if CONFIG_MEM_TRACKER
+void *xvpx_memalign(size_t align, size_t size, char *file, int line)
+{
+#if TRY_BOUNDS_CHECK
+ unsigned char *x_bounds;
+#endif
+
+ void *x;
+
+ if (g_alloc_count == 0)
+ {
+#if TRY_BOUNDS_CHECK
+ int i_rv = vpx_memory_tracker_init(BOUNDS_CHECK_PAD_SIZE, BOUNDS_CHECK_VALUE);
+#else
+ int i_rv = vpx_memory_tracker_init(0, 0);
+#endif
+
+ if (i_rv < 0)
+ {
+ _P(printf("ERROR xvpx_malloc MEM_TRACK_USAGE error vpx_memory_tracker_init().\n");)
+ }
+ }
+
+#if TRY_BOUNDS_CHECK
+ {
+ int i;
+ unsigned int tempme = BOUNDS_CHECK_VALUE;
+
+ x_bounds = vpx_memalign(align, size + (BOUNDS_CHECK_PAD_SIZE * 2));
+
+ if (x_bounds)
+ {
+ /*we're aligning the address twice here but to keep things
+ consistent we want to have the padding come before the stored
+ address so no matter what free function gets called we will
+ attempt to free the correct address*/
+ x_bounds = (unsigned char *)(((size_t *)x_bounds)[-1]);
+ x = align_addr(x_bounds + BOUNDS_CHECK_PAD_SIZE + ADDRESS_STORAGE_SIZE,
+ (int)align);
+ /* save the actual malloc address */
+ ((size_t *)x)[-1] = (size_t)x_bounds;
+
+ for (i = 0; i < BOUNDS_CHECK_PAD_SIZE; i += sizeof(unsigned int))
+ {
+ VPX_MEMCPY_L(x_bounds + i, &tempme, sizeof(unsigned int));
+ VPX_MEMCPY_L((unsigned char *)x + size + i,
+ &tempme, sizeof(unsigned int));
+ }
+ }
+ else
+ x = NULL;
+ }
+#else
+ x = vpx_memalign(align, size);
+#endif //TRY_BOUNDS_CHECK
+
+ g_alloc_count++;
+
+ vpx_memory_tracker_add((size_t)x, (unsigned int)size, file, line, 1);
+
+ return x;
+}
+
+void *xvpx_malloc(size_t size, char *file, int line)
+{
+ return xvpx_memalign(DEFAULT_ALIGNMENT, size, file, line);
+}
+
+void *xvpx_calloc(size_t num, size_t size, char *file, int line)
+{
+ void *x = xvpx_memalign(DEFAULT_ALIGNMENT, num * size, file, line);
+
+ if (x)
+ VPX_MEMSET_L(x, 0, num * size);
+
+ return x;
+}
+
+void *xvpx_realloc(void *memblk, size_t size, char *file, int line)
+{
+ struct mem_block *p = NULL;
+ int orig_size = 0,
+ orig_line = 0;
+ char *orig_file = NULL;
+
+#if TRY_BOUNDS_CHECK
+ unsigned char *x_bounds = memblk ?
+ (unsigned char *)(((size_t *)memblk)[-1]) :
+ NULL;
+#endif
+
+ void *x;
+
+ if (g_alloc_count == 0)
+ {
+#if TRY_BOUNDS_CHECK
+
+ if (!vpx_memory_tracker_init(BOUNDS_CHECK_PAD_SIZE, BOUNDS_CHECK_VALUE))
+#else
+ if (!vpx_memory_tracker_init(0, 0))
+#endif
+ {
+ _P(printf("ERROR xvpx_malloc MEM_TRACK_USAGE error vpx_memory_tracker_init().\n");)
+ }
+ }
+
+ if ((p = vpx_memory_tracker_find((size_t)memblk)))
+ {
+ orig_size = p->size;
+ orig_file = p->file;
+ orig_line = p->line;
+ }
+
+#if TRY_BOUNDS_CHECK_ON_FREE
+ vpx_memory_tracker_check_integrity(file, line);
+#endif
+
+ //have to do this regardless of success, because
+ //the memory that does get realloc'd may change
+ //the bounds values of this block
+ vpx_memory_tracker_remove((size_t)memblk);
+
+#if TRY_BOUNDS_CHECK
+ {
+ int i;
+ unsigned int tempme = BOUNDS_CHECK_VALUE;
+
+ x_bounds = vpx_realloc(memblk, size + (BOUNDS_CHECK_PAD_SIZE * 2));
+
+ if (x_bounds)
+ {
+ x_bounds = (unsigned char *)(((size_t *)x_bounds)[-1]);
+ x = align_addr(x_bounds + BOUNDS_CHECK_PAD_SIZE + ADDRESS_STORAGE_SIZE,
+ (int)DEFAULT_ALIGNMENT);
+ /* save the actual malloc address */
+ ((size_t *)x)[-1] = (size_t)x_bounds;
+
+ for (i = 0; i < BOUNDS_CHECK_PAD_SIZE; i += sizeof(unsigned int))
+ {
+ VPX_MEMCPY_L(x_bounds + i, &tempme, sizeof(unsigned int));
+ VPX_MEMCPY_L((unsigned char *)x + size + i,
+ &tempme, sizeof(unsigned int));
+ }
+ }
+ else
+ x = NULL;
+ }
+#else
+ x = vpx_realloc(memblk, size);
+#endif //TRY_BOUNDS_CHECK
+
+ if (!memblk) ++g_alloc_count;
+
+ if (x)
+ vpx_memory_tracker_add((size_t)x, (unsigned int)size, file, line, 1);
+ else
+ vpx_memory_tracker_add((size_t)memblk, orig_size, orig_file, orig_line, 1);
+
+ return x;
+}
+
+void xvpx_free(void *p_address, char *file, int line)
+{
+#if TRY_BOUNDS_CHECK
+ unsigned char *p_bounds_address = (unsigned char *)p_address;
+ //p_bounds_address -= BOUNDS_CHECK_PAD_SIZE;
+#endif
+
+#if !TRY_BOUNDS_CHECK_ON_FREE
+ (void)file;
+ (void)line;
+#endif
+
+ if (p_address)
+ {
+#if TRY_BOUNDS_CHECK_ON_FREE
+ vpx_memory_tracker_check_integrity(file, line);
+#endif
+
+ //if the addr isn't found in the list, assume it was allocated via
+ //vpx_ calls not xvpx_, therefore it does not contain any padding
+ if (vpx_memory_tracker_remove((size_t)p_address) == -2)
+ {
+ p_bounds_address = p_address;
+ _P(fprintf(stderr, "[vpx_mem][xvpx_free] addr: %p not found in"
+ " list; freed from file:%s"
+ " line:%d\n", p_address, file, line));
+ }
+ else
+ --g_alloc_count;
+
+#if TRY_BOUNDS_CHECK
+ vpx_free(p_bounds_address);
+#else
+ vpx_free(p_address);
+#endif
+
+ if (!g_alloc_count)
+ vpx_memory_tracker_destroy();
+ }
+}
+
+#endif /*CONFIG_MEM_TRACKER*/
+
+#if CONFIG_MEM_CHECKS
+#if defined(VXWORKS)
+#include <task_lib.h> //for task_delay()
+/* This function is only used to get a stack trace of the player
+object so we can se where we are having a problem. */
+static int get_my_tt(int task)
+{
+ tt(task);
+
+ return 0;
+}
+
+static void vx_sleep(int msec)
+{
+ int ticks_to_sleep = 0;
+
+ if (msec)
+ {
+ int msec_per_tick = 1000 / sys_clk_rate_get();
+
+ if (msec < msec_per_tick)
+ ticks_to_sleep++;
+ else
+ ticks_to_sleep = msec / msec_per_tick;
+ }
+
+ task_delay(ticks_to_sleep);
+}
+#endif
+#endif
+
+void *vpx_memcpy(void *dest, const void *source, size_t length)
+{
+#if CONFIG_MEM_CHECKS
+
+ if (((int)dest < 0x4000) || ((int)source < 0x4000))
+ {
+ _P(printf("WARNING: vpx_memcpy dest:0x%x source:0x%x len:%d\n", (int)dest, (int)source, length);)
+
+#if defined(VXWORKS)
+ sp(get_my_tt, task_id_self(), 0, 0, 0, 0, 0, 0, 0, 0);
+
+ vx_sleep(10000);
+#endif
+ }
+
+#endif
+
+ return VPX_MEMCPY_L(dest, source, length);
+}
+
+void *vpx_memset(void *dest, int val, size_t length)
+{
+#if CONFIG_MEM_CHECKS
+
+ if ((int)dest < 0x4000)
+ {
+ _P(printf("WARNING: vpx_memset dest:0x%x val:%d len:%d\n", (int)dest, val, length);)
+
+#if defined(VXWORKS)
+ sp(get_my_tt, task_id_self(), 0, 0, 0, 0, 0, 0, 0, 0);
+
+ vx_sleep(10000);
+#endif
+ }
+
+#endif
+
+ return VPX_MEMSET_L(dest, val, length);
+}
+
+void *vpx_memmove(void *dest, const void *src, size_t count)
+{
+#if CONFIG_MEM_CHECKS
+
+ if (((int)dest < 0x4000) || ((int)src < 0x4000))
+ {
+ _P(printf("WARNING: vpx_memmove dest:0x%x src:0x%x count:%d\n", (int)dest, (int)src, count);)
+
+#if defined(VXWORKS)
+ sp(get_my_tt, task_id_self(), 0, 0, 0, 0, 0, 0, 0, 0);
+
+ vx_sleep(10000);
+#endif
+ }
+
+#endif
+
+ return VPX_MEMMOVE_L(dest, src, count);
+}
+
+#if CONFIG_MEM_MANAGER
+
+static int vpx_mm_create_heap_memory()
+{
+ int i_rv = 0;
+
+ if (!g_mng_memory_allocated)
+ {
+#if MM_DYNAMIC_MEMORY
+ g_p_mng_memory_raw =
+ (unsigned char *)malloc(g_mm_memory_size + HMM_ADDR_ALIGN_UNIT);
+
+ if (g_p_mng_memory_raw)
+ {
+ g_p_mng_memory = (unsigned char *)((((unsigned int)g_p_mng_memory_raw) +
+ HMM_ADDR_ALIGN_UNIT - 1) &
+ -(int)HMM_ADDR_ALIGN_UNIT);
+
+ _P(printf("[vpx][mm] total memory size:%d g_p_mng_memory_raw:0x%x g_p_mng_memory:0x%x\n"
+ , g_mm_memory_size + HMM_ADDR_ALIGN_UNIT
+ , (unsigned int)g_p_mng_memory_raw
+ , (unsigned int)g_p_mng_memory);)
+ }
+ else
+ {
+ _P(printf("[vpx][mm] Couldn't allocate memory:%d for vpx memory manager.\n"
+ , g_mm_memory_size);)
+
+ i_rv = -1;
+ }
+
+ if (g_p_mng_memory)
+#endif
+ {
+ int chunk_size = 0;
+
+ g_mng_memory_allocated = 1;
+
+ hmm_init(&hmm_d);
+
+ chunk_size = g_mm_memory_size >> SHIFT_HMM_ADDR_ALIGN_UNIT;
+
+ chunk_size -= DUMMY_END_BLOCK_BAUS;
+
+ _P(printf("[vpx][mm] memory size:%d for vpx memory manager. g_p_mng_memory:0x%x chunk_size:%d\n"
+ , g_mm_memory_size
+ , (unsigned int)g_p_mng_memory
+ , chunk_size);)
+
+ hmm_new_chunk(&hmm_d, (void *)g_p_mng_memory, chunk_size);
+ }
+
+#if MM_DYNAMIC_MEMORY
+ else
+ {
+ _P(printf("[vpx][mm] Couldn't allocate memory:%d for vpx memory manager.\n"
+ , g_mm_memory_size);)
+
+ i_rv = -1;
+ }
+
+#endif
+ }
+
+ return i_rv;
+}
+
+static void *vpx_mm_realloc(void *memblk, size_t size)
+{
+ void *p_ret = NULL;
+
+ if (vpx_mm_create_heap_memory() < 0)
+ {
+ _P(printf("[vpx][mm] ERROR vpx_mm_realloc() Couldn't create memory for Heap.\n");)
+ }
+ else
+ {
+ int i_rv = 0;
+ int old_num_aaus;
+ int new_num_aaus;
+
+ old_num_aaus = hmm_true_size(memblk);
+ new_num_aaus = (size >> SHIFT_HMM_ADDR_ALIGN_UNIT) + 1;
+
+ if (old_num_aaus == new_num_aaus)
+ {
+ p_ret = memblk;
+ }
+ else
+ {
+ i_rv = hmm_resize(&hmm_d, memblk, new_num_aaus);
+
+ if (i_rv == 0)
+ {
+ p_ret = memblk;
+ }
+ else
+ {
+ /* Error. Try to malloc and then copy data. */
+ void *p_from_malloc;
+
+ new_num_aaus = (size >> SHIFT_HMM_ADDR_ALIGN_UNIT) + 1;
+ p_from_malloc = hmm_alloc(&hmm_d, new_num_aaus);
+
+ if (p_from_malloc)
+ {
+ vpx_memcpy(p_from_malloc, memblk, size);
+ hmm_free(&hmm_d, memblk);
+
+ p_ret = p_from_malloc;
+ }
+ }
+ }
+ }
+
+ return p_ret;
+}
+#endif //CONFIG_MEM_MANAGER
+
+#if USE_GLOBAL_FUNCTION_POINTERS
+# if CONFIG_MEM_TRACKER
+extern int vpx_memory_tracker_set_functions(g_malloc_func g_malloc_l
+ , g_calloc_func g_calloc_l
+ , g_realloc_func g_realloc_l
+ , g_free_func g_free_l
+ , g_memcpy_func g_memcpy_l
+ , g_memset_func g_memset_l
+ , g_memmove_func g_memmove_l);
+# endif
+#endif //USE_GLOBAL_FUNCTION_POINTERS
+int vpx_mem_set_functions(g_malloc_func g_malloc_l
+ , g_calloc_func g_calloc_l
+ , g_realloc_func g_realloc_l
+ , g_free_func g_free_l
+ , g_memcpy_func g_memcpy_l
+ , g_memset_func g_memset_l
+ , g_memmove_func g_memmove_l)
+{
+#if USE_GLOBAL_FUNCTION_POINTERS
+
+ /* If use global functions is turned on then the
+ application must set the global functions before
+ it does anything else or vpx_mem will have
+ unpredictable results. */
+ if (!g_func)
+ {
+ g_func = (struct GLOBAL_FUNC_POINTERS *)
+ g_malloc_l(sizeof(struct GLOBAL_FUNC_POINTERS));
+
+ if (!g_func)
+ {
+ return -1;
+ }
+ }
+
+#if CONFIG_MEM_TRACKER
+ {
+ int rv = 0;
+ rv = vpx_memory_tracker_set_functions(g_malloc_l
+ , g_calloc_l
+ , g_realloc_l
+ , g_free_l
+ , g_memcpy_l
+ , g_memset_l
+ , g_memmove_l);
+
+ if (rv < 0)
+ {
+ return rv;
+ }
+ }
+#endif
+
+ g_func->g_malloc = g_malloc_l;
+ g_func->g_calloc = g_calloc_l;
+ g_func->g_realloc = g_realloc_l;
+ g_func->g_free = g_free_l;
+ g_func->g_memcpy = g_memcpy_l;
+ g_func->g_memset = g_memset_l;
+ g_func->g_memmove = g_memmove_l;
+
+ return 0;
+#else
+ (void)g_malloc_l;
+ (void)g_calloc_l;
+ (void)g_realloc_l;
+ (void)g_free_l;
+ (void)g_memcpy_l;
+ (void)g_memset_l;
+ (void)g_memmove_l;
+ return -1;
+#endif
+}
+
+int vpx_mem_unset_functions()
+{
+#if USE_GLOBAL_FUNCTION_POINTERS
+
+ if (g_func)
+ {
+ g_free_func temp_free = g_func->g_free;
+ temp_free(g_func);
+ g_func = NULL;
+ }
+
+#endif
+ return 0;
+}