|
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 } |