Home | History | Annotate | Download | only in celt
      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 #if (!defined (VAR_ARRAYS) && !defined (USE_ALLOCA) && !defined (NONTHREADSAFE_PSEUDOSTACK))
     36 #error "Opus requires one of VAR_ARRAYS, USE_ALLOCA, or NONTHREADSAFE_PSEUDOSTACK be defined to select the temporary allocation mode."
     37 #endif
     38 
     39 #ifdef USE_ALLOCA
     40 # ifdef WIN32
     41 #  include <malloc.h>
     42 # else
     43 #  ifdef HAVE_ALLOCA_H
     44 #   include <alloca.h>
     45 #  else
     46 #   include <stdlib.h>
     47 #  endif
     48 # endif
     49 #endif
     50 
     51 /**
     52  * @def ALIGN(stack, size)
     53  *
     54  * Aligns the stack to a 'size' boundary
     55  *
     56  * @param stack Stack
     57  * @param size  New size boundary
     58  */
     59 
     60 /**
     61  * @def PUSH(stack, size, type)
     62  *
     63  * Allocates 'size' elements of type 'type' on the stack
     64  *
     65  * @param stack Stack
     66  * @param size  Number of elements
     67  * @param type  Type of element
     68  */
     69 
     70 /**
     71  * @def VARDECL(var)
     72  *
     73  * Declare variable on stack
     74  *
     75  * @param var Variable to declare
     76  */
     77 
     78 /**
     79  * @def ALLOC(var, size, type)
     80  *
     81  * Allocate 'size' elements of 'type' on stack
     82  *
     83  * @param var  Name of variable to allocate
     84  * @param size Number of elements
     85  * @param type Type of element
     86  */
     87 
     88 #if defined(VAR_ARRAYS)
     89 
     90 #define VARDECL(type, var)
     91 #define ALLOC(var, size, type) type var[size]
     92 #define SAVE_STACK
     93 #define RESTORE_STACK
     94 #define ALLOC_STACK
     95 
     96 #elif defined(USE_ALLOCA)
     97 
     98 #define VARDECL(type, var) type *var
     99 
    100 # ifdef WIN32
    101 #  define ALLOC(var, size, type) var = ((type*)_alloca(sizeof(type)*(size)))
    102 # else
    103 #  define ALLOC(var, size, type) var = ((type*)alloca(sizeof(type)*(size)))
    104 # endif
    105 
    106 #define SAVE_STACK
    107 #define RESTORE_STACK
    108 #define ALLOC_STACK
    109 
    110 #else
    111 
    112 #ifdef CELT_C
    113 char *global_stack=0;
    114 #else
    115 extern char *global_stack;
    116 #endif /* CELT_C */
    117 
    118 #ifdef ENABLE_VALGRIND
    119 
    120 #include <valgrind/memcheck.h>
    121 
    122 #ifdef CELT_C
    123 char *global_stack_top=0;
    124 #else
    125 extern char *global_stack_top;
    126 #endif /* CELT_C */
    127 
    128 #define ALIGN(stack, size) ((stack) += ((size) - (long)(stack)) & ((size) - 1))
    129 #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))))
    130 #define RESTORE_STACK ((global_stack = _saved_stack),VALGRIND_MAKE_MEM_NOACCESS(global_stack, global_stack_top-global_stack))
    131 #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;
    132 
    133 #else
    134 
    135 #define ALIGN(stack, size) ((stack) += ((size) - (long)(stack)) & ((size) - 1))
    136 #define PUSH(stack, size, type) (ALIGN((stack),sizeof(type)/sizeof(char)),(stack)+=(size)*(sizeof(type)/sizeof(char)),(type*)((stack)-(size)*(sizeof(type)/sizeof(char))))
    137 #define RESTORE_STACK (global_stack = _saved_stack)
    138 #define ALLOC_STACK char *_saved_stack; (global_stack = (global_stack==0) ? opus_alloc_scratch(GLOBAL_STACK_SIZE) : global_stack); _saved_stack = global_stack;
    139 
    140 #endif /* ENABLE_VALGRIND */
    141 
    142 #include "os_support.h"
    143 #define VARDECL(type, var) type *var
    144 #define ALLOC(var, size, type) var = PUSH(global_stack, size, type)
    145 #define SAVE_STACK char *_saved_stack = global_stack;
    146 
    147 #endif /* VAR_ARRAYS */
    148 
    149 
    150 #ifdef ENABLE_VALGRIND
    151 
    152 #include <valgrind/memcheck.h>
    153 #define OPUS_CHECK_ARRAY(ptr, len) VALGRIND_CHECK_MEM_IS_DEFINED(ptr, len*sizeof(*ptr))
    154 #define OPUS_CHECK_VALUE(value) VALGRIND_CHECK_VALUE_IS_DEFINED(value)
    155 #define OPUS_CHECK_ARRAY_COND(ptr, len) VALGRIND_CHECK_MEM_IS_DEFINED(ptr, len*sizeof(*ptr))
    156 #define OPUS_CHECK_VALUE_COND(value) VALGRIND_CHECK_VALUE_IS_DEFINED(value)
    157 #define OPUS_PRINT_INT(value) do {fprintf(stderr, #value " = %d at %s:%d\n", value, __FILE__, __LINE__);}while(0)
    158 #define OPUS_FPRINTF fprintf
    159 
    160 #else
    161 
    162 static inline int _opus_false(void) {return 0;}
    163 #define OPUS_CHECK_ARRAY(ptr, len) _opus_false()
    164 #define OPUS_CHECK_VALUE(value) _opus_false()
    165 #define OPUS_PRINT_INT(value) do{}while(0)
    166 #define OPUS_FPRINTF (void)
    167 
    168 #endif
    169 
    170 
    171 #endif /* STACK_ALLOC_H */
    172