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