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
8
* THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
9
* OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
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.
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.
29
#include "libguile/gc.h"
30
#include "libguile/scmconfig.h"
32
#ifdef HAVE_LIBC_STACK_END
34
extern void *__libc_stack_end;
39
return __libc_stack_end;
44
#define ABORT(msg) abort ()
46
typedef char * ptr_t; /* A generic pointer to which we can add */
47
/* byte displacements. */
48
/* Preferably identical to caddr_t, if it */
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;
63
typedef GC_signed_word signed_word;
71
# if !(defined( sony_news ) )
74
# define VOLATILE volatile
82
/* Machine dependent parameters. Some tuning parameters can be found */
83
/* near the top of gc_private.h. */
85
/* Machine specific parts contributed by various people. See README file. */
87
/* First a unified test for Linux: */
88
# if defined(linux) || defined(__linux__)
92
/* Determine the machine type: */
93
# if defined(sun) && defined(mc68000)
96
# define mach_type_known
98
# if defined(hp9000s300)
101
# define mach_type_known
103
# if defined(__OpenBSD__) && defined(m68k)
106
# define mach_type_known
108
# if defined(__OpenBSD__) && defined(__sparc__)
111
# define mach_type_known
113
# if defined(__NetBSD__) && defined(__powerpc__)
116
# define mach_type_known
118
/* in netbsd 2.0 only __m68k__ is defined, not m68k */
119
# if defined(__NetBSD__) && (defined(m68k) || defined(__m68k__))
122
# define mach_type_known
124
/* in netbsd 2.0 only __arm__ is defined, not arm32 */
125
# if defined(__NetBSD__) && (defined(arm32) || defined(__arm__))
128
# define mach_type_known
130
# if defined(__NetBSD__) && defined(__sparc__)
133
# define mach_type_known
142
# define mach_type_known
144
# if defined(mips) || defined(__mips)
147
# if defined(ultrix) || defined(__ultrix) || defined(__NetBSD__)
150
# if defined(_SYSTYPE_SVR4) || defined(SYSTYPE_SVR4) \
151
|| defined(__SYSTYPE_SVR4__)
152
# define IRIX5 /* or IRIX 6.X */
154
# define RISCOS /* or IRIX 4.X */
158
# define mach_type_known
160
# if defined(sequent) && defined(i386)
163
# define mach_type_known
165
# if defined(sun) && defined(i386)
168
# define mach_type_known
170
# if (defined(__OS2__) || defined(__EMX__)) && defined(__32BIT__)
173
# define mach_type_known
177
# define mach_type_known
179
# if defined(sun) && (defined(sparc) || defined(__sparc))
181
/* Test for SunOS 5.x */
188
# define mach_type_known
190
# if defined(sparc) && defined(unix) && !defined(sun) && !defined(linux) \
191
&& !defined(__OpenBSD__)
194
# define mach_type_known
198
# define mach_type_known
200
# if defined(_M_XENIX) && defined(_M_SYSV) && defined(_M_I386)
201
/* The above test may need refinement */
203
# if defined(_SCO_ELF)
208
# define mach_type_known
210
# if defined(_AUX_SOURCE)
213
# define mach_type_known
215
# if defined(_PA_RISC1_0) || defined(_PA_RISC1_1) || defined(_PA_RISC2_0) \
216
|| defined(hppa) || defined(__hppa__)
221
# define mach_type_known
223
# if defined(LINUX) && (defined(i386) || defined(__i386__))
225
# define mach_type_known
227
# if defined(LINUX) && (defined(__ia64__) || defined(__ia64))
229
# define mach_type_known
231
# if defined(LINUX) && defined(powerpc)
233
# define mach_type_known
235
# if defined(LINUX) && defined(__mc68000__)
237
# define mach_type_known
239
# if defined(LINUX) && (defined(sparc) || defined(__sparc__))
241
# define mach_type_known
243
# if defined(LINUX) && (defined(arm) || defined (__arm__))
245
# define mach_type_known
247
# if defined(__alpha) || defined(__alpha__)
250
# define OSF1 /* a.k.a Digital Unix */
252
# define mach_type_known
254
# if defined(_AMIGA) && !defined(AMIGA)
259
# define mach_type_known
261
# if defined(THINK_C) || defined(__MWERKS__) && !defined(__powerc)
264
# define mach_type_known
266
# if defined(__MWERKS__) && defined(__powerc)
269
# define mach_type_known
271
# if defined(macosx) || \
272
(defined(__APPLE__) && defined(__MACH__) && defined(__ppc__))
275
# define mach_type_known
277
# if defined(NeXT) && defined(mc68000)
280
# define mach_type_known
282
# if defined(NeXT) && defined(i386)
285
# define mach_type_known
287
# if defined(__OpenBSD__) && (defined(i386) || defined(__i386__))
290
# define mach_type_known
292
# if defined(__FreeBSD__) && defined(i386)
295
# define mach_type_known
297
# if defined(__NetBSD__) && defined(i386)
300
# define mach_type_known
302
# if defined(bsdi) && defined(i386)
305
# define mach_type_known
307
# if !defined(mach_type_known) && defined(__386BSD__)
310
# define mach_type_known
312
# if defined(_CX_UX) && defined(_M88K)
315
# define mach_type_known
320
# define mach_type_known
322
# if (defined(_MSDOS) || defined(_MSC_VER)) && (_M_IX86 >= 300) \
323
|| defined(_WIN32) && !defined(__CYGWIN32__) && !defined(__CYGWIN__)
325
# define MSWIN32 /* or Win32s */
326
# define mach_type_known
328
# if defined(__DJGPP__)
331
# define DJGPP /* MSDOS running the DJGPP port of GCC */
333
# define mach_type_known
335
# if defined(__CYGWIN32__) || defined(__CYGWIN__)
338
# define mach_type_known
340
# if defined(__MINGW32__)
343
# define mach_type_known
345
# if defined(__BORLANDC__)
348
# define mach_type_known
350
# if defined(_UTS) && !defined(mach_type_known)
353
# define mach_type_known
357
# define mach_type_known
360
# if defined(__WATCOMC__) && defined(__386__)
362
# if !defined(OS2) && !defined(MSWIN32) && !defined(DOS4GW)
363
# if defined(__OS2__)
366
# if defined(__WINDOWS_386__) || defined(__NT__)
373
# define mach_type_known
375
# if defined(__s390__) && defined(LINUX)
377
# define mach_type_known
379
# if defined(__GNU__)
382
# define mach_type_known
384
# if defined(__SCO_VERSION__)
387
# define mach_type_known
390
/* Feel free to add more clauses here */
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
402
scm_get_stack_base ()
404
ABORT ("Can't determine stack base");
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 */
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 */
440
* For each architecture and OS, the following need to be defined:
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.)
449
* MACH_TYPE is a string representation of the machine type.
450
* OS_TYPE is analogous for the OS.
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.
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.
460
* DATAEND, if not &end.
462
* ALIGN_DOUBLE of GC_malloc should return blocks aligned to twice
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)
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
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.
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
507
* # include "gc_private.h"
509
* main(argc, argv, envp)
511
* char **argv, **envp;
515
* GC_stackbottom = (ptr_t)(&dummy);
516
* return(real_main(argc, argv, envp));
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.
525
* An architecture may define DYNAMIC_LOADING if dynamic_load.c
526
* defined GC_register_dynamic_libraries() for the architecture.
528
* An architecture may define PREFETCH(x) to preload the cache with *x.
529
* This defaults to a no-op.
531
* PREFETCH_FOR_WRITE(x) is used if *x is about to be written.
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.
539
# define STACK_GRAN 0x1000000
541
# define MACH_TYPE "M68K"
544
# define OS_TYPE "OPENBSD"
547
# define DATASTART ((ptr_t)(&etext))
550
# define OS_TYPE "NETBSD"
553
# define DATASTART ((ptr_t)(&etext))
556
# define OS_TYPE "LINUX"
557
# define STACKBOTTOM ((ptr_t)0xf0000000)
558
# define MPROTECT_VDB
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. */
572
# define DATAEND (&_end)
575
# define DATASTART ((ptr_t)((((word) (&etext)) + 0xfff) & ~0xfff))
579
# define OS_TYPE "SUNOS4"
581
# define DATASTART ((ptr_t)((((word) (&etext)) + 0x1ffff) & ~0x1ffff))
582
# define HEURISTIC1 /* differs */
583
# define DYNAMIC_LOADING
586
# define OS_TYPE "HP"
588
# define DATASTART ((ptr_t)((((word) (&etext)) + 0xfff) & ~0xfff))
589
# define STACKBOTTOM ((ptr_t) 0xffeffffc)
590
/* empirically determined. seems to work. */
592
# define GETPAGESIZE() sysconf(_SC_PAGE_SIZE)
595
# define OS_TYPE "SYSV"
597
# define DATASTART ((ptr_t)((((word) (&etext)) + 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.
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. */
612
# include <sys/mmu.h>
613
# define GETPAGESIZE() PAGESIZE /* Is this still right? */
616
# define OS_TYPE "AMIGA"
617
/* STACKBOTTOM and DATASTART handled specially */
619
# define DATAEND /* not needed */
620
# define GETPAGESIZE() 4096
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
633
# define OS_TYPE "NEXT"
634
# define DATASTART ((ptr_t) get_etext())
635
# define STACKBOTTOM ((ptr_t) 0x4000000)
636
# define DATAEND /* not needed */
641
# define MACH_TYPE "POWERPC"
643
# define ALIGNMENT 2 /* Still necessary? Could it be 4? */
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 */
653
# define ALIGNMENT 4 /* Guess. Can someone verify? */
654
/* This was 2, but that didn't sound right. */
655
# define OS_TYPE "LINUX"
657
# define DYNAMIC_LOADING
659
# define STACK_GRAN 0x10000000
660
/* Stack usually starts at 0x80000000 */
661
# define LINUX_DATA_START
663
# define DATAEND (&_end)
667
# define OS_TYPE "MACOSX"
668
# define DATASTART ((ptr_t) get_etext())
669
# define STACKBOTTOM ((ptr_t) 0xc0000000)
670
# define DATAEND /* not needed */
675
# define MACH_TYPE "VAX"
676
# define ALIGNMENT 4 /* Pointers are longword aligned by 4.2 C compiler */
678
# define DATASTART ((ptr_t)(&etext))
680
# define OS_TYPE "BSD"
682
/* HEURISTIC2 may be OK, but it's hard to test. */
685
# define OS_TYPE "ULTRIX"
686
# define STACKBOTTOM ((ptr_t) 0x7fffc800)
691
# define MACH_TYPE "RT"
693
# define DATASTART ((ptr_t) 0x10000000)
694
# define STACKBOTTOM ((ptr_t) 0x1fffd800)
698
# define MACH_TYPE "SPARC"
699
# define ALIGNMENT 4 /* Required by hardware */
700
# define ALIGN_DOUBLE
703
# define OS_TYPE "SUNOS5"
706
extern char * GC_SysVGetDataStart();
707
# define DATASTART (ptr_t)GC_SysVGetDataStart(0x10000, &_etext)
708
# define DATAEND (&_end)
713
# define HEAP_START (ptr_t)0x40000000
715
# define HEAP_START DATAEND
718
/* HEURISTIC1 reportedly no longer works under 2.7. Thus we */
719
/* switched to HEURISTIC2, eventhough it creates some debugging */
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
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
745
# define DYNAMIC_LOADING
748
# define CPP_WORDSZ 32
749
# define OS_TYPE "DRSNX"
750
extern char * GC_SysVGetDataStart();
752
# define DATASTART (ptr_t)GC_SysVGetDataStart(0x10000, &etext)
753
# define MPROTECT_VDB
754
# define STACKBOTTOM ((ptr_t) 0xdfff0000)
755
# define DYNAMIC_LOADING
758
# define OS_TYPE "LINUX"
760
# define LINUX_DATA_START
761
# define DYNAMIC_LOADING
763
Linux Sparc non elf ?
766
# define DATAEND (&_end)
768
# define STACKBOTTOM ((ptr_t) 0xf0000000)
771
# define OS_TYPE "OPENBSD"
772
# define STACKBOTTOM ((ptr_t) 0xf8000000)
773
# define DATASTART ((ptr_t)(&etext))
778
# define MACH_TYPE "I386"
779
# define ALIGNMENT 4 /* Appears to hold for all "32 bit" compilers */
780
/* except Borland. The -a4 option fixes */
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. */
788
# define OS_TYPE "SEQUENT"
790
# define DATASTART ((ptr_t)((((word) (&etext)) + 0xfff) & ~0xfff))
791
# define STACKBOTTOM ((ptr_t) 0x3ffff000)
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
806
# define HEAP_START (ptr_t)0x40000000
808
# define HEAP_START DATAEND
812
# define OS_TYPE "SCO"
814
# define DATASTART ((ptr_t)((((word) (&etext)) + 0x3fffff) \
816
+((word)&etext & 0xfff))
817
# define STACKBOTTOM ((ptr_t) 0x7ffffffc)
820
# define OS_TYPE "SCO_ELF"
822
# define DATASTART ((ptr_t)(&etext))
823
# define STACKBOTTOM ((ptr_t) 0x08048000)
824
# define DYNAMIC_LOADING
825
# define ELF_CLASS ELFCLASS32
828
# define OS_TYPE "LINUX"
829
# define LINUX_STACKBOTTOM
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. */
839
# if !defined(LINUX_THREADS) || !defined(REDIRECT_MALLOC)
840
# define MPROTECT_VDB
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. */
847
# define DYNAMIC_LOADING
848
# ifdef UNDEFINED /* includes ro data */
850
# define DATASTART ((ptr_t)((((word) (&_etext)) + 0xfff) & ~0xfff))
852
# include <features.h>
853
# if defined(__GLIBC__) && __GLIBC__ >= 2
854
# define LINUX_DATA_START
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. */
868
# define DATAEND (&_end)
871
# define DATASTART ((ptr_t)((((word) (&etext)) + 0xfff) & ~0xfff))
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. */
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)))
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)))
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__))
913
# define STACK_GRAN 0x10000
917
# define OS_TYPE "OS2"
918
/* STACKBOTTOM and DATASTART are handled specially in */
919
/* os_dep.c. OS2 actually has the right */
921
# define DATAEND /* not needed */
924
# define OS_TYPE "MSWIN32"
925
/* STACKBOTTOM and DATASTART are handled specially in */
928
# define MPROTECT_VDB
930
# define DATAEND /* not needed */
933
# define OS_TYPE "DJGPP"
934
# include "stubinfo.h"
937
extern int __djgpp_stack_limit;
938
# define DATASTART ((ptr_t)((((word) (&etext)) + 0x1ff) & ~0x1ff))
939
/* # define STACKBOTTOM ((ptr_t)((word) _stubinfo + _stubinfo->size \
941
# define STACKBOTTOM ((ptr_t)((word) __djgpp_stack_limit + _stklen))
942
/* This may not be right. */
945
# define OS_TYPE "OPENBSD"
948
# define OS_TYPE "FREEBSD"
949
# define MPROTECT_VDB
952
# define OS_TYPE "NETBSD"
955
# define OS_TYPE "THREE86BSD"
958
# define OS_TYPE "BSDI"
960
# if defined(OPENBSD) || defined(FREEBSD) || defined(NETBSD) \
961
|| defined(THREE86BSD) || defined(BSDI)
964
# define DATASTART ((ptr_t)(&etext))
967
# define OS_TYPE "NEXT"
968
# define DATASTART ((ptr_t) get_etext())
969
# define STACKBOTTOM ((ptr_t)0xc0000000)
970
# define DATAEND /* not needed */
973
# define OS_TYPE "DOS4GW"
974
extern long __nullarea;
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)
988
# define OS_TYPE "GNU"
993
# define MACH_TYPE "NS32K"
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 */
1005
# define MACH_TYPE "MIPS"
1006
/* # define STACKBOTTOM ((ptr_t)0x7fff8000) sometimes also works. */
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. */
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
1030
# define DATASTART (ptr_t)0x10000000
1031
# define OS_TYPE "RISCOS"
1032
# define ALIGNMENT 4 /* Required by hardware */
1037
# define DATASTART ((ptr_t)(&_fdata))
1039
# define HEAP_START (ptr_t)0x30000000
1041
# define HEAP_START DATASTART
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
1051
# define CPP_WORDSZ _MIPS_SZPTR
1052
# define ALIGNMENT (_MIPS_SZPTR/8)
1053
# if CPP_WORDSZ != 64
1054
# define ALIGN_DOUBLE
1057
# define ALIGNMENT 4
1058
# define ALIGN_DOUBLE
1060
# define DYNAMIC_LOADING
1065
# define MACH_TYPE "RS6000"
1066
# define ALIGNMENT 4
1067
# define DATASTART ((ptr_t)0x20000000)
1069
# define STACKBOTTOM ((ptr_t)((ulong)&errno))
1070
# define DYNAMIC_LOADING
1071
/* For really old versions of AIX, this may have to be removed. */
1075
/* OS is assumed to be HP/UX */
1076
# define MACH_TYPE "HP_PA"
1077
# define OS_TYPE "HPUX"
1079
# define CPP_WORDSZ 64
1080
# define ALIGNMENT 8
1082
# define CPP_WORDSZ 32
1083
# define ALIGNMENT 4
1084
# define ALIGN_DOUBLE
1086
extern int __data_start;
1087
# define DATASTART ((ptr_t)(&__data_start))
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 */
1096
# define STACKBOTTOM ((ptr_t) 0x7b033000) /* from /etc/conf/h/param.h */
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)
1104
# ifndef SCM_STACK_GROWS_UP /* don't fight with scmconfig.h */
1105
# define SCM_STACK_GROWS_UP 1
1107
# define DYNAMIC_LOADING
1108
# ifndef HPUX_THREADS
1109
# define MPROTECT_VDB
1111
# include <unistd.h>
1112
# define GETPAGESIZE() sysconf(_SC_PAGE_SIZE)
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. */
1124
# define OS_TYPE "OSF1"
1125
# define DATASTART ((ptr_t) 0x140000000)
1127
# define DATAEND ((ptr_t) &_end)
1129
/* Normally HEURISTIC2 is too conervative, since */
1130
/* the text segment immediately follows the stack. */
1131
/* Hence we give an upper pound. */
1133
# define HEURISTIC2_LIMIT ((ptr_t)((word)(&__start) & ~(getpagesize()-1)))
1134
# define CPP_WORDSZ 64
1135
# define MPROTECT_VDB
1136
# define DYNAMIC_LOADING
1139
# define OS_TYPE "LINUX"
1140
# define CPP_WORDSZ 64
1141
# define STACKBOTTOM ((ptr_t) 0x120000000)
1143
# define LINUX_DATA_START
1144
# define DYNAMIC_LOADING
1145
/* This doesn't work if the collector is in a dynamic library. */
1147
# define DATASTART ((ptr_t) 0x140000000)
1150
# define DATAEND (&_end)
1151
# define MPROTECT_VDB
1152
/* Has only been superficially tested. May not */
1153
/* work on all versions. */
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. */
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)
1179
# define SEARCH_FOR_DATA_START
1180
# define DATASTART GC_data_start
1182
extern int data_start;
1183
# define DATASTART ((ptr_t)(&data_start))
1185
# define DYNAMIC_LOADING
1186
# define MPROTECT_VDB
1187
/* Requires Linux 2.3.47 or later. */
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)))
1200
# define MACH_TYPE "M88K"
1201
# define ALIGNMENT 4
1202
# define ALIGN_DOUBLE
1205
# define OS_TYPE "CX_UX"
1206
# define DATASTART ((((word)&etext + 0x3fffff) & ~0x3fffff) + 0x10000)
1209
# define OS_TYPE "DGUX"
1210
extern char * GC_SysVGetDataStart();
1211
# define DATASTART (ptr_t)GC_SysVGetDataStart(0x10000, &etext)
1213
# define STACKBOTTOM ((char*)0xf0000000) /* determined empirically */
1217
# define MACH_TYPE "S370"
1218
# define OS_TYPE "UTS4"
1219
# define ALIGNMENT 4 /* Required by hardware */
1223
extern char * GC_SysVGetDataStart();
1224
# define DATASTART (ptr_t)GC_SysVGetDataStart(0x10000, &_etext)
1225
# define DATAEND (&_end)
1230
# define ALIGNMENT 4
1232
# define DATASTART ((ptr_t)(&_etext))
1237
# define CPP_WORDSZ 32
1238
# define MACH_TYPE "ARM32"
1239
# define ALIGNMENT 4
1241
# define OS_TYPE "NETBSD"
1244
# define DATASTART ((ptr_t)(&etext))
1245
# define USE_GENERIC_PUSH_REGS
1248
# define OS_TYPE "LINUX"
1251
# define STACK_GRAN 0x10000000
1252
# define USE_GENERIC_PUSH_REGS
1254
# define DYNAMIC_LOADING
1255
# include <features.h>
1256
# if defined(__GLIBC__) && __GLIBC__ >= 2
1257
# define LINUX_DATA_START
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. */
1271
# define DATAEND (&_end)
1274
# define DATASTART ((ptr_t)((((word) (&etext)) + 0xfff) & ~0xfff))
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))
1292
# if SCM_STACK_GROWS_UP
1293
# define STACK_GROWS_DOWN 0
1295
# define STACK_GROWS_DOWN 1
1299
# define CPP_WORDSZ 32
1308
# define DATAEND (&end)
1311
# if defined(SVR4) && !defined(GETPAGESIZE)
1312
# include <unistd.h>
1313
# define GETPAGESIZE() sysconf(_SC_PAGESIZE)
1316
# ifndef GETPAGESIZE
1317
# if defined(SUNOS5) || defined(IRIX5)
1318
# include <unistd.h>
1320
# define GETPAGESIZE() getpagesize()
1323
# if defined(SUNOS5) || defined(DRSNX) || defined(UTS4)
1324
/* OS has SVR4 generic features. Probably others also qualify. */
1328
# if defined(SUNOS5) || defined(DRSNX)
1329
/* OS has SUNOS5 style semi-undocumented interface to dynamic */
1332
/* OS has SUNOS5 style signal handlers. */
1340
# if CPP_WORDSZ != 32 && CPP_WORDSZ != 64
1345
# undef DYNAMIC_LOADING
1350
# undef MPROTECT_VDB
1355
/* Postponed for now. */
1357
# undef MPROTECT_VDB
1360
# ifdef SMALL_CONFIG
1361
/* Presumably not worth the space it takes. */
1363
# undef MPROTECT_VDB
1367
# undef MPROTECT_VDB /* Can't deal with address space holes. */
1370
# if !defined(PCR_VDB) && !defined(PROC_VDB) && !defined(MPROTECT_VDB)
1371
# define DEFAULT_VDB
1375
# define PREFETCH(x)
1376
# define NO_PREFETCH
1379
# ifndef PREFETCH_FOR_WRITE
1380
# define PREFETCH_FOR_WRITE(x)
1381
# define NO_PREFETCH_FOR_WRITE
1384
# ifndef CACHE_LINE_SIZE
1385
# define CACHE_LINE_SIZE 32 /* Wild guess */
1388
# ifndef CLEAR_DOUBLE
1389
# define CLEAR_DOUBLE(x) \
1390
((word*)x)[0] = 0; \
1392
# endif /* CLEAR_DOUBLE */
1394
# if defined(_SOLARIS_PTHREADS) && !defined(SOLARIS_THREADS)
1395
# define SOLARIS_THREADS
1397
# if defined(IRIX_THREADS) && !defined(IRIX5)
1398
--> inconsistent configuration
1400
# if defined(IRIX_JDK_THREADS) && !defined(IRIX5)
1401
--> inconsistent configuration
1403
# if defined(LINUX_THREADS) && !defined(LINUX)
1404
--> inconsistent configuration
1406
# if defined(SOLARIS_THREADS) && !defined(SUNOS5)
1407
--> inconsistent configuration
1409
# if defined(HPUX_THREADS) && !defined(HPUX)
1410
--> inconsistent configuration
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)
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
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. */
1430
# if defined(LINUX) && !defined(POWERPC)
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. */
1440
# include <asm/signal.h>
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>
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__ */
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>
1471
# include <signal.h>
1473
/* Blatantly OS dependent routines, except for those that are related */
1474
/* to dynamic loading. */
1476
# if !defined(THREADS) && !defined(STACKBOTTOM) && defined(HEURISTIC2)
1477
# define NEED_FIND_LIMIT
1480
# if defined(IRIX_THREADS) || defined(HPUX_THREADS)
1481
# define NEED_FIND_LIMIT
1484
# if (defined(SUNOS4) && defined(DYNAMIC_LOADING)) && !defined(PCR)
1485
# define NEED_FIND_LIMIT
1488
# if (defined(SVR4) || defined(AUX) || defined(DGUX)) && !defined(PCR)
1489
# define NEED_FIND_LIMIT
1492
# if defined(LINUX) && \
1493
(defined(POWERPC) || defined(SPARC) || defined(ALPHA) || defined(IA64) \
1495
# define NEED_FIND_LIMIT
1498
#ifdef NEED_FIND_LIMIT
1499
# include <setjmp.h>
1503
# include <machine/trap.h>
1507
# include <proto/exec.h>
1508
# include <proto/dos.h>
1509
# include <dos/dosextens.h>
1510
# include <workbench/startup.h>
1514
# define WIN32_LEAN_AND_MEAN
1516
# include <windows.h>
1520
# include <Processes.h>
1524
# include <sys/uio.h>
1525
# include <malloc.h> /* for locking */
1528
# include <sys/types.h>
1529
# include <sys/mman.h>
1530
# include <sys/stat.h>
1535
# include <sys/siginfo.h>
1538
# define setjmp(env) sigsetjmp(env, 1)
1539
# define longjmp(env, val) siglongjmp(env, val)
1540
# define jmp_buf sigjmp_buf
1544
/* Apparently necessary for djgpp 2.01. May casuse problems with */
1545
/* other versions. */
1546
typedef long unsigned int caddr_t;
1550
# include "il/PCR_IL.h"
1551
# include "th/PCR_ThCtl.h"
1552
# include "mm/PCR_MM.h"
1555
#if !defined(NO_EXECUTE_PERMISSION)
1556
# define OPT_PROT_EXEC PROT_EXEC
1558
# define OPT_PROT_EXEC 0
1563
# include <stddef.h>
1565
# if !defined(__IBMC__) && !defined(__WATCOMC__) /* e.g. EMX */
1567
# else /* IBM's compiler */
1569
/* A kludge to get around what appears to be a header file bug */
1571
# define WORD unsigned short
1574
# define DWORD unsigned long
1578
# include <newexe.h>
1579
# include <exe386.h>
1581
# endif /* __IBMC__ */
1583
# define INCL_DOSEXCEPTIONS
1584
# define INCL_DOSPROCESS
1585
# define INCL_DOSERRORS
1586
# define INCL_DOSMODULEMGR
1587
# define INCL_DOSMEMMGR
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.
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)
1609
MEMORY_BASIC_INFORMATION buf;
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)) {
1620
if (buf.State != MEM_COMMIT) return(0);
1621
return(buf.RegionSize);
1624
void *scm_get_stack_base()
1627
ptr_t sp = (ptr_t)(&dummy);
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;
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);
1646
void *scm_get_stack_base()
1651
if (DosGetInfoBlocks(&ptib, &ppib) != NO_ERROR) {
1652
GC_err_printf0("DosGetInfoBlocks failed\n");
1653
ABORT("DosGetInfoBlocks failed\n");
1655
return((ptr_t)(ptib -> tib_pstacklimit));
1662
void *scm_get_stack_base()
1664
struct Process *proc = (struct Process*)SysBase->ThisTask;
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];*/
1673
return (char *)proc->pr_ReturnAddr + sizeof(ULONG);
1675
return (char *)proc->pr_Task.tc_SPUpper;
1679
#if 0 /* old version */
1680
void *scm_get_stack_base()
1682
extern struct WBStartup *_WBenchMsg;
1684
extern long __stack;
1686
struct Process *proc;
1687
struct CommandLineInterface *cli;
1690
if ((task = FindTask(0)) == 0) {
1691
GC_err_puts("Cannot find own task structure\n");
1692
ABORT("task missing");
1694
proc = (struct Process *)task;
1695
cli = BADDR(proc->pr_CLI);
1697
if (_WBenchMsg != 0 || cli == 0) {
1698
size = (char *)task->tc_SPUpper - (char *)task->tc_SPLower;
1700
size = cli->cli_DefaultStack * 4;
1702
return (ptr_t)(__base + GC_max(size, __stack));
1706
# else /* !AMIGA, !OS2, ... */
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;
1714
static void GC_fault_handler(sig)
1717
longjmp(GC_jmp_buf, 1);
1721
typedef void (*handler)(int);
1723
typedef void (*handler)();
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;
1732
static handler old_segv_handler, old_bus_handler;
1735
static void GC_setup_temporary_fault_handler()
1737
# if defined(SUNOS5SIGS) || defined(IRIX5) || defined(OSF1)
1738
struct sigaction act;
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 */
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);
1755
(void) sigaction(SIGSEGV, &act, &old_segv_act);
1756
# if defined(IRIX5) && defined(_sigargs) /* Irix 5.x, not 6.x */ \
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);
1763
# endif /* IRIX_THREADS */
1765
old_segv_handler = signal(SIGSEGV, GC_fault_handler);
1767
old_bus_handler = signal(SIGBUS, GC_fault_handler);
1772
static void GC_reset_fault_handler()
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 */ \
1778
(void) sigaction(SIGBUS, &old_bus_act, 0);
1781
(void) signal(SIGSEGV, old_segv_handler);
1783
(void) signal(SIGBUS, old_bus_handler);
1788
/* Single argument version, robust against whole program analysis. */
1793
static VOLATILE word sink;
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)
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. */
1810
GC_setup_temporary_fault_handler();
1811
if (setjmp(GC_jmp_buf) == 0) {
1812
result = (ptr_t)(((word)(p))
1813
& ~(MIN_PAGE_SIZE-1));
1816
result += MIN_PAGE_SIZE;
1818
result -= MIN_PAGE_SIZE;
1820
GC_noop1((word)(*result));
1823
GC_reset_fault_handler();
1825
result += MIN_PAGE_SIZE;
1832
#ifdef LINUX_STACKBOTTOM
1834
#include <sys/types.h>
1835
#include <sys/stat.h>
1838
# define STAT_SKIP 27 /* Number of fields preceding startstack */
1839
/* field in /proc/self/stat */
1841
static ptr_t GC_linux_stack_base(void)
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
1848
# define STAT_READ __real_read
1850
# define STAT_READ read
1852
char stat_buf[STAT_BUF_SIZE];
1856
size_t i, buf_offset = 0;
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");
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++];
1869
while (isspace(c)) c = stat_buf[buf_offset++];
1870
while (isdigit(c)) {
1873
c = stat_buf[buf_offset++];
1876
if (result < 0x10000000) ABORT("Absurd stack bottom value");
1877
return (ptr_t)result;
1880
#endif /* LINUX_STACKBOTTOM */
1882
void *scm_get_stack_base()
1887
result = &dummy; /* initialize to silence compiler */
1889
# define STACKBOTTOM_ALIGNMENT_M1 ((word)STACK_GRAN - 1)
1892
return(STACKBOTTOM);
1895
# if STACK_GROWS_DOWN
1896
result = (ptr_t)((((word)(&dummy))
1897
+ STACKBOTTOM_ALIGNMENT_M1)
1898
& ~STACKBOTTOM_ALIGNMENT_M1);
1900
result = (ptr_t)(((word)(&dummy))
1901
& ~STACKBOTTOM_ALIGNMENT_M1);
1903
# endif /* HEURISTIC1 */
1904
# ifdef LINUX_STACKBOTTOM
1905
result = GC_linux_stack_base();
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;
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;
1926
# endif /* HEURISTIC2 */
1927
# if STACK_GROWS_DOWN
1928
if (result == 0) result = (ptr_t)(signed_word)(-sizeof(ptr_t));
1931
# endif /* STACKBOTTOM */
1934
# endif /* ! AMIGA */
1936
# endif /* ! MSWIN32 */
1938
#endif /* mach_type_known */
1939
#endif /* ! HAVE_LIBC_STACK_END */