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.
7 * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
8 * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
10 * Permission is hereby granted to use or copy this program
11 * for any purpose, provided the above notices are retained on all copies.
12 * Permission to modify the code and to distribute modified code is granted,
13 * provided the above notices are retained, and a notice that the code was
14 * modified is included with the above copyright notice.
17 # include "private/gc_priv.h"
19 # if defined(LINUX) && !defined(POWERPC)
20 # include <linux/version.h>
21 # if (LINUX_VERSION_CODE <= 0x10400)
22 /* Ugly hack to get struct sigcontext_struct definition. Required */
23 /* for some early 1.3.X releases. Will hopefully go away soon. */
24 /* in some later Linux releases, asm/sigcontext.h may have to */
25 /* be included instead. */
27 # include <asm/signal.h>
30 /* Kernels prior to 2.1.1 defined struct sigcontext_struct instead of */
31 /* struct sigcontext. libc6 (glibc2) uses "struct sigcontext" in */
32 /* prototypes, so we have to include the top-level sigcontext.h to */
33 /* make sure the former gets defined to be the latter if appropriate. */
34 # include <features.h>
36 # if 2 == __GLIBC__ && 0 == __GLIBC_MINOR__
37 /* glibc 2.1 no longer has sigcontext.h. But signal.h */
38 /* has the right declaration for glibc 2.1. */
39 # include <sigcontext.h>
40 # endif /* 0 == __GLIBC_MINOR__ */
41 # else /* not 2 <= __GLIBC__ */
42 /* libc5 doesn't have <sigcontext.h>: go directly with the kernel */
43 /* one. Check LINUX_VERSION_CODE to see which we should reference. */
44 # include <asm/sigcontext.h>
45 # endif /* 2 <= __GLIBC__ */
48 # if !defined(OS2) && !defined(PCR) && !defined(AMIGA) && !defined(MACOS) \
50 # include <sys/types.h>
51 # if !defined(MSWIN32) && !defined(SUNOS4)
58 # define SIGSEGV 0 /* value is irrelevant */
63 /* Blatantly OS dependent routines, except for those that are related */
64 /* to dynamic loading. */
66 # if defined(HEURISTIC2) || defined(SEARCH_FOR_DATA_START)
67 # define NEED_FIND_LIMIT
70 # if !defined(STACKBOTTOM) && defined(HEURISTIC2)
71 # define NEED_FIND_LIMIT
74 # if (defined(SUNOS4) && defined(DYNAMIC_LOADING)) && !defined(PCR)
75 # define NEED_FIND_LIMIT
78 # if (defined(SVR4) || defined(AUX) || defined(DGUX) \
79 || (defined(LINUX) && defined(SPARC))) && !defined(PCR)
80 # define NEED_FIND_LIMIT
83 #if defined(FREEBSD) && defined(I386)
84 # include <machine/trap.h>
86 # define NEED_FIND_LIMIT
90 #ifdef NEED_FIND_LIMIT
94 #if defined(FREEBSD) && defined(I386)
95 # include <machine/trap.h>
100 # include "AmigaOS.c"
104 #if defined(MSWIN32) || defined(MSWINCE)
105 # define WIN32_LEAN_AND_MEAN
107 # include <windows.h>
111 # include <Processes.h>
115 # include <sys/uio.h>
116 # include <malloc.h> /* for locking */
119 # include <sys/types.h>
120 # include <sys/mman.h>
121 # include <sys/stat.h>
128 #if defined(SUNOS5SIGS) || defined (HURD) || defined(LINUX)
130 # include <sys/siginfo.h>
134 # define setjmp(env) sigsetjmp(env, 1)
135 # define longjmp(env, val) siglongjmp(env, val)
136 # define jmp_buf sigjmp_buf
140 /* for get_etext and friends */
141 #include <mach-o/getsect.h>
145 /* Apparently necessary for djgpp 2.01. May cause problems with */
146 /* other versions. */
147 typedef long unsigned int caddr_t;
151 # include "il/PCR_IL.h"
152 # include "th/PCR_ThCtl.h"
153 # include "mm/PCR_MM.h"
156 #if !defined(NO_EXECUTE_PERMISSION)
157 # define OPT_PROT_EXEC PROT_EXEC
159 # define OPT_PROT_EXEC 0
162 #if defined(LINUX) && \
163 (defined(USE_PROC_FOR_LIBRARIES) || defined(IA64) || !defined(SMALL_CONFIG))
165 /* We need to parse /proc/self/maps, either to find dynamic libraries, */
166 /* and/or to find the register backing store base (IA64). Do it once */
171 /* Repeatedly perform a read call until the buffer is filled or */
172 /* we encounter EOF. */
173 ssize_t GC_repeat_read(int fd, char *buf, size_t count)
175 ssize_t num_read = 0;
178 while (num_read < count) {
179 result = READ(fd, buf + num_read, count - num_read);
180 if (result < 0) return result;
181 if (result == 0) break;
188 * Apply fn to a buffer containing the contents of /proc/self/maps.
189 * Return the result of fn or, if we failed, 0.
192 word GC_apply_to_maps(word (*fn)(char *))
197 char maps_temp[32768];
200 /* Read /proc/self/maps */
201 /* Note that we may not allocate, and thus can't use stdio. */
202 f = open("/proc/self/maps", O_RDONLY);
203 if (-1 == f) return 0;
204 /* stat() doesn't work for /proc/self/maps, so we have to
205 read it to find out how large it is... */
208 result = GC_repeat_read(f, maps_temp, sizeof(maps_temp));
209 if (result <= 0) return 0;
211 } while (result == sizeof(maps_temp));
213 if (maps_size > sizeof(maps_temp)) {
214 /* If larger than our buffer, close and re-read it. */
216 f = open("/proc/self/maps", O_RDONLY);
217 if (-1 == f) return 0;
218 maps_buf = alloca(maps_size);
219 if (NULL == maps_buf) return 0;
220 result = GC_repeat_read(f, maps_buf, maps_size);
221 if (result <= 0) return 0;
223 /* Otherwise use the fixed size buffer */
224 maps_buf = maps_temp;
228 maps_buf[result] = '\0';
230 /* Apply fn to result. */
234 #endif /* Need GC_apply_to_maps */
236 #if defined(LINUX) && (defined(USE_PROC_FOR_LIBRARIES) || defined(IA64))
238 // GC_parse_map_entry parses an entry from /proc/self/maps so we can
239 // locate all writable data segments that belong to shared libraries.
240 // The format of one of these entries and the fields we care about
242 // XXXXXXXX-XXXXXXXX r-xp 00000000 30:05 260537 name of mapping...\n
243 // ^^^^^^^^ ^^^^^^^^ ^^^^ ^^
244 // start end prot maj_dev
250 // The parser is called with a pointer to the entry and the return value
251 // is either NULL or is advanced to the next entry(the byte after the
255 # define OFFSET_MAP_START 0
256 # define OFFSET_MAP_END 9
257 # define OFFSET_MAP_PROT 18
258 # define OFFSET_MAP_MAJDEV 32
259 # define ADDR_WIDTH 8
263 # define OFFSET_MAP_START 0
264 # define OFFSET_MAP_END 17
265 # define OFFSET_MAP_PROT 34
266 # define OFFSET_MAP_MAJDEV 56
267 # define ADDR_WIDTH 16
271 * Assign various fields of the first line in buf_ptr to *start, *end,
272 * *prot_buf and *maj_dev. Only *prot_buf may be set for unwritable maps.
274 char *GC_parse_map_entry(char *buf_ptr, word *start, word *end,
275 char *prot_buf, unsigned int *maj_dev)
280 if (buf_ptr == NULL || *buf_ptr == '\0') {
284 memcpy(prot_buf, buf_ptr+OFFSET_MAP_PROT, 4);
285 /* do the protections first. */
288 if (prot_buf[1] == 'w') {/* we can skip all of this if it's not writable. */
291 buf_ptr[OFFSET_MAP_START+ADDR_WIDTH] = '\0';
292 *start = strtoul(tok, NULL, 16);
294 tok = buf_ptr+OFFSET_MAP_END;
295 buf_ptr[OFFSET_MAP_END+ADDR_WIDTH] = '\0';
296 *end = strtoul(tok, NULL, 16);
298 buf_ptr += OFFSET_MAP_MAJDEV;
300 while (*buf_ptr != ':') buf_ptr++;
302 *maj_dev = strtoul(tok, NULL, 16);
305 while (*buf_ptr && *buf_ptr++ != '\n');
310 #endif /* Need to parse /proc/self/maps. */
312 #if defined(SEARCH_FOR_DATA_START)
313 /* The I386 case can be handled without a search. The Alpha case */
314 /* used to be handled differently as well, but the rules changed */
315 /* for recent Linux versions. This seems to be the easiest way to */
316 /* cover all versions. */
319 /* Some Linux distributions arrange to define __data_start. Some */
320 /* define data_start as a weak symbol. The latter is technically */
321 /* broken, since the user program may define data_start, in which */
322 /* case we lose. Nonetheless, we try both, prefering __data_start. */
323 /* We assume gcc-compatible pragmas. */
324 # pragma weak __data_start
325 extern int __data_start[];
326 # pragma weak data_start
327 extern int data_start[];
333 void GC_init_linux_data_start()
335 extern ptr_t GC_find_limit();
338 /* Try the easy approaches first: */
339 if ((ptr_t)__data_start != 0) {
340 GC_data_start = (ptr_t)(__data_start);
343 if ((ptr_t)data_start != 0) {
344 GC_data_start = (ptr_t)(data_start);
348 GC_data_start = GC_find_limit((ptr_t)(_end), FALSE);
354 # ifndef ECOS_GC_MEMORY_SIZE
355 # define ECOS_GC_MEMORY_SIZE (448 * 1024)
356 # endif /* ECOS_GC_MEMORY_SIZE */
358 // setjmp() function, as described in ANSI para 7.6.1.1
359 #define setjmp( __env__ ) hal_setjmp( __env__ )
361 // FIXME: This is a simple way of allocating memory which is
362 // compatible with ECOS early releases. Later releases use a more
363 // sophisticated means of allocating memory than this simple static
364 // allocator, but this method is at least bound to work.
365 static char memory[ECOS_GC_MEMORY_SIZE];
366 static char *brk = memory;
368 static void *tiny_sbrk(ptrdiff_t increment)
374 if (brk > memory + sizeof memory)
382 #define sbrk tiny_sbrk
385 #if (defined(NETBSD) || defined(OPENBSD)) && defined(__ELF__)
388 void GC_init_netbsd_elf()
390 extern ptr_t GC_find_limit();
391 extern char **environ;
392 /* This may need to be environ, without the underscore, for */
394 GC_data_start = GC_find_limit((ptr_t)&environ, FALSE);
402 # if !defined(__IBMC__) && !defined(__WATCOMC__) /* e.g. EMX */
405 unsigned short magic_number;
406 unsigned short padding[29];
410 #define E_MAGIC(x) (x).magic_number
411 #define EMAGIC 0x5A4D
412 #define E_LFANEW(x) (x).new_exe_offset
415 unsigned char magic_number[2];
416 unsigned char byte_order;
417 unsigned char word_order;
418 unsigned long exe_format_level;
421 unsigned long padding1[13];
422 unsigned long object_table_offset;
423 unsigned long object_count;
424 unsigned long padding2[31];
427 #define E32_MAGIC1(x) (x).magic_number[0]
428 #define E32MAGIC1 'L'
429 #define E32_MAGIC2(x) (x).magic_number[1]
430 #define E32MAGIC2 'X'
431 #define E32_BORDER(x) (x).byte_order
433 #define E32_WORDER(x) (x).word_order
435 #define E32_CPU(x) (x).cpu
437 #define E32_OBJTAB(x) (x).object_table_offset
438 #define E32_OBJCNT(x) (x).object_count
444 unsigned long pagemap;
445 unsigned long mapsize;
446 unsigned long reserved;
449 #define O32_FLAGS(x) (x).flags
450 #define OBJREAD 0x0001L
451 #define OBJWRITE 0x0002L
452 #define OBJINVALID 0x0080L
453 #define O32_SIZE(x) (x).size
454 #define O32_BASE(x) (x).base
456 # else /* IBM's compiler */
458 /* A kludge to get around what appears to be a header file bug */
460 # define WORD unsigned short
463 # define DWORD unsigned long
470 # endif /* __IBMC__ */
472 # define INCL_DOSEXCEPTIONS
473 # define INCL_DOSPROCESS
474 # define INCL_DOSERRORS
475 # define INCL_DOSMODULEMGR
476 # define INCL_DOSMEMMGR
480 /* Disable and enable signals during nontrivial allocations */
482 void GC_disable_signals(void)
486 DosEnterMustComplete(&nest);
487 if (nest != 1) ABORT("nested GC_disable_signals");
490 void GC_enable_signals(void)
494 DosExitMustComplete(&nest);
495 if (nest != 0) ABORT("GC_enable_signals");
501 # if !defined(PCR) && !defined(AMIGA) && !defined(MSWIN32) \
502 && !defined(MSWINCE) \
503 && !defined(MACOS) && !defined(DJGPP) && !defined(DOS4GW) \
504 && !defined(NOSYS) && !defined(ECOS)
506 # if defined(sigmask) && !defined(UTS4) && !defined(HURD)
507 /* Use the traditional BSD interface */
508 # define SIGSET_T int
509 # define SIG_DEL(set, signal) (set) &= ~(sigmask(signal))
510 # define SIG_FILL(set) (set) = 0x7fffffff
511 /* Setting the leading bit appears to provoke a bug in some */
512 /* longjmp implementations. Most systems appear not to have */
514 # define SIGSETMASK(old, new) (old) = sigsetmask(new)
516 /* Use POSIX/SYSV interface */
517 # define SIGSET_T sigset_t
518 # define SIG_DEL(set, signal) sigdelset(&(set), (signal))
519 # define SIG_FILL(set) sigfillset(&set)
520 # define SIGSETMASK(old, new) sigprocmask(SIG_SETMASK, &(new), &(old))
523 static GC_bool mask_initialized = FALSE;
525 static SIGSET_T new_mask;
527 static SIGSET_T old_mask;
529 static SIGSET_T dummy;
531 #if defined(PRINTSTATS) && !defined(THREADS)
532 # define CHECK_SIGNALS
533 int GC_sig_disabled = 0;
536 void GC_disable_signals()
538 if (!mask_initialized) {
541 SIG_DEL(new_mask, SIGSEGV);
542 SIG_DEL(new_mask, SIGILL);
543 SIG_DEL(new_mask, SIGQUIT);
545 SIG_DEL(new_mask, SIGBUS);
548 SIG_DEL(new_mask, SIGIOT);
551 SIG_DEL(new_mask, SIGEMT);
554 SIG_DEL(new_mask, SIGTRAP);
556 mask_initialized = TRUE;
558 # ifdef CHECK_SIGNALS
559 if (GC_sig_disabled != 0) ABORT("Nested disables");
562 SIGSETMASK(old_mask,new_mask);
565 void GC_enable_signals()
567 # ifdef CHECK_SIGNALS
568 if (GC_sig_disabled != 1) ABORT("Unmatched enable");
571 SIGSETMASK(dummy,old_mask);
578 /* Ivan Demakov: simplest way (to me) */
580 void GC_disable_signals() { }
581 void GC_enable_signals() { }
584 /* Find the page size */
587 # if defined(MSWIN32) || defined(MSWINCE)
588 void GC_setpagesize()
590 GetSystemInfo(&GC_sysinfo);
591 GC_page_size = GC_sysinfo.dwPageSize;
595 # if defined(MPROTECT_VDB) || defined(PROC_VDB) || defined(USE_MMAP) \
596 || defined(USE_MUNMAP)
597 void GC_setpagesize()
599 GC_page_size = GETPAGESIZE();
602 /* It's acceptable to fake it. */
603 void GC_setpagesize()
605 GC_page_size = HBLKSIZE;
611 * Find the base of the stack.
612 * Used only in single-threaded environment.
613 * With threads, GC_mark_roots needs to know how to do this.
614 * Called with allocator lock held.
616 # if defined(MSWIN32) || defined(MSWINCE)
617 # define is_writable(prot) ((prot) == PAGE_READWRITE \
618 || (prot) == PAGE_WRITECOPY \
619 || (prot) == PAGE_EXECUTE_READWRITE \
620 || (prot) == PAGE_EXECUTE_WRITECOPY)
621 /* Return the number of bytes that are writable starting at p. */
622 /* The pointer p is assumed to be page aligned. */
623 /* If base is not 0, *base becomes the beginning of the */
624 /* allocation region containing p. */
625 word GC_get_writable_length(ptr_t p, ptr_t *base)
627 MEMORY_BASIC_INFORMATION buf;
631 result = VirtualQuery(p, &buf, sizeof(buf));
632 if (result != sizeof(buf)) ABORT("Weird VirtualQuery result");
633 if (base != 0) *base = (ptr_t)(buf.AllocationBase);
634 protect = (buf.Protect & ~(PAGE_GUARD | PAGE_NOCACHE));
635 if (!is_writable(protect)) {
638 if (buf.State != MEM_COMMIT) return(0);
639 return(buf.RegionSize);
642 ptr_t GC_get_stack_base()
645 ptr_t sp = (ptr_t)(&dummy);
646 ptr_t trunc_sp = (ptr_t)((word)sp & ~(GC_page_size - 1));
647 word size = GC_get_writable_length(trunc_sp, 0);
649 return(trunc_sp + size);
653 # endif /* MS Windows */
656 # include <kernel/OS.h>
657 ptr_t GC_get_stack_base(){
659 get_thread_info(find_thread(NULL),&th);
667 ptr_t GC_get_stack_base()
672 if (DosGetInfoBlocks(&ptib, &ppib) != NO_ERROR) {
673 GC_err_printf0("DosGetInfoBlocks failed\n");
674 ABORT("DosGetInfoBlocks failed\n");
676 return((ptr_t)(ptib -> tib_pstacklimit));
683 # include "AmigaOS.c"
687 # if defined(NEED_FIND_LIMIT) || defined(UNIX_LIKE)
690 typedef void (*handler)(int);
692 typedef void (*handler)();
695 # if defined(SUNOS5SIGS) || defined(IRIX5) || defined(OSF1) || defined(HURD)
696 static struct sigaction old_segv_act;
697 # if defined(_sigargs) /* !Irix6.x */ || defined(HPUX) || defined(HURD)
698 static struct sigaction old_bus_act;
701 static handler old_segv_handler, old_bus_handler;
705 void GC_set_and_save_fault_handler(handler h)
707 void GC_set_and_save_fault_handler(h)
711 # if defined(SUNOS5SIGS) || defined(IRIX5) \
712 || defined(OSF1) || defined(HURD)
713 struct sigaction act;
717 act.sa_flags = SA_RESTART | SA_NODEFER;
719 act.sa_flags = SA_RESTART;
721 /* The presence of SA_NODEFER represents yet another gross */
722 /* hack. Under Solaris 2.3, siglongjmp doesn't appear to */
723 /* interact correctly with -lthread. We hide the confusion */
724 /* by making sure that signal handling doesn't affect the */
727 (void) sigemptyset(&act.sa_mask);
728 # ifdef GC_IRIX_THREADS
729 /* Older versions have a bug related to retrieving and */
730 /* and setting a handler at the same time. */
731 (void) sigaction(SIGSEGV, 0, &old_segv_act);
732 (void) sigaction(SIGSEGV, &act, 0);
734 (void) sigaction(SIGSEGV, &act, &old_segv_act);
735 # if defined(IRIX5) && defined(_sigargs) /* Irix 5.x, not 6.x */ \
736 || defined(HPUX) || defined(HURD)
737 /* Under Irix 5.x or HP/UX, we may get SIGBUS. */
738 /* Pthreads doesn't exist under Irix 5.x, so we */
739 /* don't have to worry in the threads case. */
740 (void) sigaction(SIGBUS, &act, &old_bus_act);
742 # endif /* GC_IRIX_THREADS */
744 old_segv_handler = signal(SIGSEGV, h);
746 old_bus_handler = signal(SIGBUS, h);
750 # endif /* NEED_FIND_LIMIT || UNIX_LIKE */
752 # ifdef NEED_FIND_LIMIT
753 /* Some tools to implement HEURISTIC2 */
754 # define MIN_PAGE_SIZE 256 /* Smallest conceivable page size, bytes */
755 /* static */ jmp_buf GC_jmp_buf;
758 void GC_fault_handler(sig)
761 longjmp(GC_jmp_buf, 1);
764 void GC_setup_temporary_fault_handler()
766 GC_set_and_save_fault_handler(GC_fault_handler);
769 void GC_reset_fault_handler()
771 # if defined(SUNOS5SIGS) || defined(IRIX5) \
772 || defined(OSF1) || defined(HURD)
773 (void) sigaction(SIGSEGV, &old_segv_act, 0);
774 # if defined(IRIX5) && defined(_sigargs) /* Irix 5.x, not 6.x */ \
775 || defined(HPUX) || defined(HURD)
776 (void) sigaction(SIGBUS, &old_bus_act, 0);
779 (void) signal(SIGSEGV, old_segv_handler);
781 (void) signal(SIGBUS, old_bus_handler);
786 /* Return the first nonaddressible location > p (up) or */
787 /* the smallest location q s.t. [q,p) is addressable (!up). */
788 /* We assume that p (up) or p-1 (!up) is addressable. */
789 ptr_t GC_find_limit(p, up)
793 static VOLATILE ptr_t result;
794 /* Needs to be static, since otherwise it may not be */
795 /* preserved across the longjmp. Can safely be */
796 /* static since it's only called once, with the */
797 /* allocation lock held. */
800 GC_setup_temporary_fault_handler();
801 if (setjmp(GC_jmp_buf) == 0) {
802 result = (ptr_t)(((word)(p))
803 & ~(MIN_PAGE_SIZE-1));
806 result += MIN_PAGE_SIZE;
808 result -= MIN_PAGE_SIZE;
810 GC_noop1((word)(*result));
813 GC_reset_fault_handler();
815 result += MIN_PAGE_SIZE;
821 #if defined(ECOS) || defined(NOSYS)
822 ptr_t GC_get_stack_base()
828 #ifdef LINUX_STACKBOTTOM
830 #include <sys/types.h>
831 #include <sys/stat.h>
834 # define STAT_SKIP 27 /* Number of fields preceding startstack */
835 /* field in /proc/self/stat */
837 # pragma weak __libc_stack_end
838 extern ptr_t __libc_stack_end;
841 /* Try to read the backing store base from /proc/self/maps. */
842 /* We look for the writable mapping with a 0 major device, */
843 /* which is as close to our frame as possible, but below it.*/
844 static word backing_store_base_from_maps(char *maps)
847 char *buf_ptr = maps;
849 unsigned int maj_dev;
850 word current_best = 0;
854 buf_ptr = GC_parse_map_entry(buf_ptr, &start, &end, prot_buf, &maj_dev);
855 if (buf_ptr == NULL) return current_best;
856 if (prot_buf[1] == 'w' && maj_dev == 0) {
857 if (end < (word)(&dummy) && start > current_best) current_best = start;
863 static word backing_store_base_from_proc(void)
865 return GC_apply_to_maps(backing_store_base_from_maps);
868 # pragma weak __libc_ia64_register_backing_store_base
869 extern ptr_t __libc_ia64_register_backing_store_base;
871 ptr_t GC_get_register_stack_base(void)
873 if (0 != &__libc_ia64_register_backing_store_base
874 && 0 != __libc_ia64_register_backing_store_base) {
875 /* Glibc 2.2.4 has a bug such that for dynamically linked */
876 /* executables __libc_ia64_register_backing_store_base is */
877 /* defined but uninitialized during constructor calls. */
878 /* Hence we check for both nonzero address and value. */
879 return __libc_ia64_register_backing_store_base;
881 word result = backing_store_base_from_proc();
883 /* Use dumb heuristics. Works only for default configuration. */
884 result = (word)GC_stackbottom - BACKING_STORE_DISPLACEMENT;
885 result += BACKING_STORE_ALIGNMENT - 1;
886 result &= ~(BACKING_STORE_ALIGNMENT - 1);
887 /* Verify that it's at least readable. If not, we goofed. */
888 GC_noop1(*(word *)result);
890 return (ptr_t)result;
895 ptr_t GC_linux_stack_base(void)
897 /* We read the stack base value from /proc/self/stat. We do this */
898 /* using direct I/O system calls in order to avoid calling malloc */
899 /* in case REDIRECT_MALLOC is defined. */
900 # define STAT_BUF_SIZE 4096
901 # define STAT_READ read
902 /* Should probably call the real read, if read is wrapped. */
903 char stat_buf[STAT_BUF_SIZE];
907 size_t i, buf_offset = 0;
909 /* First try the easy way. This should work for glibc 2.2 */
910 if (0 != &__libc_stack_end) {
912 /* Some versions of glibc set the address 16 bytes too */
913 /* low while the initialization code is running. */
914 if (((word)__libc_stack_end & 0xfff) + 0x10 < 0x1000) {
915 return __libc_stack_end + 0x10;
916 } /* Otherwise it's not safe to add 16 bytes and we fall */
917 /* back to using /proc. */
919 return __libc_stack_end;
922 f = open("/proc/self/stat", O_RDONLY);
923 if (f < 0 || STAT_READ(f, stat_buf, STAT_BUF_SIZE) < 2 * STAT_SKIP) {
924 ABORT("Couldn't read /proc/self/stat");
926 c = stat_buf[buf_offset++];
927 /* Skip the required number of fields. This number is hopefully */
928 /* constant across all Linux implementations. */
929 for (i = 0; i < STAT_SKIP; ++i) {
930 while (isspace(c)) c = stat_buf[buf_offset++];
931 while (!isspace(c)) c = stat_buf[buf_offset++];
933 while (isspace(c)) c = stat_buf[buf_offset++];
937 c = stat_buf[buf_offset++];
940 if (result < 0x10000000) ABORT("Absurd stack bottom value");
941 return (ptr_t)result;
944 #endif /* LINUX_STACKBOTTOM */
946 #ifdef FREEBSD_STACKBOTTOM
948 /* This uses an undocumented sysctl call, but at least one expert */
949 /* believes it will stay. */
952 #include <sys/types.h>
953 #include <sys/sysctl.h>
955 ptr_t GC_freebsd_stack_base(void)
957 int nm[2] = {CTL_KERN, KERN_USRSTACK};
959 size_t len = sizeof(ptr_t);
960 int r = sysctl(nm, 2, &base, &len, NULL, 0);
962 if (r) ABORT("Error getting stack base");
967 #endif /* FREEBSD_STACKBOTTOM */
969 #if !defined(BEOS) && !defined(AMIGA) && !defined(MSWIN32) \
970 && !defined(MSWINCE) && !defined(OS2)
972 ptr_t GC_get_stack_base()
974 # if defined(HEURISTIC1) || defined(HEURISTIC2) || \
975 defined(LINUX_STACKBOTTOM) || defined(FREEBSD_STACKBOTTOM)
980 # define STACKBOTTOM_ALIGNMENT_M1 ((word)STACK_GRAN - 1)
986 # ifdef STACK_GROWS_DOWN
987 result = (ptr_t)((((word)(&dummy))
988 + STACKBOTTOM_ALIGNMENT_M1)
989 & ~STACKBOTTOM_ALIGNMENT_M1);
991 result = (ptr_t)(((word)(&dummy))
992 & ~STACKBOTTOM_ALIGNMENT_M1);
994 # endif /* HEURISTIC1 */
995 # ifdef LINUX_STACKBOTTOM
996 result = GC_linux_stack_base();
998 # ifdef FREEBSD_STACKBOTTOM
999 result = GC_freebsd_stack_base();
1002 # ifdef STACK_GROWS_DOWN
1003 result = GC_find_limit((ptr_t)(&dummy), TRUE);
1004 # ifdef HEURISTIC2_LIMIT
1005 if (result > HEURISTIC2_LIMIT
1006 && (ptr_t)(&dummy) < HEURISTIC2_LIMIT) {
1007 result = HEURISTIC2_LIMIT;
1011 result = GC_find_limit((ptr_t)(&dummy), FALSE);
1012 # ifdef HEURISTIC2_LIMIT
1013 if (result < HEURISTIC2_LIMIT
1014 && (ptr_t)(&dummy) > HEURISTIC2_LIMIT) {
1015 result = HEURISTIC2_LIMIT;
1020 # endif /* HEURISTIC2 */
1021 # ifdef STACK_GROWS_DOWN
1022 if (result == 0) result = (ptr_t)(signed_word)(-sizeof(ptr_t));
1025 # endif /* STACKBOTTOM */
1028 # endif /* ! AMIGA, !OS 2, ! MS Windows, !BEOS */
1031 * Register static data segment(s) as roots.
1032 * If more data segments are added later then they need to be registered
1033 * add that point (as we do with SunOS dynamic loading),
1034 * or GC_mark_roots needs to check for them (as we do with PCR).
1035 * Called with allocator lock held.
1040 void GC_register_data_segments()
1044 HMODULE module_handle;
1045 # define PBUFSIZ 512
1046 UCHAR path[PBUFSIZ];
1048 struct exe_hdr hdrdos; /* MSDOS header. */
1049 struct e32_exe hdr386; /* Real header for my executable */
1050 struct o32_obj seg; /* Currrent segment */
1054 if (DosGetInfoBlocks(&ptib, &ppib) != NO_ERROR) {
1055 GC_err_printf0("DosGetInfoBlocks failed\n");
1056 ABORT("DosGetInfoBlocks failed\n");
1058 module_handle = ppib -> pib_hmte;
1059 if (DosQueryModuleName(module_handle, PBUFSIZ, path) != NO_ERROR) {
1060 GC_err_printf0("DosQueryModuleName failed\n");
1061 ABORT("DosGetInfoBlocks failed\n");
1063 myexefile = fopen(path, "rb");
1064 if (myexefile == 0) {
1065 GC_err_puts("Couldn't open executable ");
1066 GC_err_puts(path); GC_err_puts("\n");
1067 ABORT("Failed to open executable\n");
1069 if (fread((char *)(&hdrdos), 1, sizeof hdrdos, myexefile) < sizeof hdrdos) {
1070 GC_err_puts("Couldn't read MSDOS header from ");
1071 GC_err_puts(path); GC_err_puts("\n");
1072 ABORT("Couldn't read MSDOS header");
1074 if (E_MAGIC(hdrdos) != EMAGIC) {
1075 GC_err_puts("Executable has wrong DOS magic number: ");
1076 GC_err_puts(path); GC_err_puts("\n");
1077 ABORT("Bad DOS magic number");
1079 if (fseek(myexefile, E_LFANEW(hdrdos), SEEK_SET) != 0) {
1080 GC_err_puts("Seek to new header failed in ");
1081 GC_err_puts(path); GC_err_puts("\n");
1082 ABORT("Bad DOS magic number");
1084 if (fread((char *)(&hdr386), 1, sizeof hdr386, myexefile) < sizeof hdr386) {
1085 GC_err_puts("Couldn't read MSDOS header from ");
1086 GC_err_puts(path); GC_err_puts("\n");
1087 ABORT("Couldn't read OS/2 header");
1089 if (E32_MAGIC1(hdr386) != E32MAGIC1 || E32_MAGIC2(hdr386) != E32MAGIC2) {
1090 GC_err_puts("Executable has wrong OS/2 magic number:");
1091 GC_err_puts(path); GC_err_puts("\n");
1092 ABORT("Bad OS/2 magic number");
1094 if ( E32_BORDER(hdr386) != E32LEBO || E32_WORDER(hdr386) != E32LEWO) {
1095 GC_err_puts("Executable %s has wrong byte order: ");
1096 GC_err_puts(path); GC_err_puts("\n");
1097 ABORT("Bad byte order");
1099 if ( E32_CPU(hdr386) == E32CPU286) {
1100 GC_err_puts("GC can't handle 80286 executables: ");
1101 GC_err_puts(path); GC_err_puts("\n");
1104 if (fseek(myexefile, E_LFANEW(hdrdos) + E32_OBJTAB(hdr386),
1106 GC_err_puts("Seek to object table failed: ");
1107 GC_err_puts(path); GC_err_puts("\n");
1108 ABORT("Seek to object table failed");
1110 for (nsegs = E32_OBJCNT(hdr386); nsegs > 0; nsegs--) {
1112 if (fread((char *)(&seg), 1, sizeof seg, myexefile) < sizeof seg) {
1113 GC_err_puts("Couldn't read obj table entry from ");
1114 GC_err_puts(path); GC_err_puts("\n");
1115 ABORT("Couldn't read obj table entry");
1117 flags = O32_FLAGS(seg);
1118 if (!(flags & OBJWRITE)) continue;
1119 if (!(flags & OBJREAD)) continue;
1120 if (flags & OBJINVALID) {
1121 GC_err_printf0("Object with invalid pages?\n");
1124 GC_add_roots_inner(O32_BASE(seg), O32_BASE(seg)+O32_SIZE(seg), FALSE);
1130 # if defined(MSWIN32) || defined(MSWINCE)
1133 /* Unfortunately, we have to handle win32s very differently from NT, */
1134 /* Since VirtualQuery has very different semantics. In particular, */
1135 /* under win32s a VirtualQuery call on an unmapped page returns an */
1136 /* invalid result. Under NT, GC_register_data_segments is a noop and */
1137 /* all real work is done by GC_register_dynamic_libraries. Under */
1138 /* win32s, we cannot find the data segments associated with dll's. */
1139 /* We register the main data segment here. */
1140 GC_bool GC_no_win32_dlls = FALSE;
1141 /* This used to be set for gcc, to avoid dealing with */
1142 /* the structured exception handling issues. But we now have */
1143 /* assembly code to do that right. */
1145 void GC_init_win32()
1147 /* if we're running under win32s, assume that no DLLs will be loaded */
1148 DWORD v = GetVersion();
1149 GC_no_win32_dlls |= ((v & 0x80000000) && (v & 0xff) <= 3);
1152 /* Return the smallest address a such that VirtualQuery */
1153 /* returns correct results for all addresses between a and start. */
1154 /* Assumes VirtualQuery returns correct information for start. */
1155 ptr_t GC_least_described_address(ptr_t start)
1157 MEMORY_BASIC_INFORMATION buf;
1163 limit = GC_sysinfo.lpMinimumApplicationAddress;
1164 p = (ptr_t)((word)start & ~(GC_page_size - 1));
1166 q = (LPVOID)(p - GC_page_size);
1167 if ((ptr_t)q > (ptr_t)p /* underflow */ || q < limit) break;
1168 result = VirtualQuery(q, &buf, sizeof(buf));
1169 if (result != sizeof(buf) || buf.AllocationBase == 0) break;
1170 p = (ptr_t)(buf.AllocationBase);
1176 # ifndef REDIRECT_MALLOC
1177 /* We maintain a linked list of AllocationBase values that we know */
1178 /* correspond to malloc heap sections. Currently this is only called */
1179 /* during a GC. But there is some hope that for long running */
1180 /* programs we will eventually see most heap sections. */
1182 /* In the long run, it would be more reliable to occasionally walk */
1183 /* the malloc heap with HeapWalk on the default heap. But that */
1184 /* apparently works only for NT-based Windows. */
1186 /* In the long run, a better data structure would also be nice ... */
1187 struct GC_malloc_heap_list {
1188 void * allocation_base;
1189 struct GC_malloc_heap_list *next;
1190 } *GC_malloc_heap_l = 0;
1192 /* Is p the base of one of the malloc heap sections we already know */
1194 GC_bool GC_is_malloc_heap_base(ptr_t p)
1196 struct GC_malloc_heap_list *q = GC_malloc_heap_l;
1199 if (q -> allocation_base == p) return TRUE;
1205 void *GC_get_allocation_base(void *p)
1207 MEMORY_BASIC_INFORMATION buf;
1208 DWORD result = VirtualQuery(p, &buf, sizeof(buf));
1209 if (result != sizeof(buf)) {
1210 ABORT("Weird VirtualQuery result");
1212 return buf.AllocationBase;
1215 size_t GC_max_root_size = 100000; /* Appr. largest root size. */
1217 void GC_add_current_malloc_heap()
1219 struct GC_malloc_heap_list *new_l =
1220 malloc(sizeof(struct GC_malloc_heap_list));
1221 void * candidate = GC_get_allocation_base(new_l);
1223 if (new_l == 0) return;
1224 if (GC_is_malloc_heap_base(candidate)) {
1225 /* Try a little harder to find malloc heap. */
1226 size_t req_size = 10000;
1228 void *p = malloc(req_size);
1229 if (0 == p) { free(new_l); return; }
1230 candidate = GC_get_allocation_base(p);
1233 } while (GC_is_malloc_heap_base(candidate)
1234 && req_size < GC_max_root_size/10 && req_size < 500000);
1235 if (GC_is_malloc_heap_base(candidate)) {
1236 free(new_l); return;
1241 GC_printf1("Found new system malloc AllocationBase at 0x%lx\n",
1244 new_l -> allocation_base = candidate;
1245 new_l -> next = GC_malloc_heap_l;
1246 GC_malloc_heap_l = new_l;
1248 # endif /* REDIRECT_MALLOC */
1250 /* Is p the start of either the malloc heap, or of one of our */
1251 /* heap sections? */
1252 GC_bool GC_is_heap_base (ptr_t p)
1257 # ifndef REDIRECT_MALLOC
1258 static word last_gc_no = -1;
1260 if (last_gc_no != GC_gc_no) {
1261 GC_add_current_malloc_heap();
1262 last_gc_no = GC_gc_no;
1264 if (GC_root_size > GC_max_root_size) GC_max_root_size = GC_root_size;
1265 if (GC_is_malloc_heap_base(p)) return TRUE;
1267 for (i = 0; i < GC_n_heap_bases; i++) {
1268 if (GC_heap_bases[i] == p) return TRUE;
1274 void GC_register_root_section(ptr_t static_root)
1276 MEMORY_BASIC_INFORMATION buf;
1281 char * limit, * new_limit;
1283 if (!GC_no_win32_dlls) return;
1284 p = base = limit = GC_least_described_address(static_root);
1285 while (p < GC_sysinfo.lpMaximumApplicationAddress) {
1286 result = VirtualQuery(p, &buf, sizeof(buf));
1287 if (result != sizeof(buf) || buf.AllocationBase == 0
1288 || GC_is_heap_base(buf.AllocationBase)) break;
1289 new_limit = (char *)p + buf.RegionSize;
1290 protect = buf.Protect;
1291 if (buf.State == MEM_COMMIT
1292 && is_writable(protect)) {
1293 if ((char *)p == limit) {
1296 if (base != limit) GC_add_roots_inner(base, limit, FALSE);
1301 if (p > (LPVOID)new_limit /* overflow */) break;
1302 p = (LPVOID)new_limit;
1304 if (base != limit) GC_add_roots_inner(base, limit, FALSE);
1308 void GC_register_data_segments()
1312 GC_register_root_section((ptr_t)(&dummy));
1316 # else /* !OS2 && !Windows */
1318 # if (defined(SVR4) || defined(AUX) || defined(DGUX) \
1319 || (defined(LINUX) && defined(SPARC))) && !defined(PCR)
1320 ptr_t GC_SysVGetDataStart(max_page_size, etext_addr)
1324 word text_end = ((word)(etext_addr) + sizeof(word) - 1)
1325 & ~(sizeof(word) - 1);
1326 /* etext rounded to word boundary */
1327 word next_page = ((text_end + (word)max_page_size - 1)
1328 & ~((word)max_page_size - 1));
1329 word page_offset = (text_end & ((word)max_page_size - 1));
1330 VOLATILE char * result = (char *)(next_page + page_offset);
1331 /* Note that this isnt equivalent to just adding */
1332 /* max_page_size to &etext if &etext is at a page boundary */
1334 GC_setup_temporary_fault_handler();
1335 if (setjmp(GC_jmp_buf) == 0) {
1336 /* Try writing to the address. */
1338 GC_reset_fault_handler();
1340 GC_reset_fault_handler();
1341 /* We got here via a longjmp. The address is not readable. */
1342 /* This is known to happen under Solaris 2.4 + gcc, which place */
1343 /* string constants in the text segment, but after etext. */
1344 /* Use plan B. Note that we now know there is a gap between */
1345 /* text and data segments, so plan A bought us something. */
1346 result = (char *)GC_find_limit((ptr_t)(DATAEND), FALSE);
1348 return((ptr_t)result);
1352 # if defined(FREEBSD) && defined(I386) && !defined(PCR)
1353 /* Its unclear whether this should be identical to the above, or */
1354 /* whether it should apply to non-X86 architectures. */
1355 /* For now we don't assume that there is always an empty page after */
1356 /* etext. But in some cases there actually seems to be slightly more. */
1357 /* This also deals with holes between read-only data and writable data. */
1358 ptr_t GC_FreeBSDGetDataStart(max_page_size, etext_addr)
1362 word text_end = ((word)(etext_addr) + sizeof(word) - 1)
1363 & ~(sizeof(word) - 1);
1364 /* etext rounded to word boundary */
1365 VOLATILE word next_page = (text_end + (word)max_page_size - 1)
1366 & ~((word)max_page_size - 1);
1367 VOLATILE ptr_t result = (ptr_t)text_end;
1368 GC_setup_temporary_fault_handler();
1369 if (setjmp(GC_jmp_buf) == 0) {
1370 /* Try reading at the address. */
1371 /* This should happen before there is another thread. */
1372 for (; next_page < (word)(DATAEND); next_page += (word)max_page_size)
1373 *(VOLATILE char *)next_page;
1374 GC_reset_fault_handler();
1376 GC_reset_fault_handler();
1377 /* As above, we go to plan B */
1378 result = GC_find_limit((ptr_t)(DATAEND), FALSE);
1388 # define GC_AMIGA_DS
1389 # include "AmigaOS.c"
1392 #else /* !OS2 && !Windows && !AMIGA */
1394 void GC_register_data_segments()
1396 # if !defined(PCR) && !defined(SRC_M3) && !defined(MACOS)
1397 # if defined(REDIRECT_MALLOC) && defined(GC_SOLARIS_THREADS)
1398 /* As of Solaris 2.3, the Solaris threads implementation */
1399 /* allocates the data structure for the initial thread with */
1400 /* sbrk at process startup. It needs to be scanned, so that */
1401 /* we don't lose some malloc allocated data structures */
1402 /* hanging from it. We're on thin ice here ... */
1403 extern caddr_t sbrk();
1405 GC_add_roots_inner(DATASTART, (char *)sbrk(0), FALSE);
1407 GC_add_roots_inner(DATASTART, (char *)(DATAEND), FALSE);
1408 # if defined(DATASTART2)
1409 GC_add_roots_inner(DATASTART2, (char *)(DATAEND2), FALSE);
1415 # if defined(THINK_C)
1416 extern void* GC_MacGetDataStart(void);
1417 /* globals begin above stack and end at a5. */
1418 GC_add_roots_inner((ptr_t)GC_MacGetDataStart(),
1419 (ptr_t)LMGetCurrentA5(), FALSE);
1421 # if defined(__MWERKS__)
1423 extern void* GC_MacGetDataStart(void);
1424 /* MATTHEW: Function to handle Far Globals (CW Pro 3) */
1425 # if __option(far_data)
1426 extern void* GC_MacGetDataEnd(void);
1428 /* globals begin above stack and end at a5. */
1429 GC_add_roots_inner((ptr_t)GC_MacGetDataStart(),
1430 (ptr_t)LMGetCurrentA5(), FALSE);
1431 /* MATTHEW: Handle Far Globals */
1432 # if __option(far_data)
1433 /* Far globals follow he QD globals: */
1434 GC_add_roots_inner((ptr_t)LMGetCurrentA5(),
1435 (ptr_t)GC_MacGetDataEnd(), FALSE);
1438 extern char __data_start__[], __data_end__[];
1439 GC_add_roots_inner((ptr_t)&__data_start__,
1440 (ptr_t)&__data_end__, FALSE);
1441 # endif /* __POWERPC__ */
1442 # endif /* __MWERKS__ */
1443 # endif /* !THINK_C */
1447 /* Dynamic libraries are added at every collection, since they may */
1451 # endif /* ! AMIGA */
1452 # endif /* ! MSWIN32 && ! MSWINCE*/
1456 * Auxiliary routines for obtaining memory from OS.
1459 # if !defined(OS2) && !defined(PCR) && !defined(AMIGA) \
1460 && !defined(MSWIN32) && !defined(MSWINCE) \
1461 && !defined(MACOS) && !defined(DOS4GW)
1464 extern caddr_t sbrk();
1467 # define SBRK_ARG_T ptrdiff_t
1469 # define SBRK_ARG_T int
1474 /* The compiler seems to generate speculative reads one past the end of */
1475 /* an allocated object. Hence we need to make sure that the page */
1476 /* following the last heap page is also mapped. */
1477 ptr_t GC_unix_get_mem(bytes)
1480 caddr_t cur_brk = (caddr_t)sbrk(0);
1482 SBRK_ARG_T lsbs = (word)cur_brk & (GC_page_size-1);
1483 static caddr_t my_brk_val = 0;
1485 if ((SBRK_ARG_T)bytes < 0) return(0); /* too big */
1487 if((caddr_t)(sbrk(GC_page_size - lsbs)) == (caddr_t)(-1)) return(0);
1489 if (cur_brk == my_brk_val) {
1490 /* Use the extra block we allocated last time. */
1491 result = (ptr_t)sbrk((SBRK_ARG_T)bytes);
1492 if (result == (caddr_t)(-1)) return(0);
1493 result -= GC_page_size;
1495 result = (ptr_t)sbrk(GC_page_size + (SBRK_ARG_T)bytes);
1496 if (result == (caddr_t)(-1)) return(0);
1498 my_brk_val = result + bytes + GC_page_size; /* Always page aligned */
1499 return((ptr_t)result);
1502 #else /* Not RS6000 */
1504 #if defined(USE_MMAP)
1505 /* Tested only under Linux, IRIX5 and Solaris 2 */
1507 #ifdef USE_MMAP_FIXED
1508 # define GC_MMAP_FLAGS MAP_FIXED | MAP_PRIVATE
1509 /* Seems to yield better performance on Solaris 2, but can */
1510 /* be unreliable if something is already mapped at the address. */
1512 # define GC_MMAP_FLAGS MAP_PRIVATE
1516 # define HEAP_START 0
1519 ptr_t GC_unix_get_mem(bytes)
1523 static ptr_t last_addr = HEAP_START;
1525 # ifndef USE_MMAP_ANON
1526 static GC_bool initialized = FALSE;
1530 fd = open("/dev/zero", O_RDONLY);
1531 fcntl(fd, F_SETFD, FD_CLOEXEC);
1536 if (bytes & (GC_page_size -1)) ABORT("Bad GET_MEM arg");
1537 # ifdef USE_MMAP_ANON
1538 result = mmap(last_addr, bytes, PROT_READ | PROT_WRITE | OPT_PROT_EXEC,
1539 GC_MMAP_FLAGS | MAP_ANON, -1, 0/* offset */);
1541 result = mmap(last_addr, bytes, PROT_READ | PROT_WRITE | OPT_PROT_EXEC,
1542 GC_MMAP_FLAGS, fd, 0/* offset */);
1544 if (result == MAP_FAILED) return(0);
1545 last_addr = (ptr_t)result + bytes + GC_page_size - 1;
1546 last_addr = (ptr_t)((word)last_addr & ~(GC_page_size - 1));
1547 # if !defined(LINUX)
1548 if (last_addr == 0) {
1549 /* Oops. We got the end of the address space. This isn't */
1550 /* usable by arbitrary C code, since one-past-end pointers */
1551 /* don't work, so we discard it and try again. */
1552 munmap(result, (size_t)(-GC_page_size) - (size_t)result);
1553 /* Leave last page mapped, so we can't repeat. */
1554 return GC_unix_get_mem(bytes);
1557 GC_ASSERT(last_addr != 0);
1559 return((ptr_t)result);
1562 #else /* Not RS6000, not USE_MMAP */
1563 ptr_t GC_unix_get_mem(bytes)
1568 /* Bare sbrk isn't thread safe. Play by malloc rules. */
1569 /* The equivalent may be needed on other systems as well. */
1573 ptr_t cur_brk = (ptr_t)sbrk(0);
1574 SBRK_ARG_T lsbs = (word)cur_brk & (GC_page_size-1);
1576 if ((SBRK_ARG_T)bytes < 0) return(0); /* too big */
1578 if((ptr_t)sbrk(GC_page_size - lsbs) == (ptr_t)(-1)) return(0);
1580 result = (ptr_t)sbrk((SBRK_ARG_T)bytes);
1581 if (result == (ptr_t)(-1)) result = 0;
1589 #endif /* Not USE_MMAP */
1590 #endif /* Not RS6000 */
1596 void * os2_alloc(size_t bytes)
1600 if (DosAllocMem(&result, bytes, PAG_EXECUTE | PAG_READ |
1601 PAG_WRITE | PAG_COMMIT)
1605 if (result == 0) return(os2_alloc(bytes));
1612 # if defined(MSWIN32) || defined(MSWINCE)
1613 SYSTEM_INFO GC_sysinfo;
1618 # ifdef USE_GLOBAL_ALLOC
1619 # define GLOBAL_ALLOC_TEST 1
1621 # define GLOBAL_ALLOC_TEST GC_no_win32_dlls
1624 word GC_n_heap_bases = 0;
1626 ptr_t GC_win32_get_mem(bytes)
1631 if (GLOBAL_ALLOC_TEST) {
1632 /* VirtualAlloc doesn't like PAGE_EXECUTE_READWRITE. */
1633 /* There are also unconfirmed rumors of other */
1634 /* problems, so we dodge the issue. */
1635 result = (ptr_t) GlobalAlloc(0, bytes + HBLKSIZE);
1636 result = (ptr_t)(((word)result + HBLKSIZE) & ~(HBLKSIZE-1));
1638 /* VirtualProtect only works on regions returned by a */
1639 /* single VirtualAlloc call. Thus we allocate one */
1640 /* extra page, which will prevent merging of blocks */
1641 /* in separate regions, and eliminate any temptation */
1642 /* to call VirtualProtect on a range spanning regions. */
1643 /* This wastes a small amount of memory, and risks */
1644 /* increased fragmentation. But better alternatives */
1645 /* would require effort. */
1646 result = (ptr_t) VirtualAlloc(NULL, bytes + 1,
1647 MEM_COMMIT | MEM_RESERVE,
1648 PAGE_EXECUTE_READWRITE);
1650 if (HBLKDISPL(result) != 0) ABORT("Bad VirtualAlloc result");
1651 /* If I read the documentation correctly, this can */
1652 /* only happen if HBLKSIZE > 64k or not a power of 2. */
1653 if (GC_n_heap_bases >= MAX_HEAP_SECTS) ABORT("Too many heap sections");
1654 GC_heap_bases[GC_n_heap_bases++] = result;
1658 void GC_win32_free_heap ()
1660 if (GC_no_win32_dlls) {
1661 while (GC_n_heap_bases > 0) {
1662 GlobalFree (GC_heap_bases[--GC_n_heap_bases]);
1663 GC_heap_bases[GC_n_heap_bases] = 0;
1670 # define GC_AMIGA_AM
1671 # include "AmigaOS.c"
1677 word GC_n_heap_bases = 0;
1679 ptr_t GC_wince_get_mem(bytes)
1685 /* Round up allocation size to multiple of page size */
1686 bytes = (bytes + GC_page_size-1) & ~(GC_page_size-1);
1688 /* Try to find reserved, uncommitted pages */
1689 for (i = 0; i < GC_n_heap_bases; i++) {
1690 if (((word)(-(signed_word)GC_heap_lengths[i])
1691 & (GC_sysinfo.dwAllocationGranularity-1))
1693 result = GC_heap_bases[i] + GC_heap_lengths[i];
1698 if (i == GC_n_heap_bases) {
1699 /* Reserve more pages */
1700 word res_bytes = (bytes + GC_sysinfo.dwAllocationGranularity-1)
1701 & ~(GC_sysinfo.dwAllocationGranularity-1);
1702 /* If we ever support MPROTECT_VDB here, we will probably need to */
1703 /* ensure that res_bytes is strictly > bytes, so that VirtualProtect */
1704 /* never spans regions. It seems to be OK for a VirtualFree argument */
1705 /* to span regions, so we should be OK for now. */
1706 result = (ptr_t) VirtualAlloc(NULL, res_bytes,
1707 MEM_RESERVE | MEM_TOP_DOWN,
1708 PAGE_EXECUTE_READWRITE);
1709 if (HBLKDISPL(result) != 0) ABORT("Bad VirtualAlloc result");
1710 /* If I read the documentation correctly, this can */
1711 /* only happen if HBLKSIZE > 64k or not a power of 2. */
1712 if (GC_n_heap_bases >= MAX_HEAP_SECTS) ABORT("Too many heap sections");
1713 GC_heap_bases[GC_n_heap_bases] = result;
1714 GC_heap_lengths[GC_n_heap_bases] = 0;
1719 result = (ptr_t) VirtualAlloc(result, bytes,
1721 PAGE_EXECUTE_READWRITE);
1722 if (result != NULL) {
1723 if (HBLKDISPL(result) != 0) ABORT("Bad VirtualAlloc result");
1724 GC_heap_lengths[i] += bytes;
1733 /* For now, this only works on Win32/WinCE and some Unix-like */
1734 /* systems. If you have something else, don't define */
1736 /* We assume ANSI C to support this feature. */
1738 #if !defined(MSWIN32) && !defined(MSWINCE)
1741 #include <sys/mman.h>
1742 #include <sys/stat.h>
1743 #include <sys/types.h>
1747 /* Compute a page aligned starting address for the unmap */
1748 /* operation on a block of size bytes starting at start. */
1749 /* Return 0 if the block is too small to make this feasible. */
1750 ptr_t GC_unmap_start(ptr_t start, word bytes)
1752 ptr_t result = start;
1753 /* Round start to next page boundary. */
1754 result += GC_page_size - 1;
1755 result = (ptr_t)((word)result & ~(GC_page_size - 1));
1756 if (result + GC_page_size > start + bytes) return 0;
1760 /* Compute end address for an unmap operation on the indicated */
1762 ptr_t GC_unmap_end(ptr_t start, word bytes)
1764 ptr_t end_addr = start + bytes;
1765 end_addr = (ptr_t)((word)end_addr & ~(GC_page_size - 1));
1769 /* Under Win32/WinCE we commit (map) and decommit (unmap) */
1770 /* memory using VirtualAlloc and VirtualFree. These functions */
1771 /* work on individual allocations of virtual memory, made */
1772 /* previously using VirtualAlloc with the MEM_RESERVE flag. */
1773 /* The ranges we need to (de)commit may span several of these */
1774 /* allocations; therefore we use VirtualQuery to check */
1775 /* allocation lengths, and split up the range as necessary. */
1777 /* We assume that GC_remap is called on exactly the same range */
1778 /* as a previous call to GC_unmap. It is safe to consistently */
1779 /* round the endpoints in both places. */
1780 void GC_unmap(ptr_t start, word bytes)
1782 ptr_t start_addr = GC_unmap_start(start, bytes);
1783 ptr_t end_addr = GC_unmap_end(start, bytes);
1784 word len = end_addr - start_addr;
1785 if (0 == start_addr) return;
1786 # if defined(MSWIN32) || defined(MSWINCE)
1788 MEMORY_BASIC_INFORMATION mem_info;
1790 if (VirtualQuery(start_addr, &mem_info, sizeof(mem_info))
1791 != sizeof(mem_info))
1792 ABORT("Weird VirtualQuery result");
1793 free_len = (len < mem_info.RegionSize) ? len : mem_info.RegionSize;
1794 if (!VirtualFree(start_addr, free_len, MEM_DECOMMIT))
1795 ABORT("VirtualFree failed");
1796 GC_unmapped_bytes += free_len;
1797 start_addr += free_len;
1801 if (munmap(start_addr, len) != 0) ABORT("munmap failed");
1802 GC_unmapped_bytes += len;
1807 void GC_remap(ptr_t start, word bytes)
1809 static int zero_descr = -1;
1810 ptr_t start_addr = GC_unmap_start(start, bytes);
1811 ptr_t end_addr = GC_unmap_end(start, bytes);
1812 word len = end_addr - start_addr;
1815 # if defined(MSWIN32) || defined(MSWINCE)
1816 if (0 == start_addr) return;
1818 MEMORY_BASIC_INFORMATION mem_info;
1820 if (VirtualQuery(start_addr, &mem_info, sizeof(mem_info))
1821 != sizeof(mem_info))
1822 ABORT("Weird VirtualQuery result");
1823 alloc_len = (len < mem_info.RegionSize) ? len : mem_info.RegionSize;
1824 result = VirtualAlloc(start_addr, alloc_len,
1826 PAGE_EXECUTE_READWRITE);
1827 if (result != start_addr) {
1828 ABORT("VirtualAlloc remapping failed");
1830 GC_unmapped_bytes -= alloc_len;
1831 start_addr += alloc_len;
1835 if (-1 == zero_descr) zero_descr = open("/dev/zero", O_RDWR);
1836 fcntl(zero_descr, F_SETFD, FD_CLOEXEC);
1837 if (0 == start_addr) return;
1838 result = mmap(start_addr, len, PROT_READ | PROT_WRITE | OPT_PROT_EXEC,
1839 MAP_FIXED | MAP_PRIVATE, zero_descr, 0);
1840 if (result != start_addr) {
1841 ABORT("mmap remapping failed");
1843 GC_unmapped_bytes -= len;
1847 /* Two adjacent blocks have already been unmapped and are about to */
1848 /* be merged. Unmap the whole block. This typically requires */
1849 /* that we unmap a small section in the middle that was not previously */
1850 /* unmapped due to alignment constraints. */
1851 void GC_unmap_gap(ptr_t start1, word bytes1, ptr_t start2, word bytes2)
1853 ptr_t start1_addr = GC_unmap_start(start1, bytes1);
1854 ptr_t end1_addr = GC_unmap_end(start1, bytes1);
1855 ptr_t start2_addr = GC_unmap_start(start2, bytes2);
1856 ptr_t end2_addr = GC_unmap_end(start2, bytes2);
1857 ptr_t start_addr = end1_addr;
1858 ptr_t end_addr = start2_addr;
1860 GC_ASSERT(start1 + bytes1 == start2);
1861 if (0 == start1_addr) start_addr = GC_unmap_start(start1, bytes1 + bytes2);
1862 if (0 == start2_addr) end_addr = GC_unmap_end(start1, bytes1 + bytes2);
1863 if (0 == start_addr) return;
1864 len = end_addr - start_addr;
1865 # if defined(MSWIN32) || defined(MSWINCE)
1867 MEMORY_BASIC_INFORMATION mem_info;
1869 if (VirtualQuery(start_addr, &mem_info, sizeof(mem_info))
1870 != sizeof(mem_info))
1871 ABORT("Weird VirtualQuery result");
1872 free_len = (len < mem_info.RegionSize) ? len : mem_info.RegionSize;
1873 if (!VirtualFree(start_addr, free_len, MEM_DECOMMIT))
1874 ABORT("VirtualFree failed");
1875 GC_unmapped_bytes += free_len;
1876 start_addr += free_len;
1880 if (len != 0 && munmap(start_addr, len) != 0) ABORT("munmap failed");
1881 GC_unmapped_bytes += len;
1885 #endif /* USE_MUNMAP */
1887 /* Routine for pushing any additional roots. In THREADS */
1888 /* environment, this is also responsible for marking from */
1889 /* thread stacks. */
1891 void (*GC_push_other_roots)() = 0;
1895 PCR_ERes GC_push_thread_stack(PCR_Th_T *t, PCR_Any dummy)
1897 struct PCR_ThCtl_TInfoRep info;
1900 info.ti_stkLow = info.ti_stkHi = 0;
1901 result = PCR_ThCtl_GetInfo(t, &info);
1902 GC_push_all_stack((ptr_t)(info.ti_stkLow), (ptr_t)(info.ti_stkHi));
1906 /* Push the contents of an old object. We treat this as stack */
1907 /* data only becasue that makes it robust against mark stack */
1909 PCR_ERes GC_push_old_obj(void *p, size_t size, PCR_Any data)
1911 GC_push_all_stack((ptr_t)p, (ptr_t)p + size);
1912 return(PCR_ERes_okay);
1916 void GC_default_push_other_roots GC_PROTO((void))
1918 /* Traverse data allocated by previous memory managers. */
1920 extern struct PCR_MM_ProcsRep * GC_old_allocator;
1922 if ((*(GC_old_allocator->mmp_enumerate))(PCR_Bool_false,
1925 ABORT("Old object enumeration failed");
1928 /* Traverse all thread stacks. */
1930 PCR_ThCtl_ApplyToAllOtherThreads(GC_push_thread_stack,0))
1931 || PCR_ERes_IsErr(GC_push_thread_stack(PCR_Th_CurrThread(), 0))) {
1932 ABORT("Thread stack marking failed\n");
1940 # ifdef ALL_INTERIOR_POINTERS
1944 void GC_push_thread_structures GC_PROTO((void))
1946 /* Not our responsibibility. */
1949 extern void ThreadF__ProcessStacks();
1951 void GC_push_thread_stack(start, stop)
1954 GC_push_all_stack((ptr_t)start, (ptr_t)stop + sizeof(word));
1957 /* Push routine with M3 specific calling convention. */
1958 GC_m3_push_root(dummy1, p, dummy2, dummy3)
1960 ptr_t dummy1, dummy2;
1965 GC_PUSH_ONE_STACK(q, p);
1968 /* M3 set equivalent to RTHeap.TracedRefTypes */
1969 typedef struct { int elts[1]; } RefTypeSet;
1970 RefTypeSet GC_TracedRefTypes = {{0x1}};
1972 void GC_default_push_other_roots GC_PROTO((void))
1974 /* Use the M3 provided routine for finding static roots. */
1975 /* This is a bit dubious, since it presumes no C roots. */
1976 /* We handle the collector roots explicitly in GC_push_roots */
1977 RTMain__GlobalMapProc(GC_m3_push_root, 0, GC_TracedRefTypes);
1978 if (GC_words_allocd > 0) {
1979 ThreadF__ProcessStacks(GC_push_thread_stack);
1981 /* Otherwise this isn't absolutely necessary, and we have */
1982 /* startup ordering problems. */
1985 # endif /* SRC_M3 */
1987 # if defined(GC_SOLARIS_THREADS) || defined(GC_PTHREADS) || \
1988 defined(GC_WIN32_THREADS)
1990 extern void GC_push_all_stacks();
1992 void GC_default_push_other_roots GC_PROTO((void))
1994 GC_push_all_stacks();
1997 # endif /* GC_SOLARIS_THREADS || GC_PTHREADS */
1999 void (*GC_push_other_roots) GC_PROTO((void)) = GC_default_push_other_roots;
2001 #endif /* THREADS */
2004 * Routines for accessing dirty bits on virtual pages.
2005 * We plan to eventually implement four strategies for doing so:
2006 * DEFAULT_VDB: A simple dummy implementation that treats every page
2007 * as possibly dirty. This makes incremental collection
2008 * useless, but the implementation is still correct.
2009 * PCR_VDB: Use PPCRs virtual dirty bit facility.
2010 * PROC_VDB: Use the /proc facility for reading dirty bits. Only
2011 * works under some SVR4 variants. Even then, it may be
2012 * too slow to be entirely satisfactory. Requires reading
2013 * dirty bits for entire address space. Implementations tend
2014 * to assume that the client is a (slow) debugger.
2015 * MPROTECT_VDB:Protect pages and then catch the faults to keep track of
2016 * dirtied pages. The implementation (and implementability)
2017 * is highly system dependent. This usually fails when system
2018 * calls write to a protected page. We prevent the read system
2019 * call from doing so. It is the clients responsibility to
2020 * make sure that other system calls are similarly protected
2021 * or write only to the stack.
2023 GC_bool GC_dirty_maintained = FALSE;
2027 /* All of the following assume the allocation lock is held, and */
2028 /* signals are disabled. */
2030 /* The client asserts that unallocated pages in the heap are never */
2033 /* Initialize virtual dirty bit implementation. */
2034 void GC_dirty_init()
2037 GC_printf0("Initializing DEFAULT_VDB...\n");
2039 GC_dirty_maintained = TRUE;
2042 /* Retrieve system dirty bits for heap to a local buffer. */
2043 /* Restore the systems notion of which pages are dirty. */
2044 void GC_read_dirty()
2047 /* Is the HBLKSIZE sized page at h marked dirty in the local buffer? */
2048 /* If the actual page size is different, this returns TRUE if any */
2049 /* of the pages overlapping h are dirty. This routine may err on the */
2050 /* side of labelling pages as dirty (and this implementation does). */
2052 GC_bool GC_page_was_dirty(h)
2059 * The following two routines are typically less crucial. They matter
2060 * most with large dynamic libraries, or if we can't accurately identify
2061 * stacks, e.g. under Solaris 2.X. Otherwise the following default
2062 * versions are adequate.
2065 /* Could any valid GC heap pointer ever have been written to this page? */
2067 GC_bool GC_page_was_ever_dirty(h)
2073 /* Reset the n pages starting at h to "was never dirty" status. */
2074 void GC_is_fresh(h, n)
2081 /* I) hints that [h, h+nblocks) is about to be written. */
2082 /* II) guarantees that protection is removed. */
2083 /* (I) may speed up some dirty bit implementations. */
2084 /* (II) may be essential if we need to ensure that */
2085 /* pointer-free system call buffers in the heap are */
2086 /* not protected. */
2088 void GC_remove_protection(h, nblocks, is_ptrfree)
2095 # endif /* DEFAULT_VDB */
2098 # ifdef MPROTECT_VDB
2101 * See DEFAULT_VDB for interface descriptions.
2105 * This implementation maintains dirty bits itself by catching write
2106 * faults and keeping track of them. We assume nobody else catches
2107 * SIGBUS or SIGSEGV. We assume no write faults occur in system calls.
2108 * This means that clients must ensure that system calls don't write
2109 * to the write-protected heap. Probably the best way to do this is to
2110 * ensure that system calls write at most to POINTERFREE objects in the
2111 * heap, and do even that only if we are on a platform on which those
2112 * are not protected. Another alternative is to wrap system calls
2113 * (see example for read below), but the current implementation holds
2114 * a lock across blocking calls, making it problematic for multithreaded
2116 * We assume the page size is a multiple of HBLKSIZE.
2117 * We prefer them to be the same. We avoid protecting POINTERFREE
2118 * objects only if they are the same.
2121 # if !defined(MSWIN32) && !defined(MSWINCE) && !defined(DARWIN)
2123 # include <sys/mman.h>
2124 # include <signal.h>
2125 # include <sys/syscall.h>
2127 # define PROTECT(addr, len) \
2128 if (mprotect((caddr_t)(addr), (size_t)(len), \
2129 PROT_READ | OPT_PROT_EXEC) < 0) { \
2130 ABORT("mprotect failed"); \
2132 # define UNPROTECT(addr, len) \
2133 if (mprotect((caddr_t)(addr), (size_t)(len), \
2134 PROT_WRITE | PROT_READ | OPT_PROT_EXEC ) < 0) { \
2135 ABORT("un-mprotect failed"); \
2141 /* Using vm_protect (mach syscall) over mprotect (BSD syscall) seems to
2142 decrease the likelihood of some of the problems described below. */
2143 #include <mach/vm_map.h>
2144 extern mach_port_t GC_task_self;
2145 #define PROTECT(addr,len) \
2146 if(vm_protect(GC_task_self,(vm_address_t)(addr),(vm_size_t)(len), \
2147 FALSE,VM_PROT_READ) != KERN_SUCCESS) { \
2148 ABORT("vm_portect failed"); \
2150 #define UNPROTECT(addr,len) \
2151 if(vm_protect(GC_task_self,(vm_address_t)(addr),(vm_size_t)(len), \
2152 FALSE,VM_PROT_READ|VM_PROT_WRITE) != KERN_SUCCESS) { \
2153 ABORT("vm_portect failed"); \
2158 # include <signal.h>
2161 static DWORD protect_junk;
2162 # define PROTECT(addr, len) \
2163 if (!VirtualProtect((addr), (len), PAGE_EXECUTE_READ, \
2165 DWORD last_error = GetLastError(); \
2166 GC_printf1("Last error code: %lx\n", last_error); \
2167 ABORT("VirtualProtect failed"); \
2169 # define UNPROTECT(addr, len) \
2170 if (!VirtualProtect((addr), (len), PAGE_EXECUTE_READWRITE, \
2172 ABORT("un-VirtualProtect failed"); \
2174 # endif /* !DARWIN */
2175 # endif /* MSWIN32 || MSWINCE || DARWIN */
2177 #if defined(SUNOS4) || defined(FREEBSD)
2178 typedef void (* SIG_PF)();
2179 #endif /* SUNOS4 || FREEBSD */
2181 #if defined(SUNOS5SIGS) || defined(OSF1) || defined(LINUX) \
2184 typedef void (* SIG_PF)(int);
2186 typedef void (* SIG_PF)();
2188 #endif /* SUNOS5SIGS || OSF1 || LINUX || HURD */
2190 #if defined(MSWIN32)
2191 typedef LPTOP_LEVEL_EXCEPTION_FILTER SIG_PF;
2193 # define SIG_DFL (LPTOP_LEVEL_EXCEPTION_FILTER) (-1)
2195 #if defined(MSWINCE)
2196 typedef LONG (WINAPI *SIG_PF)(struct _EXCEPTION_POINTERS *);
2198 # define SIG_DFL (SIG_PF) (-1)
2201 #if defined(IRIX5) || defined(OSF1) || defined(HURD)
2202 typedef void (* REAL_SIG_PF)(int, int, struct sigcontext *);
2203 #endif /* IRIX5 || OSF1 || HURD */
2205 #if defined(SUNOS5SIGS)
2207 # define SIGINFO __siginfo
2209 # define SIGINFO siginfo
2212 typedef void (* REAL_SIG_PF)(int, struct SIGINFO *, void *);
2214 typedef void (* REAL_SIG_PF)();
2216 #endif /* SUNOS5SIGS */
2219 # if __GLIBC__ > 2 || __GLIBC__ == 2 && __GLIBC_MINOR__ >= 2
2220 typedef struct sigcontext s_c;
2221 # else /* glibc < 2.2 */
2222 # include <linux/version.h>
2223 # if (LINUX_VERSION_CODE >= 0x20100) && !defined(M68K) || defined(ALPHA) || defined(ARM32)
2224 typedef struct sigcontext s_c;
2226 typedef struct sigcontext_struct s_c;
2228 # endif /* glibc < 2.2 */
2229 # if defined(ALPHA) || defined(M68K)
2230 typedef void (* REAL_SIG_PF)(int, int, s_c *);
2232 # if defined(IA64) || defined(HP_PA)
2233 typedef void (* REAL_SIG_PF)(int, siginfo_t *, s_c *);
2235 typedef void (* REAL_SIG_PF)(int, s_c);
2239 /* Retrieve fault address from sigcontext structure by decoding */
2241 char * get_fault_addr(s_c *sc) {
2245 instr = *((unsigned *)(sc->sc_pc));
2246 faultaddr = sc->sc_regs[(instr >> 16) & 0x1f];
2247 faultaddr += (word) (((int)instr << 16) >> 16);
2248 return (char *)faultaddr;
2250 # endif /* !ALPHA */
2254 SIG_PF GC_old_bus_handler;
2255 SIG_PF GC_old_segv_handler; /* Also old MSWIN32 ACCESS_VIOLATION filter */
2256 #endif /* !DARWIN */
2258 #if defined(THREADS)
2259 /* We need to lock around the bitmap update in the write fault handler */
2260 /* in order to avoid the risk of losing a bit. We do this with a */
2261 /* test-and-set spin lock if we know how to do that. Otherwise we */
2262 /* check whether we are already in the handler and use the dumb but */
2263 /* safe fallback algorithm of setting all bits in the word. */
2264 /* Contention should be very rare, so we do the minimum to handle it */
2266 #ifdef GC_TEST_AND_SET_DEFINED
2267 static VOLATILE unsigned int fault_handler_lock = 0;
2268 void async_set_pht_entry_from_index(VOLATILE page_hash_table db, int index) {
2269 while (GC_test_and_set(&fault_handler_lock)) {}
2270 /* Could also revert to set_pht_entry_from_index_safe if initial */
2271 /* GC_test_and_set fails. */
2272 set_pht_entry_from_index(db, index);
2273 GC_clear(&fault_handler_lock);
2275 #else /* !GC_TEST_AND_SET_DEFINED */
2276 /* THIS IS INCORRECT! The dirty bit vector may be temporarily wrong, */
2277 /* just before we notice the conflict and correct it. We may end up */
2278 /* looking at it while it's wrong. But this requires contention */
2279 /* exactly when a GC is triggered, which seems far less likely to */
2280 /* fail than the old code, which had no reported failures. Thus we */
2281 /* leave it this way while we think of something better, or support */
2282 /* GC_test_and_set on the remaining platforms. */
2283 static VOLATILE word currently_updating = 0;
2284 void async_set_pht_entry_from_index(VOLATILE page_hash_table db, int index) {
2285 unsigned int update_dummy;
2286 currently_updating = (word)(&update_dummy);
2287 set_pht_entry_from_index(db, index);
2288 /* If we get contention in the 10 or so instruction window here, */
2289 /* and we get stopped by a GC between the two updates, we lose! */
2290 if (currently_updating != (word)(&update_dummy)) {
2291 set_pht_entry_from_index_safe(db, index);
2292 /* We claim that if two threads concurrently try to update the */
2293 /* dirty bit vector, the first one to execute UPDATE_START */
2294 /* will see it changed when UPDATE_END is executed. (Note that */
2295 /* &update_dummy must differ in two distinct threads.) It */
2296 /* will then execute set_pht_entry_from_index_safe, thus */
2297 /* returning us to a safe state, though not soon enough. */
2300 #endif /* !GC_TEST_AND_SET_DEFINED */
2301 #else /* !THREADS */
2302 # define async_set_pht_entry_from_index(db, index) \
2303 set_pht_entry_from_index(db, index)
2304 #endif /* !THREADS */
2307 #if !defined(DARWIN)
2308 # if defined (SUNOS4) || defined(FREEBSD)
2309 void GC_write_fault_handler(sig, code, scp, addr)
2311 struct sigcontext *scp;
2314 # define SIG_OK (sig == SIGSEGV || sig == SIGBUS)
2315 # define CODE_OK (FC_CODE(code) == FC_PROT \
2316 || (FC_CODE(code) == FC_OBJERR \
2317 && FC_ERRNO(code) == FC_PROT))
2320 # define SIG_OK (sig == SIGBUS)
2321 # define CODE_OK (code == BUS_PAGE_FAULT)
2323 # endif /* SUNOS4 || FREEBSD */
2325 # if defined(IRIX5) || defined(OSF1) || defined(HURD)
2327 void GC_write_fault_handler(int sig, int code, struct sigcontext *scp)
2329 # define SIG_OK (sig == SIGSEGV)
2330 # define CODE_OK (code == 2 /* experimentally determined */)
2333 # define SIG_OK (sig == SIGSEGV)
2334 # define CODE_OK (code == EACCES)
2337 # define SIG_OK (sig == SIGBUS || sig == SIGSEGV)
2338 # define CODE_OK TRUE
2340 # endif /* IRIX5 || OSF1 || HURD */
2343 # if defined(ALPHA) || defined(M68K)
2344 void GC_write_fault_handler(int sig, int code, s_c * sc)
2346 # if defined(IA64) || defined(HP_PA)
2347 void GC_write_fault_handler(int sig, siginfo_t * si, s_c * scp)
2350 void GC_write_fault_handler(int sig, int a2, int a3, int a4, s_c sc)
2352 void GC_write_fault_handler(int sig, s_c sc)
2356 # define SIG_OK (sig == SIGSEGV)
2357 # define CODE_OK TRUE
2358 /* Empirically c.trapno == 14, on IA32, but is that useful? */
2359 /* Should probably consider alignment issues on other */
2360 /* architectures. */
2363 # if defined(SUNOS5SIGS)
2365 void GC_write_fault_handler(int sig, struct SIGINFO *scp, void * context)
2367 void GC_write_fault_handler(sig, scp, context)
2369 struct SIGINFO *scp;
2373 # define SIG_OK (sig == SIGSEGV || sig == SIGBUS)
2374 # define CODE_OK (scp -> si_code == SEGV_ACCERR) \
2375 || (scp -> si_code == BUS_ADRERR) \
2376 || (scp -> si_code == BUS_UNKNOWN) \
2377 || (scp -> si_code == SEGV_UNKNOWN) \
2378 || (scp -> si_code == BUS_OBJERR)
2380 # define SIG_OK (sig == SIGSEGV)
2381 # define CODE_OK (scp -> si_code == SEGV_ACCERR)
2383 # endif /* SUNOS5SIGS */
2385 # if defined(MSWIN32) || defined(MSWINCE)
2386 LONG WINAPI GC_write_fault_handler(struct _EXCEPTION_POINTERS *exc_info)
2387 # define SIG_OK (exc_info -> ExceptionRecord -> ExceptionCode == \
2388 STATUS_ACCESS_VIOLATION)
2389 # define CODE_OK (exc_info -> ExceptionRecord -> ExceptionInformation[0] == 1)
2391 # endif /* MSWIN32 || MSWINCE */
2393 register unsigned i;
2395 char *addr = (char *) code;
2398 char * addr = (char *) (size_t) (scp -> sc_badvaddr);
2400 # if defined(OSF1) && defined(ALPHA)
2401 char * addr = (char *) (scp -> sc_traparg_a0);
2404 char * addr = (char *) (scp -> si_addr);
2407 # if defined(I386) || defined (X86_64)
2408 char * addr = (char *) (sc.cr2);
2413 struct sigcontext *scp = (struct sigcontext *)(sc);
2415 int format = (scp->sc_formatvec >> 12) & 0xf;
2416 unsigned long *framedata = (unsigned long *)(scp + 1);
2419 if (format == 0xa || format == 0xb) {
2422 } else if (format == 7) {
2425 if (framedata[1] & 0x08000000) {
2426 /* correct addr on misaligned access */
2427 ea = (ea+4095)&(~4095);
2429 } else if (format == 4) {
2432 if (framedata[1] & 0x08000000) {
2433 /* correct addr on misaligned access */
2434 ea = (ea+4095)&(~4095);
2440 char * addr = get_fault_addr(sc);
2442 # if defined(IA64) || defined(HP_PA)
2443 char * addr = si -> si_addr;
2444 /* I believe this is claimed to work on all platforms for */
2445 /* Linux 2.3.47 and later. Hopefully we don't have to */
2446 /* worry about earlier kernels on IA64. */
2448 # if defined(POWERPC)
2449 char * addr = (char *) (sc.regs->dar);
2452 char * addr = (char *)sc.fault_address;
2454 --> architecture not supported
2462 # if defined(MSWIN32) || defined(MSWINCE)
2463 char * addr = (char *) (exc_info -> ExceptionRecord
2464 -> ExceptionInformation[1]);
2465 # define sig SIGSEGV
2468 if (SIG_OK && CODE_OK) {
2469 register struct hblk * h =
2470 (struct hblk *)((word)addr & ~(GC_page_size-1));
2471 GC_bool in_allocd_block;
2474 /* Address is only within the correct physical page. */
2475 in_allocd_block = FALSE;
2476 for (i = 0; i < divHBLKSZ(GC_page_size); i++) {
2477 if (HDR(h+i) != 0) {
2478 in_allocd_block = TRUE;
2482 in_allocd_block = (HDR(addr) != 0);
2484 if (!in_allocd_block) {
2485 /* Heap blocks now begin and end on page boundaries */
2488 if (sig == SIGSEGV) {
2489 old_handler = GC_old_segv_handler;
2491 old_handler = GC_old_bus_handler;
2493 if (old_handler == SIG_DFL) {
2494 # if !defined(MSWIN32) && !defined(MSWINCE)
2495 GC_err_printf1("Segfault at 0x%lx\n", addr);
2496 ABORT("Unexpected bus error or segmentation fault");
2498 return(EXCEPTION_CONTINUE_SEARCH);
2501 # if defined (SUNOS4) || defined(FREEBSD)
2502 (*old_handler) (sig, code, scp, addr);
2505 # if defined (SUNOS5SIGS)
2506 (*(REAL_SIG_PF)old_handler) (sig, scp, context);
2509 # if defined (LINUX)
2510 # if defined(ALPHA) || defined(M68K)
2511 (*(REAL_SIG_PF)old_handler) (sig, code, sc);
2513 # if defined(IA64) || defined(HP_PA)
2514 (*(REAL_SIG_PF)old_handler) (sig, si, scp);
2516 (*(REAL_SIG_PF)old_handler) (sig, sc);
2521 # if defined (IRIX5) || defined(OSF1) || defined(HURD)
2522 (*(REAL_SIG_PF)old_handler) (sig, code, scp);
2526 return((*old_handler)(exc_info));
2530 UNPROTECT(h, GC_page_size);
2531 /* We need to make sure that no collection occurs between */
2532 /* the UNPROTECT and the setting of the dirty bit. Otherwise */
2533 /* a write by a third thread might go unnoticed. Reversing */
2534 /* the order is just as bad, since we would end up unprotecting */
2535 /* a page in a GC cycle during which it's not marked. */
2536 /* Currently we do this by disabling the thread stopping */
2537 /* signals while this handler is running. An alternative might */
2538 /* be to record the fact that we're about to unprotect, or */
2539 /* have just unprotected a page in the GC's thread structure, */
2540 /* and then to have the thread stopping code set the dirty */
2541 /* flag, if necessary. */
2542 for (i = 0; i < divHBLKSZ(GC_page_size); i++) {
2543 register int index = PHT_HASH(h+i);
2545 async_set_pht_entry_from_index(GC_dirty_pages, index);
2548 /* These reset the signal handler each time by default. */
2549 signal(SIGSEGV, (SIG_PF) GC_write_fault_handler);
2551 /* The write may not take place before dirty bits are read. */
2552 /* But then we'll fault again ... */
2553 # if defined(MSWIN32) || defined(MSWINCE)
2554 return(EXCEPTION_CONTINUE_EXECUTION);
2559 #if defined(MSWIN32) || defined(MSWINCE)
2560 return EXCEPTION_CONTINUE_SEARCH;
2562 GC_err_printf1("Segfault at 0x%lx\n", addr);
2563 ABORT("Unexpected bus error or segmentation fault");
2566 #endif /* !DARWIN */
2569 * We hold the allocation lock. We expect block h to be written
2570 * shortly. Ensure that all pages containing any part of the n hblks
2571 * starting at h are no longer protected. If is_ptrfree is false,
2572 * also ensure that they will subsequently appear to be dirty.
2574 void GC_remove_protection(h, nblocks, is_ptrfree)
2579 struct hblk * h_trunc; /* Truncated to page boundary */
2580 struct hblk * h_end; /* Page boundary following block end */
2581 struct hblk * current;
2582 GC_bool found_clean;
2584 if (!GC_dirty_maintained) return;
2585 h_trunc = (struct hblk *)((word)h & ~(GC_page_size-1));
2586 h_end = (struct hblk *)(((word)(h + nblocks) + GC_page_size-1)
2587 & ~(GC_page_size-1));
2588 found_clean = FALSE;
2589 for (current = h_trunc; current < h_end; ++current) {
2590 int index = PHT_HASH(current);
2592 if (!is_ptrfree || current < h || current >= h + nblocks) {
2593 async_set_pht_entry_from_index(GC_dirty_pages, index);
2596 UNPROTECT(h_trunc, (ptr_t)h_end - (ptr_t)h_trunc);
2599 #if !defined(DARWIN)
2600 void GC_dirty_init()
2602 # if defined(SUNOS5SIGS) || defined(IRIX5) || defined(LINUX) || \
2603 defined(OSF1) || defined(HURD)
2604 struct sigaction act, oldact;
2605 /* We should probably specify SA_SIGINFO for Linux, and handle */
2606 /* the different architectures more uniformly. */
2607 # if defined(IRIX5) || defined(LINUX) || defined(OSF1) || defined(HURD)
2608 act.sa_flags = SA_RESTART;
2609 act.sa_handler = (SIG_PF)GC_write_fault_handler;
2611 act.sa_flags = SA_RESTART | SA_SIGINFO;
2612 act.sa_sigaction = GC_write_fault_handler;
2614 (void)sigemptyset(&act.sa_mask);
2616 /* Arrange to postpone SIG_SUSPEND while we're in a write fault */
2617 /* handler. This effectively makes the handler atomic w.r.t. */
2618 /* stopping the world for GC. */
2619 (void)sigaddset(&act.sa_mask, SIG_SUSPEND);
2620 # endif /* SIG_SUSPEND */
2623 GC_printf0("Inititalizing mprotect virtual dirty bit implementation\n");
2625 GC_dirty_maintained = TRUE;
2626 if (GC_page_size % HBLKSIZE != 0) {
2627 GC_err_printf0("Page size not multiple of HBLKSIZE\n");
2628 ABORT("Page size not multiple of HBLKSIZE");
2630 # if defined(SUNOS4) || defined(FREEBSD)
2631 GC_old_bus_handler = signal(SIGBUS, GC_write_fault_handler);
2632 if (GC_old_bus_handler == SIG_IGN) {
2633 GC_err_printf0("Previously ignored bus error!?");
2634 GC_old_bus_handler = SIG_DFL;
2636 if (GC_old_bus_handler != SIG_DFL) {
2638 GC_err_printf0("Replaced other SIGBUS handler\n");
2642 # if defined(SUNOS4)
2643 GC_old_segv_handler = signal(SIGSEGV, (SIG_PF)GC_write_fault_handler);
2644 if (GC_old_segv_handler == SIG_IGN) {
2645 GC_err_printf0("Previously ignored segmentation violation!?");
2646 GC_old_segv_handler = SIG_DFL;
2648 if (GC_old_segv_handler != SIG_DFL) {
2650 GC_err_printf0("Replaced other SIGSEGV handler\n");
2654 # if defined(SUNOS5SIGS) || defined(IRIX5) || defined(LINUX) \
2655 || defined(OSF1) || defined(HURD)
2656 /* SUNOS5SIGS includes HPUX */
2657 # if defined(GC_IRIX_THREADS)
2658 sigaction(SIGSEGV, 0, &oldact);
2659 sigaction(SIGSEGV, &act, 0);
2662 int res = sigaction(SIGSEGV, &act, &oldact);
2663 if (res != 0) ABORT("Sigaction failed");
2666 # if defined(_sigargs) || defined(HURD) || !defined(SA_SIGINFO)
2667 /* This is Irix 5.x, not 6.x. Irix 5.x does not have */
2669 GC_old_segv_handler = oldact.sa_handler;
2670 # else /* Irix 6.x or SUNOS5SIGS or LINUX */
2671 if (oldact.sa_flags & SA_SIGINFO) {
2672 GC_old_segv_handler = (SIG_PF)(oldact.sa_sigaction);
2674 GC_old_segv_handler = oldact.sa_handler;
2677 if (GC_old_segv_handler == SIG_IGN) {
2678 GC_err_printf0("Previously ignored segmentation violation!?");
2679 GC_old_segv_handler = SIG_DFL;
2681 if (GC_old_segv_handler != SIG_DFL) {
2683 GC_err_printf0("Replaced other SIGSEGV handler\n");
2687 # if defined(HPUX) || defined(LINUX) || defined(HURD)
2688 sigaction(SIGBUS, &act, &oldact);
2689 GC_old_bus_handler = oldact.sa_handler;
2690 if (GC_old_bus_handler == SIG_IGN) {
2691 GC_err_printf0("Previously ignored bus error!?");
2692 GC_old_bus_handler = SIG_DFL;
2694 if (GC_old_bus_handler != SIG_DFL) {
2696 GC_err_printf0("Replaced other SIGBUS handler\n");
2699 # endif /* HPUX || LINUX || HURD */
2700 # if defined(MSWIN32)
2701 GC_old_segv_handler = SetUnhandledExceptionFilter(GC_write_fault_handler);
2702 if (GC_old_segv_handler != NULL) {
2704 GC_err_printf0("Replaced other UnhandledExceptionFilter\n");
2707 GC_old_segv_handler = SIG_DFL;
2711 #endif /* !DARWIN */
2713 int GC_incremental_protection_needs()
2715 if (GC_page_size == HBLKSIZE) {
2716 return GC_PROTECTS_POINTER_HEAP;
2718 return GC_PROTECTS_POINTER_HEAP | GC_PROTECTS_PTRFREE_HEAP;
2722 #define HAVE_INCREMENTAL_PROTECTION_NEEDS
2724 #define IS_PTRFREE(hhdr) ((hhdr)->hb_descr == 0)
2726 #define PAGE_ALIGNED(x) !((word)(x) & (GC_page_size - 1))
2727 void GC_protect_heap()
2731 struct hblk * current;
2732 struct hblk * current_start; /* Start of block to be protected. */
2733 struct hblk * limit;
2735 GC_bool protect_all =
2736 (0 != (GC_incremental_protection_needs() & GC_PROTECTS_PTRFREE_HEAP));
2737 for (i = 0; i < GC_n_heap_sects; i++) {
2738 start = GC_heap_sects[i].hs_start;
2739 len = GC_heap_sects[i].hs_bytes;
2741 PROTECT(start, len);
2743 GC_ASSERT(PAGE_ALIGNED(len))
2744 GC_ASSERT(PAGE_ALIGNED(start))
2745 current_start = current = (struct hblk *)start;
2746 limit = (struct hblk *)(start + len);
2747 while (current < limit) {
2752 GC_ASSERT(PAGE_ALIGNED(current));
2753 GET_HDR(current, hhdr);
2754 if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {
2755 /* This can happen only if we're at the beginning of a */
2756 /* heap segment, and a block spans heap segments. */
2757 /* We will handle that block as part of the preceding */
2759 GC_ASSERT(current_start == current);
2760 current_start = ++current;
2763 if (HBLK_IS_FREE(hhdr)) {
2764 GC_ASSERT(PAGE_ALIGNED(hhdr -> hb_sz));
2765 nhblks = divHBLKSZ(hhdr -> hb_sz);
2766 is_ptrfree = TRUE; /* dirty on alloc */
2768 nhblks = OBJ_SZ_TO_BLOCKS(hhdr -> hb_sz);
2769 is_ptrfree = IS_PTRFREE(hhdr);
2772 if (current_start < current) {
2773 PROTECT(current_start, (ptr_t)current - (ptr_t)current_start);
2775 current_start = (current += nhblks);
2780 if (current_start < current) {
2781 PROTECT(current_start, (ptr_t)current - (ptr_t)current_start);
2787 /* We assume that either the world is stopped or its OK to lose dirty */
2788 /* bits while this is happenning (as in GC_enable_incremental). */
2789 void GC_read_dirty()
2791 BCOPY((word *)GC_dirty_pages, GC_grungy_pages,
2792 (sizeof GC_dirty_pages));
2793 BZERO((word *)GC_dirty_pages, (sizeof GC_dirty_pages));
2797 GC_bool GC_page_was_dirty(h)
2800 register word index = PHT_HASH(h);
2802 return(HDR(h) == 0 || get_pht_entry_from_index(GC_grungy_pages, index));
2806 * Acquiring the allocation lock here is dangerous, since this
2807 * can be called from within GC_call_with_alloc_lock, and the cord
2808 * package does so. On systems that allow nested lock acquisition, this
2810 * On other systems, SET_LOCK_HOLDER and friends must be suitably defined.
2813 static GC_bool syscall_acquired_lock = FALSE; /* Protected by GC lock. */
2815 void GC_begin_syscall()
2817 if (!I_HOLD_LOCK()) {
2819 syscall_acquired_lock = TRUE;
2823 void GC_end_syscall()
2825 if (syscall_acquired_lock) {
2826 syscall_acquired_lock = FALSE;
2831 void GC_unprotect_range(addr, len)
2835 struct hblk * start_block;
2836 struct hblk * end_block;
2837 register struct hblk *h;
2840 if (!GC_dirty_maintained) return;
2841 obj_start = GC_base(addr);
2842 if (obj_start == 0) return;
2843 if (GC_base(addr + len - 1) != obj_start) {
2844 ABORT("GC_unprotect_range(range bigger than object)");
2846 start_block = (struct hblk *)((word)addr & ~(GC_page_size - 1));
2847 end_block = (struct hblk *)((word)(addr + len - 1) & ~(GC_page_size - 1));
2848 end_block += GC_page_size/HBLKSIZE - 1;
2849 for (h = start_block; h <= end_block; h++) {
2850 register word index = PHT_HASH(h);
2852 async_set_pht_entry_from_index(GC_dirty_pages, index);
2854 UNPROTECT(start_block,
2855 ((ptr_t)end_block - (ptr_t)start_block) + HBLKSIZE);
2860 /* We no longer wrap read by default, since that was causing too many */
2861 /* problems. It is preferred that the client instead avoids writing */
2862 /* to the write-protected heap with a system call. */
2863 /* This still serves as sample code if you do want to wrap system calls.*/
2865 #if !defined(MSWIN32) && !defined(MSWINCE) && !defined(GC_USE_LD_WRAP)
2866 /* Replacement for UNIX system call. */
2867 /* Other calls that write to the heap should be handled similarly. */
2868 /* Note that this doesn't work well for blocking reads: It will hold */
2869 /* the allocation lock for the entire duration of the call. Multithreaded */
2870 /* clients should really ensure that it won't block, either by setting */
2871 /* the descriptor nonblocking, or by calling select or poll first, to */
2872 /* make sure that input is available. */
2873 /* Another, preferred alternative is to ensure that system calls never */
2874 /* write to the protected heap (see above). */
2875 # if defined(__STDC__) && !defined(SUNOS4)
2876 # include <unistd.h>
2877 # include <sys/uio.h>
2878 ssize_t read(int fd, void *buf, size_t nbyte)
2881 int read(fd, buf, nbyte)
2883 int GC_read(fd, buf, nbyte)
2893 GC_unprotect_range(buf, (word)nbyte);
2894 # if defined(IRIX5) || defined(GC_LINUX_THREADS)
2895 /* Indirect system call may not always be easily available. */
2896 /* We could call _read, but that would interfere with the */
2897 /* libpthread interception of read. */
2898 /* On Linux, we have to be careful with the linuxthreads */
2899 /* read interception. */
2904 iov.iov_len = nbyte;
2905 result = readv(fd, &iov, 1);
2909 result = __read(fd, buf, nbyte);
2911 /* The two zero args at the end of this list are because one
2912 IA-64 syscall() implementation actually requires six args
2913 to be passed, even though they aren't always used. */
2914 result = syscall(SYS_read, fd, buf, nbyte, 0, 0);
2920 #endif /* !MSWIN32 && !MSWINCE && !GC_LINUX_THREADS */
2922 #if defined(GC_USE_LD_WRAP) && !defined(THREADS)
2923 /* We use the GNU ld call wrapping facility. */
2924 /* This requires that the linker be invoked with "--wrap read". */
2925 /* This can be done by passing -Wl,"--wrap read" to gcc. */
2926 /* I'm not sure that this actually wraps whatever version of read */
2927 /* is called by stdio. That code also mentions __read. */
2928 # include <unistd.h>
2929 ssize_t __wrap_read(int fd, void *buf, size_t nbyte)
2934 GC_unprotect_range(buf, (word)nbyte);
2935 result = __real_read(fd, buf, nbyte);
2940 /* We should probably also do this for __read, or whatever stdio */
2941 /* actually calls. */
2947 GC_bool GC_page_was_ever_dirty(h)
2953 /* Reset the n pages starting at h to "was never dirty" status. */
2955 void GC_is_fresh(h, n)
2961 # endif /* MPROTECT_VDB */
2966 * See DEFAULT_VDB for interface descriptions.
2970 * This implementaion assumes a Solaris 2.X like /proc pseudo-file-system
2971 * from which we can read page modified bits. This facility is far from
2972 * optimal (e.g. we would like to get the info for only some of the
2973 * address space), but it avoids intercepting system calls.
2977 #include <sys/types.h>
2978 #include <sys/signal.h>
2979 #include <sys/fault.h>
2980 #include <sys/syscall.h>
2981 #include <sys/procfs.h>
2982 #include <sys/stat.h>
2984 #define INITIAL_BUF_SZ 4096
2985 word GC_proc_buf_size = INITIAL_BUF_SZ;
2988 #ifdef GC_SOLARIS_THREADS
2989 /* We don't have exact sp values for threads. So we count on */
2990 /* occasionally declaring stack pages to be fresh. Thus we */
2991 /* need a real implementation of GC_is_fresh. We can't clear */
2992 /* entries in GC_written_pages, since that would declare all */
2993 /* pages with the given hash address to be fresh. */
2994 # define MAX_FRESH_PAGES 8*1024 /* Must be power of 2 */
2995 struct hblk ** GC_fresh_pages; /* A direct mapped cache. */
2996 /* Collisions are dropped. */
2998 # define FRESH_PAGE_SLOT(h) (divHBLKSZ((word)(h)) & (MAX_FRESH_PAGES-1))
2999 # define ADD_FRESH_PAGE(h) \
3000 GC_fresh_pages[FRESH_PAGE_SLOT(h)] = (h)
3001 # define PAGE_IS_FRESH(h) \
3002 (GC_fresh_pages[FRESH_PAGE_SLOT(h)] == (h) && (h) != 0)
3005 /* Add all pages in pht2 to pht1 */
3006 void GC_or_pages(pht1, pht2)
3007 page_hash_table pht1, pht2;
3011 for (i = 0; i < PHT_SIZE; i++) pht1[i] |= pht2[i];
3016 void GC_dirty_init()
3021 GC_dirty_maintained = TRUE;
3022 if (GC_words_allocd != 0 || GC_words_allocd_before_gc != 0) {
3025 for (i = 0; i < PHT_SIZE; i++) GC_written_pages[i] = (word)(-1);
3027 GC_printf1("Allocated words:%lu:all pages may have been written\n",
3029 (GC_words_allocd + GC_words_allocd_before_gc));
3032 sprintf(buf, "/proc/%d", getpid());
3033 fd = open(buf, O_RDONLY);
3035 ABORT("/proc open failed");
3037 GC_proc_fd = syscall(SYS_ioctl, fd, PIOCOPENPD, 0);
3039 syscall(SYS_fcntl, GC_proc_fd, F_SETFD, FD_CLOEXEC);
3040 if (GC_proc_fd < 0) {
3041 ABORT("/proc ioctl failed");
3043 GC_proc_buf = GC_scratch_alloc(GC_proc_buf_size);
3044 # ifdef GC_SOLARIS_THREADS
3045 GC_fresh_pages = (struct hblk **)
3046 GC_scratch_alloc(MAX_FRESH_PAGES * sizeof (struct hblk *));
3047 if (GC_fresh_pages == 0) {
3048 GC_err_printf0("No space for fresh pages\n");
3051 BZERO(GC_fresh_pages, MAX_FRESH_PAGES * sizeof (struct hblk *));
3055 /* Ignore write hints. They don't help us here. */
3057 void GC_remove_protection(h, nblocks, is_ptrfree)
3064 #ifdef GC_SOLARIS_THREADS
3065 # define READ(fd,buf,nbytes) syscall(SYS_read, fd, buf, nbytes)
3067 # define READ(fd,buf,nbytes) read(fd, buf, nbytes)
3070 void GC_read_dirty()
3072 unsigned long ps, np;
3075 struct prasmap * map;
3077 ptr_t current_addr, limit;
3081 BZERO(GC_grungy_pages, (sizeof GC_grungy_pages));
3084 if (READ(GC_proc_fd, bufp, GC_proc_buf_size) <= 0) {
3086 GC_printf1("/proc read failed: GC_proc_buf_size = %lu\n",
3090 /* Retry with larger buffer. */
3091 word new_size = 2 * GC_proc_buf_size;
3092 char * new_buf = GC_scratch_alloc(new_size);
3095 GC_proc_buf = bufp = new_buf;
3096 GC_proc_buf_size = new_size;
3098 if (syscall(SYS_read, GC_proc_fd, bufp, GC_proc_buf_size) <= 0) {
3099 WARN("Insufficient space for /proc read\n", 0);
3101 memset(GC_grungy_pages, 0xff, sizeof (page_hash_table));
3102 memset(GC_written_pages, 0xff, sizeof(page_hash_table));
3103 # ifdef GC_SOLARIS_THREADS
3104 BZERO(GC_fresh_pages,
3105 MAX_FRESH_PAGES * sizeof (struct hblk *));
3111 /* Copy dirty bits into GC_grungy_pages */
3112 nmaps = ((struct prpageheader *)bufp) -> pr_nmap;
3113 /* printf( "nmaps = %d, PG_REFERENCED = %d, PG_MODIFIED = %d\n",
3114 nmaps, PG_REFERENCED, PG_MODIFIED); */
3115 bufp = bufp + sizeof(struct prpageheader);
3116 for (i = 0; i < nmaps; i++) {
3117 map = (struct prasmap *)bufp;
3118 vaddr = (ptr_t)(map -> pr_vaddr);
3119 ps = map -> pr_pagesize;
3120 np = map -> pr_npage;
3121 /* printf("vaddr = 0x%X, ps = 0x%X, np = 0x%X\n", vaddr, ps, np); */
3122 limit = vaddr + ps * np;
3123 bufp += sizeof (struct prasmap);
3124 for (current_addr = vaddr;
3125 current_addr < limit; current_addr += ps){
3126 if ((*bufp++) & PG_MODIFIED) {
3127 register struct hblk * h = (struct hblk *) current_addr;
3129 while ((ptr_t)h < current_addr + ps) {
3130 register word index = PHT_HASH(h);
3132 set_pht_entry_from_index(GC_grungy_pages, index);
3133 # ifdef GC_SOLARIS_THREADS
3135 register int slot = FRESH_PAGE_SLOT(h);
3137 if (GC_fresh_pages[slot] == h) {
3138 GC_fresh_pages[slot] = 0;
3146 bufp += sizeof(long) - 1;
3147 bufp = (char *)((unsigned long)bufp & ~(sizeof(long)-1));
3149 /* Update GC_written_pages. */
3150 GC_or_pages(GC_written_pages, GC_grungy_pages);
3151 # ifdef GC_SOLARIS_THREADS
3152 /* Make sure that old stacks are considered completely clean */
3153 /* unless written again. */
3154 GC_old_stacks_are_fresh();
3160 GC_bool GC_page_was_dirty(h)
3163 register word index = PHT_HASH(h);
3164 register GC_bool result;
3166 result = get_pht_entry_from_index(GC_grungy_pages, index);
3167 # ifdef GC_SOLARIS_THREADS
3168 if (result && PAGE_IS_FRESH(h)) result = FALSE;
3169 /* This happens only if page was declared fresh since */
3170 /* the read_dirty call, e.g. because it's in an unused */
3171 /* thread stack. It's OK to treat it as clean, in */
3172 /* that case. And it's consistent with */
3173 /* GC_page_was_ever_dirty. */
3178 GC_bool GC_page_was_ever_dirty(h)
3181 register word index = PHT_HASH(h);
3182 register GC_bool result;
3184 result = get_pht_entry_from_index(GC_written_pages, index);
3185 # ifdef GC_SOLARIS_THREADS
3186 if (result && PAGE_IS_FRESH(h)) result = FALSE;
3191 /* Caller holds allocation lock. */
3192 void GC_is_fresh(h, n)
3197 register word index;
3199 # ifdef GC_SOLARIS_THREADS
3202 if (GC_fresh_pages != 0) {
3203 for (i = 0; i < n; i++) {
3204 ADD_FRESH_PAGE(h + i);
3210 # endif /* PROC_VDB */
3215 # include "vd/PCR_VD.h"
3217 # define NPAGES (32*1024) /* 128 MB */
3219 PCR_VD_DB GC_grungy_bits[NPAGES];
3221 ptr_t GC_vd_base; /* Address corresponding to GC_grungy_bits[0] */
3222 /* HBLKSIZE aligned. */
3224 void GC_dirty_init()
3226 GC_dirty_maintained = TRUE;
3227 /* For the time being, we assume the heap generally grows up */
3228 GC_vd_base = GC_heap_sects[0].hs_start;
3229 if (GC_vd_base == 0) {
3230 ABORT("Bad initial heap segment");
3232 if (PCR_VD_Start(HBLKSIZE, GC_vd_base, NPAGES*HBLKSIZE)
3234 ABORT("dirty bit initialization failed");
3238 void GC_read_dirty()
3240 /* lazily enable dirty bits on newly added heap sects */
3242 static int onhs = 0;
3243 int nhs = GC_n_heap_sects;
3244 for( ; onhs < nhs; onhs++ ) {
3245 PCR_VD_WriteProtectEnable(
3246 GC_heap_sects[onhs].hs_start,
3247 GC_heap_sects[onhs].hs_bytes );
3252 if (PCR_VD_Clear(GC_vd_base, NPAGES*HBLKSIZE, GC_grungy_bits)
3254 ABORT("dirty bit read failed");
3258 GC_bool GC_page_was_dirty(h)
3261 if((ptr_t)h < GC_vd_base || (ptr_t)h >= GC_vd_base + NPAGES*HBLKSIZE) {
3264 return(GC_grungy_bits[h - (struct hblk *)GC_vd_base] & PCR_VD_DB_dirtyBit);
3268 void GC_remove_protection(h, nblocks, is_ptrfree)
3273 PCR_VD_WriteProtectDisable(h, nblocks*HBLKSIZE);
3274 PCR_VD_WriteProtectEnable(h, nblocks*HBLKSIZE);
3277 # endif /* PCR_VDB */
3279 #if defined(MPROTECT_VDB) && defined(DARWIN)
3280 /* The following sources were used as a *reference* for this exception handling
3282 1. Apple's mach/xnu documentation
3283 2. Timothy J. Wood's "Mach Exception Handlers 101" post to the
3284 omnigroup's macosx-dev list.
3285 www.omnigroup.com/mailman/archive/macosx-dev/2000-June/002030.html
3286 3. macosx-nat.c from Apple's GDB source code.
3289 /* The bug that caused all this trouble should now be fixed. This should
3290 eventually be removed if all goes well. */
3291 /* define BROKEN_EXCEPTION_HANDLING */
3293 #include <mach/mach.h>
3294 #include <mach/mach_error.h>
3295 #include <mach/thread_status.h>
3296 #include <mach/exception.h>
3297 #include <mach/task.h>
3298 #include <pthread.h>
3300 /* These are not defined in any header, although they are documented */
3301 extern boolean_t exc_server(mach_msg_header_t *,mach_msg_header_t *);
3302 extern kern_return_t exception_raise(
3303 mach_port_t,mach_port_t,mach_port_t,
3304 exception_type_t,exception_data_t,mach_msg_type_number_t);
3305 extern kern_return_t exception_raise_state(
3306 mach_port_t,mach_port_t,mach_port_t,
3307 exception_type_t,exception_data_t,mach_msg_type_number_t,
3308 thread_state_flavor_t*,thread_state_t,mach_msg_type_number_t,
3309 thread_state_t,mach_msg_type_number_t*);
3310 extern kern_return_t exception_raise_state_identity(
3311 mach_port_t,mach_port_t,mach_port_t,
3312 exception_type_t,exception_data_t,mach_msg_type_number_t,
3313 thread_state_flavor_t*,thread_state_t,mach_msg_type_number_t,
3314 thread_state_t,mach_msg_type_number_t*);
3317 #define MAX_EXCEPTION_PORTS 16
3319 static mach_port_t GC_task_self;
3322 mach_msg_type_number_t count;
3323 exception_mask_t masks[MAX_EXCEPTION_PORTS];
3324 exception_handler_t ports[MAX_EXCEPTION_PORTS];
3325 exception_behavior_t behaviors[MAX_EXCEPTION_PORTS];
3326 thread_state_flavor_t flavors[MAX_EXCEPTION_PORTS];
3330 mach_port_t exception;
3331 #if defined(THREADS)
3337 mach_msg_header_t head;
3341 GC_MP_NORMAL, GC_MP_DISCARDING, GC_MP_STOPPED
3342 } GC_mprotect_state_t;
3344 /* FIXME: 1 and 2 seem to be safe to use in the msgh_id field,
3345 but it isn't documented. Use the source and see if they
3350 /* These values are only used on the reply port */
3353 #if defined(THREADS)
3355 GC_mprotect_state_t GC_mprotect_state;
3357 /* The following should ONLY be called when the world is stopped */
3358 static void GC_mprotect_thread_notify(mach_msg_id_t id) {
3361 mach_msg_trailer_t trailer;
3363 mach_msg_return_t r;
3365 buf.msg.head.msgh_bits =
3366 MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND,0);
3367 buf.msg.head.msgh_size = sizeof(buf.msg);
3368 buf.msg.head.msgh_remote_port = GC_ports.exception;
3369 buf.msg.head.msgh_local_port = MACH_PORT_NULL;
3370 buf.msg.head.msgh_id = id;
3374 MACH_SEND_MSG|MACH_RCV_MSG|MACH_RCV_LARGE,
3378 MACH_MSG_TIMEOUT_NONE,
3380 if(r != MACH_MSG_SUCCESS)
3381 ABORT("mach_msg failed in GC_mprotect_thread_notify");
3382 if(buf.msg.head.msgh_id != ID_ACK)
3383 ABORT("invalid ack in GC_mprotect_thread_notify");
3386 /* Should only be called by the mprotect thread */
3387 static void GC_mprotect_thread_reply() {
3389 mach_msg_return_t r;
3391 msg.head.msgh_bits =
3392 MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND,0);
3393 msg.head.msgh_size = sizeof(msg);
3394 msg.head.msgh_remote_port = GC_ports.reply;
3395 msg.head.msgh_local_port = MACH_PORT_NULL;
3396 msg.head.msgh_id = ID_ACK;
3404 MACH_MSG_TIMEOUT_NONE,
3406 if(r != MACH_MSG_SUCCESS)
3407 ABORT("mach_msg failed in GC_mprotect_thread_reply");
3410 void GC_mprotect_stop() {
3411 GC_mprotect_thread_notify(ID_STOP);
3413 void GC_mprotect_resume() {
3414 GC_mprotect_thread_notify(ID_RESUME);
3417 #else /* !THREADS */
3418 /* The compiler should optimize away any GC_mprotect_state computations */
3419 #define GC_mprotect_state GC_MP_NORMAL
3422 static void *GC_mprotect_thread(void *arg) {
3423 mach_msg_return_t r;
3424 /* These two structures contain some private kernel data. We don't need to
3425 access any of it so we don't bother defining a proper struct. The
3426 correct definitions are in the xnu source code. */
3428 mach_msg_header_t head;
3432 mach_msg_header_t head;
3433 mach_msg_body_t msgh_body;
3442 MACH_RCV_MSG|MACH_RCV_LARGE|
3443 (GC_mprotect_state == GC_MP_DISCARDING ? MACH_RCV_TIMEOUT : 0),
3447 GC_mprotect_state == GC_MP_DISCARDING ? 0 : MACH_MSG_TIMEOUT_NONE,
3450 id = r == MACH_MSG_SUCCESS ? msg.head.msgh_id : -1;
3452 #if defined(THREADS)
3453 if(GC_mprotect_state == GC_MP_DISCARDING) {
3454 if(r == MACH_RCV_TIMED_OUT) {
3455 GC_mprotect_state = GC_MP_STOPPED;
3456 GC_mprotect_thread_reply();
3459 if(r == MACH_MSG_SUCCESS && (id == ID_STOP || id == ID_RESUME))
3460 ABORT("out of order mprotect thread request");
3464 if(r != MACH_MSG_SUCCESS) {
3465 GC_err_printf2("mach_msg failed with %d %s\n",
3466 (int)r,mach_error_string(r));
3467 ABORT("mach_msg failed");
3471 #if defined(THREADS)
3473 if(GC_mprotect_state != GC_MP_NORMAL)
3474 ABORT("Called mprotect_stop when state wasn't normal");
3475 GC_mprotect_state = GC_MP_DISCARDING;
3478 if(GC_mprotect_state != GC_MP_STOPPED)
3479 ABORT("Called mprotect_resume when state wasn't stopped");
3480 GC_mprotect_state = GC_MP_NORMAL;
3481 GC_mprotect_thread_reply();
3483 #endif /* THREADS */
3485 /* Handle the message (calls catch_exception_raise) */
3486 if(!exc_server(&msg.head,&reply.head))
3487 ABORT("exc_server failed");
3488 /* Send the reply */
3492 reply.head.msgh_size,
3495 MACH_MSG_TIMEOUT_NONE,
3497 if(r != MACH_MSG_SUCCESS) {
3498 /* This will fail if the thread dies, but the thread shouldn't
3500 #ifdef BROKEN_EXCEPTION_HANDLING
3502 "mach_msg failed with %d %s while sending exc reply\n",
3503 (int)r,mach_error_string(r));
3505 ABORT("mach_msg failed while sending exception reply");
3514 /* All this SIGBUS code shouldn't be necessary. All protection faults should
3515 be going throught the mach exception handler. However, it seems a SIGBUS is
3516 occasionally sent for some unknown reason. Even more odd, it seems to be
3517 meaningless and safe to ignore. */
3518 #ifdef BROKEN_EXCEPTION_HANDLING
3520 typedef void (* SIG_PF)();
3521 static SIG_PF GC_old_bus_handler;
3523 /* Updates to this aren't atomic, but the SIGBUSs seem pretty rare.
3524 Even if this doesn't get updated property, it isn't really a problem */
3525 static int GC_sigbus_count;
3527 static void GC_darwin_sigbus(int num,siginfo_t *sip,void *context) {
3528 if(num != SIGBUS) ABORT("Got a non-sigbus signal in the sigbus handler");
3530 /* Ugh... some seem safe to ignore, but too many in a row probably means
3531 trouble. GC_sigbus_count is reset for each mach exception that is
3533 if(GC_sigbus_count >= 8) {
3534 ABORT("Got more than 8 SIGBUSs in a row!");
3537 GC_err_printf0("GC: WARNING: Ignoring SIGBUS.\n");
3540 #endif /* BROKEN_EXCEPTION_HANDLING */
3542 void GC_dirty_init() {
3546 pthread_attr_t attr;
3547 exception_mask_t mask;
3550 GC_printf0("Inititalizing mach/darwin mprotect virtual dirty bit "
3551 "implementation\n");
3553 # ifdef BROKEN_EXCEPTION_HANDLING
3554 GC_err_printf0("GC: WARNING: Enabling workarounds for various darwin "
3555 "exception handling bugs.\n");
3557 GC_dirty_maintained = TRUE;
3558 if (GC_page_size % HBLKSIZE != 0) {
3559 GC_err_printf0("Page size not multiple of HBLKSIZE\n");
3560 ABORT("Page size not multiple of HBLKSIZE");
3563 GC_task_self = me = mach_task_self();
3565 r = mach_port_allocate(me,MACH_PORT_RIGHT_RECEIVE,&GC_ports.exception);
3566 if(r != KERN_SUCCESS) ABORT("mach_port_allocate failed (exception port)");
3568 r = mach_port_insert_right(me,GC_ports.exception,GC_ports.exception,
3569 MACH_MSG_TYPE_MAKE_SEND);
3570 if(r != KERN_SUCCESS)
3571 ABORT("mach_port_insert_right failed (exception port)");
3573 #if defined(THREADS)
3574 r = mach_port_allocate(me,MACH_PORT_RIGHT_RECEIVE,&GC_ports.reply);
3575 if(r != KERN_SUCCESS) ABORT("mach_port_allocate failed (reply port)");
3578 /* The exceptions we want to catch */
3579 mask = EXC_MASK_BAD_ACCESS;
3581 r = task_get_exception_ports(
3584 GC_old_exc_ports.masks,
3585 &GC_old_exc_ports.count,
3586 GC_old_exc_ports.ports,
3587 GC_old_exc_ports.behaviors,
3588 GC_old_exc_ports.flavors
3590 if(r != KERN_SUCCESS) ABORT("task_get_exception_ports failed");
3592 r = task_set_exception_ports(
3597 MACHINE_THREAD_STATE
3599 if(r != KERN_SUCCESS) ABORT("task_set_exception_ports failed");
3601 if(pthread_attr_init(&attr) != 0) ABORT("pthread_attr_init failed");
3602 if(pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED) != 0)
3603 ABORT("pthread_attr_setdetachedstate failed");
3605 # undef pthread_create
3606 /* This will call the real pthread function, not our wrapper */
3607 if(pthread_create(&thread,&attr,GC_mprotect_thread,NULL) != 0)
3608 ABORT("pthread_create failed");
3609 pthread_attr_destroy(&attr);
3611 /* Setup the sigbus handler for ignoring the meaningless SIGBUSs */
3612 #ifdef BROKEN_EXCEPTION_HANDLING
3614 struct sigaction sa, oldsa;
3615 sa.sa_handler = (SIG_PF)GC_darwin_sigbus;
3616 sigemptyset(&sa.sa_mask);
3617 sa.sa_flags = SA_RESTART|SA_SIGINFO;
3618 if(sigaction(SIGBUS,&sa,&oldsa) < 0) ABORT("sigaction");
3619 GC_old_bus_handler = (SIG_PF)oldsa.sa_handler;
3620 if (GC_old_bus_handler != SIG_DFL) {
3622 GC_err_printf0("Replaced other SIGBUS handler\n");
3626 #endif /* BROKEN_EXCEPTION_HANDLING */
3629 /* The source code for Apple's GDB was used as a reference for the exception
3630 forwarding code. This code is similar to be GDB code only because there is
3631 only one way to do it. */
3632 static kern_return_t GC_forward_exception(
3635 exception_type_t exception,
3636 exception_data_t data,
3637 mach_msg_type_number_t data_count
3642 exception_behavior_t behavior;
3643 thread_state_flavor_t flavor;
3645 thread_state_data_t thread_state;
3646 mach_msg_type_number_t thread_state_count = THREAD_STATE_MAX;
3648 for(i=0;i<GC_old_exc_ports.count;i++)
3649 if(GC_old_exc_ports.masks[i] & (1 << exception))
3651 if(i==GC_old_exc_ports.count) ABORT("No handler for exception!");
3653 port = GC_old_exc_ports.ports[i];
3654 behavior = GC_old_exc_ports.behaviors[i];
3655 flavor = GC_old_exc_ports.flavors[i];
3657 if(behavior != EXCEPTION_DEFAULT) {
3658 r = thread_get_state(thread,flavor,thread_state,&thread_state_count);
3659 if(r != KERN_SUCCESS)
3660 ABORT("thread_get_state failed in forward_exception");
3664 case EXCEPTION_DEFAULT:
3665 r = exception_raise(port,thread,task,exception,data,data_count);
3667 case EXCEPTION_STATE:
3668 r = exception_raise_state(port,thread,task,exception,data,
3669 data_count,&flavor,thread_state,thread_state_count,
3670 thread_state,&thread_state_count);
3672 case EXCEPTION_STATE_IDENTITY:
3673 r = exception_raise_state_identity(port,thread,task,exception,data,
3674 data_count,&flavor,thread_state,thread_state_count,
3675 thread_state,&thread_state_count);
3678 r = KERN_FAILURE; /* make gcc happy */
3679 ABORT("forward_exception: unknown behavior");
3683 if(behavior != EXCEPTION_DEFAULT) {
3684 r = thread_set_state(thread,flavor,thread_state,thread_state_count);
3685 if(r != KERN_SUCCESS)
3686 ABORT("thread_set_state failed in forward_exception");
3692 #define FWD() GC_forward_exception(thread,task,exception,code,code_count)
3694 /* This violates the namespace rules but there isn't anything that can be done
3695 about it. The exception handling stuff is hard coded to call this */
3697 catch_exception_raise(
3698 mach_port_t exception_port,mach_port_t thread,mach_port_t task,
3699 exception_type_t exception,exception_data_t code,
3700 mach_msg_type_number_t code_count
3707 thread_state_flavor_t flavor = PPC_EXCEPTION_STATE;
3708 mach_msg_type_number_t exc_state_count = PPC_EXCEPTION_STATE_COUNT;
3709 ppc_exception_state_t exc_state;
3711 # error FIXME for non-ppc darwin
3715 if(exception != EXC_BAD_ACCESS || code[0] != KERN_PROTECTION_FAILURE) {
3716 #ifdef DEBUG_EXCEPTION_HANDLING
3717 /* We aren't interested, pass it on to the old handler */
3718 GC_printf3("Exception: 0x%x Code: 0x%x 0x%x in catch....\n",
3720 code_count > 0 ? code[0] : -1,
3721 code_count > 1 ? code[1] : -1);
3726 r = thread_get_state(thread,flavor,
3727 (natural_t*)&exc_state,&exc_state_count);
3728 if(r != KERN_SUCCESS) {
3729 /* The thread is supposed to be suspended while the exception handler
3730 is called. This shouldn't fail. */
3731 #ifdef BROKEN_EXCEPTION_HANDLING
3732 GC_err_printf0("thread_get_state failed in "
3733 "catch_exception_raise\n");
3734 return KERN_SUCCESS;
3736 ABORT("thread_get_state failed in catch_exception_raise");
3740 /* This is the address that caused the fault */
3741 addr = (char*) exc_state.dar;
3743 if((HDR(addr)) == 0) {
3744 /* Ugh... just like the SIGBUS problem above, it seems we get a bogus
3745 KERN_PROTECTION_FAILURE every once and a while. We wait till we get
3746 a bunch in a row before doing anything about it. If a "real" fault
3747 ever occurres it'll just keep faulting over and over and we'll hit
3748 the limit pretty quickly. */
3749 #ifdef BROKEN_EXCEPTION_HANDLING
3750 static char *last_fault;
3751 static int last_fault_count;
3753 if(addr != last_fault) {
3755 last_fault_count = 0;
3757 if(++last_fault_count < 32) {
3758 if(last_fault_count == 1)
3760 "GC: WARNING: Ignoring KERN_PROTECTION_FAILURE at %p\n",
3762 return KERN_SUCCESS;
3765 GC_err_printf1("Unexpected KERN_PROTECTION_FAILURE at %p\n",addr);
3766 /* Can't pass it along to the signal handler because that is
3767 ignoring SIGBUS signals. We also shouldn't call ABORT here as
3768 signals don't always work too well from the exception handler. */
3769 GC_err_printf0("Aborting\n");
3771 #else /* BROKEN_EXCEPTION_HANDLING */
3772 /* Pass it along to the next exception handler
3773 (which should call SIGBUS/SIGSEGV) */
3775 #endif /* !BROKEN_EXCEPTION_HANDLING */
3778 #ifdef BROKEN_EXCEPTION_HANDLING
3779 /* Reset the number of consecutive SIGBUSs */
3780 GC_sigbus_count = 0;
3783 if(GC_mprotect_state == GC_MP_NORMAL) { /* common case */
3784 h = (struct hblk*)((word)addr & ~(GC_page_size-1));
3785 UNPROTECT(h, GC_page_size);
3786 for (i = 0; i < divHBLKSZ(GC_page_size); i++) {
3787 register int index = PHT_HASH(h+i);
3788 async_set_pht_entry_from_index(GC_dirty_pages, index);
3790 } else if(GC_mprotect_state == GC_MP_DISCARDING) {
3791 /* Lie to the thread for now. No sense UNPROTECT()ing the memory
3792 when we're just going to PROTECT() it again later. The thread
3793 will just fault again once it resumes */
3795 /* Shouldn't happen, i don't think */
3796 GC_printf0("KERN_PROTECTION_FAILURE while world is stopped\n");
3799 return KERN_SUCCESS;
3803 /* These should never be called, but just in case... */
3804 kern_return_t catch_exception_raise_state(mach_port_name_t exception_port,
3805 int exception, exception_data_t code, mach_msg_type_number_t codeCnt,
3806 int flavor, thread_state_t old_state, int old_stateCnt,
3807 thread_state_t new_state, int new_stateCnt)
3809 ABORT("catch_exception_raise_state");
3810 return(KERN_INVALID_ARGUMENT);
3812 kern_return_t catch_exception_raise_state_identity(
3813 mach_port_name_t exception_port, mach_port_t thread, mach_port_t task,
3814 int exception, exception_data_t code, mach_msg_type_number_t codeCnt,
3815 int flavor, thread_state_t old_state, int old_stateCnt,
3816 thread_state_t new_state, int new_stateCnt)
3818 ABORT("catch_exception_raise_state_identity");
3819 return(KERN_INVALID_ARGUMENT);
3823 #endif /* DARWIN && MPROTECT_VDB */
3825 # ifndef HAVE_INCREMENTAL_PROTECTION_NEEDS
3826 int GC_incremental_protection_needs()
3828 return GC_PROTECTS_NONE;
3830 # endif /* !HAVE_INCREMENTAL_PROTECTION_NEEDS */
3833 * Call stack save code for debugging.
3834 * Should probably be in mach_dep.c, but that requires reorganization.
3837 /* I suspect the following works for most X86 *nix variants, so */
3838 /* long as the frame pointer is explicitly stored. In the case of gcc, */
3839 /* compiler flags (e.g. -fomit-frame-pointer) determine whether it is. */
3840 #if defined(I386) && defined(LINUX) && defined(SAVE_CALL_CHAIN)
3841 # include <features.h>
3844 struct frame *fr_savfp;
3846 long fr_arg[NARGS]; /* All the arguments go here. */
3852 # include <features.h>
3857 struct frame *fr_savfp;
3866 # if defined(SUNOS4)
3867 # include <machine/frame.h>
3869 # if defined (DRSNX)
3870 # include <sys/sparc/frame.h>
3872 # if defined(OPENBSD) || defined(NETBSD)
3875 # include <sys/frame.h>
3881 --> We only know how to to get the first 6 arguments
3885 #ifdef NEED_CALLINFO
3886 /* Fill in the pc and argument information for up to NFRAMES of my */
3887 /* callers. Ignore my frame and my callers frame. */
3890 # include <unistd.h>
3893 #endif /* NEED_CALLINFO */
3895 #ifdef SAVE_CALL_CHAIN
3897 #if NARGS == 0 && NFRAMES % 2 == 0 /* No padding */ \
3898 && defined(GC_HAVE_BUILTIN_BACKTRACE)
3900 #include <execinfo.h>
3902 void GC_save_callers (info)
3903 struct callinfo info[NFRAMES];
3905 void * tmp_info[NFRAMES + 1];
3907 # define IGNORE_FRAMES 1
3909 /* We retrieve NFRAMES+1 pc values, but discard the first, since it */
3910 /* points to our own frame. */
3911 GC_ASSERT(sizeof(struct callinfo) == sizeof(void *));
3912 npcs = backtrace((void **)tmp_info, NFRAMES + IGNORE_FRAMES);
3913 BCOPY(tmp_info+IGNORE_FRAMES, info, (npcs - IGNORE_FRAMES) * sizeof(void *));
3914 for (i = npcs - IGNORE_FRAMES; i < NFRAMES; ++i) info[i].ci_pc = 0;
3917 #else /* No builtin backtrace; do it ourselves */
3919 #if (defined(OPENBSD) || defined(NETBSD)) && defined(SPARC)
3920 # define FR_SAVFP fr_fp
3921 # define FR_SAVPC fr_pc
3923 # define FR_SAVFP fr_savfp
3924 # define FR_SAVPC fr_savpc
3927 #if defined(SPARC) && (defined(__arch64__) || defined(__sparcv9))
3933 void GC_save_callers (info)
3934 struct callinfo info[NFRAMES];
3936 struct frame *frame;
3940 /* We assume this is turned on only with gcc as the compiler. */
3941 asm("movl %%ebp,%0" : "=r"(frame));
3944 frame = (struct frame *) GC_save_regs_in_stack ();
3945 fp = (struct frame *)((long) frame -> FR_SAVFP + BIAS);
3948 for (; (!(fp HOTTER_THAN frame) && !(GC_stackbottom HOTTER_THAN (ptr_t)fp)
3949 && (nframes < NFRAMES));
3950 fp = (struct frame *)((long) fp -> FR_SAVFP + BIAS), nframes++) {
3953 info[nframes].ci_pc = fp->FR_SAVPC;
3955 for (i = 0; i < NARGS; i++) {
3956 info[nframes].ci_arg[i] = ~(fp->fr_arg[i]);
3958 # endif /* NARGS > 0 */
3960 if (nframes < NFRAMES) info[nframes].ci_pc = 0;
3963 #endif /* No builtin backtrace */
3965 #endif /* SAVE_CALL_CHAIN */
3967 #ifdef NEED_CALLINFO
3969 /* Print info to stderr. We do NOT hold the allocation lock */
3970 void GC_print_callers (info)
3971 struct callinfo info[NFRAMES];
3974 static int reentry_count = 0;
3975 GC_bool stop = FALSE;
3982 GC_err_printf0("\tCaller at allocation:\n");
3984 GC_err_printf0("\tCall chain at allocation:\n");
3986 for (i = 0; i < NFRAMES && !stop ; i++) {
3987 if (info[i].ci_pc == 0) break;
3992 GC_err_printf0("\t\targs: ");
3993 for (j = 0; j < NARGS; j++) {
3994 if (j != 0) GC_err_printf0(", ");
3995 GC_err_printf2("%d (0x%X)", ~(info[i].ci_arg[j]),
3996 ~(info[i].ci_arg[j]));
3998 GC_err_printf0("\n");
4001 if (reentry_count > 1) {
4002 /* We were called during an allocation during */
4003 /* a previous GC_print_callers call; punt. */
4004 GC_err_printf1("\t\t##PC##= 0x%lx\n", info[i].ci_pc);
4011 # if defined(GC_HAVE_BUILTIN_BACKTRACE)
4013 backtrace_symbols((void **)(&(info[i].ci_pc)), 1);
4014 char *name = sym_name[0];
4018 sprintf(buf, "##PC##= 0x%lx", info[i].ci_pc);
4020 # if defined(LINUX) && !defined(SMALL_CONFIG)
4021 /* Try for a line number. */
4024 static char exe_name[EXE_SZ];
4026 char cmd_buf[CMD_SZ];
4027 # define RESULT_SZ 200
4028 static char result_buf[RESULT_SZ];
4030 static GC_bool found_exe_name = FALSE;
4031 static GC_bool will_fail = FALSE;
4033 /* Try to get it via a hairy and expensive scheme. */
4034 /* First we get the name of the executable: */
4035 if (will_fail) goto out;
4036 if (!found_exe_name) {
4037 ret_code = readlink("/proc/self/exe", exe_name, EXE_SZ);
4038 if (ret_code < 0 || ret_code >= EXE_SZ
4039 || exe_name[0] != '/') {
4040 will_fail = TRUE; /* Dont try again. */
4043 exe_name[ret_code] = '\0';
4044 found_exe_name = TRUE;
4046 /* Then we use popen to start addr2line -e <exe> <addr> */
4047 /* There are faster ways to do this, but hopefully this */
4048 /* isn't time critical. */
4049 sprintf(cmd_buf, "/usr/bin/addr2line -f -e %s 0x%lx", exe_name,
4050 (unsigned long)info[i].ci_pc);
4051 pipe = popen(cmd_buf, "r");
4053 || (result_len = fread(result_buf, 1, RESULT_SZ - 1, pipe))
4055 if (pipe != NULL) pclose(pipe);
4059 if (result_buf[result_len - 1] == '\n') --result_len;
4060 result_buf[result_len] = 0;
4061 if (result_buf[0] == '?'
4062 || result_buf[result_len-2] == ':'
4063 && result_buf[result_len-1] == '0') {
4067 /* Get rid of embedded newline, if any. Test for "main" */
4069 char * nl = strchr(result_buf, '\n');
4070 if (nl != NULL && nl < result_buf + result_len) {
4073 if (strncmp(result_buf, "main", nl - result_buf) == 0) {
4077 if (result_len < RESULT_SZ - 25) {
4078 /* Add in hex address */
4079 sprintf(result_buf + result_len, " [0x%lx]",
4080 (unsigned long)info[i].ci_pc);
4087 GC_err_printf1("\t\t%s\n", name);
4088 # if defined(GC_HAVE_BUILTIN_BACKTRACE)
4089 free(sym_name); /* May call GC_free; that's OK */
4098 #endif /* NEED_CALLINFO */
4102 #if defined(LINUX) && defined(__ELF__) && !defined(SMALL_CONFIG)
4104 /* Dump /proc/self/maps to GC_stderr, to enable looking up names for
4105 addresses in FIND_LEAK output. */
4107 static word dump_maps(char *maps)
4109 GC_err_write(maps, strlen(maps));
4113 void GC_print_address_map()
4115 GC_err_printf0("---------- Begin address map ----------\n");
4116 GC_apply_to_maps(dump_maps);
4117 GC_err_printf0("---------- End address map ----------\n");