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.
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;
24
#include "vpx_global_handling.h"
25
#define g_alloc_count vpxglobalm(vpxmem,g_alloc_count)
29
#if CONFIG_MEM_MANAGER
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;
41
static unsigned char g_p_mng_memory[TOTAL_MEMORY_TO_ALLOCATE];
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 {
55
g_malloc_func g_malloc;
56
g_calloc_func g_calloc;
57
g_realloc_func g_realloc;
59
g_memcpy_func g_memcpy;
60
g_memset_func g_memset;
61
g_memmove_func g_memmove;
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
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() {
80
unsigned int ver = ((unsigned int)(unsigned char)VPX_MEM_VERSION_CHIEF << 24 |
81
(unsigned int)(unsigned char)VPX_MEM_VERSION_MAJOR << 16 |
82
(unsigned int)(unsigned char)VPX_MEM_VERSION_MINOR << 8 |
83
(unsigned int)(unsigned char)VPX_MEM_VERSION_PATCH);
87
int vpx_mem_set_heap_size(size_t size) {
90
#if CONFIG_MEM_MANAGER
93
if (!g_mng_memory_allocated && size) {
94
g_mm_memory_size = size;
109
void *vpx_memalign(size_t align, size_t size) {
113
#if CONFIG_MEM_MANAGER
116
if (vpx_mm_create_heap_memory() < 0) {
117
_P(printf("[vpx][mm] ERROR vpx_memalign() Couldn't create memory for Heap.\n");)
120
number_aau = ((size + align - 1 + ADDRESS_STORAGE_SIZE) >>
121
SHIFT_HMM_ADDR_ALIGN_UNIT) + 1;
123
addr = hmm_alloc(&hmm_d, number_aau);
125
addr = VPX_MALLOC_L(size + align - 1 + ADDRESS_STORAGE_SIZE);
126
#endif /*CONFIG_MEM_MANAGER*/
129
x = align_addr((unsigned char *)addr + ADDRESS_STORAGE_SIZE, (int)align);
130
/* save the actual malloc address */
131
((size_t *)x)[-1] = (size_t)addr;
137
void *vpx_malloc(size_t size) {
138
return vpx_memalign(DEFAULT_ALIGNMENT, size);
141
void *vpx_calloc(size_t num, size_t size) {
144
x = vpx_memalign(DEFAULT_ALIGNMENT, num * size);
147
VPX_MEMSET_L(x, 0, num * size);
152
void *vpx_realloc(void *memblk, size_t size) {
155
int align = DEFAULT_ALIGNMENT;
158
The realloc() function changes the size of the object pointed to by
159
ptr to the size specified by size, and returns a pointer to the
160
possibly moved block. The contents are unchanged up to the lesser
161
of the new and old sizes. If ptr is null, realloc() behaves like
162
malloc() for the specified size. If size is zero (0) and ptr is
163
not a null pointer, the object pointed to is freed.
166
new_addr = vpx_malloc(size);
170
addr = (void *)(((size_t *)memblk)[-1]);
173
#if CONFIG_MEM_MANAGER
174
new_addr = vpx_mm_realloc(addr, size + align + ADDRESS_STORAGE_SIZE);
176
new_addr = VPX_REALLOC_L(addr, size + align + ADDRESS_STORAGE_SIZE);
181
new_addr = (void *)(((size_t)
182
((unsigned char *)new_addr + ADDRESS_STORAGE_SIZE) + (align - 1)) &
184
/* save the actual malloc address */
185
((size_t *)new_addr)[-1] = (size_t)addr;
192
void vpx_free(void *memblk) {
194
void *addr = (void *)(((size_t *)memblk)[-1]);
195
#if CONFIG_MEM_MANAGER
196
hmm_free(&hmm_d, addr);
203
#if CONFIG_MEM_TRACKER
204
void *xvpx_memalign(size_t align, size_t size, char *file, int line) {
206
unsigned char *x_bounds;
211
if (g_alloc_count == 0) {
213
int i_rv = vpx_memory_tracker_init(BOUNDS_CHECK_PAD_SIZE, BOUNDS_CHECK_VALUE);
215
int i_rv = vpx_memory_tracker_init(0, 0);
219
_P(printf("ERROR xvpx_malloc MEM_TRACK_USAGE error vpx_memory_tracker_init().\n");)
226
unsigned int tempme = BOUNDS_CHECK_VALUE;
228
x_bounds = vpx_memalign(align, size + (BOUNDS_CHECK_PAD_SIZE * 2));
231
/*we're aligning the address twice here but to keep things
232
consistent we want to have the padding come before the stored
233
address so no matter what free function gets called we will
234
attempt to free the correct address*/
235
x_bounds = (unsigned char *)(((size_t *)x_bounds)[-1]);
236
x = align_addr(x_bounds + BOUNDS_CHECK_PAD_SIZE + ADDRESS_STORAGE_SIZE,
238
/* save the actual malloc address */
239
((size_t *)x)[-1] = (size_t)x_bounds;
241
for (i = 0; i < BOUNDS_CHECK_PAD_SIZE; i += sizeof(unsigned int)) {
242
VPX_MEMCPY_L(x_bounds + i, &tempme, sizeof(unsigned int));
243
VPX_MEMCPY_L((unsigned char *)x + size + i,
244
&tempme, sizeof(unsigned int));
250
x = vpx_memalign(align, size);
251
#endif /*TRY_BOUNDS_CHECK*/
255
vpx_memory_tracker_add((size_t)x, (unsigned int)size, file, line, 1);
260
void *xvpx_malloc(size_t size, char *file, int line) {
261
return xvpx_memalign(DEFAULT_ALIGNMENT, size, file, line);
264
void *xvpx_calloc(size_t num, size_t size, char *file, int line) {
265
void *x = xvpx_memalign(DEFAULT_ALIGNMENT, num * size, file, line);
268
VPX_MEMSET_L(x, 0, num * size);
273
void *xvpx_realloc(void *memblk, size_t size, char *file, int line) {
274
struct mem_block *p = NULL;
277
char *orig_file = NULL;
280
unsigned char *x_bounds = memblk ?
281
(unsigned char *)(((size_t *)memblk)[-1]) :
287
if (g_alloc_count == 0) {
290
if (!vpx_memory_tracker_init(BOUNDS_CHECK_PAD_SIZE, BOUNDS_CHECK_VALUE))
292
if (!vpx_memory_tracker_init(0, 0))
295
_P(printf("ERROR xvpx_malloc MEM_TRACK_USAGE error vpx_memory_tracker_init().\n");)
299
if ((p = vpx_memory_tracker_find((size_t)memblk))) {
305
#if TRY_BOUNDS_CHECK_ON_FREE
306
vpx_memory_tracker_check_integrity(file, line);
309
/* have to do this regardless of success, because
310
* the memory that does get realloc'd may change
311
* the bounds values of this block
313
vpx_memory_tracker_remove((size_t)memblk);
318
unsigned int tempme = BOUNDS_CHECK_VALUE;
320
x_bounds = vpx_realloc(memblk, size + (BOUNDS_CHECK_PAD_SIZE * 2));
323
x_bounds = (unsigned char *)(((size_t *)x_bounds)[-1]);
324
x = align_addr(x_bounds + BOUNDS_CHECK_PAD_SIZE + ADDRESS_STORAGE_SIZE,
325
(int)DEFAULT_ALIGNMENT);
326
/* save the actual malloc address */
327
((size_t *)x)[-1] = (size_t)x_bounds;
329
for (i = 0; i < BOUNDS_CHECK_PAD_SIZE; i += sizeof(unsigned int)) {
330
VPX_MEMCPY_L(x_bounds + i, &tempme, sizeof(unsigned int));
331
VPX_MEMCPY_L((unsigned char *)x + size + i,
332
&tempme, sizeof(unsigned int));
338
x = vpx_realloc(memblk, size);
339
#endif /*TRY_BOUNDS_CHECK*/
341
if (!memblk) ++g_alloc_count;
344
vpx_memory_tracker_add((size_t)x, (unsigned int)size, file, line, 1);
346
vpx_memory_tracker_add((size_t)memblk, orig_size, orig_file, orig_line, 1);
351
void xvpx_free(void *p_address, char *file, int line) {
353
unsigned char *p_bounds_address = (unsigned char *)p_address;
354
/*p_bounds_address -= BOUNDS_CHECK_PAD_SIZE;*/
357
#if !TRY_BOUNDS_CHECK_ON_FREE
363
#if TRY_BOUNDS_CHECK_ON_FREE
364
vpx_memory_tracker_check_integrity(file, line);
367
/* if the addr isn't found in the list, assume it was allocated via
368
* vpx_ calls not xvpx_, therefore it does not contain any padding
370
if (vpx_memory_tracker_remove((size_t)p_address) == -2) {
371
p_bounds_address = p_address;
372
_P(fprintf(stderr, "[vpx_mem][xvpx_free] addr: %p not found in"
373
" list; freed from file:%s"
374
" line:%d\n", p_address, file, line));
379
vpx_free(p_bounds_address);
385
vpx_memory_tracker_destroy();
389
#endif /*CONFIG_MEM_TRACKER*/
391
#if CONFIG_MEM_CHECKS
393
#include <task_lib.h> /*for task_delay()*/
394
/* This function is only used to get a stack trace of the player
395
object so we can se where we are having a problem. */
396
static int get_my_tt(int task) {
402
static void vx_sleep(int msec) {
403
int ticks_to_sleep = 0;
406
int msec_per_tick = 1000 / sys_clk_rate_get();
408
if (msec < msec_per_tick)
411
ticks_to_sleep = msec / msec_per_tick;
414
task_delay(ticks_to_sleep);
419
void *vpx_memcpy(void *dest, const void *source, size_t length) {
420
#if CONFIG_MEM_CHECKS
422
if (((int)dest < 0x4000) || ((int)source < 0x4000)) {
423
_P(printf("WARNING: vpx_memcpy dest:0x%x source:0x%x len:%d\n", (int)dest, (int)source, length);)
426
sp(get_my_tt, task_id_self(), 0, 0, 0, 0, 0, 0, 0, 0);
434
return VPX_MEMCPY_L(dest, source, length);
437
void *vpx_memset(void *dest, int val, size_t length) {
438
#if CONFIG_MEM_CHECKS
440
if ((int)dest < 0x4000) {
441
_P(printf("WARNING: vpx_memset dest:0x%x val:%d len:%d\n", (int)dest, val, length);)
444
sp(get_my_tt, task_id_self(), 0, 0, 0, 0, 0, 0, 0, 0);
452
return VPX_MEMSET_L(dest, val, length);
455
void *vpx_memmove(void *dest, const void *src, size_t count) {
456
#if CONFIG_MEM_CHECKS
458
if (((int)dest < 0x4000) || ((int)src < 0x4000)) {
459
_P(printf("WARNING: vpx_memmove dest:0x%x src:0x%x count:%d\n", (int)dest, (int)src, count);)
462
sp(get_my_tt, task_id_self(), 0, 0, 0, 0, 0, 0, 0, 0);
470
return VPX_MEMMOVE_L(dest, src, count);
473
#if CONFIG_MEM_MANAGER
475
static int vpx_mm_create_heap_memory() {
478
if (!g_mng_memory_allocated) {
479
#if MM_DYNAMIC_MEMORY
481
(unsigned char *)malloc(g_mm_memory_size + HMM_ADDR_ALIGN_UNIT);
483
if (g_p_mng_memory_raw) {
484
g_p_mng_memory = (unsigned char *)((((unsigned int)g_p_mng_memory_raw) +
485
HMM_ADDR_ALIGN_UNIT - 1) &
486
-(int)HMM_ADDR_ALIGN_UNIT);
488
_P(printf("[vpx][mm] total memory size:%d g_p_mng_memory_raw:0x%x g_p_mng_memory:0x%x\n"
489
, g_mm_memory_size + HMM_ADDR_ALIGN_UNIT
490
, (unsigned int)g_p_mng_memory_raw
491
, (unsigned int)g_p_mng_memory);)
493
_P(printf("[vpx][mm] Couldn't allocate memory:%d for vpx memory manager.\n"
494
, g_mm_memory_size);)
504
g_mng_memory_allocated = 1;
508
chunk_size = g_mm_memory_size >> SHIFT_HMM_ADDR_ALIGN_UNIT;
510
chunk_size -= DUMMY_END_BLOCK_BAUS;
512
_P(printf("[vpx][mm] memory size:%d for vpx memory manager. g_p_mng_memory:0x%x chunk_size:%d\n"
514
, (unsigned int)g_p_mng_memory
517
hmm_new_chunk(&hmm_d, (void *)g_p_mng_memory, chunk_size);
520
#if MM_DYNAMIC_MEMORY
522
_P(printf("[vpx][mm] Couldn't allocate memory:%d for vpx memory manager.\n"
523
, g_mm_memory_size);)
534
static void *vpx_mm_realloc(void *memblk, size_t size) {
537
if (vpx_mm_create_heap_memory() < 0) {
538
_P(printf("[vpx][mm] ERROR vpx_mm_realloc() Couldn't create memory for Heap.\n");)
544
old_num_aaus = hmm_true_size(memblk);
545
new_num_aaus = (size >> SHIFT_HMM_ADDR_ALIGN_UNIT) + 1;
547
if (old_num_aaus == new_num_aaus) {
550
i_rv = hmm_resize(&hmm_d, memblk, new_num_aaus);
555
/* Error. Try to malloc and then copy data. */
558
new_num_aaus = (size >> SHIFT_HMM_ADDR_ALIGN_UNIT) + 1;
559
p_from_malloc = hmm_alloc(&hmm_d, new_num_aaus);
562
vpx_memcpy(p_from_malloc, memblk, size);
563
hmm_free(&hmm_d, memblk);
565
p_ret = p_from_malloc;
573
#endif /*CONFIG_MEM_MANAGER*/
575
#if USE_GLOBAL_FUNCTION_POINTERS
576
# if CONFIG_MEM_TRACKER
577
extern int vpx_memory_tracker_set_functions(g_malloc_func g_malloc_l
578
, g_calloc_func g_calloc_l
579
, g_realloc_func g_realloc_l
580
, g_free_func g_free_l
581
, g_memcpy_func g_memcpy_l
582
, g_memset_func g_memset_l
583
, g_memmove_func g_memmove_l);
585
#endif /*USE_GLOBAL_FUNCTION_POINTERS*/
586
int vpx_mem_set_functions(g_malloc_func g_malloc_l
587
, g_calloc_func g_calloc_l
588
, g_realloc_func g_realloc_l
589
, g_free_func g_free_l
590
, g_memcpy_func g_memcpy_l
591
, g_memset_func g_memset_l
592
, g_memmove_func g_memmove_l) {
593
#if USE_GLOBAL_FUNCTION_POINTERS
595
/* If use global functions is turned on then the
596
application must set the global functions before
597
it does anything else or vpx_mem will have
598
unpredictable results. */
600
g_func = (struct GLOBAL_FUNC_POINTERS *)
601
g_malloc_l(sizeof(struct GLOBAL_FUNC_POINTERS));
608
#if CONFIG_MEM_TRACKER
611
rv = vpx_memory_tracker_set_functions(g_malloc_l
625
g_func->g_malloc = g_malloc_l;
626
g_func->g_calloc = g_calloc_l;
627
g_func->g_realloc = g_realloc_l;
628
g_func->g_free = g_free_l;
629
g_func->g_memcpy = g_memcpy_l;
630
g_func->g_memset = g_memset_l;
631
g_func->g_memmove = g_memmove_l;
646
int vpx_mem_unset_functions() {
647
#if USE_GLOBAL_FUNCTION_POINTERS
650
g_free_func temp_free = g_func->g_free;