1 /*
2 Copyright (C) 2001-2014, Parrot Foundation.
3
4 =head1 NAME
5
6 src/gc/alloc_memory.c - Memory allocation
7
8 =head1 DESCRIPTION
9
10 The memory (mem) API handles memory allocation,
11
12 Basically just a wrapper C<around malloc/calloc/realloc/free()> with an
13 setup function to initialize the memory pools.
14
15 =head2 Functions
16
17 =over 4
18
19 =cut
20
21 */
22
23 #include "parrot/parrot.h"
24 #include "parrot/memory.h"
25
26
27 #define PANIC_OUT_OF_MEM(size) panic_failed_allocation(__LINE__, (size))
28 #define PANIC_ZERO_ALLOCATION(func) panic_zero_byte_allocation(__LINE__, (func))
29
30 #ifndef DETAIL_MEMORY_DEBUG
31 # define MEMORY_DEBUG_DETAIL_2(s, a1, a2)
32 #else
33 # define MEMORY_DEBUG_DETAIL_2(s, a1, a2) \
34 fprintf(stderr, (s), (a1), (a2))
35 #endif
36
37 /* HEADERIZER HFILE: include/parrot/memory.h */
38 /* HEADERIZER BEGIN: static */
39 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
40
41 PARROT_DOES_NOT_RETURN
42 static void panic_failed_allocation(unsigned int line, unsigned long size);
43
44 PARROT_DOES_NOT_RETURN
45 static void panic_zero_byte_allocation(
46 unsigned int line,
47 ARGIN(const char *func))
48 __attribute__nonnull__(2);
49
50 #define ASSERT_ARGS_panic_failed_allocation __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
51 #define ASSERT_ARGS_panic_zero_byte_allocation __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
52 PARROT_ASSERT_ARG(func))
53 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
54 /* HEADERIZER END: static */
55
56
57 /*
58
59 =item C<void * mem_sys_allocate(size_t size)>
60
61 Uses C<malloc> to allocate system memory. Panics if the system cannot
62 return memory, or if a zero-byte allocation is attempted.
63
64 =cut
65
66 */
67
68 PARROT_EXPORT
69 PARROT_MALLOC
70 PARROT_CANNOT_RETURN_NULL
71 void *
mem_sys_allocate(size_t size)72 mem_sys_allocate(size_t size)
73 {
74 ASSERT_ARGS(mem_sys_allocate)
75 void * const ptr = malloc(size);
76 if (size==0)
77 PANIC_ZERO_ALLOCATION("mem_sys_allocate");
78 MEMORY_DEBUG_DETAIL_2("Allocated %i at %p\n", size, ptr);
79 if (!ptr)
80 PANIC_OUT_OF_MEM(size);
81 return ptr;
82 }
83
84 /*
85
86 =item C<void * mem_sys_allocate_zeroed(size_t size)>
87
88 Uses C<calloc> to allocate system memory. Guaranteed to succeed, Panics
89 otherwise.
90
91 =cut
92
93 */
94
95 PARROT_EXPORT
96 PARROT_MALLOC
97 PARROT_CANNOT_RETURN_NULL
98 void *
mem_sys_allocate_zeroed(size_t size)99 mem_sys_allocate_zeroed(size_t size)
100 {
101 ASSERT_ARGS(mem_sys_allocate_zeroed)
102 void * const ptr = calloc(1, size);
103
104 if (size==0)
105 PANIC_ZERO_ALLOCATION("mem_sys_allocate_zeroed");
106 MEMORY_DEBUG_DETAIL_2("Allocated %i at %p\n", size, ptr);
107 if (!ptr)
108 PANIC_OUT_OF_MEM(size);
109 return ptr;
110 }
111
112 /*
113
114 =item C<void * mem_sys_realloc(void *from, size_t size)>
115
116 Resizes a chunk of memory. Unlike C<realloc>, it can handle a
117 NULL pointer, in which case it calls C<calloc> to create the memory
118 block.
119
120 =cut
121
122 */
123
124 PARROT_EXPORT
125 PARROT_MALLOC
126 PARROT_CANNOT_RETURN_NULL
127 void *
mem_sys_realloc(ARGFREE (void * from),size_t size)128 mem_sys_realloc(ARGFREE(void *from), size_t size)
129 {
130 ASSERT_ARGS(mem_sys_realloc)
131 void *ptr;
132 if (size==0)
133 PANIC_ZERO_ALLOCATION("mem_sys_realloc");
134 MEMORY_DEBUG_DETAIL_2("Freed %p (realloc -- %i bytes)\n", from, size);
135 if (from)
136 ptr = realloc(from, size);
137 else
138 ptr = calloc(1, size);
139 MEMORY_DEBUG_DETAIL_2("Allocated %i at %p\n", size, ptr);
140 if (!ptr)
141 PANIC_OUT_OF_MEM(size);
142 return ptr;
143 }
144
145
146 /*
147
148 =item C<void * mem_sys_realloc_zeroed(void *from, size_t size, size_t old_size)>
149
150 Resizes a chunk of system memory and fills the newly allocated space
151 with zeroes. If the pointer is C<NULL> a new memory block is
152 allocated and zeroed instead.
153
154 =cut
155
156 */
157
158 PARROT_EXPORT
159 PARROT_MALLOC
160 PARROT_CANNOT_RETURN_NULL
161 void *
mem_sys_realloc_zeroed(ARGFREE (void * from),size_t size,size_t old_size)162 mem_sys_realloc_zeroed(ARGFREE(void *from), size_t size, size_t old_size)
163 {
164 ASSERT_ARGS(mem_sys_realloc_zeroed)
165 void *ptr;
166 if (size==0)
167 PANIC_ZERO_ALLOCATION("mem_sys_realloc_zeroed");
168 MEMORY_DEBUG_DETAIL_2("Freed %p (realloc -- %i bytes)\n", from, size);
169 ptr = from ? realloc(from, size) : malloc(size);
170 MEMORY_DEBUG_DETAIL_2("Allocated %i at %p\n", size, ptr);
171 if (!ptr)
172 PANIC_OUT_OF_MEM(size);
173
174 if (size > old_size)
175 memset((char*)ptr + old_size, 0, size - old_size);
176
177 return ptr;
178 }
179
180 /*
181
182 =item C<void mem_sys_free(void *from)>
183
184 Frees a chunk of memory back to the system.
185
186 =cut
187
188 */
189
190 PARROT_EXPORT
191 void
mem_sys_free(ARGFREE (void * from))192 mem_sys_free(ARGFREE(void *from))
193 {
194 ASSERT_ARGS(mem_sys_free)
195 MEMORY_DEBUG_DETAIL_2("Freed %p%s\n", from, "");
196 if (from)
197 free(from);
198 }
199
200 /*
201
202 =item C<char * mem_sys_strndup(const char *src, size_t size)>
203
204 Copy a C string with supplied size to a new block of memory allocated with
205 mem_sys_allocate, that can be later deallocated with mem_sys_free.
206
207 =cut
208
209 */
210
211 PARROT_EXPORT
212 PARROT_MALLOC
213 PARROT_CANNOT_RETURN_NULL
214 char *
mem_sys_strndup(ARGIN (const char * src),size_t size)215 mem_sys_strndup(ARGIN(const char *src), size_t size)
216 {
217 ASSERT_ARGS(mem_sys_strndup)
218
219 char * const result = (char *)mem_sys_allocate(size + 1);
220 memcpy(result, src, size);
221 result[size] = '\0';
222 return result;
223 }
224
225 /*
226
227 =item C<char * mem_sys_strdup(const char *src)>
228
229 Copy a C string to a new block of memory allocated with mem_sys_allocate,
230 that can be later deallocated with mem_sys_free.
231
232 =cut
233
234 */
235
236 PARROT_EXPORT
237 PARROT_MALLOC
238 PARROT_CANNOT_RETURN_NULL
239 char *
mem_sys_strdup(ARGIN (const char * src))240 mem_sys_strdup(ARGIN(const char *src))
241 {
242 ASSERT_ARGS(mem_sys_strdup)
243
244 const size_t l = strlen(src);
245 char * const result = (char *)mem_sys_allocate(l + 1);
246 memcpy(result, src, l);
247 result[l] = '\0';
248 return result;
249 }
250
251 /*
252
253 =item C<static void panic_failed_allocation(unsigned int line, unsigned long
254 size)>
255
256 Print an error message and die.
257
258 =cut
259
260 */
261
262 PARROT_DOES_NOT_RETURN
263 static void
panic_failed_allocation(unsigned int line,unsigned long size)264 panic_failed_allocation(unsigned int line, unsigned long size)
265 {
266 ASSERT_ARGS(panic_failed_allocation)
267
268 fprintf(stderr, "Failed allocation of %lu bytes\n", size);
269 Parrot_x_panic_and_exit(NULL, "Out of mem", __FILE__, line);
270 }
271
272 /*
273
274 =item C<static void panic_zero_byte_allocation(unsigned int line, const char
275 *func)>
276
277 Print an error message and die.
278
279 =cut
280
281 */
282
283 PARROT_DOES_NOT_RETURN
284 static void
panic_zero_byte_allocation(unsigned int line,ARGIN (const char * func))285 panic_zero_byte_allocation(unsigned int line, ARGIN(const char *func))
286 {
287 ASSERT_ARGS(panic_zero_byte_allocation)
288
289 fprintf(stderr, "Zero-byte allocation not allowed in %s", func);
290 Parrot_x_panic_and_exit(NULL, "Out of mem", __FILE__, line);
291 }
292
293 /*
294
295 =back
296
297 =cut
298
299 */
300
301 /*
302 * Local variables:
303 * c-file-style: "parrot"
304 * End:
305 * vim: expandtab shiftwidth=4 cinoptions='\:2=2' :
306 */
307