diff options
author | Magnus Holmgren <magnushol@gmail.com> | 2009-08-29 12:23:40 +0000 |
---|---|---|
committer | Magnus Holmgren <magnushol@gmail.com> | 2009-08-29 12:23:40 +0000 |
commit | 3fad1523c78e13f61283d7b81e0990f8803dc2f2 (patch) | |
tree | 6cdbc97688e782d13cf0ee406ac8356a2ae98047 | |
parent | 260ed991392a387ff9ae5bbd8dba7afd10c1faef (diff) | |
download | rockbox-3fad1523c78e13f61283d7b81e0990f8803dc2f2.tar.gz rockbox-3fad1523c78e13f61283d7b81e0990f8803dc2f2.zip |
FS#10466: Introduce a real malloc for tremor.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@22528 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | apps/codecs/codecs.make | 5 | ||||
-rw-r--r-- | apps/codecs/lib/tlsf/COPYING | 23 | ||||
-rw-r--r-- | apps/codecs/lib/tlsf/Changelog | 119 | ||||
-rw-r--r-- | apps/codecs/lib/tlsf/README | 163 | ||||
-rw-r--r-- | apps/codecs/lib/tlsf/SOURCES | 3 | ||||
-rw-r--r-- | apps/codecs/lib/tlsf/TODO | 9 | ||||
-rw-r--r-- | apps/codecs/lib/tlsf/libtlsf.make | 28 | ||||
-rw-r--r-- | apps/codecs/libtremor/block.c | 2 | ||||
-rw-r--r-- | apps/codecs/libtremor/oggmalloc.c | 80 | ||||
-rw-r--r-- | apps/codecs/libtremor/os_types.h | 8 | ||||
-rw-r--r-- | apps/codecs/libtremor/sharedbook.c | 26 | ||||
-rw-r--r-- | apps/codecs/vorbis.c | 50 |
12 files changed, 426 insertions, 90 deletions
diff --git a/apps/codecs/codecs.make b/apps/codecs/codecs.make index 85c10158d7..87ed5f2b40 100644 --- a/apps/codecs/codecs.make +++ b/apps/codecs/codecs.make | |||
@@ -14,6 +14,9 @@ OTHER_SRC += $(CODECS_SRC) | |||
14 | CODECS := $(CODECS_SRC:.c=.codec) | 14 | CODECS := $(CODECS_SRC:.c=.codec) |
15 | CODECS := $(subst $(ROOTDIR),$(BUILDDIR),$(CODECS)) | 15 | CODECS := $(subst $(ROOTDIR),$(BUILDDIR),$(CODECS)) |
16 | 16 | ||
17 | # TLSF memory allocator library | ||
18 | include $(APPSDIR)/codecs/lib/tlsf/libtlsf.make | ||
19 | |||
17 | # the codec helper library | 20 | # the codec helper library |
18 | include $(APPSDIR)/codecs/lib/libcodec.make | 21 | include $(APPSDIR)/codecs/lib/libcodec.make |
19 | OTHER_INC += -I$(APPSDIR)/codecs/lib | 22 | OTHER_INC += -I$(APPSDIR)/codecs/lib |
@@ -66,7 +69,7 @@ $(CODECDIR)/spc.codec : $(CODECDIR)/libspc.a | |||
66 | $(CODECDIR)/mpa.codec : $(CODECDIR)/libmad.a | 69 | $(CODECDIR)/mpa.codec : $(CODECDIR)/libmad.a |
67 | $(CODECDIR)/a52.codec : $(CODECDIR)/liba52.a | 70 | $(CODECDIR)/a52.codec : $(CODECDIR)/liba52.a |
68 | $(CODECDIR)/flac.codec : $(CODECDIR)/libffmpegFLAC.a | 71 | $(CODECDIR)/flac.codec : $(CODECDIR)/libffmpegFLAC.a |
69 | $(CODECDIR)/vorbis.codec : $(CODECDIR)/libtremor.a | 72 | $(CODECDIR)/vorbis.codec : $(CODECDIR)/libtremor.a $(TLSFLIB) |
70 | $(CODECDIR)/speex.codec : $(CODECDIR)/libspeex.a | 73 | $(CODECDIR)/speex.codec : $(CODECDIR)/libspeex.a |
71 | $(CODECDIR)/mpc.codec : $(CODECDIR)/libmusepack.a | 74 | $(CODECDIR)/mpc.codec : $(CODECDIR)/libmusepack.a |
72 | $(CODECDIR)/wavpack.codec : $(CODECDIR)/libwavpack.a | 75 | $(CODECDIR)/wavpack.codec : $(CODECDIR)/libwavpack.a |
diff --git a/apps/codecs/lib/tlsf/COPYING b/apps/codecs/lib/tlsf/COPYING new file mode 100644 index 0000000000..78fdbdc061 --- /dev/null +++ b/apps/codecs/lib/tlsf/COPYING | |||
@@ -0,0 +1,23 @@ | |||
1 | LICENSE INFORMATION | ||
2 | |||
3 | TLSF is released as LGPL and GPL. A copy of both licences can be found in this | ||
4 | directoy. For the GPL licence, the following exception applies. | ||
5 | |||
6 | |||
7 | TLSF is free software; you can redistribute it and/or modify it under terms of | ||
8 | the GNU General Public License as published by the Free Software Foundation; | ||
9 | either version 2, or (at your option) any later version. TLSF is distributed | ||
10 | in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the | ||
11 | implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See | ||
12 | the GNU General Public License for more details. You should have received a | ||
13 | copy of the GNU General Public License along with TLSF; see file COPYING. If | ||
14 | not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, | ||
15 | USA. | ||
16 | |||
17 | As a special exception, including TLSF header files in a file, or linking with | ||
18 | other files objects to produce an executable application, is merely considered | ||
19 | normal use of the library, and does *not* fall under the heading of "derived | ||
20 | work". Therfore does not by itself cause the resulting executable application | ||
21 | to be covered by the GNU General Public License. This exception does not | ||
22 | however invalidate any other reasons why the executable file might be covered | ||
23 | by the GNU Public License. | ||
diff --git a/apps/codecs/lib/tlsf/Changelog b/apps/codecs/lib/tlsf/Changelog new file mode 100644 index 0000000000..0cdb34a8ab --- /dev/null +++ b/apps/codecs/lib/tlsf/Changelog | |||
@@ -0,0 +1,119 @@ | |||
1 | Version History | ||
2 | --------------- | ||
3 | -v2.4.4 (October 13 2008) | ||
4 | * Corrected minor syntactic bug on statistic gathering code. | ||
5 | Reported by Tim Cussins and P. Mantegazza. | ||
6 | |||
7 | -v2.4.3 (July 30 2008) | ||
8 | * Minor fixes to compile with the greenhills compiler. | ||
9 | Reported by "Kaya, Sinan SEA" <sinan.kaya@siemens.com> | ||
10 | * Small change in the license in order to include TLSF in the RTEMS | ||
11 | project. | ||
12 | |||
13 | -v2.4.2 (May 16 2008) (Herman ten Brugge) | ||
14 | * Memory usage statistics added again, with cleaner and more compacted | ||
15 | code. | ||
16 | |||
17 | -v2.4.1 (April 30 2008) | ||
18 | * Fixed a bug in the tlsf_realloc function: init the pool automatically | ||
19 | on the first call. | ||
20 | Reported by: Alejandro Mery <amery@geeks.cl> | ||
21 | |||
22 | -v2.4 (Feb 19 2008) | ||
23 | * "rtl_*" functions renamed to "tlsf_*". | ||
24 | * Added the add_new_area function to insert new memory areas to an | ||
25 | existing memory pool. | ||
26 | * A single TLSF pool can manage non-contiguous memory areas. | ||
27 | * Support for mmap and sbrk added. | ||
28 | * The init_memory_pool is not longer needed when used on a system | ||
29 | with mmap or sbrk. | ||
30 | * Removed the get_used_size counting.The same functionality can be | ||
31 | implemented outside the TLSF code. | ||
32 | |||
33 | -v2.3.2 (Sep 27 2007) | ||
34 | * Minor cosmetic code improvements. | ||
35 | |||
36 | -v2.3.1 (Jul 30 2007) | ||
37 | * Fixed some minor bugs in the version 2.3. Herman ten Brugge | ||
38 | <hermantenbrugge@home.nl> | ||
39 | |||
40 | -v2.3 (Jul 28 2007) Released a new version with all the contributions | ||
41 | received from Herman ten Brugge <hermantenbrugge@home.nl> | ||
42 | (This is his summary of changes in the TLSF's code): | ||
43 | * Add 64 bit support. It now runs on x86_64 and solaris64. | ||
44 | * I also tested this on vxworks/32 and solaris/32 and i386/32 | ||
45 | processors. | ||
46 | * Remove assembly code. I could not measure any performance difference | ||
47 | on my core2 processor. This also makes the code more portable. | ||
48 | * Moved defines/typedefs from tlsf.h to tlsf.c | ||
49 | * Changed MIN_BLOCK_SIZE to sizeof (free_ptr_t) and BHDR_OVERHEAD to | ||
50 | (sizeof (bhdr_t) - MIN_BLOCK_SIZE). This does not change the fact | ||
51 | that the minumum size is still sizeof (bhdr_t). | ||
52 | * Changed all C++ comment style to C style. (// -> /* ... *./) | ||
53 | * Used ls_bit instead of ffs and ms_bit instead of fls. I did this to | ||
54 | avoid confusion with the standard ffs function which returns | ||
55 | different values. | ||
56 | * Created set_bit/clear_bit fuctions because they are not present | ||
57 | on x86_64. | ||
58 | * Added locking support + extra file target.h to show how to use it. | ||
59 | * Added get_used_size function | ||
60 | * Added rtl_realloc and rtl_calloc function | ||
61 | * Implemented realloc clever support. | ||
62 | * Added some test code in the example directory. | ||
63 | |||
64 | -- Thank you very much for your help Herman! | ||
65 | |||
66 | -v2.2.1 (Oct 23 2006) | ||
67 | * Support for ARMv5 implemented by Adam Scislowicz | ||
68 | <proteuskor@gmail.com>. Thank you for your contribution. | ||
69 | |||
70 | - v2.2.0 (Jun 30 2006) Miguel Masmano & Ismael Ripoll. | ||
71 | |||
72 | * Blocks smaller than 128 bytes are stored on a single | ||
73 | segregated list. The already existing bits maps and data | ||
74 | structures are used. | ||
75 | * Minor code speed-up improvements. | ||
76 | * Worst case response time both on malloc and free improved. | ||
77 | * External fragmantation also improved!. | ||
78 | * Segragared lists are AGAIN sorted by LIFO order. Version | ||
79 | 2.1b was proven to be no better than 2.1. | ||
80 | |||
81 | - v2.1b: Allocation policy has been always a LIFO Good-Fit, that | ||
82 | is, between several free blocks in the same range, TLSF will | ||
83 | always allocate the most recently released. In this version of | ||
84 | TLSF, we have implemented a FIFO Good-Fit. However, | ||
85 | fragmentation doesn't seems to be altered so is it worth it?. | ||
86 | |||
87 | - v2.1: Realloc and calloc included again in TLSF 2.0. | ||
88 | |||
89 | - v2.0: In this version, TLSF has been programmed from scratch. | ||
90 | Now the allocator is provided as an unique file. Realloc and | ||
91 | calloc are not longer implemented. | ||
92 | |||
93 | |||
94 | - v1.4: Created the section "Version History". Studied real | ||
95 | behaviour of actual applications (regular applications tend | ||
96 | to require small memory blocks (less than 16 bytes) whereas | ||
97 | TLSF is optimised to be used with blocks larger than 16 | ||
98 | bytes: Added special lists to deal with blocks smaller than | ||
99 | 16 bytes. | ||
100 | |||
101 | |||
102 | - v1.3: Change of concept, now the main TLSF structure is created | ||
103 | inside of the beginning of the block instead of being an | ||
104 | static structure, allowing multiple TLSFs working at the | ||
105 | same time. Now, TLSF uses specific processor instructions to | ||
106 | deal with bitmaps. TLSF sanity functions added to find TLSF | ||
107 | overflows. The TLSF code will not be RTLinux-oriented any | ||
108 | more. | ||
109 | |||
110 | - v1.1 ... v1.2: Many little bugs fixed, code cleaned and splitted | ||
111 | in several files because of cosmetic requirements. | ||
112 | Starting from TLSF v1.1, MaRTE OS | ||
113 | (http://marte.unican.es) uses the TLSF allocator | ||
114 | as its default memory allocator. | ||
115 | |||
116 | - v0.1 ... v1.0: First implementations were created for testing and | ||
117 | research purposes. Basically TLSF is implemented to | ||
118 | be used by RTLinux-GPL (www.rtlinux-gpl.org), so | ||
119 | it is RTLinux-oriented. | ||
diff --git a/apps/codecs/lib/tlsf/README b/apps/codecs/lib/tlsf/README new file mode 100644 index 0000000000..d755905b16 --- /dev/null +++ b/apps/codecs/lib/tlsf/README | |||
@@ -0,0 +1,163 @@ | |||
1 | |||
2 | TLSF Memory Storage allocator implementation. | ||
3 | Version 2.4 Feb 2008 | ||
4 | |||
5 | Authors: Miguel Masmano, Ismael Ripoll & Alfons Crespo. | ||
6 | Copyright UPVLC, OCERA Consortium. | ||
7 | |||
8 | TLSF is released in the GPL/LGPL licence. The exact terms of the licence | ||
9 | are described in the COPYING file. | ||
10 | |||
11 | This component provides basic memory allocation functions: | ||
12 | malloc and free, as defined in the standard "C" library. | ||
13 | |||
14 | This allocator was designed to provide real-time performance, that is: | ||
15 | 1.- Bounded time malloc and free. | ||
16 | 2.- Fast response time. | ||
17 | 3.- Efficient memory management, that is low fragmentation. | ||
18 | |||
19 | |||
20 | The worst response time for both malloc and free is O(1). | ||
21 | |||
22 | |||
23 | |||
24 | How to use it: | ||
25 | |||
26 | This code is prepared to be used as a stand-alone code that can be | ||
27 | linked with a regular application or it can be compiled to be a Linux | ||
28 | module (which required the BigPhysicalArea patch). Initially the | ||
29 | module was designed to work jointly with RTLinux-GPL, but it can be | ||
30 | used as a stand alone Linux module. | ||
31 | |||
32 | When compiled as a regular linux process the API is: | ||
33 | |||
34 | Initialisation and destruction functions | ||
35 | ---------------------------------------- | ||
36 | |||
37 | init_memory_pool may be called before any request or release call: | ||
38 | |||
39 | - size_t init_memory_pool(size_t, void *); | ||
40 | - void destroy_memory_pool(void *); | ||
41 | |||
42 | Request and release functions | ||
43 | ----------------------------- | ||
44 | |||
45 | As can be seen, there are two functions for each traditional memory | ||
46 | allocation function (malloc, free, realloc, and calloc). One with the | ||
47 | prefix "tlsf_" and the other with the suffix "_ex". | ||
48 | |||
49 | The versions with the prefix "tlsf_" provides the expected behaviour, | ||
50 | that is, allocating/releasing memory from the default memory pool. The | ||
51 | default memory pool is the last pool initialised by the | ||
52 | init_memory_pool function. | ||
53 | |||
54 | On the other hand, the functions with the prefix "_ex" enable the use of several memory pools. | ||
55 | |||
56 | - void *tlsf_malloc(size_t); | ||
57 | - void *malloc_ex(size_t, void *); | ||
58 | |||
59 | - void tlsf_free(void *ptr); | ||
60 | - void free_ex(void *, void *); | ||
61 | |||
62 | - void *tlsf_realloc(void *ptr, size_t size); | ||
63 | - void *realloc_ex(void *, size_t, void *); | ||
64 | |||
65 | - void *tlsf_calloc(size_t nelem, size_t elem_size); | ||
66 | - void *calloc_ex(size_t, size_t, void *); | ||
67 | |||
68 | EXAMPLE OF USE: | ||
69 | |||
70 | char memory_pool[1024*1024]; | ||
71 | |||
72 | { | ||
73 | ... | ||
74 | |||
75 | init_memory_pool(1024*1024, memory_pool); | ||
76 | |||
77 | ... | ||
78 | |||
79 | ptr1=malloc_ex(100, memory_pool); | ||
80 | ptr2=tlsf_malloc(100); // This function will use memory_pool | ||
81 | |||
82 | ... | ||
83 | |||
84 | tlsf_free(ptr2); | ||
85 | free_ex(ptr1, memory_pool); | ||
86 | } | ||
87 | |||
88 | Growing the memory pool | ||
89 | ----------------------- | ||
90 | |||
91 | Starting from the version 2.4, the function add_new_area adds an | ||
92 | memory area to an existing memory pool. | ||
93 | |||
94 | - size_t add_new_area(void *, size_t, void *); | ||
95 | |||
96 | This feature is pretty useful when an existing memory pool is running | ||
97 | low and we want to add more free memory to it. | ||
98 | EXAMPLE OF USE: | ||
99 | |||
100 | char memory_pool[1024*1024]; | ||
101 | char memory_pool2[1024*1024]; | ||
102 | |||
103 | { | ||
104 | ... | ||
105 | |||
106 | init_memory_pool(1024*1024, memory_pool); | ||
107 | |||
108 | ... | ||
109 | |||
110 | ptr[0]=malloc_ex(1024*256 memory_pool); | ||
111 | ptr[1]=malloc_ex(1024*512, memory_pool); | ||
112 | add_new_area(memory_pool2, 1024*1024, memory_pool); | ||
113 | // Now we have an extra free memory area of 1Mb | ||
114 | // The next malloc may not fail | ||
115 | ptr[2]=malloc_ex(1024*512, memory_pool); | ||
116 | |||
117 | ... | ||
118 | |||
119 | } | ||
120 | |||
121 | |||
122 | SBRK and MMAP support | ||
123 | --------------------- | ||
124 | |||
125 | The version 2.4 can use the functions SBRK and MMAP to _automatically_ | ||
126 | growing the memory pool, before running out of memory. | ||
127 | |||
128 | So, when this feature is enabled, unless the operating system were out | ||
129 | of memory, a malloc operation would not fail due to an "out-of-memory" | ||
130 | error. | ||
131 | |||
132 | To enable this support, compile tlsf.c with the FLAGS -DUSE_MMAP=1 or | ||
133 | -DUSE_SBRK=1 depending on whether you want to use "mmap" or "sbrk" or both. | ||
134 | |||
135 | ** By default (default Makefile) this feature is enabled. | ||
136 | |||
137 | EXAMPLE OF USE: | ||
138 | |||
139 | gcc -o tlsf.o -O2 -Wall -DUSE_MMAP=1 -DUSE_SBRK=1 | ||
140 | |||
141 | --- | ||
142 | |||
143 | If the sbrk/mmap support is enabled and we are _only_ going to use one | ||
144 | memory pool, it is not necessary to call init_memory_pool | ||
145 | |||
146 | EXAMPLE OF USE (with MMAP/SBRK support enabled): | ||
147 | |||
148 | { | ||
149 | ... | ||
150 | |||
151 | ptr2=tlsf_malloc(100); // This function will use memory_pool | ||
152 | |||
153 | ... | ||
154 | |||
155 | tlsf_free(ptr2); | ||
156 | } | ||
157 | |||
158 | |||
159 | |||
160 | |||
161 | This work has been supported by the followin projects: | ||
162 | EUROPEAN: IST-2001-35102(OCERA) http://www.ocera.org. | ||
163 | SPANISH: TIN2005-08665-C3-03 | ||
diff --git a/apps/codecs/lib/tlsf/SOURCES b/apps/codecs/lib/tlsf/SOURCES new file mode 100644 index 0000000000..eb9d93756e --- /dev/null +++ b/apps/codecs/lib/tlsf/SOURCES | |||
@@ -0,0 +1,3 @@ | |||
1 | #if CONFIG_CODEC == SWCODEC /* software codec platforms */ | ||
2 | src/tlsf.c | ||
3 | #endif | ||
diff --git a/apps/codecs/lib/tlsf/TODO b/apps/codecs/lib/tlsf/TODO new file mode 100644 index 0000000000..d7c07b8421 --- /dev/null +++ b/apps/codecs/lib/tlsf/TODO | |||
@@ -0,0 +1,9 @@ | |||
1 | To do list | ||
2 | ========== | ||
3 | |||
4 | * Add mmap/sbrk support (DONE - V2.4). | ||
5 | |||
6 | * TLSF rounds-up request size to the head of a free list. | ||
7 | It has been shown to be a good policy for small blocks (<2048). | ||
8 | But for larger blocks this policy may cause excesive fragmentation. | ||
9 | A deeper analisys should be done. | ||
diff --git a/apps/codecs/lib/tlsf/libtlsf.make b/apps/codecs/lib/tlsf/libtlsf.make new file mode 100644 index 0000000000..464487f87f --- /dev/null +++ b/apps/codecs/lib/tlsf/libtlsf.make | |||
@@ -0,0 +1,28 @@ | |||
1 | # __________ __ ___. | ||
2 | # Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
3 | # Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
4 | # Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
5 | # Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
6 | # \/ \/ \/ \/ \/ | ||
7 | # $Id$ | ||
8 | # | ||
9 | |||
10 | TLSFLIB := $(CODECDIR)/libtlsf.a | ||
11 | TLSFLIB_SRC := $(call preprocess, $(APPSDIR)/codecs/lib/tlsf/SOURCES) | ||
12 | TLSFLIB_OBJ := $(call c2obj, $(TLSFLIB_SRC)) | ||
13 | OTHER_SRC += $(TLSFLIB_SRC) | ||
14 | |||
15 | $(TLSFLIB): $(TLSFLIB_OBJ) | ||
16 | $(SILENT)$(shell rm -f $@) | ||
17 | $(call PRINTS,AR $(@F))$(AR) rcs $@ $^ >/dev/null | ||
18 | |||
19 | TLSFLIBFLAGS = $(CODECFLAGS) -ffunction-sections | ||
20 | |||
21 | ifdef SIMVER | ||
22 | TLSFLIBFLAGS += -DTLSF_STATISTIC=1 | ||
23 | endif | ||
24 | |||
25 | $(CODECDIR)/lib/tlsf/src/%.o: $(APPSDIR)/codecs/lib/tlsf/src/%.c | ||
26 | $(SILENT)mkdir -p $(dir $@) | ||
27 | $(call PRINTS,CC $(subst $(ROOTDIR)/,,$<))$(CC) \ | ||
28 | -I$(dir $<) $(TLSFLIBFLAGS) -c $< -o $@ | ||
diff --git a/apps/codecs/libtremor/block.c b/apps/codecs/libtremor/block.c index 3947b90239..8a461e325f 100644 --- a/apps/codecs/libtremor/block.c +++ b/apps/codecs/libtremor/block.c | |||
@@ -283,7 +283,7 @@ void vorbis_dsp_clear(vorbis_dsp_state *v){ | |||
283 | codec_setup_info *ci=(codec_setup_info *)(vi?vi->codec_setup:NULL); | 283 | codec_setup_info *ci=(codec_setup_info *)(vi?vi->codec_setup:NULL); |
284 | private_state *b=(private_state *)v->backend_state; | 284 | private_state *b=(private_state *)v->backend_state; |
285 | 285 | ||
286 | if(NULL == v->iram_double_pcm) | 286 | if(NULL == v->iram_double_pcm && vi != NULL) |
287 | { | 287 | { |
288 | /* pcm buffer came from oggmalloc rather than iram */ | 288 | /* pcm buffer came from oggmalloc rather than iram */ |
289 | for(i=0;i<vi->channels;i++) | 289 | for(i=0;i<vi->channels;i++) |
diff --git a/apps/codecs/libtremor/oggmalloc.c b/apps/codecs/libtremor/oggmalloc.c index 6da7cfcedc..3d60370641 100644 --- a/apps/codecs/libtremor/oggmalloc.c +++ b/apps/codecs/libtremor/oggmalloc.c | |||
@@ -1,85 +1,63 @@ | |||
1 | #include "os_types.h" | 1 | #include "os_types.h" |
2 | #include "../lib/tlsf/src/tlsf.h" | ||
2 | 3 | ||
3 | #if defined(CPU_ARM) || defined(CPU_COLDFIRE) | 4 | #if defined(CPU_ARM) || defined(CPU_COLDFIRE) || defined(CPU_MIPS) |
4 | #include <setjmp.h> | 5 | #include <setjmp.h> |
5 | extern jmp_buf rb_jump_buf; | 6 | extern jmp_buf rb_jump_buf; |
7 | #define LONGJMP(x) longjmp(rb_jump_buf, x) | ||
8 | #elif defined(SIMULATOR) | ||
9 | #define LONGJMP(x) do { DEBUGF("Vorbis: allocation failed!\n"); return NULL; } while (false) | ||
10 | #else | ||
11 | #define LONGJMP(x) return NULL | ||
6 | #endif | 12 | #endif |
7 | 13 | ||
8 | static size_t tmp_ptr; | ||
9 | |||
10 | void ogg_malloc_init(void) | 14 | void ogg_malloc_init(void) |
11 | { | 15 | { |
12 | mallocbuf = ci->codec_get_buffer(&bufsize); | 16 | size_t bufsize; |
13 | tmp_ptr = bufsize & ~3; | 17 | void* buf = ci->codec_get_buffer(&bufsize); |
14 | mem_ptr = 0; | 18 | init_memory_pool(bufsize, buf); |
15 | } | 19 | } |
16 | 20 | ||
17 | void *ogg_malloc(size_t size) | 21 | void ogg_malloc_destroy() |
18 | { | 22 | { |
19 | void* x; | 23 | size_t bufsize; |
20 | 24 | void* buf = ci->codec_get_buffer(&bufsize); | |
21 | size = (size + 3) & ~3; | 25 | destroy_memory_pool(buf); |
22 | |||
23 | if (mem_ptr + size > tmp_ptr) | ||
24 | #if defined(CPU_ARM) || defined(CPU_COLDFIRE) | ||
25 | longjmp(rb_jump_buf, 1); | ||
26 | #else | ||
27 | return NULL; | ||
28 | #endif | ||
29 | |||
30 | x = &mallocbuf[mem_ptr]; | ||
31 | mem_ptr += size; /* Keep memory 32-bit aligned */ | ||
32 | |||
33 | return x; | ||
34 | } | 26 | } |
35 | 27 | ||
36 | void *ogg_tmpmalloc(size_t size) | 28 | void *ogg_malloc(size_t size) |
37 | { | 29 | { |
38 | size = (size + 3) & ~3; | 30 | void* x = tlsf_malloc(size); |
39 | 31 | ||
40 | if (mem_ptr + size > tmp_ptr) | 32 | if (x == NULL) |
41 | return NULL; | 33 | LONGJMP(1); |
42 | 34 | ||
43 | tmp_ptr -= size; | 35 | return x; |
44 | return &mallocbuf[tmp_ptr]; | ||
45 | } | 36 | } |
46 | 37 | ||
47 | void *ogg_calloc(size_t nmemb, size_t size) | 38 | void *ogg_calloc(size_t nmemb, size_t size) |
48 | { | 39 | { |
49 | void *x; | 40 | void *x = tlsf_calloc(nmemb, size); |
50 | x = ogg_malloc(nmemb * size); | ||
51 | if (x == NULL) | ||
52 | return NULL; | ||
53 | ci->memset(x, 0, nmemb * size); | ||
54 | return x; | ||
55 | } | ||
56 | 41 | ||
57 | void *ogg_tmpcalloc(size_t nmemb, size_t size) | ||
58 | { | ||
59 | void *x; | ||
60 | x = ogg_tmpmalloc(nmemb * size); | ||
61 | if (x == NULL) | 42 | if (x == NULL) |
62 | return NULL; | 43 | LONGJMP(1); |
63 | ci->memset(x, 0, nmemb * size); | 44 | |
64 | return x; | 45 | return x; |
65 | } | 46 | } |
66 | 47 | ||
67 | void *ogg_realloc(void *ptr, size_t size) | 48 | void *ogg_realloc(void *ptr, size_t size) |
68 | { | 49 | { |
69 | void *x; | 50 | void *x = tlsf_realloc(ptr, size); |
70 | (void)ptr; | ||
71 | x = ogg_malloc(size); | ||
72 | return x; | ||
73 | } | ||
74 | 51 | ||
75 | long ogg_tmpmalloc_pos(void) | 52 | if (x == NULL) |
76 | { | 53 | LONGJMP(1); |
77 | return tmp_ptr; | 54 | |
55 | return x; | ||
78 | } | 56 | } |
79 | 57 | ||
80 | void ogg_tmpmalloc_free(long pos) | 58 | void ogg_free(void* ptr) |
81 | { | 59 | { |
82 | tmp_ptr = pos; | 60 | tlsf_free(ptr); |
83 | } | 61 | } |
84 | 62 | ||
85 | /* Allocate IRAM buffer */ | 63 | /* Allocate IRAM buffer */ |
diff --git a/apps/codecs/libtremor/os_types.h b/apps/codecs/libtremor/os_types.h index 4c7d17ef3a..337c055d54 100644 --- a/apps/codecs/libtremor/os_types.h +++ b/apps/codecs/libtremor/os_types.h | |||
@@ -38,16 +38,14 @@ | |||
38 | #define _ogg_malloc ogg_malloc | 38 | #define _ogg_malloc ogg_malloc |
39 | #define _ogg_calloc ogg_calloc | 39 | #define _ogg_calloc ogg_calloc |
40 | #define _ogg_realloc ogg_realloc | 40 | #define _ogg_realloc ogg_realloc |
41 | #define _ogg_free(x) do { } while(0) | 41 | #define _ogg_free ogg_free |
42 | 42 | ||
43 | void ogg_malloc_init(void); | 43 | void ogg_malloc_init(void); |
44 | void ogg_malloc_destroy(void); | ||
44 | void *ogg_malloc(size_t size); | 45 | void *ogg_malloc(size_t size); |
45 | void *ogg_tmpmalloc(size_t size); | ||
46 | void *ogg_calloc(size_t nmemb, size_t size); | 46 | void *ogg_calloc(size_t nmemb, size_t size); |
47 | void *ogg_tmpcalloc(size_t nmemb, size_t size); | ||
48 | void *ogg_realloc(void *ptr, size_t size); | 47 | void *ogg_realloc(void *ptr, size_t size); |
49 | long ogg_tmpmalloc_pos(void); | 48 | void ogg_free(void *ptr); |
50 | void ogg_tmpmalloc_free(long pos); | ||
51 | void iram_malloc_init(void); | 49 | void iram_malloc_init(void); |
52 | void *iram_malloc(size_t size); | 50 | void *iram_malloc(size_t size); |
53 | 51 | ||
diff --git a/apps/codecs/libtremor/sharedbook.c b/apps/codecs/libtremor/sharedbook.c index edabf3ccb3..853d1f5d61 100644 --- a/apps/codecs/libtremor/sharedbook.c +++ b/apps/codecs/libtremor/sharedbook.c | |||
@@ -71,7 +71,7 @@ static ogg_int32_t _float32_unpack(long val,int *point){ | |||
71 | static ogg_uint32_t *_make_words(long *l,long n,long sparsecount){ | 71 | static ogg_uint32_t *_make_words(long *l,long n,long sparsecount){ |
72 | long i,j,count=0; | 72 | long i,j,count=0; |
73 | ogg_uint32_t marker[33]; | 73 | ogg_uint32_t marker[33]; |
74 | ogg_uint32_t *r=(ogg_uint32_t *)ogg_tmpmalloc((sparsecount?sparsecount:n)*sizeof(*r)); | 74 | ogg_uint32_t *r=(ogg_uint32_t *)_ogg_malloc((sparsecount?sparsecount:n)*sizeof(*r)); |
75 | memset(marker,0,sizeof(marker)); | 75 | memset(marker,0,sizeof(marker)); |
76 | 76 | ||
77 | for(i=0;i<n;i++){ | 77 | for(i=0;i<n;i++){ |
@@ -87,7 +87,7 @@ static ogg_uint32_t *_make_words(long *l,long n,long sparsecount){ | |||
87 | /* update ourself */ | 87 | /* update ourself */ |
88 | if(length<32 && (entry>>length)){ | 88 | if(length<32 && (entry>>length)){ |
89 | /* error condition; the lengths must specify an overpopulated tree */ | 89 | /* error condition; the lengths must specify an overpopulated tree */ |
90 | /* _ogg_free(r); */ | 90 | _ogg_free(r); |
91 | return(NULL); | 91 | return(NULL); |
92 | } | 92 | } |
93 | r[count++]=entry; | 93 | r[count++]=entry; |
@@ -188,9 +188,8 @@ static ogg_int32_t *_book_unquantize(const static_codebook *b,int n, | |||
188 | ogg_int32_t mindel=_float32_unpack(b->q_min,&minpoint); | 188 | ogg_int32_t mindel=_float32_unpack(b->q_min,&minpoint); |
189 | ogg_int32_t delta=_float32_unpack(b->q_delta,&delpoint); | 189 | ogg_int32_t delta=_float32_unpack(b->q_delta,&delpoint); |
190 | ogg_int32_t *r=(ogg_int32_t *)_ogg_calloc(n*b->dim,sizeof(*r)); | 190 | ogg_int32_t *r=(ogg_int32_t *)_ogg_calloc(n*b->dim,sizeof(*r)); |
191 | int *rp=(int *)ogg_tmpcalloc(n*b->dim,sizeof(*rp)); | 191 | int *rp=(int *)_ogg_calloc(n*b->dim,sizeof(*rp)); |
192 | 192 | ||
193 | memset(rp, 0, n*b->dim*sizeof(*rp)); | ||
194 | *maxpoint=minpoint; | 193 | *maxpoint=minpoint; |
195 | 194 | ||
196 | /* maptype 1 and 2 both use a quantized value vector, but | 195 | /* maptype 1 and 2 both use a quantized value vector, but |
@@ -277,7 +276,7 @@ static ogg_int32_t *_book_unquantize(const static_codebook *b,int n, | |||
277 | if(rp[j]<*maxpoint) | 276 | if(rp[j]<*maxpoint) |
278 | r[j]>>=*maxpoint-rp[j]; | 277 | r[j]>>=*maxpoint-rp[j]; |
279 | 278 | ||
280 | /* _ogg_free(rp); */ | 279 | _ogg_free(rp); |
281 | return(r); | 280 | return(r); |
282 | } | 281 | } |
283 | return(NULL); | 282 | return(NULL); |
@@ -325,7 +324,6 @@ static int sort32a(const void *a,const void *b){ | |||
325 | int vorbis_book_init_decode(codebook *c,const static_codebook *s){ | 324 | int vorbis_book_init_decode(codebook *c,const static_codebook *s){ |
326 | int i,j,n=0,tabn; | 325 | int i,j,n=0,tabn; |
327 | int *sortindex; | 326 | int *sortindex; |
328 | long pos = ogg_tmpmalloc_pos(); | ||
329 | memset(c,0,sizeof(*c)); | 327 | memset(c,0,sizeof(*c)); |
330 | 328 | ||
331 | /* count actually used entries */ | 329 | /* count actually used entries */ |
@@ -350,9 +348,13 @@ int vorbis_book_init_decode(codebook *c,const static_codebook *s){ | |||
350 | 348 | ||
351 | /* perform sort */ | 349 | /* perform sort */ |
352 | ogg_uint32_t *codes=_make_words(s->lengthlist,s->entries,c->used_entries); | 350 | ogg_uint32_t *codes=_make_words(s->lengthlist,s->entries,c->used_entries); |
353 | ogg_uint32_t **codep=(ogg_uint32_t **)ogg_tmpmalloc(sizeof(*codep)*n); | 351 | ogg_uint32_t **codep=(ogg_uint32_t **)_ogg_malloc(sizeof(*codep)*n); |
354 | 352 | ||
355 | if(codes==NULL||codep==NULL)goto err_out; | 353 | if(codes==NULL||codep==NULL){ |
354 | _ogg_free(codep); | ||
355 | _ogg_free(codes); | ||
356 | goto err_out; | ||
357 | } | ||
356 | 358 | ||
357 | for(i=0;i<n;i++){ | 359 | for(i=0;i<n;i++){ |
358 | codes[i]=bitreverse(codes[i]); | 360 | codes[i]=bitreverse(codes[i]); |
@@ -361,7 +363,7 @@ int vorbis_book_init_decode(codebook *c,const static_codebook *s){ | |||
361 | 363 | ||
362 | qsort(codep,n,sizeof(*codep),sort32a); | 364 | qsort(codep,n,sizeof(*codep),sort32a); |
363 | 365 | ||
364 | sortindex=(int *)ogg_tmpmalloc(n*sizeof(*sortindex)); | 366 | sortindex=(int *)_ogg_malloc(n*sizeof(*sortindex)); |
365 | c->codelist=(ogg_uint32_t *)_ogg_malloc(n*sizeof(*c->codelist)); | 367 | c->codelist=(ogg_uint32_t *)_ogg_malloc(n*sizeof(*c->codelist)); |
366 | /* the index is a reverse index */ | 368 | /* the index is a reverse index */ |
367 | for(i=0;i<n;i++){ | 369 | for(i=0;i<n;i++){ |
@@ -371,7 +373,8 @@ int vorbis_book_init_decode(codebook *c,const static_codebook *s){ | |||
371 | 373 | ||
372 | for(i=0;i<n;i++) | 374 | for(i=0;i<n;i++) |
373 | c->codelist[sortindex[i]]=codes[i]; | 375 | c->codelist[sortindex[i]]=codes[i]; |
374 | /* _ogg_free(codes); */ | 376 | _ogg_free(codep); |
377 | _ogg_free(codes); | ||
375 | 378 | ||
376 | 379 | ||
377 | 380 | ||
@@ -387,6 +390,7 @@ int vorbis_book_init_decode(codebook *c,const static_codebook *s){ | |||
387 | if(s->lengthlist[i]>0) | 390 | if(s->lengthlist[i]>0) |
388 | c->dec_codelengths[sortindex[n++]]=s->lengthlist[i]; | 391 | c->dec_codelengths[sortindex[n++]]=s->lengthlist[i]; |
389 | 392 | ||
393 | _ogg_free(sortindex); | ||
390 | c->dec_firsttablen=_ilog(c->used_entries)-4; /* this is magic */ | 394 | c->dec_firsttablen=_ilog(c->used_entries)-4; /* this is magic */ |
391 | if(c->dec_firsttablen<5)c->dec_firsttablen=5; | 395 | if(c->dec_firsttablen<5)c->dec_firsttablen=5; |
392 | if(c->dec_firsttablen>8)c->dec_firsttablen=8; | 396 | if(c->dec_firsttablen>8)c->dec_firsttablen=8; |
@@ -434,10 +438,8 @@ int vorbis_book_init_decode(codebook *c,const static_codebook *s){ | |||
434 | } | 438 | } |
435 | } | 439 | } |
436 | 440 | ||
437 | ogg_tmpmalloc_free(pos); | ||
438 | return(0); | 441 | return(0); |
439 | err_out: | 442 | err_out: |
440 | ogg_tmpmalloc_free(pos); | ||
441 | vorbis_book_clear(c); | 443 | vorbis_book_clear(c); |
442 | return(-1); | 444 | return(-1); |
443 | } | 445 | } |
diff --git a/apps/codecs/vorbis.c b/apps/codecs/vorbis.c index f14aeead84..7e078139ce 100644 --- a/apps/codecs/vorbis.c +++ b/apps/codecs/vorbis.c | |||
@@ -22,10 +22,13 @@ | |||
22 | #include "codeclib.h" | 22 | #include "codeclib.h" |
23 | #include "libtremor/ivorbisfile.h" | 23 | #include "libtremor/ivorbisfile.h" |
24 | #include "libtremor/ogg.h" | 24 | #include "libtremor/ogg.h" |
25 | #ifdef SIMULATOR | ||
26 | #include "lib/tlsf/src/tlsf.h" | ||
27 | #endif | ||
25 | 28 | ||
26 | CODEC_HEADER | 29 | CODEC_HEADER |
27 | 30 | ||
28 | #if defined(CPU_ARM) || defined(CPU_COLDFIRE) | 31 | #if defined(CPU_ARM) || defined(CPU_COLDFIRE) || defined(CPU_MIPS) |
29 | #include <setjmp.h> | 32 | #include <setjmp.h> |
30 | jmp_buf rb_jump_buf; | 33 | jmp_buf rb_jump_buf; |
31 | #endif | 34 | #endif |
@@ -76,8 +79,7 @@ static long tell_handler(void *datasource) | |||
76 | } | 79 | } |
77 | 80 | ||
78 | /* This sets the DSP parameters based on the current logical bitstream | 81 | /* This sets the DSP parameters based on the current logical bitstream |
79 | * (sampling rate, number of channels, etc). It also tries to guess | 82 | * (sampling rate, number of channels, etc). |
80 | * reasonable buffer parameters based on the current quality setting. | ||
81 | */ | 83 | */ |
82 | static bool vorbis_set_codec_parameters(OggVorbis_File *vf) | 84 | static bool vorbis_set_codec_parameters(OggVorbis_File *vf) |
83 | { | 85 | { |
@@ -86,7 +88,6 @@ static bool vorbis_set_codec_parameters(OggVorbis_File *vf) | |||
86 | vi = ov_info(vf, -1); | 88 | vi = ov_info(vf, -1); |
87 | 89 | ||
88 | if (vi == NULL) { | 90 | if (vi == NULL) { |
89 | //ci->splash(HZ*2, "Vorbis Error"); | ||
90 | return false; | 91 | return false; |
91 | } | 92 | } |
92 | 93 | ||
@@ -120,27 +121,23 @@ enum codec_status codec_main(void) | |||
120 | ogg_int64_t vf_pcmlengths[2]; | 121 | ogg_int64_t vf_pcmlengths[2]; |
121 | 122 | ||
122 | ci->configure(DSP_SET_SAMPLE_DEPTH, 24); | 123 | ci->configure(DSP_SET_SAMPLE_DEPTH, 24); |
123 | /* Note: These are sane defaults for these values. Perhaps | ||
124 | * they should be set differently based on quality setting | ||
125 | */ | ||
126 | 124 | ||
127 | #if defined(CPU_ARM) || defined(CPU_COLDFIRE) | 125 | if (codec_init()) { |
128 | if (setjmp(rb_jump_buf) != 0) | 126 | error = CODEC_ERROR; |
129 | { | 127 | goto exit; |
128 | } | ||
129 | |||
130 | ogg_malloc_init(); | ||
131 | |||
132 | #if defined(CPU_ARM) || defined(CPU_COLDFIRE) || defined(CPU_MIPS) | ||
133 | if (setjmp(rb_jump_buf) != 0) { | ||
130 | /* malloc failed; skip to next track */ | 134 | /* malloc failed; skip to next track */ |
131 | error = CODEC_ERROR; | 135 | error = CODEC_ERROR; |
132 | goto done; | 136 | goto done; |
133 | } | 137 | } |
134 | #endif | 138 | #endif |
135 | 139 | ||
136 | /* We need to flush reserver memory every track load. */ | ||
137 | next_track: | 140 | next_track: |
138 | if (codec_init()) { | ||
139 | error = CODEC_ERROR; | ||
140 | goto exit; | ||
141 | } | ||
142 | ogg_malloc_init(); | ||
143 | |||
144 | while (!*ci->taginfo_ready && !ci->stop_codec) | 141 | while (!*ci->taginfo_ready && !ci->stop_codec) |
145 | ci->sleep(1); | 142 | ci->sleep(1); |
146 | 143 | ||
@@ -166,6 +163,10 @@ next_track: | |||
166 | * get here. | 163 | * get here. |
167 | */ | 164 | */ |
168 | if (!error) { | 165 | if (!error) { |
166 | ogg_free(vf.offsets); | ||
167 | ogg_free(vf.dataoffsets); | ||
168 | ogg_free(vf.serialnos); | ||
169 | |||
169 | vf.offsets = vf_offsets; | 170 | vf.offsets = vf_offsets; |
170 | vf.dataoffsets = &vf_dataoffsets; | 171 | vf.dataoffsets = &vf_dataoffsets; |
171 | vf.serialnos = &vf_serialnos; | 172 | vf.serialnos = &vf_serialnos; |
@@ -183,7 +184,7 @@ next_track: | |||
183 | vf.ready_state = OPENED; | 184 | vf.ready_state = OPENED; |
184 | vf.links = 1; | 185 | vf.links = 1; |
185 | } else { | 186 | } else { |
186 | //ci->logf("ov_open: %d", error); | 187 | DEBUGF("Vorbis: ov_open failed: %d", error); |
187 | error = CODEC_ERROR; | 188 | error = CODEC_ERROR; |
188 | goto done; | 189 | goto done; |
189 | } | 190 | } |
@@ -225,7 +226,7 @@ next_track: | |||
225 | if (n == 0) { | 226 | if (n == 0) { |
226 | eof = 1; | 227 | eof = 1; |
227 | } else if (n < 0) { | 228 | } else if (n < 0) { |
228 | DEBUGF("Error decoding frame\n"); | 229 | DEBUGF("Vorbis: Error decoding frame\n"); |
229 | } else { | 230 | } else { |
230 | ci->pcmbuf_insert(pcm[0], pcm[1], n); | 231 | ci->pcmbuf_insert(pcm[0], pcm[1], n); |
231 | ci->set_offset(ov_raw_tell(&vf)); | 232 | ci->set_offset(ov_raw_tell(&vf)); |
@@ -235,6 +236,15 @@ next_track: | |||
235 | error = CODEC_OK; | 236 | error = CODEC_OK; |
236 | 237 | ||
237 | done: | 238 | done: |
239 | #if 0 /* defined(SIMULATOR) */ | ||
240 | { | ||
241 | size_t bufsize; | ||
242 | void* buf = ci->codec_get_buffer(&bufsize); | ||
243 | |||
244 | DEBUGF("Vorbis: Memory max: %u\n", get_max_size(buf)); | ||
245 | } | ||
246 | #endif | ||
247 | |||
238 | if (ci->request_next_track()) { | 248 | if (ci->request_next_track()) { |
239 | /* Clean things up for the next track */ | 249 | /* Clean things up for the next track */ |
240 | vf.dataoffsets = NULL; | 250 | vf.dataoffsets = NULL; |
@@ -246,6 +256,6 @@ done: | |||
246 | } | 256 | } |
247 | 257 | ||
248 | exit: | 258 | exit: |
259 | ogg_malloc_destroy(); | ||
249 | return error; | 260 | return error; |
250 | } | 261 | } |
251 | |||