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