Change to the linux kernel coding style
[wmaker-crm.git] / WINGs / memory.c
1 /*
2  *  Window Maker miscelaneous function library
3  *
4  *  Copyright (c) 1997-2003 Alfredo K. Kojima
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20
21 #include "wconfig.h"
22 #include "WUtil.h"
23
24 #include <stdlib.h>
25 #include <sys/types.h>
26 #include <unistd.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <assert.h>
30 #include <signal.h>
31
32 #ifdef TEST_WITH_GC
33 #include <gc/gc.h>
34 #endif
35
36 #ifndef False
37 # define False 0
38 #endif
39 #ifndef True
40 # define True 1
41 #endif
42
43 static void defaultHandler(int bla)
44 {
45         if (bla)
46                 kill(getpid(), SIGABRT);
47         else
48                 exit(1);
49 }
50
51 static waborthandler *aborthandler = (waborthandler *) defaultHandler;
52
53 #define wAbort(a) (*aborthandler)(a)
54
55 waborthandler *wsetabort(waborthandler * handler)
56 {
57         waborthandler *old = aborthandler;
58
59         aborthandler = handler;
60
61         return old;
62 }
63
64 static int Aborting = 0;        /* if we're in the middle of an emergency exit */
65
66 static WMHashTable *table = NULL;
67
68 void *wmalloc(size_t size)
69 {
70         void *tmp;
71
72         assert(size > 0);
73
74 #ifdef TEST_WITH_GC
75         tmp = GC_malloc(size);
76 #else
77         tmp = malloc(size);
78 #endif
79         if (tmp == NULL) {
80                 wwarning("malloc() failed. Retrying after 2s.");
81                 sleep(2);
82 #ifdef TEST_WITH_GC
83                 tmp = GC_malloc(size);
84 #else
85                 tmp = malloc(size);
86 #endif
87                 if (tmp == NULL) {
88                         if (Aborting) {
89                                 fputs("Really Bad Error: recursive malloc() failure.", stderr);
90                                 exit(-1);
91                         } else {
92                                 wfatal("virtual memory exhausted");
93                                 Aborting = 1;
94                                 wAbort(False);
95                         }
96                 }
97         }
98         return tmp;
99 }
100
101 void *wmalloc0(size_t size)
102 {
103         void *ptr = wmalloc(size);
104         if (!ptr)
105                 return NULL;
106
107         memset(ptr, 0, size);
108
109         return ptr;
110 }
111
112 void *wrealloc(void *ptr, size_t newsize)
113 {
114         void *nptr;
115
116         if (!ptr) {
117                 nptr = wmalloc(newsize);
118         } else if (newsize == 0) {
119                 wfree(ptr);
120                 nptr = NULL;
121         } else {
122 #ifdef TEST_WITH_GC
123                 nptr = GC_realloc(ptr, newsize);
124 #else
125                 nptr = realloc(ptr, newsize);
126 #endif
127                 if (nptr == NULL) {
128                         wwarning("realloc() failed. Retrying after 2s.");
129                         sleep(2);
130 #ifdef TEST_WITH_GC
131                         nptr = GC_realloc(ptr, newsize);
132 #else
133                         nptr = realloc(ptr, newsize);
134 #endif
135                         if (nptr == NULL) {
136                                 if (Aborting) {
137                                         fputs("Really Bad Error: recursive realloc() failure.", stderr);
138                                         exit(-1);
139                                 } else {
140                                         wfatal("virtual memory exhausted");
141                                         Aborting = 1;
142                                         wAbort(False);
143                                 }
144                         }
145                 }
146         }
147         return nptr;
148 }
149
150 void *wretain(void *ptr)
151 {
152         int *refcount;
153
154         if (!table) {
155                 table = WMCreateHashTable(WMIntHashCallbacks);
156         }
157
158         refcount = WMHashGet(table, ptr);
159         if (!refcount) {
160                 refcount = wmalloc(sizeof(int));
161                 *refcount = 1;
162                 WMHashInsert(table, ptr, refcount);
163 #ifdef VERBOSE
164                 printf("== %i (%p)\n", *refcount, ptr);
165 #endif
166         } else {
167                 (*refcount)++;
168 #ifdef VERBOSE
169                 printf("+ %i (%p)\n", *refcount, ptr);
170 #endif
171         }
172
173         return ptr;
174 }
175
176 void wfree(void *ptr)
177 {
178 #ifdef TEST_WITH_GC
179         GC_free(ptr);
180 #else
181         free(ptr);
182 #endif
183 }
184
185 void wrelease(void *ptr)
186 {
187         int *refcount;
188
189         refcount = WMHashGet(table, ptr);
190         if (!refcount) {
191                 wwarning("trying to release unexisting data %p", ptr);
192         } else {
193                 (*refcount)--;
194                 if (*refcount < 1) {
195 #ifdef VERBOSE
196                         printf("RELEASING %p\n", ptr);
197 #endif
198                         WMHashRemove(table, ptr);
199                         wfree(refcount);
200                         wfree(ptr);
201                 }
202 #ifdef VERBOSE
203                 else {
204                         printf("- %i (%p)\n", *refcount, ptr);
205                 }
206 #endif
207         }
208 }