A few minor cleanups.
[pwmd.git] / src / mem.c
blobf2641c2169551767a5228f155480d97812ed9d71
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 #ifdef DEBUG
31 #include <execinfo.h>
33 #define BACKTRACE(fn) { \
34 int n, nptrs; \
35 char **strings; \
36 void *buffer[20]; \
37 nptrs = backtrace(buffer, 20); \
38 strings = backtrace_symbols(buffer, nptrs); \
39 for (n = 0; n < nptrs; n++) \
40 fprintf(stderr, "BACKTRACE (%s) %i: %s\n", fn, n, strings[n]); \
41 fprintf(stderr, "\n"); \
42 fflush(stderr); \
44 #else
45 #define BACKTRACE(fn)
46 #endif
48 #include "mem.h"
50 #ifdef USE_PTH_THREADS
51 #include <pth.h>
52 #else
53 #include <pthread.h>
54 #endif
56 #include "gettext.h"
57 #define N_(msgid) gettext(msgid)
59 static struct memlist_s *memlist;
60 #ifdef USE_PTH_THREADS
61 static pth_mutex_t mem_mutex;
62 #else
63 static pthread_mutex_t mem_mutex;
64 #endif
65 #ifdef DEBUG
66 static size_t allocations, deallocations;
67 #endif
69 void xmem_init()
71 static int init;
73 if (!init)
74 #ifdef USE_PTH_THREADS
75 pth_mutex_init(&mem_mutex);
76 #else
77 pthread_mutex_init(&mem_mutex, NULL);
78 #endif
80 init = 1;
83 static int memlist_remove(void *ptr, const char *func)
85 struct memlist_s *m, *last = NULL, *p;
87 #ifdef USE_PTH_THREADS
88 pth_mutex_acquire(&mem_mutex, FALSE, NULL);
89 #else
90 pthread_mutex_lock(&mem_mutex);
91 #endif
93 for (m = memlist; m; m = m->next) {
94 if (m->ptr == ptr) {
95 #ifdef DEBUG
96 fprintf(stderr, "%s: %p %i\n", func, ptr, m->size);
97 #endif
98 memset(m->ptr, 0, m->size);
99 free(m->ptr);
101 p = m->next;
102 free(m);
103 #ifdef DEBUG
104 deallocations++;
105 #endif
107 if (last)
108 last->next = p;
109 else
110 memlist = p;
112 #ifdef USE_PTH_THREADS
113 pth_mutex_release(&mem_mutex);
114 #else
115 pthread_mutex_unlock(&mem_mutex);
116 #endif
117 return 1;
120 last = m;
123 #ifdef USE_PTH_THREADS
124 pth_mutex_release(&mem_mutex);
125 #else
126 pthread_mutex_unlock(&mem_mutex);
127 #endif
128 return 0;
131 static void memlist_prepend(struct memlist_s *new)
133 #ifdef USE_PTH_THREADS
134 pth_mutex_acquire(&mem_mutex, FALSE, NULL);
135 #else
136 pthread_mutex_lock(&mem_mutex);
137 #endif
138 #ifdef DEBUG
139 allocations++;
140 #endif
141 new->next = memlist;
142 memlist = new;
143 #ifdef USE_PTH_THREADS
144 pth_mutex_release(&mem_mutex);
145 #else
146 pthread_mutex_unlock(&mem_mutex);
147 #endif
150 void xfree(void *ptr)
152 if (!ptr)
153 return;
155 if (!memlist_remove(ptr, __FUNCTION__)) {
156 warnx(N_("%s: %p not found"), __FUNCTION__, ptr);
157 assert(0);
161 void *xmalloc(size_t size)
163 void *p;
164 struct memlist_s *m;
166 if ((m = (struct memlist_s *)malloc(sizeof(struct memlist_s))) == NULL)
167 return NULL;
169 if ((p = (void *)malloc(size)) == NULL) {
170 free(m);
171 return NULL;
174 m->ptr = p;
175 m->size = size;
176 memlist_prepend(m);
177 #ifdef DEBUG
178 fprintf(stderr, "%s: %p %i\n", __FUNCTION__, p, size);
179 BACKTRACE(__FUNCTION__);
180 #endif
181 return m->ptr;
184 void *xcalloc(size_t nmemb, size_t size)
186 void *p;
187 struct memlist_s *m;
189 if ((m = (struct memlist_s *)malloc(sizeof(struct memlist_s))) == NULL)
190 return NULL;
192 if ((p = calloc(nmemb, size)) == NULL) {
193 free(m);
194 return NULL;
197 m->ptr = p;
198 m->size = nmemb * size;
199 memlist_prepend(m);
200 #ifdef DEBUG
201 fprintf(stderr, "%s: %p %i\n", __FUNCTION__, p, nmemb * size);
202 BACKTRACE(__FUNCTION__);
203 #endif
204 return m->ptr;
207 void *xrealloc(void *ptr, size_t size)
209 void *p;
210 struct memlist_s *m;
212 if (!size && ptr) {
213 xfree(ptr);
214 return NULL;
217 if (!ptr)
218 return xmalloc(size);
220 #ifdef USE_PTH_THREADS
221 pth_mutex_acquire(&mem_mutex, FALSE, NULL);
222 #else
223 pthread_mutex_lock(&mem_mutex);
224 #endif
226 for (m = memlist; m; m = m->next) {
227 if (m->ptr == ptr) {
228 if ((p = (void *)malloc(size)) == NULL) {
229 #ifdef USE_PTH_THREADS
230 pth_mutex_release(&mem_mutex);
231 #else
232 pthread_mutex_unlock(&mem_mutex);
233 #endif
234 return NULL;
237 memcpy(p, m->ptr, size < m->size ? size : m->size);
238 memset(m->ptr, 0, m->size);
239 free(m->ptr);
240 m->ptr = p;
241 m->size = size;
242 #ifdef DEBUG
243 fprintf(stderr, "%s: %p %i\n", __FUNCTION__, p, size);
244 BACKTRACE(__FUNCTION__);
245 #endif
246 #ifdef USE_PTH_THREADS
247 pth_mutex_release(&mem_mutex);
248 #else
249 pthread_mutex_unlock(&mem_mutex);
250 #endif
251 return m->ptr;
255 warnx(N_("%s: %p not found"), __FUNCTION__, ptr);
256 #ifdef USE_PTH_THREADS
257 pth_mutex_release(&mem_mutex);
258 #else
259 pthread_mutex_unlock(&mem_mutex);
260 #endif
261 assert(0);
262 return NULL;
265 char *xstrdup(const char *str)
267 char *t, *tp;
268 size_t len;
269 const char *p;
271 len = strlen(str) + 1;
273 if ((t = (char *)xmalloc(len * sizeof(char))) == NULL)
274 return NULL;
276 for (p = str, tp = t; *p; p++)
277 *tp++ = *p;
279 *tp = 0;
280 #ifdef DEBUG
281 fprintf(stderr, "%s: %p\n", __FUNCTION__, t);
282 BACKTRACE(__FUNCTION__);
283 #endif
284 return t;
287 void xpanic(void)
289 struct memlist_s *m;
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 = memlist)
298 xfree(m->ptr);
300 #ifdef USE_PTH_THREADS
301 pth_mutex_release(&mem_mutex);
302 #else
303 pthread_mutex_unlock(&mem_mutex);
304 #endif
307 #ifdef DEBUG
308 void xdump(void)
310 struct memlist_s *m;
311 size_t total = 0;
313 #ifdef USE_PTH_THREADS
314 pth_mutex_acquire(&mem_mutex, FALSE, NULL);
315 #else
316 pthread_mutex_lock(&mem_mutex);
317 #endif
319 for (m = memlist; m; m = m->next) {
320 fprintf(stderr, "%s: %p %i\n", __FUNCTION__, m->ptr, m->size);
321 total += m->size;
324 fprintf(stderr, "Total unfreed: %i bytes, allocations: %i, deallocations: %i\n", total,
325 allocations, deallocations);
326 #ifdef USE_PTH_THREADS
327 pth_mutex_release(&mem_mutex);
328 #else
329 pthread_mutex_unlock(&mem_mutex);
330 #endif
332 #endif