Line data Source code
1 : /* Copyright (C) 2002-2003 Jean-Marc Valin
2 : Copyright (C) 2007-2009 Xiph.Org Foundation */
3 : /**
4 : @file stack_alloc.h
5 : @brief Temporary memory allocation on stack
6 : */
7 : /*
8 : Redistribution and use in source and binary forms, with or without
9 : modification, are permitted provided that the following conditions
10 : are met:
11 :
12 : - Redistributions of source code must retain the above copyright
13 : notice, this list of conditions and the following disclaimer.
14 :
15 : - Redistributions in binary form must reproduce the above copyright
16 : notice, this list of conditions and the following disclaimer in the
17 : documentation and/or other materials provided with the distribution.
18 :
19 : THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 : ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 : LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 : A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
23 : OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 : EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 : PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 : PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 : LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 : NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 : SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 : */
31 :
32 : #ifndef STACK_ALLOC_H
33 : #define STACK_ALLOC_H
34 :
35 : #include "opus_types.h"
36 : #include "opus_defines.h"
37 :
38 : #if (!defined (VAR_ARRAYS) && !defined (USE_ALLOCA) && !defined (NONTHREADSAFE_PSEUDOSTACK))
39 : #error "Opus requires one of VAR_ARRAYS, USE_ALLOCA, or NONTHREADSAFE_PSEUDOSTACK be defined to select the temporary allocation mode."
40 : #endif
41 :
42 : #ifdef USE_ALLOCA
43 : # ifdef WIN32
44 : # include <malloc.h>
45 : # else
46 : # ifdef HAVE_ALLOCA_H
47 : # include <alloca.h>
48 : # else
49 : # include <stdlib.h>
50 : # endif
51 : # endif
52 : #endif
53 :
54 : /**
55 : * @def ALIGN(stack, size)
56 : *
57 : * Aligns the stack to a 'size' boundary
58 : *
59 : * @param stack Stack
60 : * @param size New size boundary
61 : */
62 :
63 : /**
64 : * @def PUSH(stack, size, type)
65 : *
66 : * Allocates 'size' elements of type 'type' on the stack
67 : *
68 : * @param stack Stack
69 : * @param size Number of elements
70 : * @param type Type of element
71 : */
72 :
73 : /**
74 : * @def VARDECL(var)
75 : *
76 : * Declare variable on stack
77 : *
78 : * @param var Variable to declare
79 : */
80 :
81 : /**
82 : * @def ALLOC(var, size, type)
83 : *
84 : * Allocate 'size' elements of 'type' on stack
85 : *
86 : * @param var Name of variable to allocate
87 : * @param size Number of elements
88 : * @param type Type of element
89 : */
90 :
91 : #if defined(VAR_ARRAYS)
92 :
93 : #define VARDECL(type, var)
94 : #define ALLOC(var, size, type) type var[size]
95 : #define SAVE_STACK
96 : #define RESTORE_STACK
97 : #define ALLOC_STACK
98 : /* C99 does not allow VLAs of size zero */
99 : #define ALLOC_NONE 1
100 :
101 : #elif defined(USE_ALLOCA)
102 :
103 : #define VARDECL(type, var) type *var
104 :
105 : # ifdef WIN32
106 : # define ALLOC(var, size, type) var = ((type*)_alloca(sizeof(type)*(size)))
107 : # else
108 : # define ALLOC(var, size, type) var = ((type*)alloca(sizeof(type)*(size)))
109 : # endif
110 :
111 : #define SAVE_STACK
112 : #define RESTORE_STACK
113 : #define ALLOC_STACK
114 : #define ALLOC_NONE 0
115 :
116 : #else
117 :
118 : #ifdef CELT_C
119 : char *scratch_ptr=0;
120 : char *global_stack=0;
121 : #else
122 : extern char *global_stack;
123 : extern char *scratch_ptr;
124 : #endif /* CELT_C */
125 :
126 : #ifdef ENABLE_VALGRIND
127 :
128 : #include <valgrind/memcheck.h>
129 :
130 : #ifdef CELT_C
131 : char *global_stack_top=0;
132 : #else
133 : extern char *global_stack_top;
134 : #endif /* CELT_C */
135 :
136 : #define ALIGN(stack, size) ((stack) += ((size) - (long)(stack)) & ((size) - 1))
137 : #define PUSH(stack, size, type) (VALGRIND_MAKE_MEM_NOACCESS(stack, global_stack_top-stack),ALIGN((stack),sizeof(type)/sizeof(char)),VALGRIND_MAKE_MEM_UNDEFINED(stack, ((size)*sizeof(type)/sizeof(char))),(stack)+=(2*(size)*sizeof(type)/sizeof(char)),(type*)((stack)-(2*(size)*sizeof(type)/sizeof(char))))
138 : #define RESTORE_STACK ((global_stack = _saved_stack),VALGRIND_MAKE_MEM_NOACCESS(global_stack, global_stack_top-global_stack))
139 : #define ALLOC_STACK char *_saved_stack; ((global_stack = (global_stack==0) ? ((global_stack_top=opus_alloc_scratch(GLOBAL_STACK_SIZE*2)+(GLOBAL_STACK_SIZE*2))-(GLOBAL_STACK_SIZE*2)) : global_stack),VALGRIND_MAKE_MEM_NOACCESS(global_stack, global_stack_top-global_stack)); _saved_stack = global_stack;
140 :
141 : #else
142 :
143 : #define ALIGN(stack, size) ((stack) += ((size) - (long)(stack)) & ((size) - 1))
144 : #define PUSH(stack, size, type) (ALIGN((stack),sizeof(type)/sizeof(char)),(stack)+=(size)*(sizeof(type)/sizeof(char)),(type*)((stack)-(size)*(sizeof(type)/sizeof(char))))
145 : #if 0 /* Set this to 1 to instrument pseudostack usage */
146 : #define RESTORE_STACK (printf("%ld %s:%d\n", global_stack-scratch_ptr, __FILE__, __LINE__),global_stack = _saved_stack)
147 : #else
148 : #define RESTORE_STACK (global_stack = _saved_stack)
149 : #endif
150 : #define ALLOC_STACK char *_saved_stack; (global_stack = (global_stack==0) ? (scratch_ptr=opus_alloc_scratch(GLOBAL_STACK_SIZE)) : global_stack); _saved_stack = global_stack;
151 :
152 : #endif /* ENABLE_VALGRIND */
153 :
154 : #include "os_support.h"
155 : #define VARDECL(type, var) type *var
156 : #define ALLOC(var, size, type) var = PUSH(global_stack, size, type)
157 : #define SAVE_STACK char *_saved_stack = global_stack;
158 : #define ALLOC_NONE 0
159 :
160 : #endif /* VAR_ARRAYS */
161 :
162 :
163 : #ifdef ENABLE_VALGRIND
164 :
165 : #include <valgrind/memcheck.h>
166 : #define OPUS_CHECK_ARRAY(ptr, len) VALGRIND_CHECK_MEM_IS_DEFINED(ptr, len*sizeof(*ptr))
167 : #define OPUS_CHECK_VALUE(value) VALGRIND_CHECK_VALUE_IS_DEFINED(value)
168 : #define OPUS_CHECK_ARRAY_COND(ptr, len) VALGRIND_CHECK_MEM_IS_DEFINED(ptr, len*sizeof(*ptr))
169 : #define OPUS_CHECK_VALUE_COND(value) VALGRIND_CHECK_VALUE_IS_DEFINED(value)
170 : #define OPUS_PRINT_INT(value) do {fprintf(stderr, #value " = %d at %s:%d\n", value, __FILE__, __LINE__);}while(0)
171 : #define OPUS_FPRINTF fprintf
172 :
173 : #else
174 :
175 0 : static OPUS_INLINE int _opus_false(void) {return 0;}
176 : #define OPUS_CHECK_ARRAY(ptr, len) _opus_false()
177 : #define OPUS_CHECK_VALUE(value) _opus_false()
178 : #define OPUS_PRINT_INT(value) do{}while(0)
179 : #define OPUS_FPRINTF (void)
180 :
181 : #endif
182 :
183 :
184 : #endif /* STACK_ALLOC_H */
|