src/server/util/system.c

changeset 14
b8bf95b39952
parent 1
3c066d52342d
child 24
1a7853a4257e
equal deleted inserted replaced
13:1fdbf4170ef4 14:b8bf95b39952
1 /*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3 *
4 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
5 *
6 * THE BSD LICENSE
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * Redistributions of source code must retain the above copyright notice, this
12 * list of conditions and the following disclaimer.
13 * Redistributions in binary form must reproduce the above copyright notice,
14 * this list of conditions and the following disclaimer in the documentation
15 * and/or other materials provided with the distribution.
16 *
17 * Neither the name of the nor the names of its contributors may be
18 * used to endorse or promote products derived from this software without
19 * specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
25 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
28 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 /*
35 * system.c: A grab bag of system-level abstractions
36 *
37 * Many authors
38 */
39
40 #if (defined(__GNUC__) && (__GNUC__ > 2))
41 #include <new>
42 using namespace std;
43 #else
44 //include <new.h>
45 #endif
46 #include "../daemon/netsite.h"
47 #include "ereport.h"
48
49 #ifdef XP_WIN32
50 #include <windows.h>
51 #include <process.h>
52 #endif
53
54 static int thread_malloc_key = -1;
55
56 static char* temp_dir = NULL;
57
58 #ifdef XP_WIN32
59 _PNH original_newhandler = 0;
60 #else
61 typedef void (newhandler)(void);
62 static newhandler *original_newhandler = 0;
63 #endif
64
65 #include "pool.h"
66 #include "systhr.h"
67
68 #define MALLOC_KEY \
69 ((pool_handle_t *)(thread_malloc_key != -1 ? systhread_getdata(thread_malloc_key) : NULL))
70
71
72 #ifdef MCC_DEBUG
73 #define DEBUG_MALLOC
74 #endif
75
76 #ifdef DEBUG_MALLOC
77
78 /* The debug malloc routines provide several functions:
79 *
80 * - detect allocated memory overflow/underflow
81 * - detect multiple frees
82 * - intentionally clobbers malloc'd buffers
83 * - intentionally clobbers freed buffers
84 */
85 #define DEBUG_MAGIC 0x12345678
86 #define DEBUG_MARGIN 32
87 #define DEBUG_MARGIN_CHAR '*'
88 #define DEBUG_MALLOC_CHAR '.'
89 #define DEBUG_FREE_CHAR 'X'
90 #endif /* DEBUG_MALLOC */
91
92 NSAPI_PUBLIC char *system_version()
93 {
94 //return PRODUCT_ID"/"PRODUCT_VERSION_ID;
95 return "Solaris 11 Express";
96 }
97
98 NSAPI_PUBLIC pool_handle_t *system_pool(void)
99 {
100 return MALLOC_KEY;
101 }
102
103 NSAPI_PUBLIC void *system_malloc(int size)
104 {
105 void *ret;
106 ret = pool_malloc(MALLOC_KEY, size);
107 if (!ret) {
108 //ereport_outofmemory();
109 PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
110 }
111 return ret;
112 }
113
114
115 NSAPI_PUBLIC void *system_calloc(int size)
116 {
117 void *ret;
118 ret = pool_malloc(MALLOC_KEY, size);
119 if(ret) {
120 ZERO(ret, size);
121 } else {
122 //ereport_outofmemory();
123 PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
124 }
125 return ret;
126 }
127
128
129 NSAPI_PUBLIC void *system_realloc(void *ptr, int size)
130 {
131 void *ret;
132 ret = pool_realloc(MALLOC_KEY, ptr, size);
133 if (!ret) {
134 //ereport_outofmemory();
135 PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
136 }
137 return ret;
138 }
139
140
141 NSAPI_PUBLIC void system_free(void *ptr)
142 {
143 pool_free(MALLOC_KEY, ptr);
144 }
145
146 NSAPI_PUBLIC char *system_strdup(const char *ptr)
147 {
148 //NS_ASSERT(ptr);
149 char *ret;
150 ret = pool_strdup(MALLOC_KEY, ptr);
151 if (!ret) {
152 //ereport_outofmemory();
153 PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
154 }
155 return ret;
156 }
157
158
159 NSAPI_PUBLIC void *system_malloc_perm(int size)
160 {
161 void *ret;
162 #ifndef DEBUG_MALLOC
163 ret = malloc(size);
164 #else
165 char *ptr = (char *)malloc(size + 2*DEBUG_MARGIN+2*sizeof(int));
166 char *real_ptr;
167 int *magic;
168 int *length;
169
170 magic = (int *)ptr;
171 *magic = DEBUG_MAGIC;
172 ptr += sizeof(int);
173 length = (int *)ptr;
174 *length = size;
175 ptr += sizeof(int);
176 memset(ptr, DEBUG_MARGIN_CHAR, DEBUG_MARGIN);
177 ptr += DEBUG_MARGIN;
178 memset(ptr, DEBUG_MALLOC_CHAR, size);
179 real_ptr = ptr;
180 ptr += size;
181 memset(ptr, DEBUG_MARGIN_CHAR, DEBUG_MARGIN);
182
183 ret = real_ptr;
184 #endif
185 if (!ret) {
186 //ereport_outofmemory();
187 PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
188 }
189 return ret;
190 }
191
192 NSAPI_PUBLIC void *system_calloc_perm(int size)
193 {
194 void *ret = system_malloc_perm(size);
195 if(ret)
196 ZERO(ret, size);
197 return ret;
198 }
199
200 NSAPI_PUBLIC void *system_realloc_perm(void *ptr, int size)
201 {
202 void *ret;
203
204 #ifndef DEBUG_MALLOC
205 ret = realloc(ptr, size);
206 #else
207 int *magic, *length;
208 char *baseptr;
209 char *cptr;
210
211 /* realloc semantics allow realloc(NULL, size) */
212 if (ptr == NULL)
213 return system_malloc_perm(size);
214
215 cptr = (char *)ptr - DEBUG_MARGIN - 2 * sizeof(int);
216 magic = (int *)cptr;
217 if (*magic == DEBUG_MAGIC) {
218 cptr += sizeof(int);
219 length = (int *)cptr;
220 if (*length < size) {
221 char *newptr = (char *)system_malloc_perm(size);
222 memcpy(newptr, ptr, *length);
223 system_free_perm(ptr);
224
225 ret = newptr;
226 }else {
227 ret = ptr;
228 }
229 } else {
230 ereport(LOG_WARN, XP_GetAdminString(DBT_systemReallocSmallerSize));
231 ret = realloc(ptr, size);
232 }
233 #endif
234
235 if (!ret) {
236 //ereport_outofmemory();
237 PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
238 }
239
240 return ret;
241 }
242
243 NSAPI_PUBLIC void system_free_perm(void *ptr)
244 {
245 #ifdef DEBUG_MALLOC
246 int *length, *magic;
247 char *baseptr, *cptr;
248 int index;
249
250 NS_ASSERT(ptr);
251
252 cptr = baseptr = ((char *)ptr) - DEBUG_MARGIN - 2*sizeof(int);
253
254 magic = (int *)cptr;
255 if (*magic == DEBUG_MAGIC) {
256 cptr += sizeof(int);
257
258 length = (int *)cptr;
259
260 cptr += sizeof(int);
261 for (index=0; index<DEBUG_MARGIN; index++)
262 if (cptr[index] != DEBUG_MARGIN_CHAR) {
263 ereport(LOG_CATASTROPHE, XP_GetAdminString(DBT_systemRFreeCorruptMemoryPre));
264 break;
265 }
266
267 cptr += DEBUG_MARGIN + *length;
268 for (index=0; index<DEBUG_MARGIN; index++)
269 if (cptr[index] != DEBUG_MARGIN_CHAR) {
270 ereport(LOG_CATASTROPHE, XP_GetAdminString(DBT_systemRFreeCorruptMemoryPost));
271 break;
272 }
273
274 memset(baseptr, DEBUG_FREE_CHAR, *length + 2*DEBUG_MARGIN+sizeof(int));
275 } else {
276 ereport(LOG_CATASTROPHE, XP_GetAdminString(DBT_systemRFreeUnallocatedMem));
277 }
278 free(baseptr);
279 #else
280 free(ptr);
281 #endif
282 }
283
284 NSAPI_PUBLIC char *system_strdup_perm(const char *ptr)
285 {
286 char *ret;
287
288 #ifndef DEBUG_MALLOC
289 //NS_ASSERT(ptr);
290 ret = strdup(ptr);
291 #else
292 int len = strlen(ptr);
293 char *nptr = (char *)system_malloc_perm(len+1);
294 memcpy(nptr, ptr, len);
295 nptr[len] = '\0';
296 ret = nptr;
297 #endif
298
299 if (!ret) {
300 //ereport_outofmemory();
301 PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
302 }
303
304 return ret;
305 }
306
307 NSAPI_PUBLIC void system_set_temp_dir(const char *dir)
308 {
309 // Leak any previously-allocated dir in case someone still has a reference
310 temp_dir = STRDUP(dir);
311 }
312
313 NSAPI_PUBLIC const char *system_get_temp_dir(void)
314 {
315 char* dir = temp_dir;
316
317 if (!dir) {
318 #ifdef XP_WIN32
319 dir = getenv("TEMP");
320 if (!dir) dir = getenv("TMP");
321 if (!dir) dir = "C:\\TEMP";
322 #else
323 dir = "/tmp";
324 #endif
325 }
326
327 return dir;
328 }
329
330 NSAPI_PUBLIC int
331 getThreadMallocKey(void)
332 {
333 return thread_malloc_key;
334 }
335
336 NSAPI_PUBLIC void
337 InitThreadMallocKey(void)
338 {
339 PR_NewThreadPrivateIndex((unsigned int *)&thread_malloc_key, NULL);
340 PR_ASSERT(thread_malloc_key);
341 }
342
343 #ifdef XP_WIN32
344 static int _cdecl system_newhandler(unsigned int size)
345 {
346 //ereport_outofmemory();
347
348 if (original_newhandler) {
349 // Let original handler deal with things
350 return (*original_newhandler)(size);
351 }
352
353 // Tell new not to retry the allocation
354 return 0;
355 }
356 #else
357 static void system_newhandler()
358 {
359 // We want to preserve the original new semantics, but we don't know what
360 // those semantics are. Some platforms throw xalloc while others throw
361 // bad_alloc.
362
363 //ereport_outofmemory();
364
365 if (original_newhandler) {
366 // Let original handler deal with things
367 (*original_newhandler)();
368 } else {
369 // No original handler to call; try to remove all handlers
370 static PRBool flagRemovedHandler = PR_FALSE;
371 if (flagRemovedHandler) {
372 abort();
373 }
374 //set_new_handler(0); // TODO: set_new_handler
375 flagRemovedHandler = PR_TRUE;
376 }
377 }
378 #endif
379
380 NSAPI_PUBLIC void system_setnewhandler(void)
381 {
382 #ifdef XP_WIN32
383 original_newhandler = _set_new_handler(system_newhandler);
384 #else
385 //original_newhandler = set_new_handler(system_newhandler); // TODO: ...
386 #endif
387 }

mercurial