1 // cl_alloca(). 2 3 #ifndef _CL_ALLOCA_H 4 #define _CL_ALLOCA_H 5 6 #include "base/cl_macros.h" 7 #include <cstdlib> 8 9 namespace cln { 10 11 // Allocating temporary data of arbitrary size. 12 // We prefer to allocate it on the stack instead of via malloc(), because 13 // that's fully inlinable and causes less cache misses. But the global stack 14 // size of applications is limited (typically 8 MB on Unix, 1 MB on Windows), 15 // and we don't want users of CLN to need to change these limits. Therefore 16 // we use stack allocation only for amounts < 64KB, and malloc() for larger 17 // blocks. 18 // Usage: 19 // {CL_ALLOCA_STACK; 20 // ... 21 // ... = cl_alloca(...); 22 // ... 23 // ... = cl_small_alloca(...); 24 // ... 25 // ... = cl_alloca(...); 26 // ... 27 // } 28 // CL_ALLOCA_STACK declares that use of cl_alloca() and cl_small_alloca() is 29 // possible. Then cl_alloca() and cl_small_alloca() can be used an arbitrary 30 // number of times to get room. 31 // The allocated room's extent ends at the end of the { ... } block. 32 // In every C function CL_ALLOCA_STACK should only called once. 33 // Because of a gcc bug, functions using these macros shouldn't be declared 34 // inline. 35 // cl_alloca(size) fetches a block of size bytes. 36 // cl_small_alloca(size) fetches a block of size bytes, with size < 65536. 37 // CL_SMALL_ALLOCA_STACK is similar to CL_ALLOCA_STACK, but allows only 38 // the use of cl_small_alloca(), not cl_alloca(). 39 40 // CL_ALLOCA_STACK creates a variable containing a linked list of pointers 41 // to be freed when the block is exited. 42 43 struct cl_alloca_header { 44 cl_alloca_header* next; 45 intptr_t usable_memory[1]; // "intptr_t" guarantees alignment 46 }; 47 48 extern cl_alloca_header* cl_alloc_alloca_header (size_t size); 49 extern void cl_free_alloca_header (cl_alloca_header* pointer); 50 51 class cl_alloca_stack { 52 cl_alloca_header* pointer; 53 public: cl_alloca_stack()54 cl_alloca_stack () { pointer = NULL; } ~cl_alloca_stack()55 ~cl_alloca_stack () { if (pointer) cl_free_alloca_header(pointer); } push(cl_alloca_header * p)56 void* push (cl_alloca_header* p) { p->next = pointer; pointer = p; return &p->usable_memory; } 57 }; 58 59 #define CL_ALLOCA_STACK \ 60 cl_alloca_stack _alloca_stack 61 62 #define CL_ALLOCA_MAX 65536 63 64 #if defined(__GNUC__) && !defined(__riscos) && !defined(__convex__) 65 #define cl_alloca(size) ((size) >= CL_ALLOCA_MAX ? _alloca_stack.push(cl_alloc_alloca_header(size)) : __builtin_alloca(size)) 66 #define cl_small_alloca(size) __builtin_alloca(size) 67 #define CL_SMALL_ALLOCA_STACK 68 #elif !defined(NO_ALLOCA) && !defined(__sparc__) && !defined(__sparc64__) 69 #define cl_alloca(size) ((size) >= CL_ALLOCA_MAX ? _alloca_stack.push(cl_alloc_alloca_header(size)) : alloca(size)) 70 #define cl_small_alloca(size) alloca(size) 71 #define CL_SMALL_ALLOCA_STACK 72 #else 73 #define cl_alloca(size) _alloca_stack.push(cl_alloc_alloca_header(size)) 74 #define cl_small_alloca(size) _alloca_stack.push(cl_alloc_alloca_header(size)) 75 #define CL_SMALL_ALLOCA_STACK CL_ALLOCA_STACK 76 #endif 77 78 // cl_alloc_array(type,size) 79 // cl_small_alloc_array(type,size) 80 // allocate an array with dynamic extent. 81 #define cl_alloc_array(arrayeltype,arraysize) \ 82 (arrayeltype*)cl_alloca((arraysize)*sizeof(arrayeltype)) 83 #define cl_small_alloc_array(arrayeltype,arraysize) \ 84 (arrayeltype*)cl_small_alloca((arraysize)*sizeof(arrayeltype)) 85 86 } // namespace cln 87 88 #endif /* _CL_ALLOCA_H */ 89