media/libvpx/vpx_mem/vpx_mem.c

branch
TOR_BUG_9701
changeset 15
b8a032363ba2
equal deleted inserted replaced
-1:000000000000 0:a9178d8aed02
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
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
28
29 #if CONFIG_MEM_MANAGER
30 # include "heapmm.h"
31 # include "hmm_intrnl.h"
32
33 # define SHIFT_HMM_ADDR_ALIGN_UNIT 5
34 # define TOTAL_MEMORY_TO_ALLOCATE 20971520 /* 20 * 1024 * 1024 */
35
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
43
44 static size_t g_mm_memory_size = TOTAL_MEMORY_TO_ALLOCATE;
45
46 static hmm_descriptor hmm_d;
47 static int g_mng_memory_allocated = 0;
48
49 static int vpx_mm_create_heap_memory();
50 static void *vpx_mm_realloc(void *memblk, size_t size);
51 #endif /*CONFIG_MEM_MANAGER*/
52
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;
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;
63
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 */
78
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);
84 return ver;
85 }
86
87 int vpx_mem_set_heap_size(size_t size) {
88 int ret = -1;
89
90 #if CONFIG_MEM_MANAGER
91 #if MM_DYNAMIC_MEMORY
92
93 if (!g_mng_memory_allocated && size) {
94 g_mm_memory_size = size;
95 ret = 0;
96 } else
97 ret = -3;
98
99 #else
100 ret = -2;
101 #endif
102 #else
103 (void)size;
104 #endif
105
106 return ret;
107 }
108
109 void *vpx_memalign(size_t align, size_t size) {
110 void *addr,
111 * x = NULL;
112
113 #if CONFIG_MEM_MANAGER
114 int number_aau;
115
116 if (vpx_mm_create_heap_memory() < 0) {
117 _P(printf("[vpx][mm] ERROR vpx_memalign() Couldn't create memory for Heap.\n");)
118 }
119
120 number_aau = ((size + align - 1 + ADDRESS_STORAGE_SIZE) >>
121 SHIFT_HMM_ADDR_ALIGN_UNIT) + 1;
122
123 addr = hmm_alloc(&hmm_d, number_aau);
124 #else
125 addr = VPX_MALLOC_L(size + align - 1 + ADDRESS_STORAGE_SIZE);
126 #endif /*CONFIG_MEM_MANAGER*/
127
128 if (addr) {
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;
132 }
133
134 return x;
135 }
136
137 void *vpx_malloc(size_t size) {
138 return vpx_memalign(DEFAULT_ALIGNMENT, size);
139 }
140
141 void *vpx_calloc(size_t num, size_t size) {
142 void *x;
143
144 x = vpx_memalign(DEFAULT_ALIGNMENT, num * size);
145
146 if (x)
147 VPX_MEMSET_L(x, 0, num * size);
148
149 return x;
150 }
151
152 void *vpx_realloc(void *memblk, size_t size) {
153 void *addr,
154 * new_addr = NULL;
155 int align = DEFAULT_ALIGNMENT;
156
157 /*
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.
164 */
165 if (!memblk)
166 new_addr = vpx_malloc(size);
167 else if (!size)
168 vpx_free(memblk);
169 else {
170 addr = (void *)(((size_t *)memblk)[-1]);
171 memblk = NULL;
172
173 #if CONFIG_MEM_MANAGER
174 new_addr = vpx_mm_realloc(addr, size + align + ADDRESS_STORAGE_SIZE);
175 #else
176 new_addr = VPX_REALLOC_L(addr, size + align + ADDRESS_STORAGE_SIZE);
177 #endif
178
179 if (new_addr) {
180 addr = new_addr;
181 new_addr = (void *)(((size_t)
182 ((unsigned char *)new_addr + ADDRESS_STORAGE_SIZE) + (align - 1)) &
183 (size_t) - align);
184 /* save the actual malloc address */
185 ((size_t *)new_addr)[-1] = (size_t)addr;
186 }
187 }
188
189 return new_addr;
190 }
191
192 void vpx_free(void *memblk) {
193 if (memblk) {
194 void *addr = (void *)(((size_t *)memblk)[-1]);
195 #if CONFIG_MEM_MANAGER
196 hmm_free(&hmm_d, addr);
197 #else
198 VPX_FREE_L(addr);
199 #endif
200 }
201 }
202
203 #if CONFIG_MEM_TRACKER
204 void *xvpx_memalign(size_t align, size_t size, char *file, int line) {
205 #if TRY_BOUNDS_CHECK
206 unsigned char *x_bounds;
207 #endif
208
209 void *x;
210
211 if (g_alloc_count == 0) {
212 #if TRY_BOUNDS_CHECK
213 int i_rv = vpx_memory_tracker_init(BOUNDS_CHECK_PAD_SIZE, BOUNDS_CHECK_VALUE);
214 #else
215 int i_rv = vpx_memory_tracker_init(0, 0);
216 #endif
217
218 if (i_rv < 0) {
219 _P(printf("ERROR xvpx_malloc MEM_TRACK_USAGE error vpx_memory_tracker_init().\n");)
220 }
221 }
222
223 #if TRY_BOUNDS_CHECK
224 {
225 int i;
226 unsigned int tempme = BOUNDS_CHECK_VALUE;
227
228 x_bounds = vpx_memalign(align, size + (BOUNDS_CHECK_PAD_SIZE * 2));
229
230 if (x_bounds) {
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,
237 (int)align);
238 /* save the actual malloc address */
239 ((size_t *)x)[-1] = (size_t)x_bounds;
240
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));
245 }
246 } else
247 x = NULL;
248 }
249 #else
250 x = vpx_memalign(align, size);
251 #endif /*TRY_BOUNDS_CHECK*/
252
253 g_alloc_count++;
254
255 vpx_memory_tracker_add((size_t)x, (unsigned int)size, file, line, 1);
256
257 return x;
258 }
259
260 void *xvpx_malloc(size_t size, char *file, int line) {
261 return xvpx_memalign(DEFAULT_ALIGNMENT, size, file, line);
262 }
263
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);
266
267 if (x)
268 VPX_MEMSET_L(x, 0, num * size);
269
270 return x;
271 }
272
273 void *xvpx_realloc(void *memblk, size_t size, char *file, int line) {
274 struct mem_block *p = NULL;
275 int orig_size = 0,
276 orig_line = 0;
277 char *orig_file = NULL;
278
279 #if TRY_BOUNDS_CHECK
280 unsigned char *x_bounds = memblk ?
281 (unsigned char *)(((size_t *)memblk)[-1]) :
282 NULL;
283 #endif
284
285 void *x;
286
287 if (g_alloc_count == 0) {
288 #if TRY_BOUNDS_CHECK
289
290 if (!vpx_memory_tracker_init(BOUNDS_CHECK_PAD_SIZE, BOUNDS_CHECK_VALUE))
291 #else
292 if (!vpx_memory_tracker_init(0, 0))
293 #endif
294 {
295 _P(printf("ERROR xvpx_malloc MEM_TRACK_USAGE error vpx_memory_tracker_init().\n");)
296 }
297 }
298
299 if ((p = vpx_memory_tracker_find((size_t)memblk))) {
300 orig_size = p->size;
301 orig_file = p->file;
302 orig_line = p->line;
303 }
304
305 #if TRY_BOUNDS_CHECK_ON_FREE
306 vpx_memory_tracker_check_integrity(file, line);
307 #endif
308
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
312 */
313 vpx_memory_tracker_remove((size_t)memblk);
314
315 #if TRY_BOUNDS_CHECK
316 {
317 int i;
318 unsigned int tempme = BOUNDS_CHECK_VALUE;
319
320 x_bounds = vpx_realloc(memblk, size + (BOUNDS_CHECK_PAD_SIZE * 2));
321
322 if (x_bounds) {
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;
328
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));
333 }
334 } else
335 x = NULL;
336 }
337 #else
338 x = vpx_realloc(memblk, size);
339 #endif /*TRY_BOUNDS_CHECK*/
340
341 if (!memblk) ++g_alloc_count;
342
343 if (x)
344 vpx_memory_tracker_add((size_t)x, (unsigned int)size, file, line, 1);
345 else
346 vpx_memory_tracker_add((size_t)memblk, orig_size, orig_file, orig_line, 1);
347
348 return x;
349 }
350
351 void xvpx_free(void *p_address, char *file, int line) {
352 #if TRY_BOUNDS_CHECK
353 unsigned char *p_bounds_address = (unsigned char *)p_address;
354 /*p_bounds_address -= BOUNDS_CHECK_PAD_SIZE;*/
355 #endif
356
357 #if !TRY_BOUNDS_CHECK_ON_FREE
358 (void)file;
359 (void)line;
360 #endif
361
362 if (p_address) {
363 #if TRY_BOUNDS_CHECK_ON_FREE
364 vpx_memory_tracker_check_integrity(file, line);
365 #endif
366
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
369 */
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));
375 } else
376 --g_alloc_count;
377
378 #if TRY_BOUNDS_CHECK
379 vpx_free(p_bounds_address);
380 #else
381 vpx_free(p_address);
382 #endif
383
384 if (!g_alloc_count)
385 vpx_memory_tracker_destroy();
386 }
387 }
388
389 #endif /*CONFIG_MEM_TRACKER*/
390
391 #if CONFIG_MEM_CHECKS
392 #if defined(VXWORKS)
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) {
397 tt(task);
398
399 return 0;
400 }
401
402 static void vx_sleep(int msec) {
403 int ticks_to_sleep = 0;
404
405 if (msec) {
406 int msec_per_tick = 1000 / sys_clk_rate_get();
407
408 if (msec < msec_per_tick)
409 ticks_to_sleep++;
410 else
411 ticks_to_sleep = msec / msec_per_tick;
412 }
413
414 task_delay(ticks_to_sleep);
415 }
416 #endif
417 #endif
418
419 void *vpx_memcpy(void *dest, const void *source, size_t length) {
420 #if CONFIG_MEM_CHECKS
421
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);)
424
425 #if defined(VXWORKS)
426 sp(get_my_tt, task_id_self(), 0, 0, 0, 0, 0, 0, 0, 0);
427
428 vx_sleep(10000);
429 #endif
430 }
431
432 #endif
433
434 return VPX_MEMCPY_L(dest, source, length);
435 }
436
437 void *vpx_memset(void *dest, int val, size_t length) {
438 #if CONFIG_MEM_CHECKS
439
440 if ((int)dest < 0x4000) {
441 _P(printf("WARNING: vpx_memset dest:0x%x val:%d len:%d\n", (int)dest, val, length);)
442
443 #if defined(VXWORKS)
444 sp(get_my_tt, task_id_self(), 0, 0, 0, 0, 0, 0, 0, 0);
445
446 vx_sleep(10000);
447 #endif
448 }
449
450 #endif
451
452 return VPX_MEMSET_L(dest, val, length);
453 }
454
455 void *vpx_memmove(void *dest, const void *src, size_t count) {
456 #if CONFIG_MEM_CHECKS
457
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);)
460
461 #if defined(VXWORKS)
462 sp(get_my_tt, task_id_self(), 0, 0, 0, 0, 0, 0, 0, 0);
463
464 vx_sleep(10000);
465 #endif
466 }
467
468 #endif
469
470 return VPX_MEMMOVE_L(dest, src, count);
471 }
472
473 #if CONFIG_MEM_MANAGER
474
475 static int vpx_mm_create_heap_memory() {
476 int i_rv = 0;
477
478 if (!g_mng_memory_allocated) {
479 #if MM_DYNAMIC_MEMORY
480 g_p_mng_memory_raw =
481 (unsigned char *)malloc(g_mm_memory_size + HMM_ADDR_ALIGN_UNIT);
482
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);
487
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);)
492 } else {
493 _P(printf("[vpx][mm] Couldn't allocate memory:%d for vpx memory manager.\n"
494 , g_mm_memory_size);)
495
496 i_rv = -1;
497 }
498
499 if (g_p_mng_memory)
500 #endif
501 {
502 int chunk_size = 0;
503
504 g_mng_memory_allocated = 1;
505
506 hmm_init(&hmm_d);
507
508 chunk_size = g_mm_memory_size >> SHIFT_HMM_ADDR_ALIGN_UNIT;
509
510 chunk_size -= DUMMY_END_BLOCK_BAUS;
511
512 _P(printf("[vpx][mm] memory size:%d for vpx memory manager. g_p_mng_memory:0x%x chunk_size:%d\n"
513 , g_mm_memory_size
514 , (unsigned int)g_p_mng_memory
515 , chunk_size);)
516
517 hmm_new_chunk(&hmm_d, (void *)g_p_mng_memory, chunk_size);
518 }
519
520 #if MM_DYNAMIC_MEMORY
521 else {
522 _P(printf("[vpx][mm] Couldn't allocate memory:%d for vpx memory manager.\n"
523 , g_mm_memory_size);)
524
525 i_rv = -1;
526 }
527
528 #endif
529 }
530
531 return i_rv;
532 }
533
534 static void *vpx_mm_realloc(void *memblk, size_t size) {
535 void *p_ret = NULL;
536
537 if (vpx_mm_create_heap_memory() < 0) {
538 _P(printf("[vpx][mm] ERROR vpx_mm_realloc() Couldn't create memory for Heap.\n");)
539 } else {
540 int i_rv = 0;
541 int old_num_aaus;
542 int new_num_aaus;
543
544 old_num_aaus = hmm_true_size(memblk);
545 new_num_aaus = (size >> SHIFT_HMM_ADDR_ALIGN_UNIT) + 1;
546
547 if (old_num_aaus == new_num_aaus) {
548 p_ret = memblk;
549 } else {
550 i_rv = hmm_resize(&hmm_d, memblk, new_num_aaus);
551
552 if (i_rv == 0) {
553 p_ret = memblk;
554 } else {
555 /* Error. Try to malloc and then copy data. */
556 void *p_from_malloc;
557
558 new_num_aaus = (size >> SHIFT_HMM_ADDR_ALIGN_UNIT) + 1;
559 p_from_malloc = hmm_alloc(&hmm_d, new_num_aaus);
560
561 if (p_from_malloc) {
562 vpx_memcpy(p_from_malloc, memblk, size);
563 hmm_free(&hmm_d, memblk);
564
565 p_ret = p_from_malloc;
566 }
567 }
568 }
569 }
570
571 return p_ret;
572 }
573 #endif /*CONFIG_MEM_MANAGER*/
574
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);
584 # endif
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
594
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. */
599 if (!g_func) {
600 g_func = (struct GLOBAL_FUNC_POINTERS *)
601 g_malloc_l(sizeof(struct GLOBAL_FUNC_POINTERS));
602
603 if (!g_func) {
604 return -1;
605 }
606 }
607
608 #if CONFIG_MEM_TRACKER
609 {
610 int rv = 0;
611 rv = vpx_memory_tracker_set_functions(g_malloc_l
612 , g_calloc_l
613 , g_realloc_l
614 , g_free_l
615 , g_memcpy_l
616 , g_memset_l
617 , g_memmove_l);
618
619 if (rv < 0) {
620 return rv;
621 }
622 }
623 #endif
624
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;
632
633 return 0;
634 #else
635 (void)g_malloc_l;
636 (void)g_calloc_l;
637 (void)g_realloc_l;
638 (void)g_free_l;
639 (void)g_memcpy_l;
640 (void)g_memset_l;
641 (void)g_memmove_l;
642 return -1;
643 #endif
644 }
645
646 int vpx_mem_unset_functions() {
647 #if USE_GLOBAL_FUNCTION_POINTERS
648
649 if (g_func) {
650 g_free_func temp_free = g_func->g_free;
651 temp_free(g_func);
652 g_func = NULL;
653 }
654
655 #endif
656 return 0;
657 }

mercurial