1 |
/* |
2 |
* Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers |
3 |
* Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved. |
4 |
* Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved. |
5 |
* Copyright (c) 1999 by Hewlett-Packard Company. All rights reserved. |
6 |
* Copyright (c) 2000, 2001, 2002, 2003, 2004 Free Software Foundation |
7 |
* |
8 |
* THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED |
9 |
* OR IMPLIED. ANY USE IS AT YOUR OWN RISK. |
10 |
* |
11 |
* Permission is hereby granted to use or copy this program |
12 |
* for any purpose, provided the above notices are retained on all copies. |
13 |
* Permission to modify the code and to distribute modified code is granted, |
14 |
* provided the above notices are retained, and a notice that the code was |
15 |
* modified is included with the above copyright notice. |
16 |
* |
17 |
*/ |
18 |
|
19 |
/* |
20 |
* Copied from gc5.2, files "os_dep.c", "gc_priv.h", "mark.c" and "gcconfig.h", |
21 |
* and modified for Guile by Marius Vollmer. |
22 |
*/ |
23 |
|
24 |
#if HAVE_CONFIG_H |
25 |
# include <config.h> |
26 |
#endif |
27 |
|
28 |
#include <ctype.h> |
29 |
#include "libguile/gc.h" |
30 |
#include "libguile/scmconfig.h" |
31 |
|
32 |
#ifdef HAVE_LIBC_STACK_END |
33 |
|
34 |
extern void *__libc_stack_end; |
35 |
|
36 |
void * |
37 |
scm_get_stack_base () |
38 |
{ |
39 |
return __libc_stack_end; |
40 |
} |
41 |
|
42 |
#else |
43 |
|
44 |
#define ABORT(msg) abort () |
45 |
|
46 |
typedef char * ptr_t; /* A generic pointer to which we can add */ |
47 |
/* byte displacements. */ |
48 |
/* Preferably identical to caddr_t, if it */ |
49 |
/* exists. */ |
50 |
|
51 |
/* Define word and signed_word to be unsigned and signed types of the */ |
52 |
/* size as char * or void *. There seems to be no way to do this */ |
53 |
/* even semi-portably. The following is probably no better/worse */ |
54 |
/* than almost anything else. */ |
55 |
/* The ANSI standard suggests that size_t and ptr_diff_t might be */ |
56 |
/* better choices. But those appear to have incorrect definitions */ |
57 |
/* on may systems. Notably "typedef int size_t" seems to be both */ |
58 |
/* frequent and WRONG. */ |
59 |
typedef unsigned long GC_word; |
60 |
typedef long GC_signed_word; |
61 |
|
62 |
typedef GC_word word; |
63 |
typedef GC_signed_word signed_word; |
64 |
|
65 |
typedef int GC_bool; |
66 |
# define TRUE 1 |
67 |
# define FALSE 0 |
68 |
|
69 |
#if defined(__STDC__) |
70 |
# include <stdlib.h> |
71 |
# if !(defined( sony_news ) ) |
72 |
# include <stddef.h> |
73 |
# endif |
74 |
# define VOLATILE volatile |
75 |
#else |
76 |
# ifdef MSWIN32 |
77 |
# include <stdlib.h> |
78 |
# endif |
79 |
# define VOLATILE |
80 |
#endif |
81 |
|
82 |
/* Machine dependent parameters. Some tuning parameters can be found */ |
83 |
/* near the top of gc_private.h. */ |
84 |
|
85 |
/* Machine specific parts contributed by various people. See README file. */ |
86 |
|
87 |
/* First a unified test for Linux: */ |
88 |
# if defined(linux) || defined(__linux__) |
89 |
# define LINUX |
90 |
# endif |
91 |
|
92 |
/* Determine the machine type: */ |
93 |
# if defined(sun) && defined(mc68000) |
94 |
# define M68K |
95 |
# define SUNOS4 |
96 |
# define mach_type_known |
97 |
# endif |
98 |
# if defined(hp9000s300) |
99 |
# define M68K |
100 |
# define HP |
101 |
# define mach_type_known |
102 |
# endif |
103 |
# if defined(__OpenBSD__) && defined(m68k) |
104 |
# define M68K |
105 |
# define OPENBSD |
106 |
# define mach_type_known |
107 |
# endif |
108 |
# if defined(__OpenBSD__) && defined(__sparc__) |
109 |
# define SPARC |
110 |
# define OPENBSD |
111 |
# define mach_type_known |
112 |
# endif |
113 |
# if defined(__NetBSD__) && defined(__powerpc__) |
114 |
# define POWERPC |
115 |
# define NETBSD |
116 |
# define mach_type_known |
117 |
# endif |
118 |
/* in netbsd 2.0 only __m68k__ is defined, not m68k */ |
119 |
# if defined(__NetBSD__) && (defined(m68k) || defined(__m68k__)) |
120 |
# define M68K |
121 |
# define NETBSD |
122 |
# define mach_type_known |
123 |
# endif |
124 |
/* in netbsd 2.0 only __arm__ is defined, not arm32 */ |
125 |
# if defined(__NetBSD__) && (defined(arm32) || defined(__arm__)) |
126 |
# define ARM32 |
127 |
# define NETBSD |
128 |
# define mach_type_known |
129 |
# endif |
130 |
# if defined(__NetBSD__) && defined(__sparc__) |
131 |
# define SPARC |
132 |
# define NETBSD |
133 |
# define mach_type_known |
134 |
# endif |
135 |
# if defined(vax) |
136 |
# define VAX |
137 |
# ifdef ultrix |
138 |
# define ULTRIX |
139 |
# else |
140 |
# define BSD |
141 |
# endif |
142 |
# define mach_type_known |
143 |
# endif |
144 |
# if defined(mips) || defined(__mips) |
145 |
# define MIPS |
146 |
# if !defined(LINUX) |
147 |
# if defined(ultrix) || defined(__ultrix) || defined(__NetBSD__) |
148 |
# define ULTRIX |
149 |
# else |
150 |
# if defined(_SYSTYPE_SVR4) || defined(SYSTYPE_SVR4) \ |
151 |
|| defined(__SYSTYPE_SVR4__) |
152 |
# define IRIX5 /* or IRIX 6.X */ |
153 |
# else |
154 |
# define RISCOS /* or IRIX 4.X */ |
155 |
# endif |
156 |
# endif |
157 |
# endif /* !LINUX */ |
158 |
# define mach_type_known |
159 |
# endif |
160 |
# if defined(sequent) && defined(i386) |
161 |
# define I386 |
162 |
# define SEQUENT |
163 |
# define mach_type_known |
164 |
# endif |
165 |
# if defined(sun) && defined(i386) |
166 |
# define I386 |
167 |
# define SUNOS5 |
168 |
# define mach_type_known |
169 |
# endif |
170 |
# if (defined(__OS2__) || defined(__EMX__)) && defined(__32BIT__) |
171 |
# define I386 |
172 |
# define OS2 |
173 |
# define mach_type_known |
174 |
# endif |
175 |
# if defined(ibm032) |
176 |
# define RT |
177 |
# define mach_type_known |
178 |
# endif |
179 |
# if defined(sun) && (defined(sparc) || defined(__sparc)) |
180 |
# define SPARC |
181 |
/* Test for SunOS 5.x */ |
182 |
# include <errno.h> |
183 |
# ifdef ECHRNG |
184 |
# define SUNOS5 |
185 |
# else |
186 |
# define SUNOS4 |
187 |
# endif |
188 |
# define mach_type_known |
189 |
# endif |
190 |
# if defined(sparc) && defined(unix) && !defined(sun) && !defined(linux) \ |
191 |
&& !defined(__OpenBSD__) |
192 |
# define SPARC |
193 |
# define DRSNX |
194 |
# define mach_type_known |
195 |
# endif |
196 |
# if defined(_IBMR2) |
197 |
# define RS6000 |
198 |
# define mach_type_known |
199 |
# endif |
200 |
# if defined(_M_XENIX) && defined(_M_SYSV) && defined(_M_I386) |
201 |
/* The above test may need refinement */ |
202 |
# define I386 |
203 |
# if defined(_SCO_ELF) |
204 |
# define SCO_ELF |
205 |
# else |
206 |
# define SCO |
207 |
# endif |
208 |
# define mach_type_known |
209 |
# endif |
210 |
# if defined(_AUX_SOURCE) |
211 |
# define M68K |
212 |
# define SYSV |
213 |
# define mach_type_known |
214 |
# endif |
215 |
# if defined(_PA_RISC1_0) || defined(_PA_RISC1_1) || defined(_PA_RISC2_0) \ |
216 |
|| defined(hppa) || defined(__hppa__) |
217 |
# define HP_PA |
218 |
# ifndef LINUX |
219 |
# define HPUX |
220 |
# endif |
221 |
# define mach_type_known |
222 |
# endif |
223 |
# if defined(LINUX) && (defined(i386) || defined(__i386__)) |
224 |
# define I386 |
225 |
# define mach_type_known |
226 |
# endif |
227 |
# if defined(LINUX) && (defined(__ia64__) || defined(__ia64)) |
228 |
# define IA64 |
229 |
# define mach_type_known |
230 |
# endif |
231 |
# if defined(LINUX) && defined(powerpc) |
232 |
# define POWERPC |
233 |
# define mach_type_known |
234 |
# endif |
235 |
# if defined(LINUX) && defined(__mc68000__) |
236 |
# define M68K |
237 |
# define mach_type_known |
238 |
# endif |
239 |
# if defined(LINUX) && (defined(sparc) || defined(__sparc__)) |
240 |
# define SPARC |
241 |
# define mach_type_known |
242 |
# endif |
243 |
# if defined(LINUX) && (defined(arm) || defined (__arm__)) |
244 |
# define ARM32 |
245 |
# define mach_type_known |
246 |
# endif |
247 |
# if defined(__alpha) || defined(__alpha__) |
248 |
# define ALPHA |
249 |
# if !defined(LINUX) |
250 |
# define OSF1 /* a.k.a Digital Unix */ |
251 |
# endif |
252 |
# define mach_type_known |
253 |
# endif |
254 |
# if defined(_AMIGA) && !defined(AMIGA) |
255 |
# define AMIGA |
256 |
# endif |
257 |
# ifdef AMIGA |
258 |
# define M68K |
259 |
# define mach_type_known |
260 |
# endif |
261 |
# if defined(THINK_C) || defined(__MWERKS__) && !defined(__powerc) |
262 |
# define M68K |
263 |
# define MACOS |
264 |
# define mach_type_known |
265 |
# endif |
266 |
# if defined(__MWERKS__) && defined(__powerc) |
267 |
# define POWERPC |
268 |
# define MACOS |
269 |
# define mach_type_known |
270 |
# endif |
271 |
# if defined(macosx) || \ |
272 |
(defined(__APPLE__) && defined(__MACH__) && defined(__ppc__)) |
273 |
# define MACOSX |
274 |
# define POWERPC |
275 |
# define mach_type_known |
276 |
# endif |
277 |
# if defined(NeXT) && defined(mc68000) |
278 |
# define M68K |
279 |
# define NEXT |
280 |
# define mach_type_known |
281 |
# endif |
282 |
# if defined(NeXT) && defined(i386) |
283 |
# define I386 |
284 |
# define NEXT |
285 |
# define mach_type_known |
286 |
# endif |
287 |
# if defined(__OpenBSD__) && (defined(i386) || defined(__i386__)) |
288 |
# define I386 |
289 |
# define OPENBSD |
290 |
# define mach_type_known |
291 |
# endif |
292 |
# if defined(__FreeBSD__) && defined(i386) |
293 |
# define I386 |
294 |
# define FREEBSD |
295 |
# define mach_type_known |
296 |
# endif |
297 |
# if defined(__NetBSD__) && defined(i386) |
298 |
# define I386 |
299 |
# define NETBSD |
300 |
# define mach_type_known |
301 |
# endif |
302 |
# if defined(bsdi) && defined(i386) |
303 |
# define I386 |
304 |
# define BSDI |
305 |
# define mach_type_known |
306 |
# endif |
307 |
# if !defined(mach_type_known) && defined(__386BSD__) |
308 |
# define I386 |
309 |
# define THREE86BSD |
310 |
# define mach_type_known |
311 |
# endif |
312 |
# if defined(_CX_UX) && defined(_M88K) |
313 |
# define M88K |
314 |
# define CX_UX |
315 |
# define mach_type_known |
316 |
# endif |
317 |
# if defined(DGUX) |
318 |
# define M88K |
319 |
/* DGUX defined */ |
320 |
# define mach_type_known |
321 |
# endif |
322 |
# if (defined(_MSDOS) || defined(_MSC_VER)) && (_M_IX86 >= 300) \ |
323 |
|| defined(_WIN32) && !defined(__CYGWIN32__) && !defined(__CYGWIN__) |
324 |
# define I386 |
325 |
# define MSWIN32 /* or Win32s */ |
326 |
# define mach_type_known |
327 |
# endif |
328 |
# if defined(__DJGPP__) |
329 |
# define I386 |
330 |
# ifndef DJGPP |
331 |
# define DJGPP /* MSDOS running the DJGPP port of GCC */ |
332 |
# endif |
333 |
# define mach_type_known |
334 |
# endif |
335 |
# if defined(__CYGWIN32__) || defined(__CYGWIN__) |
336 |
# define I386 |
337 |
# define CYGWIN32 |
338 |
# define mach_type_known |
339 |
# endif |
340 |
# if defined(__MINGW32__) |
341 |
# define I386 |
342 |
# define MSWIN32 |
343 |
# define mach_type_known |
344 |
# endif |
345 |
# if defined(__BORLANDC__) |
346 |
# define I386 |
347 |
# define MSWIN32 |
348 |
# define mach_type_known |
349 |
# endif |
350 |
# if defined(_UTS) && !defined(mach_type_known) |
351 |
# define S370 |
352 |
# define UTS4 |
353 |
# define mach_type_known |
354 |
# endif |
355 |
# if defined(__pj__) |
356 |
# define PJ |
357 |
# define mach_type_known |
358 |
# endif |
359 |
/* Ivan Demakov */ |
360 |
# if defined(__WATCOMC__) && defined(__386__) |
361 |
# define I386 |
362 |
# if !defined(OS2) && !defined(MSWIN32) && !defined(DOS4GW) |
363 |
# if defined(__OS2__) |
364 |
# define OS2 |
365 |
# else |
366 |
# if defined(__WINDOWS_386__) || defined(__NT__) |
367 |
# define MSWIN32 |
368 |
# else |
369 |
# define DOS4GW |
370 |
# endif |
371 |
# endif |
372 |
# endif |
373 |
# define mach_type_known |
374 |
# endif |
375 |
# if defined(__s390__) && defined(LINUX) |
376 |
# define S370 |
377 |
# define mach_type_known |
378 |
# endif |
379 |
# if defined(__GNU__) |
380 |
# define I386 |
381 |
# define GNU |
382 |
# define mach_type_known |
383 |
# endif |
384 |
# if defined(__SCO_VERSION__) |
385 |
# define I386 |
386 |
# define SYSV |
387 |
# define mach_type_known |
388 |
# endif |
389 |
|
390 |
/* Feel free to add more clauses here */ |
391 |
|
392 |
/* Or manually define the machine type here. A machine type is */ |
393 |
/* characterized by the architecture. Some */ |
394 |
/* machine types are further subdivided by OS. */ |
395 |
/* the macros ULTRIX, RISCOS, and BSD to distinguish. */ |
396 |
/* Note that SGI IRIX is treated identically to RISCOS. */ |
397 |
/* SYSV on an M68K actually means A/UX. */ |
398 |
/* The distinction in these cases is usually the stack starting address */ |
399 |
# ifndef mach_type_known |
400 |
|
401 |
void * |
402 |
scm_get_stack_base () |
403 |
{ |
404 |
return NULL; |
405 |
} |
406 |
|
407 |
# else |
408 |
/* Mapping is: M68K ==> Motorola 680X0 */ |
409 |
/* (SUNOS4,HP,NEXT, and SYSV (A/UX), */ |
410 |
/* MACOS and AMIGA variants) */ |
411 |
/* I386 ==> Intel 386 */ |
412 |
/* (SEQUENT, OS2, SCO, LINUX, NETBSD, */ |
413 |
/* FREEBSD, THREE86BSD, MSWIN32, */ |
414 |
/* BSDI,SUNOS5, NEXT, other variants) */ |
415 |
/* NS32K ==> Encore Multimax */ |
416 |
/* MIPS ==> R2000 or R3000 */ |
417 |
/* (RISCOS, ULTRIX variants) */ |
418 |
/* VAX ==> DEC VAX */ |
419 |
/* (BSD, ULTRIX variants) */ |
420 |
/* RS6000 ==> IBM RS/6000 AIX3.X */ |
421 |
/* RT ==> IBM PC/RT */ |
422 |
/* HP_PA ==> HP9000/700 & /800 */ |
423 |
/* HP/UX */ |
424 |
/* SPARC ==> SPARC under SunOS */ |
425 |
/* (SUNOS4, SUNOS5, */ |
426 |
/* DRSNX variants) */ |
427 |
/* ALPHA ==> DEC Alpha */ |
428 |
/* (OSF1 and LINUX variants) */ |
429 |
/* M88K ==> Motorola 88XX0 */ |
430 |
/* (CX_UX and DGUX) */ |
431 |
/* S370 ==> 370-like machine */ |
432 |
/* running Amdahl UTS4 */ |
433 |
/* ARM32 ==> Intel StrongARM */ |
434 |
/* IA64 ==> Intel IA64 */ |
435 |
/* (e.g. Itanium) */ |
436 |
|
437 |
|
438 |
/* |
439 |
* For each architecture and OS, the following need to be defined: |
440 |
* |
441 |
* CPP_WORD_SZ is a simple integer constant representing the word size. |
442 |
* in bits. We assume byte addressibility, where a byte has 8 bits. |
443 |
* We also assume CPP_WORD_SZ is either 32 or 64. |
444 |
* (We care about the length of pointers, not hardware |
445 |
* bus widths. Thus a 64 bit processor with a C compiler that uses |
446 |
* 32 bit pointers should use CPP_WORD_SZ of 32, not 64. Default is 32.) |
447 |
* |
448 |
* MACH_TYPE is a string representation of the machine type. |
449 |
* OS_TYPE is analogous for the OS. |
450 |
* |
451 |
* ALIGNMENT is the largest N, such that |
452 |
* all pointer are guaranteed to be aligned on N byte boundaries. |
453 |
* defining it to be 1 will always work, but perform poorly. |
454 |
* |
455 |
* DATASTART is the beginning of the data segment. |
456 |
* On UNIX systems, the collector will scan the area between DATASTART |
457 |
* and DATAEND for root pointers. |
458 |
* |
459 |
* DATAEND, if not &end. |
460 |
* |
461 |
* ALIGN_DOUBLE of GC_malloc should return blocks aligned to twice |
462 |
* the pointer size. |
463 |
* |
464 |
* STACKBOTTOM is the cool end of the stack, which is usually the |
465 |
* highest address in the stack. |
466 |
* Under PCR or OS/2, we have other ways of finding thread stacks. |
467 |
* For each machine, the following should: |
468 |
* 1) define SCM_STACK_GROWS_UP if the stack grows toward higher addresses, and |
469 |
* 2) define exactly one of |
470 |
* STACKBOTTOM (should be defined to be an expression) |
471 |
* HEURISTIC1 |
472 |
* HEURISTIC2 |
473 |
* If either of the last two macros are defined, then STACKBOTTOM is computed |
474 |
* during collector startup using one of the following two heuristics: |
475 |
* HEURISTIC1: Take an address inside GC_init's frame, and round it up to |
476 |
* the next multiple of STACK_GRAN. |
477 |
* HEURISTIC2: Take an address inside GC_init's frame, increment it repeatedly |
478 |
* in small steps (decrement if SCM_STACK_GROWS_UP), and read the value |
479 |
* at each location. Remember the value when the first |
480 |
* Segmentation violation or Bus error is signalled. Round that |
481 |
* to the nearest plausible page boundary, and use that instead |
482 |
* of STACKBOTTOM. |
483 |
* |
484 |
* Gustavo Rodriguez-Rivera points out that on most (all?) Unix machines, |
485 |
* the value of environ is a pointer that can serve as STACKBOTTOM. |
486 |
* I expect that HEURISTIC2 can be replaced by this approach, which |
487 |
* interferes far less with debugging. |
488 |
* |
489 |
* If no expression for STACKBOTTOM can be found, and neither of the above |
490 |
* heuristics are usable, the collector can still be used with all of the above |
491 |
* undefined, provided one of the following is done: |
492 |
* 1) GC_mark_roots can be changed to somehow mark from the correct stack(s) |
493 |
* without reference to STACKBOTTOM. This is appropriate for use in |
494 |
* conjunction with thread packages, since there will be multiple stacks. |
495 |
* (Allocating thread stacks in the heap, and treating them as ordinary |
496 |
* heap data objects is also possible as a last resort. However, this is |
497 |
* likely to introduce significant amounts of excess storage retention |
498 |
* unless the dead parts of the thread stacks are periodically cleared.) |
499 |
* 2) Client code may set GC_stackbottom before calling any GC_ routines. |
500 |
* If the author of the client code controls the main program, this is |
501 |
* easily accomplished by introducing a new main program, setting |
502 |
* GC_stackbottom to the address of a local variable, and then calling |
503 |
* the original main program. The new main program would read something |
504 |
* like: |
505 |
* |
506 |
* # include "gc_private.h" |
507 |
* |
508 |
* main(argc, argv, envp) |
509 |
* int argc; |
510 |
* char **argv, **envp; |
511 |
* { |
512 |
* int dummy; |
513 |
* |
514 |
* GC_stackbottom = (ptr_t)(&dummy); |
515 |
* return(real_main(argc, argv, envp)); |
516 |
* } |
517 |
* |
518 |
* |
519 |
* Each architecture may also define the style of virtual dirty bit |
520 |
* implementation to be used: |
521 |
* MPROTECT_VDB: Write protect the heap and catch faults. |
522 |
* PROC_VDB: Use the SVR4 /proc primitives to read dirty bits. |
523 |
* |
524 |
* An architecture may define DYNAMIC_LOADING if dynamic_load.c |
525 |
* defined GC_register_dynamic_libraries() for the architecture. |
526 |
* |
527 |
* An architecture may define PREFETCH(x) to preload the cache with *x. |
528 |
* This defaults to a no-op. |
529 |
* |
530 |
* PREFETCH_FOR_WRITE(x) is used if *x is about to be written. |
531 |
* |
532 |
* An architecture may also define CLEAR_DOUBLE(x) to be a fast way to |
533 |
* clear the two words at GC_malloc-aligned address x. By default, |
534 |
* word stores of 0 are used instead. |
535 |
*/ |
536 |
|
537 |
|
538 |
# define STACK_GRAN 0x1000000 |
539 |
# ifdef M68K |
540 |
# define MACH_TYPE "M68K" |
541 |
# define ALIGNMENT 2 |
542 |
# ifdef OPENBSD |
543 |
# define OS_TYPE "OPENBSD" |
544 |
# define HEURISTIC2 |
545 |
extern char etext; |
546 |
# define DATASTART ((ptr_t)(&etext)) |
547 |
# endif |
548 |
# ifdef NETBSD |
549 |
# define OS_TYPE "NETBSD" |
550 |
# define HEURISTIC2 |
551 |
extern char etext; |
552 |
# define DATASTART ((ptr_t)(&etext)) |
553 |
# endif |
554 |
# ifdef LINUX |
555 |
# define OS_TYPE "LINUX" |
556 |
# define STACKBOTTOM ((ptr_t)0xf0000000) |
557 |
# define MPROTECT_VDB |
558 |
# ifdef __ELF__ |
559 |
# define DYNAMIC_LOADING |
560 |
extern char **__environ; |
561 |
# define DATASTART ((ptr_t)(&__environ)) |
562 |
/* hideous kludge: __environ is the first */ |
563 |
/* word in crt0.o, and delimits the start */ |
564 |
/* of the data segment, no matter which */ |
565 |
/* ld options were passed through. */ |
566 |
/* We could use _etext instead, but that */ |
567 |
/* would include .rodata, which may */ |
568 |
/* contain large read-only data tables */ |
569 |
/* that we'd rather not scan. */ |
570 |
extern int _end; |
571 |
# define DATAEND (&_end) |
572 |
# else |
573 |
extern int etext; |
574 |
# define DATASTART ((ptr_t)((((word) (&etext)) + 0xfff) & ~0xfff)) |
575 |
# endif |
576 |
# endif |
577 |
# ifdef SUNOS4 |
578 |
# define OS_TYPE "SUNOS4" |
579 |
extern char etext; |
580 |
# define DATASTART ((ptr_t)((((word) (&etext)) + 0x1ffff) & ~0x1ffff)) |
581 |
# define HEURISTIC1 /* differs */ |
582 |
# define DYNAMIC_LOADING |
583 |
# endif |
584 |
# ifdef HP |
585 |
# define OS_TYPE "HP" |
586 |
extern char etext; |
587 |
# define DATASTART ((ptr_t)((((word) (&etext)) + 0xfff) & ~0xfff)) |
588 |
# define STACKBOTTOM ((ptr_t) 0xffeffffc) |
589 |
/* empirically determined. seems to work. */ |
590 |
# include <unistd.h> |
591 |
# define GETPAGESIZE() sysconf(_SC_PAGE_SIZE) |
592 |
# endif |
593 |
# ifdef SYSV |
594 |
# define OS_TYPE "SYSV" |
595 |
extern etext; |
596 |
# define DATASTART ((ptr_t)((((word) (&etext)) + 0x3fffff) \ |
597 |
& ~0x3fffff) \ |
598 |
+((word)&etext & 0x1fff)) |
599 |
/* This only works for shared-text binaries with magic number 0413. |
600 |
The other sorts of SysV binaries put the data at the end of the text, |
601 |
in which case the default of &etext would work. Unfortunately, |
602 |
handling both would require having the magic-number available. |
603 |
-- Parag |
604 |
*/ |
605 |
# define STACKBOTTOM ((ptr_t)0xFFFFFFFE) |
606 |
/* The stack starts at the top of memory, but */ |
607 |
/* 0x0 cannot be used as setjump_test complains */ |
608 |
/* that the stack direction is incorrect. Two */ |
609 |
/* bytes down from 0x0 should be safe enough. */ |
610 |
/* --Parag */ |
611 |
# include <sys/mmu.h> |
612 |
# define GETPAGESIZE() PAGESIZE /* Is this still right? */ |
613 |
# endif |
614 |
# ifdef AMIGA |
615 |
# define OS_TYPE "AMIGA" |
616 |
/* STACKBOTTOM and DATASTART handled specially */ |
617 |
/* in os_dep.c */ |
618 |
# define DATAEND /* not needed */ |
619 |
# define GETPAGESIZE() 4096 |
620 |
# endif |
621 |
# ifdef MACOS |
622 |
# ifndef __LOWMEM__ |
623 |
# include <LowMem.h> |
624 |
# endif |
625 |
# define OS_TYPE "MACOS" |
626 |
/* see os_dep.c for details of global data segments. */ |
627 |
# define STACKBOTTOM ((ptr_t) LMGetCurStackBase()) |
628 |
# define DATAEND /* not needed */ |
629 |
# define GETPAGESIZE() 4096 |
630 |
# endif |
631 |
# ifdef NEXT |
632 |
# define OS_TYPE "NEXT" |
633 |
# define DATASTART ((ptr_t) get_etext()) |
634 |
# define STACKBOTTOM ((ptr_t) 0x4000000) |
635 |
# define DATAEND /* not needed */ |
636 |
# endif |
637 |
# endif |
638 |
|
639 |
# ifdef POWERPC |
640 |
# define MACH_TYPE "POWERPC" |
641 |
# ifdef MACOS |
642 |
# define ALIGNMENT 2 /* Still necessary? Could it be 4? */ |
643 |
# ifndef __LOWMEM__ |
644 |
# include <LowMem.h> |
645 |
# endif |
646 |
# define OS_TYPE "MACOS" |
647 |
/* see os_dep.c for details of global data segments. */ |
648 |
# define STACKBOTTOM ((ptr_t) LMGetCurStackBase()) |
649 |
# define DATAEND /* not needed */ |
650 |
# endif |
651 |
# ifdef LINUX |
652 |
# define ALIGNMENT 4 /* Guess. Can someone verify? */ |
653 |
/* This was 2, but that didn't sound right. */ |
654 |
# define OS_TYPE "LINUX" |
655 |
# define HEURISTIC1 |
656 |
# define DYNAMIC_LOADING |
657 |
# undef STACK_GRAN |
658 |
# define STACK_GRAN 0x10000000 |
659 |
/* Stack usually starts at 0x80000000 */ |
660 |
# define LINUX_DATA_START |
661 |
extern int _end; |
662 |
# define DATAEND (&_end) |
663 |
# endif |
664 |
# ifdef MACOSX |
665 |
# define ALIGNMENT 4 |
666 |
# define OS_TYPE "MACOSX" |
667 |
# define DATASTART ((ptr_t) get_etext()) |
668 |
# define STACKBOTTOM ((ptr_t) 0xc0000000) |
669 |
# define DATAEND /* not needed */ |
670 |
# endif |
671 |
# endif |
672 |
|
673 |
# ifdef VAX |
674 |
# define MACH_TYPE "VAX" |
675 |
# define ALIGNMENT 4 /* Pointers are longword aligned by 4.2 C compiler */ |
676 |
extern char etext; |
677 |
# define DATASTART ((ptr_t)(&etext)) |
678 |
# ifdef BSD |
679 |
# define OS_TYPE "BSD" |
680 |
# define HEURISTIC1 |
681 |
/* HEURISTIC2 may be OK, but it's hard to test. */ |
682 |
# endif |
683 |
# ifdef ULTRIX |
684 |
# define OS_TYPE "ULTRIX" |
685 |
# define STACKBOTTOM ((ptr_t) 0x7fffc800) |
686 |
# endif |
687 |
# endif |
688 |
|
689 |
# ifdef RT |
690 |
# define MACH_TYPE "RT" |
691 |
# define ALIGNMENT 4 |
692 |
# define DATASTART ((ptr_t) 0x10000000) |
693 |
# define STACKBOTTOM ((ptr_t) 0x1fffd800) |
694 |
# endif |
695 |
|
696 |
# ifdef SPARC |
697 |
# define MACH_TYPE "SPARC" |
698 |
# define ALIGNMENT 4 /* Required by hardware */ |
699 |
# define ALIGN_DOUBLE |
700 |
extern int etext; |
701 |
# ifdef SUNOS5 |
702 |
# define OS_TYPE "SUNOS5" |
703 |
extern int _etext; |
704 |
extern int _end; |
705 |
extern char * GC_SysVGetDataStart(); |
706 |
# define DATASTART (ptr_t)GC_SysVGetDataStart(0x10000, &_etext) |
707 |
# define DATAEND (&_end) |
708 |
# ifndef USE_MMAP |
709 |
# define USE_MMAP |
710 |
# endif |
711 |
# ifdef USE_MMAP |
712 |
# define HEAP_START (ptr_t)0x40000000 |
713 |
# else |
714 |
# define HEAP_START DATAEND |
715 |
# endif |
716 |
# define PROC_VDB |
717 |
/* HEURISTIC1 reportedly no longer works under 2.7. Thus we */ |
718 |
/* switched to HEURISTIC2, eventhough it creates some debugging */ |
719 |
/* issues. */ |
720 |
# define HEURISTIC2 |
721 |
# include <unistd.h> |
722 |
# define GETPAGESIZE() sysconf(_SC_PAGESIZE) |
723 |
/* getpagesize() appeared to be missing from at least one */ |
724 |
/* Solaris 5.4 installation. Weird. */ |
725 |
# define DYNAMIC_LOADING |
726 |
# endif |
727 |
# ifdef SUNOS4 |
728 |
# define OS_TYPE "SUNOS4" |
729 |
/* [If you have a weak stomach, don't read this.] */ |
730 |
/* We would like to use: */ |
731 |
/* # define DATASTART ((ptr_t)((((word) (&etext)) + 0x1fff) & ~0x1fff)) */ |
732 |
/* This fails occasionally, due to an ancient, but very */ |
733 |
/* persistent ld bug. &etext is set 32 bytes too high. */ |
734 |
/* We instead read the text segment size from the a.out */ |
735 |
/* header, which happens to be mapped into our address space */ |
736 |
/* at the start of the text segment. The detective work here */ |
737 |
/* was done by Robert Ehrlich, Manuel Serrano, and Bernard */ |
738 |
/* Serpette of INRIA. */ |
739 |
/* This assumes ZMAGIC, i.e. demand-loadable executables. */ |
740 |
# define TEXTSTART 0x2000 |
741 |
# define DATASTART ((ptr_t)(*(int *)(TEXTSTART+0x4)+TEXTSTART)) |
742 |
# define MPROTECT_VDB |
743 |
# define HEURISTIC1 |
744 |
# define DYNAMIC_LOADING |
745 |
# endif |
746 |
# ifdef DRSNX |
747 |
# define CPP_WORDSZ 32 |
748 |
# define OS_TYPE "DRSNX" |
749 |
extern char * GC_SysVGetDataStart(); |
750 |
extern int etext; |
751 |
# define DATASTART (ptr_t)GC_SysVGetDataStart(0x10000, &etext) |
752 |
# define MPROTECT_VDB |
753 |
# define STACKBOTTOM ((ptr_t) 0xdfff0000) |
754 |
# define DYNAMIC_LOADING |
755 |
# endif |
756 |
# ifdef LINUX |
757 |
# define OS_TYPE "LINUX" |
758 |
# ifdef __ELF__ |
759 |
# define LINUX_DATA_START |
760 |
# define DYNAMIC_LOADING |
761 |
# else |
762 |
Linux Sparc non elf ? |
763 |
# endif |
764 |
extern int _end; |
765 |
# define DATAEND (&_end) |
766 |
# define SVR4 |
767 |
# define STACKBOTTOM ((ptr_t) 0xf0000000) |
768 |
# endif |
769 |
# ifdef OPENBSD |
770 |
# define OS_TYPE "OPENBSD" |
771 |
# define STACKBOTTOM ((ptr_t) 0xf8000000) |
772 |
# define DATASTART ((ptr_t)(&etext)) |
773 |
# endif |
774 |
# endif |
775 |
|
776 |
# ifdef I386 |
777 |
# define MACH_TYPE "I386" |
778 |
# define ALIGNMENT 4 /* Appears to hold for all "32 bit" compilers */ |
779 |
/* except Borland. The -a4 option fixes */ |
780 |
/* Borland. */ |
781 |
/* Ivan Demakov: For Watcom the option is -zp4. */ |
782 |
# ifndef SMALL_CONFIG |
783 |
# define ALIGN_DOUBLE /* Not strictly necessary, but may give speed */ |
784 |
/* improvement on Pentiums. */ |
785 |
# endif |
786 |
# ifdef SEQUENT |
787 |
# define OS_TYPE "SEQUENT" |
788 |
extern int etext; |
789 |
# define DATASTART ((ptr_t)((((word) (&etext)) + 0xfff) & ~0xfff)) |
790 |
# define STACKBOTTOM ((ptr_t) 0x3ffff000) |
791 |
# endif |
792 |
# ifdef SUNOS5 |
793 |
# define OS_TYPE "SUNOS5" |
794 |
extern int etext, _start; |
795 |
extern char * GC_SysVGetDataStart(); |
796 |
# define DATASTART GC_SysVGetDataStart(0x1000, &etext) |
797 |
# define STACKBOTTOM ((ptr_t)(&_start)) |
798 |
/** At least in Solaris 2.5, PROC_VDB gives wrong values for dirty bits. */ |
799 |
/*# define PROC_VDB*/ |
800 |
# define DYNAMIC_LOADING |
801 |
# ifndef USE_MMAP |
802 |
# define USE_MMAP |
803 |
# endif |
804 |
# ifdef USE_MMAP |
805 |
# define HEAP_START (ptr_t)0x40000000 |
806 |
# else |
807 |
# define HEAP_START DATAEND |
808 |
# endif |
809 |
# endif |
810 |
# ifdef SCO |
811 |
# define OS_TYPE "SCO" |
812 |
extern int etext; |
813 |
# define DATASTART ((ptr_t)((((word) (&etext)) + 0x3fffff) \ |
814 |
& ~0x3fffff) \ |
815 |
+((word)&etext & 0xfff)) |
816 |
# define STACKBOTTOM ((ptr_t) 0x7ffffffc) |
817 |
# endif |
818 |
# ifdef SCO_ELF |
819 |
# define OS_TYPE "SCO_ELF" |
820 |
extern int etext; |
821 |
# define DATASTART ((ptr_t)(&etext)) |
822 |
# define STACKBOTTOM ((ptr_t) 0x08048000) |
823 |
# define DYNAMIC_LOADING |
824 |
# define ELF_CLASS ELFCLASS32 |
825 |
# endif |
826 |
# ifdef LINUX |
827 |
# define OS_TYPE "LINUX" |
828 |
# define LINUX_STACKBOTTOM |
829 |
# if 0 |
830 |
# define HEURISTIC1 |
831 |
# undef STACK_GRAN |
832 |
# define STACK_GRAN 0x10000000 |
833 |
/* STACKBOTTOM is usually 0xc0000000, but this changes with */ |
834 |
/* different kernel configurations. In particular, systems */ |
835 |
/* with 2GB physical memory will usually move the user */ |
836 |
/* address space limit, and hence initial SP to 0x80000000. */ |
837 |
# endif |
838 |
# if !defined(LINUX_THREADS) || !defined(REDIRECT_MALLOC) |
839 |
# define MPROTECT_VDB |
840 |
# else |
841 |
/* We seem to get random errors in incremental mode, */ |
842 |
/* possibly because Linux threads is itself a malloc client */ |
843 |
/* and can't deal with the signals. */ |
844 |
# endif |
845 |
# ifdef __ELF__ |
846 |
# define DYNAMIC_LOADING |
847 |
# ifdef UNDEFINED /* includes ro data */ |
848 |
extern int _etext; |
849 |
# define DATASTART ((ptr_t)((((word) (&_etext)) + 0xfff) & ~0xfff)) |
850 |
# endif |
851 |
# include <features.h> |
852 |
# if defined(__GLIBC__) && __GLIBC__ >= 2 |
853 |
# define LINUX_DATA_START |
854 |
# else |
855 |
extern char **__environ; |
856 |
# define DATASTART ((ptr_t)(&__environ)) |
857 |
/* hideous kludge: __environ is the first */ |
858 |
/* word in crt0.o, and delimits the start */ |
859 |
/* of the data segment, no matter which */ |
860 |
/* ld options were passed through. */ |
861 |
/* We could use _etext instead, but that */ |
862 |
/* would include .rodata, which may */ |
863 |
/* contain large read-only data tables */ |
864 |
/* that we'd rather not scan. */ |
865 |
# endif |
866 |
extern int _end; |
867 |
# define DATAEND (&_end) |
868 |
# else |
869 |
extern int etext; |
870 |
# define DATASTART ((ptr_t)((((word) (&etext)) + 0xfff) & ~0xfff)) |
871 |
# endif |
872 |
# ifdef USE_I686_PREFETCH |
873 |
# define PREFETCH(x) \ |
874 |
__asm__ __volatile__ (" prefetchnta %0": : "m"(*(char *)(x))) |
875 |
/* Empirically prefetcht0 is much more effective at reducing */ |
876 |
/* cache miss stalls for the targetted load instructions. But it */ |
877 |
/* seems to interfere enough with other cache traffic that the net */ |
878 |
/* result is worse than prefetchnta. */ |
879 |
# if 0 |
880 |
/* Using prefetches for write seems to have a slight negative */ |
881 |
/* impact on performance, at least for a PIII/500. */ |
882 |
# define PREFETCH_FOR_WRITE(x) \ |
883 |
__asm__ __volatile__ (" prefetcht0 %0": : "m"(*(char *)(x))) |
884 |
# endif |
885 |
# endif |
886 |
# ifdef USE_3DNOW_PREFETCH |
887 |
# define PREFETCH(x) \ |
888 |
__asm__ __volatile__ (" prefetch %0": : "m"(*(char *)(x))) |
889 |
# define PREFETCH_FOR_WRITE(x) |
890 |
__asm__ __volatile__ (" prefetchw %0": : "m"(*(char *)(x))) |
891 |
# endif |
892 |
# endif |
893 |
# ifdef CYGWIN32 |
894 |
# define OS_TYPE "CYGWIN32" |
895 |
extern int _data_start__; |
896 |
extern int _data_end__; |
897 |
extern int _bss_start__; |
898 |
extern int _bss_end__; |
899 |
/* For binutils 2.9.1, we have */ |
900 |
/* DATASTART = _data_start__ */ |
901 |
/* DATAEND = _bss_end__ */ |
902 |
/* whereas for some earlier versions it was */ |
903 |
/* DATASTART = _bss_start__ */ |
904 |
/* DATAEND = _data_end__ */ |
905 |
/* To get it right for both, we take the */ |
906 |
/* minumum/maximum of the two. */ |
907 |
# define MAX(x,y) ((x) > (y) ? (x) : (y)) |
908 |
# define MIN(x,y) ((x) < (y) ? (x) : (y)) |
909 |
# define DATASTART ((ptr_t) MIN(&_data_start__, &_bss_start__)) |
910 |
# define DATAEND ((ptr_t) MAX(&_data_end__, &_bss_end__)) |
911 |
# undef STACK_GRAN |
912 |
# define STACK_GRAN 0x10000 |
913 |
# define HEURISTIC1 |
914 |
# endif |
915 |
# ifdef OS2 |
916 |
# define OS_TYPE "OS2" |
917 |
/* STACKBOTTOM and DATASTART are handled specially in */ |
918 |
/* os_dep.c. OS2 actually has the right */ |
919 |
/* system call! */ |
920 |
# define DATAEND /* not needed */ |
921 |
# endif |
922 |
# ifdef MSWIN32 |
923 |
# define OS_TYPE "MSWIN32" |
924 |
/* STACKBOTTOM and DATASTART are handled specially in */ |
925 |
/* os_dep.c. */ |
926 |
# ifndef __WATCOMC__ |
927 |
# define MPROTECT_VDB |
928 |
# endif |
929 |
# define DATAEND /* not needed */ |
930 |
# endif |
931 |
# ifdef DJGPP |
932 |
# define OS_TYPE "DJGPP" |
933 |
# include "stubinfo.h" |
934 |
extern int etext; |
935 |
extern int _stklen; |
936 |
extern int __djgpp_stack_limit; |
937 |
# define DATASTART ((ptr_t)((((word) (&etext)) + 0x1ff) & ~0x1ff)) |
938 |
/* # define STACKBOTTOM ((ptr_t)((word) _stubinfo + _stubinfo->size \ |
939 |
+ _stklen)) */ |
940 |
# define STACKBOTTOM ((ptr_t)((word) __djgpp_stack_limit + _stklen)) |
941 |
/* This may not be right. */ |
942 |
# endif |
943 |
# ifdef OPENBSD |
944 |
# define OS_TYPE "OPENBSD" |
945 |
# endif |
946 |
# ifdef FREEBSD |
947 |
# define OS_TYPE "FREEBSD" |
948 |
# define MPROTECT_VDB |
949 |
# endif |
950 |
# ifdef NETBSD |
951 |
# define OS_TYPE "NETBSD" |
952 |
# endif |
953 |
# ifdef THREE86BSD |
954 |
# define OS_TYPE "THREE86BSD" |
955 |
# endif |
956 |
# ifdef BSDI |
957 |
# define OS_TYPE "BSDI" |
958 |
# endif |
959 |
# if defined(OPENBSD) || defined(FREEBSD) || defined(NETBSD) \ |
960 |
|| defined(THREE86BSD) || defined(BSDI) |
961 |
# define HEURISTIC2 |
962 |
extern char etext; |
963 |
# define DATASTART ((ptr_t)(&etext)) |
964 |
# endif |
965 |
# ifdef NEXT |
966 |
# define OS_TYPE "NEXT" |
967 |
# define DATASTART ((ptr_t) get_etext()) |
968 |
# define STACKBOTTOM ((ptr_t)0xc0000000) |
969 |
# define DATAEND /* not needed */ |
970 |
# endif |
971 |
# ifdef DOS4GW |
972 |
# define OS_TYPE "DOS4GW" |
973 |
extern long __nullarea; |
974 |
extern char _end; |
975 |
extern char *_STACKTOP; |
976 |
/* Depending on calling conventions Watcom C either precedes |
977 |
or does not precedes with undescore names of C-variables. |
978 |
Make sure startup code variables always have the same names. */ |
979 |
#pragma aux __nullarea "*"; |
980 |
#pragma aux _end "*"; |
981 |
# define STACKBOTTOM ((ptr_t) _STACKTOP) |
982 |
/* confused? me too. */ |
983 |
# define DATASTART ((ptr_t) &__nullarea) |
984 |
# define DATAEND ((ptr_t) &_end) |
985 |
# endif |
986 |
# ifdef GNU |
987 |
# define OS_TYPE "GNU" |
988 |
# endif |
989 |
# endif |
990 |
|
991 |
# ifdef NS32K |
992 |
# define MACH_TYPE "NS32K" |
993 |
# define ALIGNMENT 4 |
994 |
extern char **environ; |
995 |
# define DATASTART ((ptr_t)(&environ)) |
996 |
/* hideous kludge: environ is the first */ |
997 |
/* word in crt0.o, and delimits the start */ |
998 |
/* of the data segment, no matter which */ |
999 |
/* ld options were passed through. */ |
1000 |
# define STACKBOTTOM ((ptr_t) 0xfffff000) /* for Encore */ |
1001 |
# endif |
1002 |
|
1003 |
# ifdef MIPS |
1004 |
# define MACH_TYPE "MIPS" |
1005 |
/* # define STACKBOTTOM ((ptr_t)0x7fff8000) sometimes also works. */ |
1006 |
# ifdef LINUX |
1007 |
/* This was developed for a linuxce style platform. Probably */ |
1008 |
/* needs to be tweaked for workstation class machines. */ |
1009 |
# define OS_TYPE "LINUX" |
1010 |
extern int __data_start; |
1011 |
# define DATASTART ((ptr_t)(&__data_start)) |
1012 |
# define ALIGNMENT 4 |
1013 |
# define USE_GENERIC_PUSH_REGS 1 |
1014 |
# define STACKBOTTOM 0x80000000 |
1015 |
/* In many cases, this should probably use LINUX_STACKBOTTOM */ |
1016 |
/* instead. But some kernel versions seem to give the wrong */ |
1017 |
/* value from /proc. */ |
1018 |
# endif /* Linux */ |
1019 |
# ifdef ULTRIX |
1020 |
# define HEURISTIC2 |
1021 |
# define DATASTART (ptr_t)0x10000000 |
1022 |
/* Could probably be slightly higher since */ |
1023 |
/* startup code allocates lots of stuff. */ |
1024 |
# define OS_TYPE "ULTRIX" |
1025 |
# define ALIGNMENT 4 |
1026 |
# endif |
1027 |
# ifdef RISCOS |
1028 |
# define HEURISTIC2 |
1029 |
# define DATASTART (ptr_t)0x10000000 |
1030 |
# define OS_TYPE "RISCOS" |
1031 |
# define ALIGNMENT 4 /* Required by hardware */ |
1032 |
# endif |
1033 |
# ifdef IRIX5 |
1034 |
# define HEURISTIC2 |
1035 |
extern int _fdata; |
1036 |
# define DATASTART ((ptr_t)(&_fdata)) |
1037 |
# ifdef USE_MMAP |
1038 |
# define HEAP_START (ptr_t)0x30000000 |
1039 |
# else |
1040 |
# define HEAP_START DATASTART |
1041 |
# endif |
1042 |
/* Lowest plausible heap address. */ |
1043 |
/* In the MMAP case, we map there. */ |
1044 |
/* In either case it is used to identify */ |
1045 |
/* heap sections so they're not */ |
1046 |
/* considered as roots. */ |
1047 |
# define OS_TYPE "IRIX5" |
1048 |
# define MPROTECT_VDB |
1049 |
# ifdef _MIPS_SZPTR |
1050 |
# define CPP_WORDSZ _MIPS_SZPTR |
1051 |
# define ALIGNMENT (_MIPS_SZPTR/8) |
1052 |
# if CPP_WORDSZ != 64 |
1053 |
# define ALIGN_DOUBLE |
1054 |
# endif |
1055 |
# else |
1056 |
# define ALIGNMENT 4 |
1057 |
# define ALIGN_DOUBLE |
1058 |
# endif |
1059 |
# define DYNAMIC_LOADING |
1060 |
# endif |
1061 |
# endif |
1062 |
|
1063 |
# ifdef RS6000 |
1064 |
# define MACH_TYPE "RS6000" |
1065 |
# define ALIGNMENT 4 |
1066 |
# define DATASTART ((ptr_t)0x20000000) |
1067 |
extern int errno; |
1068 |
# define STACKBOTTOM ((ptr_t)((ulong)&errno)) |
1069 |
# define DYNAMIC_LOADING |
1070 |
/* For really old versions of AIX, this may have to be removed. */ |
1071 |
# endif |
1072 |
|
1073 |
# ifdef HP_PA |
1074 |
/* OS is assumed to be HP/UX */ |
1075 |
# define MACH_TYPE "HP_PA" |
1076 |
# define OS_TYPE "HPUX" |
1077 |
# ifdef __LP64__ |
1078 |
# define CPP_WORDSZ 64 |
1079 |
# define ALIGNMENT 8 |
1080 |
# else |
1081 |
# define CPP_WORDSZ 32 |
1082 |
# define ALIGNMENT 4 |
1083 |
# define ALIGN_DOUBLE |
1084 |
# endif |
1085 |
extern int __data_start; |
1086 |
# define DATASTART ((ptr_t)(&__data_start)) |
1087 |
# if 0 |
1088 |
/* The following appears to work for 7xx systems running HP/UX */ |
1089 |
/* 9.xx Furthermore, it might result in much faster */ |
1090 |
/* collections than HEURISTIC2, which may involve scanning */ |
1091 |
/* segments that directly precede the stack. It is not the */ |
1092 |
/* default, since it may not work on older machine/OS */ |
1093 |
/* combinations. (Thanks to Raymond X.T. Nijssen for uncovering */ |
1094 |
/* this.) */ |
1095 |
# define STACKBOTTOM ((ptr_t) 0x7b033000) /* from /etc/conf/h/param.h */ |
1096 |
# else |
1097 |
/* Gustavo Rodriguez-Rivera suggested changing HEURISTIC2 */ |
1098 |
/* to this. We'll probably do this on other platforms, too. */ |
1099 |
/* For now I'll use it where I can test it. */ |
1100 |
extern char ** environ; |
1101 |
# define STACKBOTTOM ((ptr_t)environ) |
1102 |
# endif |
1103 |
# ifndef SCM_STACK_GROWS_UP /* don't fight with scmconfig.h */ |
1104 |
# define SCM_STACK_GROWS_UP 1 |
1105 |
# endif |
1106 |
# define DYNAMIC_LOADING |
1107 |
# ifndef HPUX_THREADS |
1108 |
# define MPROTECT_VDB |
1109 |
# endif |
1110 |
# include <unistd.h> |
1111 |
# define GETPAGESIZE() sysconf(_SC_PAGE_SIZE) |
1112 |
# endif |
1113 |
|
1114 |
# ifdef ALPHA |
1115 |
# define MACH_TYPE "ALPHA" |
1116 |
# define ALIGNMENT 8 |
1117 |
# define USE_GENERIC_PUSH_REGS |
1118 |
/* Gcc and probably the DEC/Compaq compiler spill pointers to preserved */ |
1119 |
/* fp registers in some cases when the target is a 21264. The assembly */ |
1120 |
/* code doesn't handle that yet, and version dependencies make that a */ |
1121 |
/* bit tricky. Do the easy thing for now. */ |
1122 |
# ifdef OSF1 |
1123 |
# define OS_TYPE "OSF1" |
1124 |
# define DATASTART ((ptr_t) 0x140000000) |
1125 |
extern _end; |
1126 |
# define DATAEND ((ptr_t) &_end) |
1127 |
# define HEURISTIC2 |
1128 |
/* Normally HEURISTIC2 is too conervative, since */ |
1129 |
/* the text segment immediately follows the stack. */ |
1130 |
/* Hence we give an upper pound. */ |
1131 |
extern int __start; |
1132 |
# define HEURISTIC2_LIMIT ((ptr_t)((word)(&__start) & ~(getpagesize()-1))) |
1133 |
# define CPP_WORDSZ 64 |
1134 |
# define MPROTECT_VDB |
1135 |
# define DYNAMIC_LOADING |
1136 |
# endif |
1137 |
# ifdef LINUX |
1138 |
# define OS_TYPE "LINUX" |
1139 |
# define CPP_WORDSZ 64 |
1140 |
# define STACKBOTTOM ((ptr_t) 0x120000000) |
1141 |
# ifdef __ELF__ |
1142 |
# define LINUX_DATA_START |
1143 |
# define DYNAMIC_LOADING |
1144 |
/* This doesn't work if the collector is in a dynamic library. */ |
1145 |
# else |
1146 |
# define DATASTART ((ptr_t) 0x140000000) |
1147 |
# endif |
1148 |
extern int _end; |
1149 |
# define DATAEND (&_end) |
1150 |
# define MPROTECT_VDB |
1151 |
/* Has only been superficially tested. May not */ |
1152 |
/* work on all versions. */ |
1153 |
# endif |
1154 |
# endif |
1155 |
|
1156 |
# ifdef IA64 |
1157 |
# define MACH_TYPE "IA64" |
1158 |
# define ALIGN_DOUBLE |
1159 |
/* Requires 16 byte alignment for malloc */ |
1160 |
# define ALIGNMENT 8 |
1161 |
# define USE_GENERIC_PUSH_REGS |
1162 |
/* We need to get preserved registers in addition to register windows. */ |
1163 |
/* That's easiest to do with setjmp. */ |
1164 |
# ifdef HPUX |
1165 |
--> needs work |
1166 |
# endif |
1167 |
# ifdef LINUX |
1168 |
# define OS_TYPE "LINUX" |
1169 |
# define CPP_WORDSZ 64 |
1170 |
/* This should really be done through /proc, but that */ |
1171 |
/* requires we run on an IA64 kernel. */ |
1172 |
# define STACKBOTTOM ((ptr_t) 0xa000000000000000l) |
1173 |
/* We also need the base address of the register stack */ |
1174 |
/* backing store. There is probably a better way to */ |
1175 |
/* get that, too ... */ |
1176 |
# define BACKING_STORE_BASE ((ptr_t) 0x9fffffff80000000l) |
1177 |
# if 1 |
1178 |
# define SEARCH_FOR_DATA_START |
1179 |
# define DATASTART GC_data_start |
1180 |
# else |
1181 |
extern int data_start; |
1182 |
# define DATASTART ((ptr_t)(&data_start)) |
1183 |
# endif |
1184 |
# define DYNAMIC_LOADING |
1185 |
# define MPROTECT_VDB |
1186 |
/* Requires Linux 2.3.47 or later. */ |
1187 |
extern int _end; |
1188 |
# define DATAEND (&_end) |
1189 |
# define PREFETCH(x) \ |
1190 |
__asm__ (" lfetch [%0]": : "r"((void *)(x))) |
1191 |
# define PREFETCH_FOR_WRITE(x) \ |
1192 |
__asm__ (" lfetch.excl [%0]": : "r"((void *)(x))) |
1193 |
# define CLEAR_DOUBLE(x) \ |
1194 |
__asm__ (" stf.spill [%0]=f0": : "r"((void *)(x))) |
1195 |
# endif |
1196 |
# endif |
1197 |
|
1198 |
# ifdef M88K |
1199 |
# define MACH_TYPE "M88K" |
1200 |
# define ALIGNMENT 4 |
1201 |
# define ALIGN_DOUBLE |
1202 |
extern int etext; |
1203 |
# ifdef CX_UX |
1204 |
# define OS_TYPE "CX_UX" |
1205 |
# define DATASTART ((((word)&etext + 0x3fffff) & ~0x3fffff) + 0x10000) |
1206 |
# endif |
1207 |
# ifdef DGUX |
1208 |
# define OS_TYPE "DGUX" |
1209 |
extern char * GC_SysVGetDataStart(); |
1210 |
# define DATASTART (ptr_t)GC_SysVGetDataStart(0x10000, &etext) |
1211 |
# endif |
1212 |
# define STACKBOTTOM ((char*)0xf0000000) /* determined empirically */ |
1213 |
# endif |
1214 |
|
1215 |
# ifdef S370 |
1216 |
# define MACH_TYPE "S370" |
1217 |
# define OS_TYPE "UTS4" |
1218 |
# define ALIGNMENT 4 /* Required by hardware */ |
1219 |
extern int etext; |
1220 |
extern int _etext; |
1221 |
extern int _end; |
1222 |
extern char * GC_SysVGetDataStart(); |
1223 |
# define DATASTART (ptr_t)GC_SysVGetDataStart(0x10000, &_etext) |
1224 |
# define DATAEND (&_end) |
1225 |
# define HEURISTIC2 |
1226 |
# endif |
1227 |
|
1228 |
# if defined(PJ) |
1229 |
# define ALIGNMENT 4 |
1230 |
extern int _etext; |
1231 |
# define DATASTART ((ptr_t)(&_etext)) |
1232 |
# define HEURISTIC1 |
1233 |
# endif |
1234 |
|
1235 |
# ifdef ARM32 |
1236 |
# define CPP_WORDSZ 32 |
1237 |
# define MACH_TYPE "ARM32" |
1238 |
# define ALIGNMENT 4 |
1239 |
# ifdef NETBSD |
1240 |
# define OS_TYPE "NETBSD" |
1241 |
# define HEURISTIC2 |
1242 |
extern char etext; |
1243 |
# define DATASTART ((ptr_t)(&etext)) |
1244 |
# define USE_GENERIC_PUSH_REGS |
1245 |
# endif |
1246 |
# ifdef LINUX |
1247 |
# define OS_TYPE "LINUX" |
1248 |
# define HEURISTIC1 |
1249 |
# undef STACK_GRAN |
1250 |
# define STACK_GRAN 0x10000000 |
1251 |
# define USE_GENERIC_PUSH_REGS |
1252 |
# ifdef __ELF__ |
1253 |
# define DYNAMIC_LOADING |
1254 |
# include <features.h> |
1255 |
# if defined(__GLIBC__) && __GLIBC__ >= 2 |
1256 |
# define LINUX_DATA_START |
1257 |
# else |
1258 |
extern char **__environ; |
1259 |
# define DATASTART ((ptr_t)(&__environ)) |
1260 |
/* hideous kludge: __environ is the first */ |
1261 |
/* word in crt0.o, and delimits the start */ |
1262 |
/* of the data segment, no matter which */ |
1263 |
/* ld options were passed through. */ |
1264 |
/* We could use _etext instead, but that */ |
1265 |
/* would include .rodata, which may */ |
1266 |
/* contain large read-only data tables */ |
1267 |
/* that we'd rather not scan. */ |
1268 |
# endif |
1269 |
extern int _end; |
1270 |
# define DATAEND (&_end) |
1271 |
# else |
1272 |
extern int etext; |
1273 |
# define DATASTART ((ptr_t)((((word) (&etext)) + 0xfff) & ~0xfff)) |
1274 |
# endif |
1275 |
# endif |
1276 |
#endif |
1277 |
|
1278 |
#ifdef LINUX_DATA_START |
1279 |
/* Some Linux distributions arrange to define __data_start. Some */ |
1280 |
/* define data_start as a weak symbol. The latter is technically */ |
1281 |
/* broken, since the user program may define data_start, in which */ |
1282 |
/* case we lose. Nonetheless, we try both, prefering __data_start. */ |
1283 |
/* We assume gcc. */ |
1284 |
# pragma weak __data_start |
1285 |
extern int __data_start; |
1286 |
# pragma weak data_start |
1287 |
extern int data_start; |
1288 |
# define DATASTART ((ptr_t)(&__data_start != 0? &__data_start : &data_start)) |
1289 |
#endif |
1290 |
|
1291 |
# if SCM_STACK_GROWS_UP |
1292 |
# define STACK_GROWS_DOWN 0 |
1293 |
# else |
1294 |
# define STACK_GROWS_DOWN 1 |
1295 |
#endif |
1296 |
|
1297 |
# ifndef CPP_WORDSZ |
1298 |
# define CPP_WORDSZ 32 |
1299 |
# endif |
1300 |
|
1301 |
# ifndef OS_TYPE |
1302 |
# define OS_TYPE "" |
1303 |
# endif |
1304 |
|
1305 |
# ifndef DATAEND |
1306 |
extern int end; |
1307 |
# define DATAEND (&end) |
1308 |
# endif |
1309 |
|
1310 |
# if defined(SVR4) && !defined(GETPAGESIZE) |
1311 |
# include <unistd.h> |
1312 |
# define GETPAGESIZE() sysconf(_SC_PAGESIZE) |
1313 |
# endif |
1314 |
|
1315 |
# ifndef GETPAGESIZE |
1316 |
# if defined(SUNOS5) || defined(IRIX5) |
1317 |
# include <unistd.h> |
1318 |
# endif |
1319 |
# define GETPAGESIZE() getpagesize() |
1320 |
# endif |
1321 |
|
1322 |
# if defined(SUNOS5) || defined(DRSNX) || defined(UTS4) |
1323 |
/* OS has SVR4 generic features. Probably others also qualify. */ |
1324 |
# define SVR4 |
1325 |
# endif |
1326 |
|
1327 |
# if defined(SUNOS5) || defined(DRSNX) |
1328 |
/* OS has SUNOS5 style semi-undocumented interface to dynamic */ |
1329 |
/* loader. */ |
1330 |
# define SUNOS5DL |
1331 |
/* OS has SUNOS5 style signal handlers. */ |
1332 |
# define SUNOS5SIGS |
1333 |
# endif |
1334 |
|
1335 |
# if defined(HPUX) |
1336 |
# define SUNOS5SIGS |
1337 |
# endif |
1338 |
|
1339 |
# if CPP_WORDSZ != 32 && CPP_WORDSZ != 64 |
1340 |
-> bad word size |
1341 |
# endif |
1342 |
|
1343 |
# ifdef PCR |
1344 |
# undef DYNAMIC_LOADING |
1345 |
# undef STACKBOTTOM |
1346 |
# undef HEURISTIC1 |
1347 |
# undef HEURISTIC2 |
1348 |
# undef PROC_VDB |
1349 |
# undef MPROTECT_VDB |
1350 |
# define PCR_VDB |
1351 |
# endif |
1352 |
|
1353 |
# ifdef SRC_M3 |
1354 |
/* Postponed for now. */ |
1355 |
# undef PROC_VDB |
1356 |
# undef MPROTECT_VDB |
1357 |
# endif |
1358 |
|
1359 |
# ifdef SMALL_CONFIG |
1360 |
/* Presumably not worth the space it takes. */ |
1361 |
# undef PROC_VDB |
1362 |
# undef MPROTECT_VDB |
1363 |
# endif |
1364 |
|
1365 |
# ifdef USE_MUNMAP |
1366 |
# undef MPROTECT_VDB /* Can't deal with address space holes. */ |
1367 |
# endif |
1368 |
|
1369 |
# if !defined(PCR_VDB) && !defined(PROC_VDB) && !defined(MPROTECT_VDB) |
1370 |
# define DEFAULT_VDB |
1371 |
# endif |
1372 |
|
1373 |
# ifndef PREFETCH |
1374 |
# define PREFETCH(x) |
1375 |
# define NO_PREFETCH |
1376 |
# endif |
1377 |
|
1378 |
# ifndef PREFETCH_FOR_WRITE |
1379 |
# define PREFETCH_FOR_WRITE(x) |
1380 |
# define NO_PREFETCH_FOR_WRITE |
1381 |
# endif |
1382 |
|
1383 |
# ifndef CACHE_LINE_SIZE |
1384 |
# define CACHE_LINE_SIZE 32 /* Wild guess */ |
1385 |
# endif |
1386 |
|
1387 |
# ifndef CLEAR_DOUBLE |
1388 |
# define CLEAR_DOUBLE(x) \ |
1389 |
((word*)x)[0] = 0; \ |
1390 |
((word*)x)[1] = 0; |
1391 |
# endif /* CLEAR_DOUBLE */ |
1392 |
|
1393 |
# if defined(_SOLARIS_PTHREADS) && !defined(SOLARIS_THREADS) |
1394 |
# define SOLARIS_THREADS |
1395 |
# endif |
1396 |
# if defined(IRIX_THREADS) && !defined(IRIX5) |
1397 |
--> inconsistent configuration |
1398 |
# endif |
1399 |
# if defined(IRIX_JDK_THREADS) && !defined(IRIX5) |
1400 |
--> inconsistent configuration |
1401 |
# endif |
1402 |
# if defined(LINUX_THREADS) && !defined(LINUX) |
1403 |
--> inconsistent configuration |
1404 |
# endif |
1405 |
# if defined(SOLARIS_THREADS) && !defined(SUNOS5) |
1406 |
--> inconsistent configuration |
1407 |
# endif |
1408 |
# if defined(HPUX_THREADS) && !defined(HPUX) |
1409 |
--> inconsistent configuration |
1410 |
# endif |
1411 |
# if defined(PCR) || defined(SRC_M3) || \ |
1412 |
defined(SOLARIS_THREADS) || defined(WIN32_THREADS) || \ |
1413 |
defined(IRIX_THREADS) || defined(LINUX_THREADS) || \ |
1414 |
defined(IRIX_JDK_THREADS) || defined(HPUX_THREADS) |
1415 |
# define THREADS |
1416 |
# endif |
1417 |
|
1418 |
# if defined(HP_PA) || defined(M88K) || defined(POWERPC) \ |
1419 |
|| (defined(I386) && defined(OS2)) || defined(UTS4) || defined(LINT) |
1420 |
/* Use setjmp based hack to mark from callee-save registers. */ |
1421 |
# define USE_GENERIC_PUSH_REGS |
1422 |
# endif |
1423 |
# if defined(SPARC) && !defined(LINUX) |
1424 |
# define SAVE_CALL_CHAIN |
1425 |
# define ASM_CLEAR_CODE /* Stack clearing is crucial, and we */ |
1426 |
/* include assembly code to do it well. */ |
1427 |
# endif |
1428 |
|
1429 |
# if defined(LINUX) && !defined(POWERPC) |
1430 |
|
1431 |
# if 0 |
1432 |
# include <linux/version.h> |
1433 |
# if (LINUX_VERSION_CODE <= 0x10400) |
1434 |
/* Ugly hack to get struct sigcontext_struct definition. Required */ |
1435 |
/* for some early 1.3.X releases. Will hopefully go away soon. */ |
1436 |
/* in some later Linux releases, asm/sigcontext.h may have to */ |
1437 |
/* be included instead. */ |
1438 |
# define __KERNEL__ |
1439 |
# include <asm/signal.h> |
1440 |
# undef __KERNEL__ |
1441 |
# endif |
1442 |
|
1443 |
# else |
1444 |
|
1445 |
/* Kernels prior to 2.1.1 defined struct sigcontext_struct instead of */ |
1446 |
/* struct sigcontext. libc6 (glibc2) uses "struct sigcontext" in */ |
1447 |
/* prototypes, so we have to include the top-level sigcontext.h to */ |
1448 |
/* make sure the former gets defined to be the latter if appropriate. */ |
1449 |
# include <features.h> |
1450 |
# if 2 <= __GLIBC__ |
1451 |
# if 2 == __GLIBC__ && 0 == __GLIBC_MINOR__ |
1452 |
/* glibc 2.1 no longer has sigcontext.h. But signal.h */ |
1453 |
/* has the right declaration for glibc 2.1. */ |
1454 |
# include <sigcontext.h> |
1455 |
# endif /* 0 == __GLIBC_MINOR__ */ |
1456 |
# else /* not 2 <= __GLIBC__ */ |
1457 |
/* libc5 doesn't have <sigcontext.h>: go directly with the kernel */ |
1458 |
/* one. Check LINUX_VERSION_CODE to see which we should reference. */ |
1459 |
# include <asm/sigcontext.h> |
1460 |
# endif /* 2 <= __GLIBC__ */ |
1461 |
# endif |
1462 |
# endif |
1463 |
# if !defined(OS2) && !defined(PCR) && !defined(AMIGA) && !defined(MACOS) |
1464 |
# include <sys/types.h> |
1465 |
# if !defined(MSWIN32) && !defined(SUNOS4) |
1466 |
# include <unistd.h> |
1467 |
# endif |
1468 |
# endif |
1469 |
|
1470 |
# include <signal.h> |
1471 |
|
1472 |
/* Blatantly OS dependent routines, except for those that are related */ |
1473 |
/* to dynamic loading. */ |
1474 |
|
1475 |
# if !defined(THREADS) && !defined(STACKBOTTOM) && defined(HEURISTIC2) |
1476 |
# define NEED_FIND_LIMIT |
1477 |
# endif |
1478 |
|
1479 |
# if defined(IRIX_THREADS) || defined(HPUX_THREADS) |
1480 |
# define NEED_FIND_LIMIT |
1481 |
# endif |
1482 |
|
1483 |
# if (defined(SUNOS4) && defined(DYNAMIC_LOADING)) && !defined(PCR) |
1484 |
# define NEED_FIND_LIMIT |
1485 |
# endif |
1486 |
|
1487 |
# if (defined(SVR4) || defined(AUX) || defined(DGUX)) && !defined(PCR) |
1488 |
# define NEED_FIND_LIMIT |
1489 |
# endif |
1490 |
|
1491 |
# if defined(LINUX) && \ |
1492 |
(defined(POWERPC) || defined(SPARC) || defined(ALPHA) || defined(IA64) \ |
1493 |
|| defined(MIPS)) |
1494 |
# define NEED_FIND_LIMIT |
1495 |
# endif |
1496 |
|
1497 |
#ifdef NEED_FIND_LIMIT |
1498 |
# include <setjmp.h> |
1499 |
#endif |
1500 |
|
1501 |
#ifdef FREEBSD |
1502 |
# include <machine/trap.h> |
1503 |
#endif |
1504 |
|
1505 |
#ifdef AMIGA |
1506 |
# include <proto/exec.h> |
1507 |
# include <proto/dos.h> |
1508 |
# include <dos/dosextens.h> |
1509 |
# include <workbench/startup.h> |
1510 |
#endif |
1511 |
|
1512 |
#ifdef MSWIN32 |
1513 |
# define WIN32_LEAN_AND_MEAN |
1514 |
# define NOSERVICE |
1515 |
# include <windows.h> |
1516 |
#endif |
1517 |
|
1518 |
#ifdef MACOS |
1519 |
# include <Processes.h> |
1520 |
#endif |
1521 |
|
1522 |
#ifdef IRIX5 |
1523 |
# include <sys/uio.h> |
1524 |
# include <malloc.h> /* for locking */ |
1525 |
#endif |
1526 |
#ifdef USE_MMAP |
1527 |
# include <sys/types.h> |
1528 |
# include <sys/mman.h> |
1529 |
# include <sys/stat.h> |
1530 |
# include <fcntl.h> |
1531 |
#endif |
1532 |
|
1533 |
#ifdef SUNOS5SIGS |
1534 |
# include <sys/siginfo.h> |
1535 |
# undef setjmp |
1536 |
# undef longjmp |
1537 |
# define setjmp(env) sigsetjmp(env, 1) |
1538 |
# define longjmp(env, val) siglongjmp(env, val) |
1539 |
# define jmp_buf sigjmp_buf |
1540 |
#endif |
1541 |
|
1542 |
#ifdef DJGPP |
1543 |
/* Apparently necessary for djgpp 2.01. May casuse problems with */ |
1544 |
/* other versions. */ |
1545 |
typedef long unsigned int caddr_t; |
1546 |
#endif |
1547 |
|
1548 |
#ifdef PCR |
1549 |
# include "il/PCR_IL.h" |
1550 |
# include "th/PCR_ThCtl.h" |
1551 |
# include "mm/PCR_MM.h" |
1552 |
#endif |
1553 |
|
1554 |
#if !defined(NO_EXECUTE_PERMISSION) |
1555 |
# define OPT_PROT_EXEC PROT_EXEC |
1556 |
#else |
1557 |
# define OPT_PROT_EXEC 0 |
1558 |
#endif |
1559 |
|
1560 |
# ifdef OS2 |
1561 |
|
1562 |
# include <stddef.h> |
1563 |
|
1564 |
# if !defined(__IBMC__) && !defined(__WATCOMC__) /* e.g. EMX */ |
1565 |
|
1566 |
# else /* IBM's compiler */ |
1567 |
|
1568 |
/* A kludge to get around what appears to be a header file bug */ |
1569 |
# ifndef WORD |
1570 |
# define WORD unsigned short |
1571 |
# endif |
1572 |
# ifndef DWORD |
1573 |
# define DWORD unsigned long |
1574 |
# endif |
1575 |
|
1576 |
# define EXE386 1 |
1577 |
# include <newexe.h> |
1578 |
# include <exe386.h> |
1579 |
|
1580 |
# endif /* __IBMC__ */ |
1581 |
|
1582 |
# define INCL_DOSEXCEPTIONS |
1583 |
# define INCL_DOSPROCESS |
1584 |
# define INCL_DOSERRORS |
1585 |
# define INCL_DOSMODULEMGR |
1586 |
# define INCL_DOSMEMMGR |
1587 |
# include <os2.h> |
1588 |
|
1589 |
# endif /*!OS/2 */ |
1590 |
|
1591 |
/* |
1592 |
* Find the base of the stack. |
1593 |
* Used only in single-threaded environment. |
1594 |
* With threads, GC_mark_roots needs to know how to do this. |
1595 |
* Called with allocator lock held. |
1596 |
*/ |
1597 |
# ifdef MSWIN32 |
1598 |
# define is_writable(prot) ((prot) == PAGE_READWRITE \ |
1599 |
|| (prot) == PAGE_WRITECOPY \ |
1600 |
|| (prot) == PAGE_EXECUTE_READWRITE \ |
1601 |
|| (prot) == PAGE_EXECUTE_WRITECOPY) |
1602 |
/* Return the number of bytes that are writable starting at p. */ |
1603 |
/* The pointer p is assumed to be page aligned. */ |
1604 |
/* If base is not 0, *base becomes the beginning of the */ |
1605 |
/* allocation region containing p. */ |
1606 |
static word GC_get_writable_length(ptr_t p, ptr_t *base) |
1607 |
{ |
1608 |
MEMORY_BASIC_INFORMATION buf; |
1609 |
word result; |
1610 |
word protect; |
1611 |
|
1612 |
result = VirtualQuery(p, &buf, sizeof(buf)); |
1613 |
if (result != sizeof(buf)) ABORT("Weird VirtualQuery result"); |
1614 |
if (base != 0) *base = (ptr_t)(buf.AllocationBase); |
1615 |
protect = (buf.Protect & ~(PAGE_GUARD | PAGE_NOCACHE)); |
1616 |
if (!is_writable(protect)) { |
1617 |
return(0); |
1618 |
} |
1619 |
if (buf.State != MEM_COMMIT) return(0); |
1620 |
return(buf.RegionSize); |
1621 |
} |
1622 |
|
1623 |
void *scm_get_stack_base() |
1624 |
{ |
1625 |
int dummy; |
1626 |
ptr_t sp = (ptr_t)(&dummy); |
1627 |
ptr_t trunc_sp; |
1628 |
word size; |
1629 |
static word GC_page_size = 0; |
1630 |
if (!GC_page_size) { |
1631 |
SYSTEM_INFO sysinfo; |
1632 |
GetSystemInfo(&sysinfo); |
1633 |
GC_page_size = sysinfo.dwPageSize; |
1634 |
} |
1635 |
trunc_sp = (ptr_t)((word)sp & ~(GC_page_size - 1)); |
1636 |
size = GC_get_writable_length(trunc_sp, 0); |
1637 |
return(trunc_sp + size); |
1638 |
} |
1639 |
|
1640 |
|
1641 |
# else |
1642 |
|
1643 |
# ifdef OS2 |
1644 |
|
1645 |
void *scm_get_stack_base() |
1646 |
{ |
1647 |
PTIB ptib; |
1648 |
PPIB ppib; |
1649 |
|
1650 |
if (DosGetInfoBlocks(&ptib, &ppib) != NO_ERROR) { |
1651 |
GC_err_printf0("DosGetInfoBlocks failed\n"); |
1652 |
ABORT("DosGetInfoBlocks failed\n"); |
1653 |
} |
1654 |
return((ptr_t)(ptib -> tib_pstacklimit)); |
1655 |
} |
1656 |
|
1657 |
# else |
1658 |
|
1659 |
# ifdef AMIGA |
1660 |
|
1661 |
void *scm_get_stack_base() |
1662 |
{ |
1663 |
struct Process *proc = (struct Process*)SysBase->ThisTask; |
1664 |
|
1665 |
/* Reference: Amiga Guru Book Pages: 42,567,574 */ |
1666 |
if (proc->pr_Task.tc_Node.ln_Type==NT_PROCESS |
1667 |
&& proc->pr_CLI != NULL) { |
1668 |
/* first ULONG is StackSize */ |
1669 |
/*longPtr = proc->pr_ReturnAddr; |
1670 |
size = longPtr[0];*/ |
1671 |
|
1672 |
return (char *)proc->pr_ReturnAddr + sizeof(ULONG); |
1673 |
} else { |
1674 |
return (char *)proc->pr_Task.tc_SPUpper; |
1675 |
} |
1676 |
} |
1677 |
|
1678 |
#if 0 /* old version */ |
1679 |
void *scm_get_stack_base() |
1680 |
{ |
1681 |
extern struct WBStartup *_WBenchMsg; |
1682 |
extern long __base; |
1683 |
extern long __stack; |
1684 |
struct Task *task; |
1685 |
struct Process *proc; |
1686 |
struct CommandLineInterface *cli; |
1687 |
long size; |
1688 |
|
1689 |
if ((task = FindTask(0)) == 0) { |
1690 |
GC_err_puts("Cannot find own task structure\n"); |
1691 |
ABORT("task missing"); |
1692 |
} |
1693 |
proc = (struct Process *)task; |
1694 |
cli = BADDR(proc->pr_CLI); |
1695 |
|
1696 |
if (_WBenchMsg != 0 || cli == 0) { |
1697 |
size = (char *)task->tc_SPUpper - (char *)task->tc_SPLower; |
1698 |
} else { |
1699 |
size = cli->cli_DefaultStack * 4; |
1700 |
} |
1701 |
return (ptr_t)(__base + GC_max(size, __stack)); |
1702 |
} |
1703 |
#endif /* 0 */ |
1704 |
|
1705 |
# else /* !AMIGA, !OS2, ... */ |
1706 |
|
1707 |
# ifdef NEED_FIND_LIMIT |
1708 |
/* Some tools to implement HEURISTIC2 */ |
1709 |
# define MIN_PAGE_SIZE 256 /* Smallest conceivable page size, bytes */ |
1710 |
/* static */ jmp_buf GC_jmp_buf; |
1711 |
|
1712 |
/*ARGSUSED*/ |
1713 |
static void GC_fault_handler(sig) |
1714 |
int sig; |
1715 |
{ |
1716 |
longjmp(GC_jmp_buf, 1); |
1717 |
} |
1718 |
|
1719 |
# ifdef __STDC__ |
1720 |
typedef void (*handler)(int); |
1721 |
# else |
1722 |
typedef void (*handler)(); |
1723 |
# endif |
1724 |
|
1725 |
# if defined(SUNOS5SIGS) || defined(IRIX5) || defined(OSF1) |
1726 |
static struct sigaction old_segv_act; |
1727 |
# if defined(_sigargs) || defined(HPUX) /* !Irix6.x */ |
1728 |
static struct sigaction old_bus_act; |
1729 |
# endif |
1730 |
# else |
1731 |
static handler old_segv_handler, old_bus_handler; |
1732 |
# endif |
1733 |
|
1734 |
static void GC_setup_temporary_fault_handler() |
1735 |
{ |
1736 |
# if defined(SUNOS5SIGS) || defined(IRIX5) || defined(OSF1) |
1737 |
struct sigaction act; |
1738 |
|
1739 |
act.sa_handler = GC_fault_handler; |
1740 |
act.sa_flags = SA_RESTART | SA_NODEFER; |
1741 |
/* The presence of SA_NODEFER represents yet another gross */ |
1742 |
/* hack. Under Solaris 2.3, siglongjmp doesn't appear to */ |
1743 |
/* interact correctly with -lthread. We hide the confusion */ |
1744 |
/* by making sure that signal handling doesn't affect the */ |
1745 |
/* signal mask. */ |
1746 |
|
1747 |
(void) sigemptyset(&act.sa_mask); |
1748 |
# ifdef IRIX_THREADS |
1749 |
/* Older versions have a bug related to retrieving and */ |
1750 |
/* and setting a handler at the same time. */ |
1751 |
(void) sigaction(SIGSEGV, 0, &old_segv_act); |
1752 |
(void) sigaction(SIGSEGV, &act, 0); |
1753 |
# else |
1754 |
(void) sigaction(SIGSEGV, &act, &old_segv_act); |
1755 |
# if defined(IRIX5) && defined(_sigargs) /* Irix 5.x, not 6.x */ \ |
1756 |
|| defined(HPUX) |
1757 |
/* Under Irix 5.x or HP/UX, we may get SIGBUS. */ |
1758 |
/* Pthreads doesn't exist under Irix 5.x, so we */ |
1759 |
/* don't have to worry in the threads case. */ |
1760 |
(void) sigaction(SIGBUS, &act, &old_bus_act); |
1761 |
# endif |
1762 |
# endif /* IRIX_THREADS */ |
1763 |
# else |
1764 |
old_segv_handler = signal(SIGSEGV, GC_fault_handler); |
1765 |
# ifdef SIGBUS |
1766 |
old_bus_handler = signal(SIGBUS, GC_fault_handler); |
1767 |
# endif |
1768 |
# endif |
1769 |
} |
1770 |
|
1771 |
static void GC_reset_fault_handler() |
1772 |
{ |
1773 |
# if defined(SUNOS5SIGS) || defined(IRIX5) || defined(OSF1) |
1774 |
(void) sigaction(SIGSEGV, &old_segv_act, 0); |
1775 |
# if defined(IRIX5) && defined(_sigargs) /* Irix 5.x, not 6.x */ \ |
1776 |
|| defined(HPUX) |
1777 |
(void) sigaction(SIGBUS, &old_bus_act, 0); |
1778 |
# endif |
1779 |
# else |
1780 |
(void) signal(SIGSEGV, old_segv_handler); |
1781 |
# ifdef SIGBUS |
1782 |
(void) signal(SIGBUS, old_bus_handler); |
1783 |
# endif |
1784 |
# endif |
1785 |
} |
1786 |
|
1787 |
/* Single argument version, robust against whole program analysis. */ |
1788 |
static void |
1789 |
GC_noop1(x) |
1790 |
word x; |
1791 |
{ |
1792 |
static VOLATILE word sink; |
1793 |
sink = x; |
1794 |
} |
1795 |
|
1796 |
/* Return the first nonaddressible location > p (up) or */ |
1797 |
/* the smallest location q s.t. [q,p] is addressible (!up). */ |
1798 |
static ptr_t GC_find_limit(p, up) |
1799 |
ptr_t p; |
1800 |
GC_bool up; |
1801 |
{ |
1802 |
static VOLATILE ptr_t result; |
1803 |
/* Needs to be static, since otherwise it may not be */ |
1804 |
/* preserved across the longjmp. Can safely be */ |
1805 |
/* static since it's only called once, with the */ |
1806 |
/* allocation lock held. */ |
1807 |
|
1808 |
|
1809 |
GC_setup_temporary_fault_handler(); |
1810 |
if (setjmp(GC_jmp_buf) == 0) { |
1811 |
result = (ptr_t)(((word)(p)) |
1812 |
& ~(MIN_PAGE_SIZE-1)); |
1813 |
for (;;) { |
1814 |
if (up) { |
1815 |
result += MIN_PAGE_SIZE; |
1816 |
} else { |
1817 |
result -= MIN_PAGE_SIZE; |
1818 |
} |
1819 |
GC_noop1((word)(*result)); |
1820 |
} |
1821 |
} |
1822 |
GC_reset_fault_handler(); |
1823 |
if (!up) { |
1824 |
result += MIN_PAGE_SIZE; |
1825 |
} |
1826 |
return(result); |
1827 |
} |
1828 |
|
1829 |
# endif |
1830 |
|
1831 |
#ifdef LINUX_STACKBOTTOM |
1832 |
|
1833 |
#include <sys/types.h> |
1834 |
#include <sys/stat.h> |
1835 |
#include <fcntl.h> |
1836 |
|
1837 |
# define STAT_SKIP 27 /* Number of fields preceding startstack */ |
1838 |
/* field in /proc/self/stat */ |
1839 |
|
1840 |
static ptr_t GC_linux_stack_base(void) |
1841 |
{ |
1842 |
/* We read the stack base value from /proc/self/stat. We do this */ |
1843 |
/* using direct I/O system calls in order to avoid calling malloc */ |
1844 |
/* in case REDIRECT_MALLOC is defined. */ |
1845 |
# define STAT_BUF_SIZE 4096 |
1846 |
# ifdef USE_LD_WRAP |
1847 |
# define STAT_READ __real_read |
1848 |
# else |
1849 |
# define STAT_READ read |
1850 |
# endif |
1851 |
char stat_buf[STAT_BUF_SIZE]; |
1852 |
int f; |
1853 |
char c; |
1854 |
word result = 0; |
1855 |
size_t i, buf_offset = 0; |
1856 |
|
1857 |
f = open("/proc/self/stat", O_RDONLY); |
1858 |
if (f < 0 || STAT_READ(f, stat_buf, STAT_BUF_SIZE) < 2 * STAT_SKIP) { |
1859 |
ABORT("Couldn't read /proc/self/stat"); |
1860 |
} |
1861 |
c = stat_buf[buf_offset++]; |
1862 |
/* Skip the required number of fields. This number is hopefully */ |
1863 |
/* constant across all Linux implementations. */ |
1864 |
for (i = 0; i < STAT_SKIP; ++i) { |
1865 |
while (isspace(c)) c = stat_buf[buf_offset++]; |
1866 |
while (!isspace(c)) c = stat_buf[buf_offset++]; |
1867 |
} |
1868 |
while (isspace(c)) c = stat_buf[buf_offset++]; |
1869 |
while (isdigit(c)) { |
1870 |
result *= 10; |
1871 |
result += c - '0'; |
1872 |
c = stat_buf[buf_offset++]; |
1873 |
} |
1874 |
close(f); |
1875 |
if (result < 0x10000000) ABORT("Absurd stack bottom value"); |
1876 |
return (ptr_t)result; |
1877 |
} |
1878 |
|
1879 |
#endif /* LINUX_STACKBOTTOM */ |
1880 |
|
1881 |
void *scm_get_stack_base() |
1882 |
{ |
1883 |
word dummy; |
1884 |
void *result; |
1885 |
|
1886 |
result = &dummy; /* initialize to silence compiler */ |
1887 |
|
1888 |
# define STACKBOTTOM_ALIGNMENT_M1 ((word)STACK_GRAN - 1) |
1889 |
|
1890 |
# ifdef STACKBOTTOM |
1891 |
return(STACKBOTTOM); |
1892 |
# else |
1893 |
# ifdef HEURISTIC1 |
1894 |
# if STACK_GROWS_DOWN |
1895 |
result = (ptr_t)((((word)(&dummy)) |
1896 |
+ STACKBOTTOM_ALIGNMENT_M1) |
1897 |
& ~STACKBOTTOM_ALIGNMENT_M1); |
1898 |
# else |
1899 |
result = (ptr_t)(((word)(&dummy)) |
1900 |
& ~STACKBOTTOM_ALIGNMENT_M1); |
1901 |
# endif |
1902 |
# endif /* HEURISTIC1 */ |
1903 |
# ifdef LINUX_STACKBOTTOM |
1904 |
result = GC_linux_stack_base(); |
1905 |
# endif |
1906 |
# ifdef HEURISTIC2 |
1907 |
# if STACK_GROWS_DOWN |
1908 |
result = GC_find_limit((ptr_t)(&dummy), TRUE); |
1909 |
# ifdef HEURISTIC2_LIMIT |
1910 |
if (result > HEURISTIC2_LIMIT |
1911 |
&& (ptr_t)(&dummy) < HEURISTIC2_LIMIT) { |
1912 |
result = HEURISTIC2_LIMIT; |
1913 |
} |
1914 |
# endif |
1915 |
# else |
1916 |
result = GC_find_limit((ptr_t)(&dummy), FALSE); |
1917 |
# ifdef HEURISTIC2_LIMIT |
1918 |
if (result < HEURISTIC2_LIMIT |
1919 |
&& (ptr_t)(&dummy) > HEURISTIC2_LIMIT) { |
1920 |
result = HEURISTIC2_LIMIT; |
1921 |
} |
1922 |
# endif |
1923 |
# endif |
1924 |
|
1925 |
# endif /* HEURISTIC2 */ |
1926 |
# if STACK_GROWS_DOWN |
1927 |
if (result == 0) result = (ptr_t)(signed_word)(-sizeof(ptr_t)); |
1928 |
# endif |
1929 |
return(result); |
1930 |
# endif /* STACKBOTTOM */ |
1931 |
} |
1932 |
|
1933 |
# endif /* ! AMIGA */ |
1934 |
# endif /* ! OS2 */ |
1935 |
# endif /* ! MSWIN32 */ |
1936 |
|
1937 |
#endif /* mach_type_known */ |
1938 |
#endif /* ! HAVE_LIBC_STACK_END */ |