1 #ifndef XALLOC_H__ 2 #define XALLOC_H__ 1 3 4 #include "driver.h" 5 6 #include "strfuns.h" 7 #include "svalue.h" 8 9 /* --- Macros --- */ 10 11 /* void xallocate(void * dest, size_t size, const char * txt) 12 * Allocate <size> bytes using xalloc() and assign the pointer to <dest>. 13 * If the memory can't be allocated, call errorf() using an error message 14 * containing the description <txt> 15 */ 16 17 #define xallocate(dest,size,txt) \ 18 if (NULL == ((dest) = xalloc(size))) {\ 19 errorf("(%s:%d) Out of memory (%zu bytes) for %s\n"\ 20 , __FILE__, __LINE__, (size_t)(size), txt); \ 21 } else {} 22 23 24 /* void outofmemory(const char * txt) 25 * Throw an 'out of memory' error for an allocation of unknown size with the 26 * description <txt>. 27 * 28 * void outofmem(size_t size, const char * txt) 29 * Throw an 'out of memory' error for an allocation of <size> with the 30 * description <txt>. 31 * 32 * void outofmem1(size_t size, const char * txt, mixed arg) 33 * Like outofmem(), but allows for printf-style args. In return, txt must 34 * be a string literal. 35 * TODO: Add more macros like: outofmem_swap(ob), outofmem_fun(funname,len,txt), 36 * TODO:: outofmem_gen(txt but no length)..., then convert all out-of-mem 37 * TODO:: descriptions. 38 */ 39 40 #define outofmemory(txt) \ 41 errorf("(%s:%d) Out of memory for %s\n", __FILE__, __LINE__, txt) 42 43 #define outofmem(size,txt) \ 44 errorf("(%s:%d) Out of memory (%zu bytes) for %s\n"\ 45 , __FILE__, __LINE__, (size_t)(size), txt) 46 47 #define outofmem1(size,txt,arg1) \ 48 errorf("(%s:%d) Out of memory (%zu bytes) for " txt "\n"\ 49 , __FILE__, __LINE__, (size_t)(size), arg1) 50 51 52 /* void memsafe(void * expr, size_t size, const char * txt) 53 * <expr> is a memory allocating function (allocating roughly <size> bytes), 54 * returning a pointer. If this pointer is NULL, an 'out of memory' error 55 * is thrown using <txt> as description. 56 */ 57 58 #define memsafe(expr,size,txt) \ 59 do { \ 60 size_t memsafe_size = size; \ 61 if (NULL == (expr)) {\ 62 errorf("(%s:%d) Out of memory (%zu bytes) for %s\n"\ 63 , __FILE__, __LINE__, (size_t)(memsafe_size), txt); \ 64 } else {} \ 65 } while(0) 66 67 /* --- Constants --- */ 68 69 /* Allocation privilege levels */ 70 enum malloc_privileges { 71 MALLOC_USER = 0, 72 MALLOC_MASTER = 1, 73 MALLOC_SYSTEM = 2, 74 }; 75 76 /* memory limits */ 77 enum memory_limit_types { 78 MALLOC_SOFT_LIMIT = 1, 79 MALLOC_HARD_LIMIT = 2, 80 }; 81 /* low memory conditions */ 82 enum low_memory_conditions { 83 NO_MALLOC_LIMIT_EXCEEDED = 0, 84 SOFT_MALLOC_LIMIT_EXCEEDED = MALLOC_SOFT_LIMIT, 85 HARD_MALLOC_LIMIT_EXCEEDED = MALLOC_HARD_LIMIT, 86 }; 87 /* Flags for available reserves */ 88 enum available_reserve_flags { 89 USER_RESERVE_AVAILABLE = 0x1, 90 MASTER_RESERVE_AVAILABLE = 0x2, 91 SYSTEM_RESERVE_AVAILABLE = 0x4, 92 }; 93 94 /* --- Variables --- */ 95 96 extern Bool out_of_memory; 97 extern int malloc_privilege; 98 extern char *reserved_user_area; 99 extern char *reserved_master_area; 100 extern char *reserved_system_area; 101 extern mp_int reserved_user_size; 102 extern mp_int reserved_master_size; 103 extern mp_int reserved_system_size; 104 extern mp_int min_malloced; 105 extern mp_int min_small_malloced; 106 extern int stack_direction; 107 108 109 /* --- Prototypes --- */ 110 111 /* TODO: It would be nice to have a 'safe xalloc' which would either return 112 * TODO:: a pointer or throw an Out-of-memory error. Alas, with all the 113 * TODO:: local copies of inter_sp/inter_pc this is not so easy. 114 * TODO: Check what C99 says about free() and friends; if possible, exchange 115 * TODO:: all POINTER with void*. 116 */ 117 /* xalloc(): normal allocation 118 * xalloc_traced(): allocation with given file/line 119 * xalloc_pass(): allocation using MTRACE_PASS as file/line args 120 * 121 * Ditto for rexalloc(). 122 */ 123 124 #if defined(MALLOC_TRACE) 125 126 #define xalloc(size) xalloc_traced((size), __FILE__, __LINE__) 127 #define pxalloc(size) pxalloc_traced((size), __FILE__, __LINE__) 128 #define rexalloc(old, size) rexalloc_traced((old), (size), __FILE__, __LINE__) 129 #define prexalloc(old, size) prexalloc_traced((old), (size), __FILE__, __LINE__) 130 131 #else 132 133 #define xalloc(size) xalloc_traced(size) 134 #define pxalloc(size) pxalloc_traced(size) 135 #define rexalloc(old, size) rexalloc_traced((old), (size)) 136 #define prexalloc(old, size) prexalloc_traced((old), (size)) 137 138 #endif 139 140 #define xalloc_pass(size) xalloc_traced((size) MTRACE_PASS) 141 #define rexalloc_pass(old,size) rexalloc_traced((old),(size) MTRACE_PASS) 142 143 extern size_t xalloced_size (POINTER p) __attribute__((nonnull(1))); 144 extern size_t xalloc_overhead (void); 145 146 extern POINTER xalloc_traced(size_t size MTRACE_DECL) 147 MALLOC __attribute__ ((warn_unused_result)); 148 149 extern void xfree(POINTER); 150 151 extern POINTER rexalloc_traced(POINTER, size_t size MTRACE_DECL) 152 MALLOC __attribute__((warn_unused_result)); 153 154 extern POINTER pxalloc_traced(size_t size MTRACE_DECL) 155 MALLOC __attribute__ ((warn_unused_result)); 156 extern POINTER prexalloc_traced(POINTER, size_t size MTRACE_DECL) 157 MALLOC __attribute__((warn_unused_result)); 158 159 extern void pfree(POINTER); 160 extern void * malloc_increment_size (void *vp, size_t size) 161 __attribute__((nonnull(1))); 162 163 #ifdef GC_SUPPORT 164 extern void x_clear_ref (POINTER p) __attribute__((nonnull(1))); 165 extern int x_mark_ref (POINTER p) __attribute__((nonnull(1))); 166 extern Bool x_test_ref (POINTER p) __attribute__((nonnull(1))); 167 #endif /* GC_SUPPORT */ 168 169 #ifdef MALLOC_TRACE 170 extern void store_print_block_dispatch_info(void *block, void (*func)(int, void *, int) ); 171 extern Bool is_freed(void *p, p_uint minsize) __attribute__((nonnull(1))); 172 #endif /* MALLOC_TRACE */ 173 174 #ifdef CHECK_OBJECT_GC_REF 175 extern void note_object_allocation_info ( void *block ) __attribute__((nonnull(1))); 176 extern void note_program_allocation_info ( void *block ) __attribute__((nonnull(1))); 177 extern Bool is_object_allocation ( void *block ) __attribute__((nonnull(1))); 178 extern Bool is_program_allocation ( void *block ) __attribute__((nonnull(1))); 179 #endif /* CHECK_OBJECT_RC_REF */ 180 181 /* Functions directly exported from the allocator: */ 182 183 extern void mem_dump_data(strbuf_t *sbuf) __attribute__((nonnull(1))); 184 extern void mem_dump_extdata(strbuf_t *sbuf) __attribute__((nonnull(1))); 185 extern void mem_dinfo_data(svalue_t *svp, int value) __attribute__((nonnull(1))); 186 extern void mem_consolidate (Bool force); 187 extern Bool mem_dump_memory(int fd); 188 #ifdef MALLOC_EXT_STATISTICS 189 extern void mem_update_stats(void); 190 #endif /* MALLOC_EXT_STATISTICS */ 191 192 #ifdef GC_SUPPORT 193 extern void mem_clear_ref_flags(void); 194 extern void mem_free_unrefed_memory(void); 195 #endif /* GC_SUPPORT */ 196 197 /* --- Associated functions --- */ 198 199 #if defined(MALLOC_TRACE) 200 #define string_copy(s) string_copy_traced(s, __FILE__ "::string_copy", __LINE__) 201 #else 202 #define string_copy(s) string_copy_traced(s) 203 #endif 204 205 extern char * string_copy_traced(const char *str MTRACE_DECL) MALLOC 206 __attribute__((nonnull(1))) __attribute__((warn_unused_result)); 207 extern void dump_lpc_trace (int d, void *p) __attribute__((nonnull(2))); 208 extern void dump_malloc_trace (int d, void *adr) __attribute__((nonnull(2))); 209 210 extern void get_stack_direction (void); 211 extern void assert_stack_gap(void); 212 extern void reserve_memory (void); 213 extern void reallocate_reserved_areas(void); 214 extern void check_for_soft_malloc_limit(void); 215 extern void notify_lowmemory_condition(enum memory_limit_types what); 216 217 extern Bool set_memory_limit(enum memory_limit_types what, mp_int limit); 218 extern mp_int get_memory_limit(enum memory_limit_types what); 219 220 #endif /* XALLOC_H__ */ 221