Commit | Line | Data |
---|---|---|
460b9539 | 1 | /* |
2 | * This file is part of DisOrder. | |
320598d4 | 3 | * Copyright (C) 2004, 2005, 2006, 2007 Richard Kettlewell |
460b9539 | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | |
6 | * it under the terms of the GNU General Public License as published by | |
7 | * the Free Software Foundation; either version 2 of the License, or | |
8 | * (at your option) any later version. | |
9 | * | |
10 | * This program is distributed in the hope that it will be useful, but | |
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | * General Public License for more details. | |
14 | * | |
15 | * You should have received a copy of the GNU General Public License | |
16 | * along with this program; if not, write to the Free Software | |
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 | |
18 | * USA | |
19 | */ | |
b5bafc5c RK |
20 | /** @file lib/mem.c |
21 | * @brief Memory management | |
22 | */ | |
460b9539 | 23 | |
05b75f8d | 24 | #include "common.h" |
460b9539 | 25 | |
320598d4 | 26 | #if GC |
460b9539 | 27 | #include <gc.h> |
320598d4 | 28 | #endif |
460b9539 | 29 | #include <errno.h> |
460b9539 | 30 | |
31 | #include "mem.h" | |
32 | #include "log.h" | |
33 | #include "printf.h" | |
34 | ||
35 | #include "disorder.h" | |
36 | ||
b5bafc5c RK |
37 | /** @brief Allocate and zero out |
38 | * @param n Number of bytes to allocate | |
39 | * @return Pointer to allocated memory, or 0 | |
40 | */ | |
460b9539 | 41 | static void *malloc_and_zero(size_t n) { |
42 | void *ptr = malloc(n); | |
43 | ||
44 | if(ptr) memset(ptr, 0, n); | |
45 | return ptr; | |
46 | } | |
47 | ||
320598d4 RK |
48 | #if GC |
49 | static void *(*do_malloc)(size_t) = GC_malloc; | |
50 | static void *(*do_realloc)(void *, size_t) = GC_realloc; | |
51 | static void *(*do_malloc_atomic)(size_t) = GC_malloc_atomic; | |
52 | static void (*do_free)(void *) = GC_free; | |
53 | #else | |
54 | static void *(*do_malloc)(size_t) = malloc_and_zero; | |
55 | static void *(*do_realloc)(void *, size_t) = realloc; | |
56 | static void *(*do_malloc_atomic)(size_t) = malloc; | |
57 | static void (*do_free)(void *) = free; | |
58 | #endif | |
59 | ||
b5bafc5c RK |
60 | /** @brief Initialize memory management |
61 | * | |
62 | * Must be called by all programs that use garbage collection. Define | |
63 | * @c ${DISORDER_GC} to @c no to suppress use of the collector | |
64 | * (e.g. for debugging purposes). | |
65 | */ | |
320598d4 RK |
66 | void mem_init(void) { |
67 | #if GC | |
460b9539 | 68 | const char *e; |
69 | ||
320598d4 | 70 | if(((e = getenv("DISORDER_GC")) && !strcmp(e, "no"))) { |
460b9539 | 71 | do_malloc = malloc_and_zero; |
72 | do_malloc_atomic = malloc; | |
73 | do_realloc = realloc; | |
74 | do_free = free; | |
433e561f | 75 | } else { |
460b9539 | 76 | GC_init(); |
433e561f | 77 | assert(GC_all_interior_pointers); |
78 | } | |
320598d4 | 79 | #endif |
460b9539 | 80 | } |
81 | ||
b5bafc5c RK |
82 | /** @brief Allocate memory |
83 | * @param n Bytes to allocate | |
84 | * @return Pointer to allocated memory | |
85 | * | |
86 | * Terminates the process on error. The allocated memory is always | |
87 | * 0-filled. | |
88 | */ | |
460b9539 | 89 | void *xmalloc(size_t n) { |
90 | void *ptr; | |
91 | ||
92 | if(!(ptr = do_malloc(n)) && n) | |
93 | fatal(errno, "error allocating memory"); | |
94 | return ptr; | |
95 | } | |
96 | ||
b5bafc5c RK |
97 | /** @brief Reallocate memory |
98 | * @param ptr Block to reallocated | |
99 | * @param n Bytes to allocate | |
100 | * @return Pointer to allocated memory | |
101 | * | |
102 | * Terminates the process on error. It is NOT guaranteed that any | |
103 | * additional memory allocated is 0-filled. | |
104 | */ | |
460b9539 | 105 | void *xrealloc(void *ptr, size_t n) { |
106 | if(!(ptr = do_realloc(ptr, n)) && n) | |
107 | fatal(errno, "error allocating memory"); | |
108 | return ptr; | |
109 | } | |
110 | ||
b5bafc5c RK |
111 | /** @brief Allocate memory |
112 | * @param count Number of objects to allocate | |
113 | * @param size Size of one object | |
114 | * @return Pointer to allocated memory | |
115 | * | |
116 | * Terminates the process on error. The allocated memory is always | |
117 | * 0-filled. | |
118 | */ | |
460b9539 | 119 | void *xcalloc(size_t count, size_t size) { |
120 | if(count > SIZE_MAX / size) | |
121 | fatal(0, "excessively large calloc"); | |
122 | return xmalloc(count * size); | |
123 | } | |
124 | ||
b5bafc5c RK |
125 | /** @brief Allocate memory |
126 | * @param n Bytes to allocate | |
127 | * @return Pointer to allocated memory | |
128 | * | |
129 | * Terminates the process on error. The allocated memory is not | |
130 | * guaranteed to be 0-filled and is not suitable for storing pointers | |
131 | * in. | |
132 | */ | |
460b9539 | 133 | void *xmalloc_noptr(size_t n) { |
134 | void *ptr; | |
135 | ||
136 | if(!(ptr = do_malloc_atomic(n)) && n) | |
137 | fatal(errno, "error allocating memory"); | |
138 | return ptr; | |
139 | } | |
140 | ||
b5bafc5c RK |
141 | /** @brief Reallocate memory |
142 | * @param ptr Block to reallocated | |
143 | * @param n Bytes to allocate | |
144 | * @return Pointer to allocated memory | |
145 | * | |
146 | * Terminates the processf on error. It is NOT guaranteed that any | |
147 | * additional memory allocated is 0-filled. The block must have been | |
148 | * allocated with xmalloc_noptr() (or xrealloc_noptr()) initially. | |
149 | */ | |
460b9539 | 150 | void *xrealloc_noptr(void *ptr, size_t n) { |
151 | if(ptr == 0) | |
152 | return xmalloc_noptr(n); | |
153 | if(!(ptr = do_realloc(ptr, n)) && n) | |
154 | fatal(errno, "error allocating memory"); | |
155 | return ptr; | |
156 | } | |
157 | ||
b5bafc5c RK |
158 | /** @brief Duplicate a string |
159 | * @param s String to copy | |
160 | * @return New copy of string | |
161 | * | |
162 | * This uses the equivalent of xmalloc_noptr() to allocate the new string. | |
163 | */ | |
460b9539 | 164 | char *xstrdup(const char *s) { |
165 | char *t; | |
166 | ||
167 | if(!(t = do_malloc_atomic(strlen(s) + 1))) | |
168 | fatal(errno, "error allocating memory"); | |
169 | return strcpy(t, s); | |
170 | } | |
171 | ||
b5bafc5c RK |
172 | /** @brief Duplicate a prefix of a string |
173 | * @param s String to copy | |
174 | * @param n Prefix of string to copy | |
175 | * @return New copy of string | |
176 | * | |
177 | * This uses the equivalent of xmalloc_noptr() to allocate the new string. | |
178 | * @p n must not exceed the length of the string. | |
179 | */ | |
460b9539 | 180 | char *xstrndup(const char *s, size_t n) { |
181 | char *t; | |
182 | ||
183 | if(!(t = do_malloc_atomic(n + 1))) | |
184 | fatal(errno, "error allocating memory"); | |
185 | memcpy(t, s, n); | |
186 | t[n] = 0; | |
187 | return t; | |
188 | } | |
189 | ||
b5bafc5c RK |
190 | /** @brief Free memory |
191 | * @param ptr Block to free or 0 | |
192 | */ | |
460b9539 | 193 | void xfree(void *ptr) { |
194 | do_free(ptr); | |
195 | } | |
196 | ||
197 | /* | |
198 | Local Variables: | |
199 | c-basic-offset:2 | |
200 | comment-column:40 | |
201 | End: | |
202 | */ |