~peter-pearse/ubuntu/natty/guile-1.8/prop001

« back to all changes in this revision

Viewing changes to libguile/gc_os_dep.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Schepler
  • Date: 2006-11-09 03:11:16 UTC
  • Revision ID: james.westby@ubuntu.com-20061109031116-hu0q1jxqg12y6yeg
Tags: upstream-1.8.1+1
ImportĀ upstreamĀ versionĀ 1.8.1+1

Show diffs side-by-side

added added

removed removed

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