Made the custom memory (de)allocators C99 compliant.
[pwmd.git] / src / mem.c
blob7bd90067810254242fb7098c18a4211e77e13b76
1 /* vim:tw=78:ts=8:sw=4:set ft=c: */
2 /*
3 Copyright (C) 2006-2010 Ben Kibbey <bjk@luxsci.net>
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.
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.
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 02110-1301 USA
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <string.h>
23 #include <assert.h>
24 #include <err.h>
26 #ifdef HAVE_CONFIG_H
27 #include <config.h>
28 #endif
30 #include "mem.h"
32 #ifdef USE_PTH_THREADS
33 #include <pth.h>
34 #else
35 #include <pthread.h>
36 #endif
38 #include "gettext.h"
39 #define N_(msgid) gettext(msgid)
41 static struct memlist_s *memlist;
42 #ifdef USE_PTH_THREADS
43 static pth_mutex_t mem_mutex;
44 #else
45 static pthread_mutex_t mem_mutex;
46 #endif
47 #ifdef DEBUG
48 static size_t allocations, deallocations;
49 #endif
51 void xmem_init()
53 static int init;
55 if (!init)
56 #ifdef USE_PTH_THREADS
57 pth_mutex_init(&mem_mutex);
58 #else
59 pthread_mutex_init(&mem_mutex, NULL);
60 #endif
62 init = 1;
65 static int memlist_remove(void *ptr, const char *func)
67 struct memlist_s *m, *last = NULL, *p;
69 #ifdef USE_PTH_THREADS
70 pth_mutex_acquire(&mem_mutex, FALSE, NULL);
71 #else
72 pthread_mutex_lock(&mem_mutex);
73 #endif
75 for (m = memlist; m; m = m->next) {
76 if (m->ptr == ptr) {
77 #ifdef DEBUG
78 fprintf(stderr, "%s: %p %i\n", func, ptr, m->size);
79 #endif
80 memset(m->ptr, 0, m->size);
81 free(m->ptr);
83 p = m->next;
84 free(m);
85 #ifdef DEBUG
86 deallocations++;
87 #endif
89 if (last)
90 last->next = p;
91 else
92 memlist = p;
94 #ifdef USE_PTH_THREADS
95 pth_mutex_release(&mem_mutex);
96 #else
97 pthread_mutex_unlock(&mem_mutex);
98 #endif
99 return 1;
102 last = m;
105 #ifdef USE_PTH_THREADS
106 pth_mutex_release(&mem_mutex);
107 #else
108 pthread_mutex_unlock(&mem_mutex);
109 #endif
110 return 0;
113 static void memlist_prepend(struct memlist_s *new)
115 #ifdef USE_PTH_THREADS
116 pth_mutex_acquire(&mem_mutex, FALSE, NULL);
117 #else
118 pthread_mutex_lock(&mem_mutex);
119 #endif
120 #ifdef DEBUG
121 allocations++;
122 #endif
123 new->next = memlist;
124 memlist = new;
125 #ifdef USE_PTH_THREADS
126 pth_mutex_release(&mem_mutex);
127 #else
128 pthread_mutex_unlock(&mem_mutex);
129 #endif
132 void xfree(void *ptr)
134 if (!ptr)
135 return;
137 if (!memlist_remove(ptr, __FUNCTION__)) {
138 warnx(N_("%s: %p not found"), __FUNCTION__, ptr);
139 assert(0);
143 void *xmalloc(size_t size)
145 void *p;
146 struct memlist_s *m;
148 if ((m = (struct memlist_s *)malloc(sizeof(struct memlist_s))) == NULL)
149 return NULL;
151 if ((p = (void *)malloc(size)) == NULL) {
152 free(m);
153 return NULL;
156 m->ptr = p;
157 m->size = size;
158 memlist_prepend(m);
159 #ifdef DEBUG
160 fprintf(stderr, "%s: %p %i\n", __FUNCTION__, p, size);
161 #endif
162 return m->ptr;
165 void *xcalloc(size_t nmemb, size_t size)
167 void *p;
168 struct memlist_s *m;
170 if ((m = (struct memlist_s *)malloc(sizeof(struct memlist_s))) == NULL)
171 return NULL;
173 if ((p = calloc(nmemb, size)) == NULL) {
174 free(m);
175 return NULL;
178 m->ptr = p;
179 m->size = nmemb * size;
180 memlist_prepend(m);
181 #ifdef DEBUG
182 fprintf(stderr, "%s: %p %i\n", __FUNCTION__, p, nmemb * size);
183 #endif
184 return m->ptr;
187 void *xrealloc(void *ptr, size_t size)
189 void *p;
190 struct memlist_s *m;
192 if (!size && ptr) {
193 xfree(ptr);
194 return NULL;
197 if (!ptr)
198 return xmalloc(size);
200 #ifdef USE_PTH_THREADS
201 pth_mutex_acquire(&mem_mutex, FALSE, NULL);
202 #else
203 pthread_mutex_lock(&mem_mutex);
204 #endif
206 for (m = memlist; m; m = m->next) {
207 if (m->ptr == ptr) {
208 if ((p = (void *)malloc(size)) == NULL) {
209 #ifdef USE_PTH_THREADS
210 pth_mutex_release(&mem_mutex);
211 #else
212 pthread_mutex_unlock(&mem_mutex);
213 #endif
214 return NULL;
217 memcpy(p, m->ptr, size < m->size ? size : m->size);
218 memset(m->ptr, 0, m->size);
219 free(m->ptr);
220 m->ptr = p;
221 m->size = size;
222 #ifdef DEBUG
223 fprintf(stderr, "%s: %p %i\n", __FUNCTION__, p, size);
224 #endif
225 #ifdef USE_PTH_THREADS
226 pth_mutex_release(&mem_mutex);
227 #else
228 pthread_mutex_unlock(&mem_mutex);
229 #endif
230 return m->ptr;
234 warnx(N_("%s: %p not found"), __FUNCTION__, ptr);
235 #ifdef USE_PTH_THREADS
236 pth_mutex_release(&mem_mutex);
237 #else
238 pthread_mutex_unlock(&mem_mutex);
239 #endif
240 assert(0);
241 return NULL;
244 char *xstrdup(const char *str)
246 char *t, *tp;
247 size_t len;
248 const char *p;
250 len = strlen(str) + 1;
252 if ((t = (char *)xmalloc(len * sizeof(char))) == NULL)
253 return NULL;
255 for (p = str, tp = t; *p; p++)
256 *tp++ = *p;
258 *tp = 0;
259 #ifdef DEBUG
260 fprintf(stderr, "%s: %p\n", __FUNCTION__, t);
261 #endif
262 return t;
265 void xpanic(void)
267 struct memlist_s *m;
269 #ifdef USE_PTH_THREADS
270 pth_mutex_acquire(&mem_mutex, FALSE, NULL);
271 #else
272 pthread_mutex_lock(&mem_mutex);
273 #endif
275 for (m = memlist; m; m = memlist)
276 xfree(m->ptr);
278 #ifdef USE_PTH_THREADS
279 pth_mutex_release(&mem_mutex);
280 #else
281 pthread_mutex_unlock(&mem_mutex);
282 #endif
285 #ifdef DEBUG
286 void xdump(void)
288 struct memlist_s *m;
289 size_t total = 0;
291 #ifdef USE_PTH_THREADS
292 pth_mutex_acquire(&mem_mutex, FALSE, NULL);
293 #else
294 pthread_mutex_lock(&mem_mutex);
295 #endif
297 for (m = memlist; m; m = m->next) {
298 fprintf(stderr, "%s: %p %i\n", __FUNCTION__, m->ptr, m->size);
299 total += m->size;
302 fprintf(stderr, "Total unfreed: %i bytes, allocations: %i, deallocations: %i\n", total,
303 allocations, deallocations);
304 #ifdef USE_PTH_THREADS
305 pth_mutex_release(&mem_mutex);
306 #else
307 pthread_mutex_unlock(&mem_mutex);
308 #endif
310 #endif