Fixed a potential memory leak with IMPORT.
[pwmd.git] / src / mem.c
blob72f188862b3ce25cee8f080f4aaf9e7c4367710f
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 (size <= 0)
149 return NULL;
151 if ((m = (struct memlist_s *)malloc(sizeof(struct memlist_s))) == NULL)
152 return NULL;
154 if ((p = (void *)malloc(size)) == NULL) {
155 free(m);
156 return NULL;
159 m->ptr = p;
160 m->size = size;
161 memlist_prepend(m);
162 #ifdef DEBUG
163 fprintf(stderr, "%s: %p %i\n", __FUNCTION__, p, size);
164 #endif
165 return m->ptr;
168 void *xcalloc(size_t nmemb, size_t size)
170 void *p;
171 struct memlist_s *m;
173 if (size <= 0)
174 return NULL;
176 if ((m = (struct memlist_s *)malloc(sizeof(struct memlist_s))) == NULL)
177 return NULL;
179 if ((p = calloc(nmemb, size)) == NULL) {
180 free(m);
181 return NULL;
184 m->ptr = p;
185 m->size = nmemb * size;
186 memlist_prepend(m);
187 #ifdef DEBUG
188 fprintf(stderr, "%s: %p %i\n", __FUNCTION__, p, nmemb * size);
189 #endif
190 return m->ptr;
193 void *xrealloc(void *ptr, size_t size)
195 void *p;
196 struct memlist_s *m;
198 if (size <= 0)
199 return ptr;
201 if (!ptr)
202 return xmalloc(size);
204 #ifdef USE_PTH_THREADS
205 pth_mutex_acquire(&mem_mutex, FALSE, NULL);
206 #else
207 pthread_mutex_lock(&mem_mutex);
208 #endif
210 for (m = memlist; m; m = m->next) {
211 if (m->ptr == ptr) {
212 if ((p = (void *)malloc(size)) == NULL) {
213 #ifdef USE_PTH_THREADS
214 pth_mutex_release(&mem_mutex);
215 #else
216 pthread_mutex_unlock(&mem_mutex);
217 #endif
218 return NULL;
221 memcpy(p, m->ptr, size < m->size ? size : m->size);
222 memset(m->ptr, 0, m->size);
223 free(m->ptr);
224 m->ptr = p;
225 m->size = size;
226 #ifdef DEBUG
227 fprintf(stderr, "%s: %p %i\n", __FUNCTION__, p, size);
228 #endif
229 #ifdef USE_PTH_THREADS
230 pth_mutex_release(&mem_mutex);
231 #else
232 pthread_mutex_unlock(&mem_mutex);
233 #endif
234 return m->ptr;
238 warnx(N_("%s: %p not found"), __FUNCTION__, ptr);
239 #ifdef USE_PTH_THREADS
240 pth_mutex_release(&mem_mutex);
241 #else
242 pthread_mutex_unlock(&mem_mutex);
243 #endif
244 assert(0);
245 return NULL;
248 char *xstrdup(const char *str)
250 char *t, *tp;
251 size_t len;
252 const char *p;
254 if (!str)
255 return NULL;
257 len = strlen(str) + 1;
259 if ((t = (char *)xmalloc(len * sizeof(char))) == NULL)
260 return NULL;
262 for (p = str, tp = t; *p; p++)
263 *tp++ = *p;
265 *tp = 0;
266 #ifdef DEBUG
267 fprintf(stderr, "%s: %p\n", __FUNCTION__, t);
268 #endif
269 return t;
272 void xpanic(void)
274 struct memlist_s *m;
276 #ifdef USE_PTH_THREADS
277 pth_mutex_acquire(&mem_mutex, FALSE, NULL);
278 #else
279 pthread_mutex_lock(&mem_mutex);
280 #endif
282 for (m = memlist; m; m = memlist)
283 xfree(m->ptr);
285 #ifdef USE_PTH_THREADS
286 pth_mutex_release(&mem_mutex);
287 #else
288 pthread_mutex_unlock(&mem_mutex);
289 #endif
292 #ifdef DEBUG
293 void xdump(void)
295 struct memlist_s *m;
296 size_t total = 0;
298 #ifdef USE_PTH_THREADS
299 pth_mutex_acquire(&mem_mutex, FALSE, NULL);
300 #else
301 pthread_mutex_lock(&mem_mutex);
302 #endif
304 for (m = memlist; m; m = m->next) {
305 fprintf(stderr, "%s: %p %i\n", __FUNCTION__, m->ptr, m->size);
306 total += m->size;
309 fprintf(stderr, "Total unfreed: %i bytes, allocations: %i, deallocations: %i\n", total,
310 allocations, deallocations);
311 #ifdef USE_PTH_THREADS
312 pth_mutex_release(&mem_mutex);
313 #else
314 pthread_mutex_unlock(&mem_mutex);
315 #endif
317 #endif