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.
19 # include "private/gc_priv.h"
21 # include "atomic_ops.h"
24 # if defined(LINUX) && !defined(POWERPC)
25 # include <linux/version.h>
26 # if (LINUX_VERSION_CODE <= 0x10400)
27 /* Ugly hack to get struct sigcontext_struct definition. Required */
28 /* for some early 1.3.X releases. Will hopefully go away soon. */
29 /* in some later Linux releases, asm/sigcontext.h may have to */
30 /* be included instead. */
32 # include <asm/signal.h>
35 /* Kernels prior to 2.1.1 defined struct sigcontext_struct instead of */
36 /* struct sigcontext. libc6 (glibc2) uses "struct sigcontext" in */
37 /* prototypes, so we have to include the top-level sigcontext.h to */
38 /* make sure the former gets defined to be the latter if appropriate. */
39 # include <features.h>
41 # if 2 == __GLIBC__ && 0 == __GLIBC_MINOR__
42 /* glibc 2.1 no longer has sigcontext.h. But signal.h */
43 /* has the right declaration for glibc 2.1. */
44 # include <sigcontext.h>
45 # endif /* 0 == __GLIBC_MINOR__ */
46 # else /* not 2 <= __GLIBC__ */
47 /* libc5 doesn't have <sigcontext.h>: go directly with the kernel */
48 /* one. Check LINUX_VERSION_CODE to see which we should reference. */
49 # include <asm/sigcontext.h>
50 # endif /* 2 <= __GLIBC__ */
53 # if !defined(OS2) && !defined(PCR) && !defined(AMIGA) && !defined(MACOS) \
55 # include <sys/types.h>
56 # if !defined(MSWIN32)
63 # define SIGSEGV 0 /* value is irrelevant */
72 #if defined(LINUX) || defined(LINUX_STACKBOTTOM)
76 /* Blatantly OS dependent routines, except for those that are related */
77 /* to dynamic loading. */
85 #if defined(MSWIN32) || defined(MSWINCE) || defined(CYGWIN32)
86 # define WIN32_LEAN_AND_MEAN
89 /* It's not clear this is completely kosher under Cygwin. But it */
90 /* allows us to get a working GC_get_stack_base. */
94 # include <Processes.h>
99 # include <malloc.h> /* for locking */
102 #if defined(LINUX) || defined(FREEBSD) || defined(SOLARIS) || defined(IRIX5) \
103 || defined(USE_MMAP) || defined(USE_MUNMAP)
104 # define MMAP_SUPPORTED
107 #if defined(MMAP_SUPPORTED) || defined(ADD_HEAP_GUARD_PAGES)
108 # if defined(USE_MUNMAP) && !defined(USE_MMAP)
109 --> USE_MUNMAP requires USE_MMAP
111 # include <sys/types.h>
112 # include <sys/mman.h>
113 # include <sys/stat.h>
118 /* for get_etext and friends */
119 #include <mach-o/getsect.h>
123 /* Apparently necessary for djgpp 2.01. May cause problems with */
124 /* other versions. */
125 typedef long unsigned int caddr_t;
129 # include "il/PCR_IL.h"
130 # include "th/PCR_ThCtl.h"
131 # include "mm/PCR_MM.h"
134 #if !defined(NO_EXECUTE_PERMISSION)
135 # define OPT_PROT_EXEC PROT_EXEC
137 # define OPT_PROT_EXEC 0
140 #if defined(LINUX) && \
141 (defined(USE_PROC_FOR_LIBRARIES) || defined(IA64) || !defined(SMALL_CONFIG))
142 # define NEED_PROC_MAPS
145 #ifdef NEED_PROC_MAPS
146 /* We need to parse /proc/self/maps, either to find dynamic libraries, */
147 /* and/or to find the register backing store base (IA64). Do it once */
152 /* Repeatedly perform a read call until the buffer is filled or */
153 /* we encounter EOF. */
154 ssize_t GC_repeat_read(int fd, char *buf, size_t count)
156 ssize_t num_read = 0;
159 while (num_read < count) {
160 result = READ(fd, buf + num_read, count - num_read);
161 if (result < 0) return result;
162 if (result == 0) break;
168 /* Determine the length of a file by incrementally reading it into a */
169 /* This would be sily to use on a file supporting lseek, but Linux */
170 /* /proc files usually do not. */
171 size_t GC_get_file_len(int f)
175 # define GET_FILE_LEN_BUF_SZ 500
176 char buf[GET_FILE_LEN_BUF_SZ];
179 result = read(f, buf, GET_FILE_LEN_BUF_SZ);
180 if (result == -1) return 0;
182 } while (result > 0);
186 size_t GC_get_maps_len(void)
188 int f = open("/proc/self/maps", O_RDONLY);
189 size_t result = GC_get_file_len(f);
195 * Copy the contents of /proc/self/maps to a buffer in our address space.
196 * Return the address of the buffer, or zero on failure.
197 * This code could be simplified if we could determine its size
200 char * GC_get_maps(void)
204 static char init_buf[1];
205 static char *maps_buf = init_buf;
206 static size_t maps_buf_sz = 1;
207 size_t maps_size, old_maps_size = 0;
209 /* The buffer is essentially static, so there must be a single client. */
210 GC_ASSERT(I_HOLD_LOCK());
212 /* Note that in the presence of threads, the maps file can */
213 /* essentially shrink asynchronously and unexpectedly as */
214 /* threads that we already think of as dead release their */
215 /* stacks. And there is no easy way to read the entire */
216 /* file atomically. This is arguably a misfeature of the */
217 /* /proc/.../maps interface. */
219 /* Since we dont believe the file can grow */
220 /* asynchronously, it should suffice to first determine */
221 /* the size (using lseek or read), and then to reread the */
222 /* file. If the size is inconsistent we have to retry. */
223 /* This only matters with threads enabled, and if we use */
224 /* this to locate roots (not the default). */
226 /* Determine the initial size of /proc/self/maps. */
227 /* Note that lseek doesn't work, at least as of 2.6.15. */
229 maps_size = GC_get_maps_len();
230 if (0 == maps_size) return 0;
232 maps_size = 4000; /* Guess */
235 /* Read /proc/self/maps, growing maps_buf as necessary. */
236 /* Note that we may not allocate conventionally, and */
237 /* thus can't use stdio. */
239 while (maps_size >= maps_buf_sz) {
240 /* Grow only by powers of 2, since we leak "too small" buffers. */
241 while (maps_size >= maps_buf_sz) maps_buf_sz *= 2;
242 maps_buf = GC_scratch_alloc(maps_buf_sz);
244 /* Recompute initial length, since we allocated. */
245 /* This can only happen a few times per program */
247 maps_size = GC_get_maps_len();
248 if (0 == maps_size) return 0;
250 if (maps_buf == 0) return 0;
252 GC_ASSERT(maps_buf_sz >= maps_size + 1);
253 f = open("/proc/self/maps", O_RDONLY);
254 if (-1 == f) return 0;
256 old_maps_size = maps_size;
260 result = GC_repeat_read(f, maps_buf, maps_buf_sz-1);
261 if (result <= 0) return 0;
263 } while (result == maps_buf_sz-1);
266 if (maps_size > old_maps_size) {
267 GC_err_printf("Old maps size = %d, new maps size = %d\n",
268 old_maps_size, maps_size);
269 ABORT("Unexpected asynchronous /proc/self/maps growth: "
270 "Unregistered thread?");
273 } while (maps_size >= maps_buf_sz || maps_size < old_maps_size);
274 /* In the single-threaded case, the second clause is false. */
275 maps_buf[maps_size] = '\0';
277 /* Apply fn to result. */
282 // GC_parse_map_entry parses an entry from /proc/self/maps so we can
283 // locate all writable data segments that belong to shared libraries.
284 // The format of one of these entries and the fields we care about
286 // XXXXXXXX-XXXXXXXX r-xp 00000000 30:05 260537 name of mapping...\n
287 // ^^^^^^^^ ^^^^^^^^ ^^^^ ^^
288 // start end prot maj_dev
290 // Note that since about august 2003 kernels, the columns no longer have
291 // fixed offsets on 64-bit kernels. Hence we no longer rely on fixed offsets
292 // anywhere, which is safer anyway.
296 * Assign various fields of the first line in buf_ptr to *start, *end,
297 * *prot, *maj_dev and *mapping_name. Mapping_name may be NULL.
298 * *prot and *mapping_name are assigned pointers into the original
301 char *GC_parse_map_entry(char *buf_ptr, ptr_t *start, ptr_t *end,
302 char **prot, unsigned int *maj_dev,
305 char *start_start, *end_start, *maj_dev_start;
309 if (buf_ptr == NULL || *buf_ptr == '\0') {
314 while (isspace(*p)) ++p;
316 GC_ASSERT(isxdigit(*start_start));
317 *start = (ptr_t)strtoul(start_start, &endp, 16); p = endp;
322 GC_ASSERT(isxdigit(*end_start));
323 *end = (ptr_t)strtoul(end_start, &endp, 16); p = endp;
324 GC_ASSERT(isspace(*p));
326 while (isspace(*p)) ++p;
327 GC_ASSERT(*p == 'r' || *p == '-');
329 /* Skip past protection field to offset field */
330 while (!isspace(*p)) ++p; while (isspace(*p)) ++p;
331 GC_ASSERT(isxdigit(*p));
332 /* Skip past offset field, which we ignore */
333 while (!isspace(*p)) ++p; while (isspace(*p)) ++p;
335 GC_ASSERT(isxdigit(*maj_dev_start));
336 *maj_dev = strtoul(maj_dev_start, NULL, 16);
338 if (mapping_name == 0) {
339 while (*p && *p++ != '\n');
341 while (*p && *p != '\n' && *p != '/' && *p != '[') p++;
343 while (*p && *p++ != '\n');
349 /* Try to read the backing store base from /proc/self/maps. */
350 /* Return the bounds of the writable mapping with a 0 major device, */
351 /* which includes the address passed as data. */
352 /* Return FALSE if there is no such mapping. */
353 GC_bool GC_enclosing_mapping(ptr_t addr, ptr_t *startp, ptr_t *endp)
356 ptr_t my_start, my_end;
357 unsigned int maj_dev;
358 char *maps = GC_get_maps();
359 char *buf_ptr = maps;
361 if (0 == maps) return(FALSE);
363 buf_ptr = GC_parse_map_entry(buf_ptr, &my_start, &my_end,
366 if (buf_ptr == NULL) return FALSE;
367 if (prot[1] == 'w' && maj_dev == 0) {
368 if (my_end > addr && my_start <= addr) {
378 #if defined(REDIRECT_MALLOC)
379 /* Find the text(code) mapping for the library whose name, after */
380 /* stripping the directory part, starts with nm. */
381 GC_bool GC_text_mapping(char *nm, ptr_t *startp, ptr_t *endp)
383 size_t nm_len = strlen(nm);
386 ptr_t my_start, my_end;
387 unsigned int maj_dev;
388 char *maps = GC_get_maps();
389 char *buf_ptr = maps;
391 if (0 == maps) return(FALSE);
393 buf_ptr = GC_parse_map_entry(buf_ptr, &my_start, &my_end,
394 &prot, &maj_dev, &map_path);
396 if (buf_ptr == NULL) return FALSE;
397 if (prot[0] == 'r' && prot[1] == '-' && prot[2] == 'x') {
399 /* Set p to point just past last slash, if any. */
400 while (*p != '\0' && *p != '\n' && *p != ' ' && *p != '\t') ++p;
401 while (*p != '/' && p >= map_path) --p;
403 if (strncmp(nm, p, nm_len) == 0) {
412 #endif /* REDIRECT_MALLOC */
415 static ptr_t backing_store_base_from_proc(void)
417 ptr_t my_start, my_end;
418 if (!GC_enclosing_mapping(GC_save_regs_in_stack(), &my_start, &my_end)) {
419 if (GC_print_stats) {
420 GC_log_printf("Failed to find backing store base from /proc\n");
428 #endif /* NEED_PROC_MAPS */
430 #if defined(SEARCH_FOR_DATA_START)
431 /* The I386 case can be handled without a search. The Alpha case */
432 /* used to be handled differently as well, but the rules changed */
433 /* for recent Linux versions. This seems to be the easiest way to */
434 /* cover all versions. */
436 # if defined(LINUX) || defined(HURD)
437 /* Some Linux distributions arrange to define __data_start. Some */
438 /* define data_start as a weak symbol. The latter is technically */
439 /* broken, since the user program may define data_start, in which */
440 /* case we lose. Nonetheless, we try both, prefering __data_start. */
441 /* We assume gcc-compatible pragmas. */
442 # pragma weak __data_start
443 extern int __data_start[];
444 # pragma weak data_start
445 extern int data_start[];
451 void GC_init_linux_data_start()
453 extern ptr_t GC_find_limit(ptr_t, GC_bool);
455 # if defined(LINUX) || defined(HURD)
456 /* Try the easy approaches first: */
457 if ((ptr_t)__data_start != 0) {
458 GC_data_start = (ptr_t)(__data_start);
461 if ((ptr_t)data_start != 0) {
462 GC_data_start = (ptr_t)(data_start);
466 GC_data_start = GC_find_limit((ptr_t)(_end), FALSE);
472 # ifndef ECOS_GC_MEMORY_SIZE
473 # define ECOS_GC_MEMORY_SIZE (448 * 1024)
474 # endif /* ECOS_GC_MEMORY_SIZE */
476 // FIXME: This is a simple way of allocating memory which is
477 // compatible with ECOS early releases. Later releases use a more
478 // sophisticated means of allocating memory than this simple static
479 // allocator, but this method is at least bound to work.
480 static char memory[ECOS_GC_MEMORY_SIZE];
481 static char *brk = memory;
483 static void *tiny_sbrk(ptrdiff_t increment)
489 if (brk > memory + sizeof memory)
497 #define sbrk tiny_sbrk
500 #if (defined(NETBSD) || defined(OPENBSD)) && defined(__ELF__)
503 void GC_init_netbsd_elf(void)
505 extern ptr_t GC_find_limit(ptr_t, GC_bool);
506 extern char **environ;
507 /* This may need to be environ, without the underscore, for */
509 GC_data_start = GC_find_limit((ptr_t)&environ, FALSE);
517 # if !defined(__IBMC__) && !defined(__WATCOMC__) /* e.g. EMX */
520 unsigned short magic_number;
521 unsigned short padding[29];
525 #define E_MAGIC(x) (x).magic_number
526 #define EMAGIC 0x5A4D
527 #define E_LFANEW(x) (x).new_exe_offset
530 unsigned char magic_number[2];
531 unsigned char byte_order;
532 unsigned char word_order;
533 unsigned long exe_format_level;
536 unsigned long padding1[13];
537 unsigned long object_table_offset;
538 unsigned long object_count;
539 unsigned long padding2[31];
542 #define E32_MAGIC1(x) (x).magic_number[0]
543 #define E32MAGIC1 'L'
544 #define E32_MAGIC2(x) (x).magic_number[1]
545 #define E32MAGIC2 'X'
546 #define E32_BORDER(x) (x).byte_order
548 #define E32_WORDER(x) (x).word_order
550 #define E32_CPU(x) (x).cpu
552 #define E32_OBJTAB(x) (x).object_table_offset
553 #define E32_OBJCNT(x) (x).object_count
559 unsigned long pagemap;
560 unsigned long mapsize;
561 unsigned long reserved;
564 #define O32_FLAGS(x) (x).flags
565 #define OBJREAD 0x0001L
566 #define OBJWRITE 0x0002L
567 #define OBJINVALID 0x0080L
568 #define O32_SIZE(x) (x).size
569 #define O32_BASE(x) (x).base
571 # else /* IBM's compiler */
573 /* A kludge to get around what appears to be a header file bug */
575 # define WORD unsigned short
578 # define DWORD unsigned long
585 # endif /* __IBMC__ */
587 # define INCL_DOSEXCEPTIONS
588 # define INCL_DOSPROCESS
589 # define INCL_DOSERRORS
590 # define INCL_DOSMODULEMGR
591 # define INCL_DOSMEMMGR
595 /* Disable and enable signals during nontrivial allocations */
597 void GC_disable_signals(void)
601 DosEnterMustComplete(&nest);
602 if (nest != 1) ABORT("nested GC_disable_signals");
605 void GC_enable_signals(void)
609 DosExitMustComplete(&nest);
610 if (nest != 0) ABORT("GC_enable_signals");
616 # if !defined(PCR) && !defined(AMIGA) && !defined(MSWIN32) \
617 && !defined(MSWINCE) \
618 && !defined(MACOS) && !defined(DJGPP) && !defined(DOS4GW) \
619 && !defined(NOSYS) && !defined(ECOS)
622 /* Use the traditional BSD interface */
623 # define SIGSET_T int
624 # define SIG_DEL(set, signal) (set) &= ~(sigmask(signal))
625 # define SIG_FILL(set) (set) = 0x7fffffff
626 /* Setting the leading bit appears to provoke a bug in some */
627 /* longjmp implementations. Most systems appear not to have */
629 # define SIGSETMASK(old, new) (old) = sigsetmask(new)
632 /* Use POSIX/SYSV interface */
633 # define SIGSET_T sigset_t
634 # define SIG_DEL(set, signal) sigdelset(&(set), (signal))
635 # define SIG_FILL(set) sigfillset(&set)
636 # define SIGSETMASK(old, new) sigprocmask(SIG_SETMASK, &(new), &(old))
639 static GC_bool mask_initialized = FALSE;
641 static SIGSET_T new_mask;
643 static SIGSET_T old_mask;
645 static SIGSET_T dummy;
647 #if defined(GC_ASSERTIONS) && !defined(THREADS)
648 # define CHECK_SIGNALS
649 int GC_sig_disabled = 0;
652 void GC_disable_signals(void)
654 if (!mask_initialized) {
657 SIG_DEL(new_mask, SIGSEGV);
658 SIG_DEL(new_mask, SIGILL);
659 SIG_DEL(new_mask, SIGQUIT);
661 SIG_DEL(new_mask, SIGBUS);
664 SIG_DEL(new_mask, SIGIOT);
667 SIG_DEL(new_mask, SIGEMT);
670 SIG_DEL(new_mask, SIGTRAP);
672 mask_initialized = TRUE;
674 # ifdef CHECK_SIGNALS
675 if (GC_sig_disabled != 0) ABORT("Nested disables");
678 SIGSETMASK(old_mask,new_mask);
681 void GC_enable_signals(void)
683 # ifdef CHECK_SIGNALS
684 if (GC_sig_disabled != 1) ABORT("Unmatched enable");
687 SIGSETMASK(dummy,old_mask);
694 /* Ivan Demakov: simplest way (to me) */
696 void GC_disable_signals() { }
697 void GC_enable_signals() { }
700 /* Find the page size */
703 # if defined(MSWIN32) || defined(MSWINCE)
704 void GC_setpagesize(void)
706 GetSystemInfo(&GC_sysinfo);
707 GC_page_size = GC_sysinfo.dwPageSize;
711 # if defined(MPROTECT_VDB) || defined(PROC_VDB) || defined(USE_MMAP)
712 void GC_setpagesize(void)
714 GC_page_size = GETPAGESIZE();
717 /* It's acceptable to fake it. */
718 void GC_setpagesize(void)
720 GC_page_size = HBLKSIZE;
726 * Find the base of the stack.
727 * Used only in single-threaded environment.
728 * With threads, GC_mark_roots needs to know how to do this.
729 * Called with allocator lock held.
731 # if defined(MSWIN32) || defined(MSWINCE) || defined(CYGWIN32)
732 # define is_writable(prot) ((prot) == PAGE_READWRITE \
733 || (prot) == PAGE_WRITECOPY \
734 || (prot) == PAGE_EXECUTE_READWRITE \
735 || (prot) == PAGE_EXECUTE_WRITECOPY)
736 /* Return the number of bytes that are writable starting at p. */
737 /* The pointer p is assumed to be page aligned. */
738 /* If base is not 0, *base becomes the beginning of the */
739 /* allocation region containing p. */
740 word GC_get_writable_length(ptr_t p, ptr_t *base)
742 MEMORY_BASIC_INFORMATION buf;
746 result = VirtualQuery(p, &buf, sizeof(buf));
747 if (result != sizeof(buf)) ABORT("Weird VirtualQuery result");
748 if (base != 0) *base = (ptr_t)(buf.AllocationBase);
749 protect = (buf.Protect & ~(PAGE_GUARD | PAGE_NOCACHE));
750 if (!is_writable(protect)) {
753 if (buf.State != MEM_COMMIT) return(0);
754 return(buf.RegionSize);
757 GC_API int GC_get_stack_base(struct GC_stack_base *sb)
760 ptr_t sp = (ptr_t)(&dummy);
761 ptr_t trunc_sp = (ptr_t)((word)sp & ~(GC_page_size - 1));
762 word size = GC_get_writable_length(trunc_sp, 0);
764 sb -> mem_base = trunc_sp + size;
768 #define HAVE_GET_STACK_BASE
770 /* This is always called from the main thread. */
771 ptr_t GC_get_main_stack_base(void)
773 struct GC_stack_base sb;
775 GC_get_stack_base(&sb);
776 return (ptr_t)sb.mem_base;
779 # endif /* MS Windows */
782 # include <kernel/OS.h>
783 ptr_t GC_get_main_stack_base(void){
785 get_thread_info(find_thread(NULL),&th);
793 ptr_t GC_get_main_stack_base(void)
798 if (DosGetInfoBlocks(&ptib, &ppib) != NO_ERROR) {
799 GC_err_printf("DosGetInfoBlocks failed\n");
800 ABORT("DosGetInfoBlocks failed\n");
802 return((ptr_t)(ptib -> tib_pstacklimit));
809 # include "AmigaOS.c"
813 # if defined(NEED_FIND_LIMIT) || defined(UNIX_LIKE)
815 typedef void (*handler)(int);
817 # if defined(SUNOS5SIGS) || defined(IRIX5) || defined(OSF1) \
818 || defined(HURD) || defined(NETBSD)
819 static struct sigaction old_segv_act;
820 # if defined(_sigargs) /* !Irix6.x */ || defined(HPUX) \
821 || defined(HURD) || defined(NETBSD)
822 static struct sigaction old_bus_act;
825 static handler old_segv_handler, old_bus_handler;
828 void GC_set_and_save_fault_handler(handler h)
830 # if defined(SUNOS5SIGS) || defined(IRIX5) \
831 || defined(OSF1) || defined(HURD) || defined(NETBSD)
832 struct sigaction act;
835 # if 0 /* Was necessary for Solaris 2.3 and very temporary */
837 act.sa_flags = SA_RESTART | SA_NODEFER;
839 act.sa_flags = SA_RESTART;
842 (void) sigemptyset(&act.sa_mask);
843 # ifdef GC_IRIX_THREADS
844 /* Older versions have a bug related to retrieving and */
845 /* and setting a handler at the same time. */
846 (void) sigaction(SIGSEGV, 0, &old_segv_act);
847 (void) sigaction(SIGSEGV, &act, 0);
849 (void) sigaction(SIGSEGV, &act, &old_segv_act);
850 # if defined(IRIX5) && defined(_sigargs) /* Irix 5.x, not 6.x */ \
851 || defined(HPUX) || defined(HURD) || defined(NETBSD)
852 /* Under Irix 5.x or HP/UX, we may get SIGBUS. */
853 /* Pthreads doesn't exist under Irix 5.x, so we */
854 /* don't have to worry in the threads case. */
855 (void) sigaction(SIGBUS, &act, &old_bus_act);
857 # endif /* GC_IRIX_THREADS */
859 old_segv_handler = signal(SIGSEGV, h);
861 old_bus_handler = signal(SIGBUS, h);
865 # endif /* NEED_FIND_LIMIT || UNIX_LIKE */
867 # if defined(NEED_FIND_LIMIT) || \
868 defined(USE_PROC_FOR_LIBRARIES) && defined(THREADS)
869 /* Some tools to implement HEURISTIC2 */
870 # define MIN_PAGE_SIZE 256 /* Smallest conceivable page size, bytes */
873 void GC_fault_handler(int sig)
875 LONGJMP(GC_jmp_buf, 1);
878 void GC_setup_temporary_fault_handler(void)
880 /* Handler is process-wide, so this should only happen in */
881 /* one thread at a time. */
882 GC_ASSERT(I_HOLD_LOCK());
883 GC_set_and_save_fault_handler(GC_fault_handler);
886 void GC_reset_fault_handler(void)
888 # if defined(SUNOS5SIGS) || defined(IRIX5) \
889 || defined(OSF1) || defined(HURD) || defined(NETBSD)
890 (void) sigaction(SIGSEGV, &old_segv_act, 0);
891 # if defined(IRIX5) && defined(_sigargs) /* Irix 5.x, not 6.x */ \
892 || defined(HPUX) || defined(HURD) || defined(NETBSD)
893 (void) sigaction(SIGBUS, &old_bus_act, 0);
896 (void) signal(SIGSEGV, old_segv_handler);
898 (void) signal(SIGBUS, old_bus_handler);
903 /* Return the first nonaddressible location > p (up) or */
904 /* the smallest location q s.t. [q,p) is addressable (!up). */
905 /* We assume that p (up) or p-1 (!up) is addressable. */
906 /* Requires allocation lock. */
907 ptr_t GC_find_limit_with_bound(ptr_t p, GC_bool up, ptr_t bound)
909 static volatile ptr_t result;
910 /* Safer if static, since otherwise it may not be */
911 /* preserved across the longjmp. Can safely be */
912 /* static since it's only called with the */
913 /* allocation lock held. */
915 GC_ASSERT(I_HOLD_LOCK());
916 GC_setup_temporary_fault_handler();
917 if (SETJMP(GC_jmp_buf) == 0) {
918 result = (ptr_t)(((word)(p))
919 & ~(MIN_PAGE_SIZE-1));
922 result += MIN_PAGE_SIZE;
923 if (result >= bound) return bound;
925 result -= MIN_PAGE_SIZE;
926 if (result <= bound) return bound;
928 GC_noop1((word)(*result));
931 GC_reset_fault_handler();
933 result += MIN_PAGE_SIZE;
938 ptr_t GC_find_limit(ptr_t p, GC_bool up)
941 return GC_find_limit_with_bound(p, up, (ptr_t)(word)(-1));
943 return GC_find_limit_with_bound(p, up, 0);
948 #if defined(ECOS) || defined(NOSYS)
949 ptr_t GC_get_main_stack_base(void)
955 #ifdef HPUX_STACKBOTTOM
957 #include <sys/param.h>
958 #include <sys/pstat.h>
960 ptr_t GC_get_register_stack_base(void)
962 struct pst_vm_status vm_status;
965 while (pstat_getprocvm(&vm_status, sizeof(vm_status), 0, i++) == 1) {
966 if (vm_status.pst_type == PS_RSESTACK) {
967 return (ptr_t) vm_status.pst_vaddr;
971 /* old way to get the register stackbottom */
972 return (ptr_t)(((word)GC_stackbottom - BACKING_STORE_DISPLACEMENT - 1)
973 & ~(BACKING_STORE_ALIGNMENT - 1));
976 #endif /* HPUX_STACK_BOTTOM */
978 #ifdef LINUX_STACKBOTTOM
980 #include <sys/types.h>
981 #include <sys/stat.h>
983 # define STAT_SKIP 27 /* Number of fields preceding startstack */
984 /* field in /proc/self/stat */
986 #ifdef USE_LIBC_PRIVATES
987 # pragma weak __libc_stack_end
988 extern ptr_t __libc_stack_end;
992 # ifdef USE_LIBC_PRIVATES
993 # pragma weak __libc_ia64_register_backing_store_base
994 extern ptr_t __libc_ia64_register_backing_store_base;
997 ptr_t GC_get_register_stack_base(void)
1001 # ifdef USE_LIBC_PRIVATES
1002 if (0 != &__libc_ia64_register_backing_store_base
1003 && 0 != __libc_ia64_register_backing_store_base) {
1004 /* Glibc 2.2.4 has a bug such that for dynamically linked */
1005 /* executables __libc_ia64_register_backing_store_base is */
1006 /* defined but uninitialized during constructor calls. */
1007 /* Hence we check for both nonzero address and value. */
1008 return __libc_ia64_register_backing_store_base;
1011 result = backing_store_base_from_proc();
1013 result = GC_find_limit(GC_save_regs_in_stack(), FALSE);
1014 /* Now seems to work better than constant displacement */
1015 /* heuristic used in 6.X versions. The latter seems to */
1016 /* fail for 2.6 kernels. */
1022 ptr_t GC_linux_stack_base(void)
1024 /* We read the stack base value from /proc/self/stat. We do this */
1025 /* using direct I/O system calls in order to avoid calling malloc */
1026 /* in case REDIRECT_MALLOC is defined. */
1027 # define STAT_BUF_SIZE 4096
1028 # define STAT_READ read
1029 /* Should probably call the real read, if read is wrapped. */
1030 char stat_buf[STAT_BUF_SIZE];
1034 size_t i, buf_offset = 0;
1036 /* First try the easy way. This should work for glibc 2.2 */
1037 /* This fails in a prelinked ("prelink" command) executable */
1038 /* since the correct value of __libc_stack_end never */
1039 /* becomes visible to us. The second test works around */
1041 # ifdef USE_LIBC_PRIVATES
1042 if (0 != &__libc_stack_end && 0 != __libc_stack_end ) {
1044 /* Some versions of glibc set the address 16 bytes too */
1045 /* low while the initialization code is running. */
1046 if (((word)__libc_stack_end & 0xfff) + 0x10 < 0x1000) {
1047 return __libc_stack_end + 0x10;
1048 } /* Otherwise it's not safe to add 16 bytes and we fall */
1049 /* back to using /proc. */
1050 # elif defined(SPARC)
1051 /* Older versions of glibc for 64-bit Sparc do not set
1052 * this variable correctly, it gets set to either zero
1055 if (__libc_stack_end != (ptr_t) (unsigned long)0x1)
1056 return __libc_stack_end;
1058 return __libc_stack_end;
1062 f = open("/proc/self/stat", O_RDONLY);
1063 if (f < 0 || STAT_READ(f, stat_buf, STAT_BUF_SIZE) < 2 * STAT_SKIP) {
1064 ABORT("Couldn't read /proc/self/stat");
1066 c = stat_buf[buf_offset++];
1067 /* Skip the required number of fields. This number is hopefully */
1068 /* constant across all Linux implementations. */
1069 for (i = 0; i < STAT_SKIP; ++i) {
1070 while (isspace(c)) c = stat_buf[buf_offset++];
1071 while (!isspace(c)) c = stat_buf[buf_offset++];
1073 while (isspace(c)) c = stat_buf[buf_offset++];
1074 while (isdigit(c)) {
1077 c = stat_buf[buf_offset++];
1080 if (result < 0x100000) ABORT("Absurd stack bottom value");
1081 return (ptr_t)result;
1084 #endif /* LINUX_STACKBOTTOM */
1086 #ifdef FREEBSD_STACKBOTTOM
1088 /* This uses an undocumented sysctl call, but at least one expert */
1089 /* believes it will stay. */
1092 #include <sys/types.h>
1093 #include <sys/sysctl.h>
1095 ptr_t GC_freebsd_stack_base(void)
1097 int nm[2] = {CTL_KERN, KERN_USRSTACK};
1099 size_t len = sizeof(ptr_t);
1100 int r = sysctl(nm, 2, &base, &len, NULL, 0);
1102 if (r) ABORT("Error getting stack base");
1107 #endif /* FREEBSD_STACKBOTTOM */
1109 #if !defined(BEOS) && !defined(AMIGA) && !defined(MSWIN32) \
1110 && !defined(MSWINCE) && !defined(OS2) && !defined(NOSYS) && !defined(ECOS) \
1111 && !defined(CYGWIN32)
1113 ptr_t GC_get_main_stack_base(void)
1115 # if defined(HEURISTIC1) || defined(HEURISTIC2)
1120 # define STACKBOTTOM_ALIGNMENT_M1 ((word)STACK_GRAN - 1)
1123 return(STACKBOTTOM);
1126 # ifdef STACK_GROWS_DOWN
1127 result = (ptr_t)((((word)(&dummy))
1128 + STACKBOTTOM_ALIGNMENT_M1)
1129 & ~STACKBOTTOM_ALIGNMENT_M1);
1131 result = (ptr_t)(((word)(&dummy))
1132 & ~STACKBOTTOM_ALIGNMENT_M1);
1134 # endif /* HEURISTIC1 */
1135 # ifdef LINUX_STACKBOTTOM
1136 result = GC_linux_stack_base();
1138 # ifdef FREEBSD_STACKBOTTOM
1139 result = GC_freebsd_stack_base();
1142 # ifdef STACK_GROWS_DOWN
1143 result = GC_find_limit((ptr_t)(&dummy), TRUE);
1144 # ifdef HEURISTIC2_LIMIT
1145 if (result > HEURISTIC2_LIMIT
1146 && (ptr_t)(&dummy) < HEURISTIC2_LIMIT) {
1147 result = HEURISTIC2_LIMIT;
1151 result = GC_find_limit((ptr_t)(&dummy), FALSE);
1152 # ifdef HEURISTIC2_LIMIT
1153 if (result < HEURISTIC2_LIMIT
1154 && (ptr_t)(&dummy) > HEURISTIC2_LIMIT) {
1155 result = HEURISTIC2_LIMIT;
1160 # endif /* HEURISTIC2 */
1161 # ifdef STACK_GROWS_DOWN
1162 if (result == 0) result = (ptr_t)(signed_word)(-sizeof(ptr_t));
1165 # endif /* STACKBOTTOM */
1168 # endif /* ! AMIGA, !OS 2, ! MS Windows, !BEOS, !NOSYS, !ECOS */
1170 #if defined(GC_LINUX_THREADS) && !defined(HAVE_GET_STACK_BASE)
1172 #include <pthread.h>
1175 ptr_t GC_greatest_stack_base_below(ptr_t bound);
1176 /* From pthread_support.c */
1179 int GC_get_stack_base(struct GC_stack_base *b)
1181 pthread_attr_t attr;
1184 if (pthread_getattr_np(pthread_self(), &attr) != 0) {
1185 WARN("pthread_getattr_np failed\n", 0);
1186 return GC_UNIMPLEMENTED;
1188 if (pthread_attr_getstack(&attr, &(b -> mem_base), &size) != 0) {
1189 ABORT("pthread_attr_getstack failed");
1191 # ifdef STACK_GROWS_DOWN
1192 b -> mem_base = (char *)(b -> mem_base) + size;
1195 /* We could try backing_store_base_from_proc, but that's safe */
1196 /* only if no mappings are being asynchronously created. */
1197 /* Subtracting the size from the stack base doesn't work for at */
1198 /* least the main thread. */
1201 ptr_t bsp = GC_save_regs_in_stack();
1202 ptr_t next_stack = GC_greatest_stack_base_below(bsp);
1203 if (0 == next_stack) {
1204 b -> reg_base = GC_find_limit(bsp, FALSE);
1206 /* Avoid walking backwards into preceding memory stack and */
1208 b -> reg_base = GC_find_limit_with_bound(bsp, FALSE, next_stack);
1216 #define HAVE_GET_STACK_BASE
1218 #endif /* GC_LINUX_THREADS */
1220 #ifndef HAVE_GET_STACK_BASE
1221 /* Retrieve stack base. */
1222 /* Using the GC_find_limit version is risky. */
1223 /* On IA64, for example, there is no guard page between the */
1224 /* stack of one thread and the register backing store of the */
1225 /* next. Thus this is likely to identify way too large a */
1226 /* "stack" and thus at least result in disastrous performance. */
1227 /* FIXME - Implement better strategies here. */
1228 int GC_get_stack_base(struct GC_stack_base *b)
1232 # ifdef NEED_FIND_LIMIT
1233 # ifdef STACK_GROWS_DOWN
1234 b -> mem_base = GC_find_limit((ptr_t)(&dummy), TRUE);
1236 b -> reg_base = GC_find_limit(GC_save_regs_in_stack(), FALSE);
1239 b -> mem_base = GC_find_limit(&dummy, FALSE);
1243 return GC_UNIMPLEMENTED;
1249 * Register static data segment(s) as roots.
1250 * If more data segments are added later then they need to be registered
1251 * add that point (as we do with SunOS dynamic loading),
1252 * or GC_mark_roots needs to check for them (as we do with PCR).
1253 * Called with allocator lock held.
1258 void GC_register_data_segments(void)
1262 HMODULE module_handle;
1263 # define PBUFSIZ 512
1264 UCHAR path[PBUFSIZ];
1266 struct exe_hdr hdrdos; /* MSDOS header. */
1267 struct e32_exe hdr386; /* Real header for my executable */
1268 struct o32_obj seg; /* Currrent segment */
1272 if (DosGetInfoBlocks(&ptib, &ppib) != NO_ERROR) {
1273 GC_err_printf("DosGetInfoBlocks failed\n");
1274 ABORT("DosGetInfoBlocks failed\n");
1276 module_handle = ppib -> pib_hmte;
1277 if (DosQueryModuleName(module_handle, PBUFSIZ, path) != NO_ERROR) {
1278 GC_err_printf("DosQueryModuleName failed\n");
1279 ABORT("DosGetInfoBlocks failed\n");
1281 myexefile = fopen(path, "rb");
1282 if (myexefile == 0) {
1283 GC_err_puts("Couldn't open executable ");
1284 GC_err_puts(path); GC_err_puts("\n");
1285 ABORT("Failed to open executable\n");
1287 if (fread((char *)(&hdrdos), 1, sizeof hdrdos, myexefile) < sizeof hdrdos) {
1288 GC_err_puts("Couldn't read MSDOS header from ");
1289 GC_err_puts(path); GC_err_puts("\n");
1290 ABORT("Couldn't read MSDOS header");
1292 if (E_MAGIC(hdrdos) != EMAGIC) {
1293 GC_err_puts("Executable has wrong DOS magic number: ");
1294 GC_err_puts(path); GC_err_puts("\n");
1295 ABORT("Bad DOS magic number");
1297 if (fseek(myexefile, E_LFANEW(hdrdos), SEEK_SET) != 0) {
1298 GC_err_puts("Seek to new header failed in ");
1299 GC_err_puts(path); GC_err_puts("\n");
1300 ABORT("Bad DOS magic number");
1302 if (fread((char *)(&hdr386), 1, sizeof hdr386, myexefile) < sizeof hdr386) {
1303 GC_err_puts("Couldn't read MSDOS header from ");
1304 GC_err_puts(path); GC_err_puts("\n");
1305 ABORT("Couldn't read OS/2 header");
1307 if (E32_MAGIC1(hdr386) != E32MAGIC1 || E32_MAGIC2(hdr386) != E32MAGIC2) {
1308 GC_err_puts("Executable has wrong OS/2 magic number:");
1309 GC_err_puts(path); GC_err_puts("\n");
1310 ABORT("Bad OS/2 magic number");
1312 if ( E32_BORDER(hdr386) != E32LEBO || E32_WORDER(hdr386) != E32LEWO) {
1313 GC_err_puts("Executable %s has wrong byte order: ");
1314 GC_err_puts(path); GC_err_puts("\n");
1315 ABORT("Bad byte order");
1317 if ( E32_CPU(hdr386) == E32CPU286) {
1318 GC_err_puts("GC can't handle 80286 executables: ");
1319 GC_err_puts(path); GC_err_puts("\n");
1322 if (fseek(myexefile, E_LFANEW(hdrdos) + E32_OBJTAB(hdr386),
1324 GC_err_puts("Seek to object table failed: ");
1325 GC_err_puts(path); GC_err_puts("\n");
1326 ABORT("Seek to object table failed");
1328 for (nsegs = E32_OBJCNT(hdr386); nsegs > 0; nsegs--) {
1330 if (fread((char *)(&seg), 1, sizeof seg, myexefile) < sizeof seg) {
1331 GC_err_puts("Couldn't read obj table entry from ");
1332 GC_err_puts(path); GC_err_puts("\n");
1333 ABORT("Couldn't read obj table entry");
1335 flags = O32_FLAGS(seg);
1336 if (!(flags & OBJWRITE)) continue;
1337 if (!(flags & OBJREAD)) continue;
1338 if (flags & OBJINVALID) {
1339 GC_err_printf("Object with invalid pages?\n");
1342 GC_add_roots_inner(O32_BASE(seg), O32_BASE(seg)+O32_SIZE(seg), FALSE);
1348 # if defined(MSWIN32) || defined(MSWINCE)
1351 /* Unfortunately, we have to handle win32s very differently from NT, */
1352 /* Since VirtualQuery has very different semantics. In particular, */
1353 /* under win32s a VirtualQuery call on an unmapped page returns an */
1354 /* invalid result. Under NT, GC_register_data_segments is a noop and */
1355 /* all real work is done by GC_register_dynamic_libraries. Under */
1356 /* win32s, we cannot find the data segments associated with dll's. */
1357 /* We register the main data segment here. */
1358 GC_bool GC_no_win32_dlls = FALSE;
1359 /* This used to be set for gcc, to avoid dealing with */
1360 /* the structured exception handling issues. But we now have */
1361 /* assembly code to do that right. */
1363 # if defined(GWW_VDB)
1365 # ifndef _BASETSD_H_
1366 typedef ULONG * PULONG_PTR;
1368 typedef UINT (WINAPI * GetWriteWatch_type)(
1369 DWORD, PVOID, SIZE_T, PVOID*, PULONG_PTR, PULONG);
1370 static GetWriteWatch_type GetWriteWatch_func;
1371 static DWORD GetWriteWatch_alloc_flag;
1373 # define GC_GWW_AVAILABLE() (GetWriteWatch_func != NULL)
1375 static void detect_GetWriteWatch(void)
1377 static GC_bool done;
1381 GetWriteWatch_func = (GetWriteWatch_type)
1382 GetProcAddress(GetModuleHandle("kernel32.dll"), "GetWriteWatch");
1383 if (GetWriteWatch_func != NULL) {
1384 /* Also check whether VirtualAlloc accepts MEM_WRITE_WATCH, */
1385 /* as some versions of kernel32.dll have one but not the */
1386 /* other, making the feature completely broken. */
1387 void * page = VirtualAlloc(NULL, GC_page_size,
1388 MEM_WRITE_WATCH | MEM_RESERVE,
1392 ULONG_PTR count = 16;
1394 /* Check that it actually works. In spite of some */
1395 /* documentation it actually seems to exist on W2K. */
1396 /* This test may be unnecessary, but ... */
1397 if (GetWriteWatch_func(WRITE_WATCH_FLAG_RESET,
1402 /* GetWriteWatch always fails. */
1403 GetWriteWatch_func = NULL;
1405 GetWriteWatch_alloc_flag = MEM_WRITE_WATCH;
1407 VirtualFree(page, GC_page_size, MEM_RELEASE);
1409 /* GetWriteWatch will be useless. */
1410 GetWriteWatch_func = NULL;
1413 if (GC_print_stats) {
1414 if (GetWriteWatch_func == NULL) {
1415 GC_log_printf("Did not find a usable GetWriteWatch()\n");
1417 GC_log_printf("Using GetWriteWatch()\n");
1423 # endif /* GWW_VDB */
1425 GC_bool GC_wnt = FALSE;
1426 /* This is a Windows NT derivative, i.e. NT, W2K, XP or later. */
1428 void GC_init_win32(void)
1431 /* If we're running under win32s, assume that no DLLs will be loaded */
1432 /* I doubt anyone still runs win32s, but ... */
1433 DWORD v = GetVersion();
1434 GC_wnt = !(v & 0x80000000);
1435 GC_no_win32_dlls |= ((!GC_wnt) && (v & 0xff) <= 3);
1438 /* Return the smallest address a such that VirtualQuery */
1439 /* returns correct results for all addresses between a and start. */
1440 /* Assumes VirtualQuery returns correct information for start. */
1441 ptr_t GC_least_described_address(ptr_t start)
1443 MEMORY_BASIC_INFORMATION buf;
1449 limit = GC_sysinfo.lpMinimumApplicationAddress;
1450 p = (ptr_t)((word)start & ~(GC_page_size - 1));
1452 q = (LPVOID)(p - GC_page_size);
1453 if ((ptr_t)q > (ptr_t)p /* underflow */ || q < limit) break;
1454 result = VirtualQuery(q, &buf, sizeof(buf));
1455 if (result != sizeof(buf) || buf.AllocationBase == 0) break;
1456 p = (ptr_t)(buf.AllocationBase);
1462 # ifndef REDIRECT_MALLOC
1463 /* We maintain a linked list of AllocationBase values that we know */
1464 /* correspond to malloc heap sections. Currently this is only called */
1465 /* during a GC. But there is some hope that for long running */
1466 /* programs we will eventually see most heap sections. */
1468 /* In the long run, it would be more reliable to occasionally walk */
1469 /* the malloc heap with HeapWalk on the default heap. But that */
1470 /* apparently works only for NT-based Windows. */
1472 /* In the long run, a better data structure would also be nice ... */
1473 struct GC_malloc_heap_list {
1474 void * allocation_base;
1475 struct GC_malloc_heap_list *next;
1476 } *GC_malloc_heap_l = 0;
1478 /* Is p the base of one of the malloc heap sections we already know */
1480 GC_bool GC_is_malloc_heap_base(ptr_t p)
1482 struct GC_malloc_heap_list *q = GC_malloc_heap_l;
1485 if (q -> allocation_base == p) return TRUE;
1491 void *GC_get_allocation_base(void *p)
1493 MEMORY_BASIC_INFORMATION buf;
1494 size_t result = VirtualQuery(p, &buf, sizeof(buf));
1495 if (result != sizeof(buf)) {
1496 ABORT("Weird VirtualQuery result");
1498 return buf.AllocationBase;
1501 size_t GC_max_root_size = 100000; /* Appr. largest root size. */
1503 void GC_add_current_malloc_heap()
1505 struct GC_malloc_heap_list *new_l =
1506 malloc(sizeof(struct GC_malloc_heap_list));
1507 void * candidate = GC_get_allocation_base(new_l);
1509 if (new_l == 0) return;
1510 if (GC_is_malloc_heap_base(candidate)) {
1511 /* Try a little harder to find malloc heap. */
1512 size_t req_size = 10000;
1514 void *p = malloc(req_size);
1515 if (0 == p) { free(new_l); return; }
1516 candidate = GC_get_allocation_base(p);
1519 } while (GC_is_malloc_heap_base(candidate)
1520 && req_size < GC_max_root_size/10 && req_size < 500000);
1521 if (GC_is_malloc_heap_base(candidate)) {
1522 free(new_l); return;
1526 GC_log_printf("Found new system malloc AllocationBase at %p\n",
1528 new_l -> allocation_base = candidate;
1529 new_l -> next = GC_malloc_heap_l;
1530 GC_malloc_heap_l = new_l;
1532 # endif /* REDIRECT_MALLOC */
1534 /* Is p the start of either the malloc heap, or of one of our */
1535 /* heap sections? */
1536 GC_bool GC_is_heap_base (ptr_t p)
1541 # ifndef REDIRECT_MALLOC
1542 if (GC_root_size > GC_max_root_size) GC_max_root_size = GC_root_size;
1543 if (GC_is_malloc_heap_base(p)) return TRUE;
1545 for (i = 0; i < GC_n_heap_bases; i++) {
1546 if (GC_heap_bases[i] == p) return TRUE;
1552 void GC_register_root_section(ptr_t static_root)
1554 MEMORY_BASIC_INFORMATION buf;
1559 char * limit, * new_limit;
1561 if (!GC_no_win32_dlls) return;
1562 p = base = limit = GC_least_described_address(static_root);
1563 while (p < GC_sysinfo.lpMaximumApplicationAddress) {
1564 result = VirtualQuery(p, &buf, sizeof(buf));
1565 if (result != sizeof(buf) || buf.AllocationBase == 0
1566 || GC_is_heap_base(buf.AllocationBase)) break;
1567 new_limit = (char *)p + buf.RegionSize;
1568 protect = buf.Protect;
1569 if (buf.State == MEM_COMMIT
1570 && is_writable(protect)) {
1571 if ((char *)p == limit) {
1574 if (base != limit) GC_add_roots_inner(base, limit, FALSE);
1579 if (p > (LPVOID)new_limit /* overflow */) break;
1580 p = (LPVOID)new_limit;
1582 if (base != limit) GC_add_roots_inner(base, limit, FALSE);
1586 void GC_register_data_segments()
1590 GC_register_root_section((ptr_t)(&dummy));
1594 # else /* !OS2 && !Windows */
1596 # if (defined(SVR4) || defined(AUX) || defined(DGUX) \
1597 || (defined(LINUX) && defined(SPARC))) && !defined(PCR)
1598 ptr_t GC_SysVGetDataStart(size_t max_page_size, ptr_t etext_addr)
1600 word text_end = ((word)(etext_addr) + sizeof(word) - 1)
1601 & ~(sizeof(word) - 1);
1602 /* etext rounded to word boundary */
1603 word next_page = ((text_end + (word)max_page_size - 1)
1604 & ~((word)max_page_size - 1));
1605 word page_offset = (text_end & ((word)max_page_size - 1));
1606 volatile char * result = (char *)(next_page + page_offset);
1607 /* Note that this isnt equivalent to just adding */
1608 /* max_page_size to &etext if &etext is at a page boundary */
1610 GC_setup_temporary_fault_handler();
1611 if (SETJMP(GC_jmp_buf) == 0) {
1612 /* Try writing to the address. */
1614 GC_reset_fault_handler();
1616 GC_reset_fault_handler();
1617 /* We got here via a longjmp. The address is not readable. */
1618 /* This is known to happen under Solaris 2.4 + gcc, which place */
1619 /* string constants in the text segment, but after etext. */
1620 /* Use plan B. Note that we now know there is a gap between */
1621 /* text and data segments, so plan A bought us something. */
1622 result = (char *)GC_find_limit((ptr_t)(DATAEND), FALSE);
1624 return((ptr_t)result);
1628 # if defined(FREEBSD) && (defined(I386) || defined(X86_64) || defined(powerpc) || defined(__powerpc__)) && !defined(PCR)
1629 /* Its unclear whether this should be identical to the above, or */
1630 /* whether it should apply to non-X86 architectures. */
1631 /* For now we don't assume that there is always an empty page after */
1632 /* etext. But in some cases there actually seems to be slightly more. */
1633 /* This also deals with holes between read-only data and writable data. */
1634 ptr_t GC_FreeBSDGetDataStart(size_t max_page_size, ptr_t etext_addr)
1636 word text_end = ((word)(etext_addr) + sizeof(word) - 1)
1637 & ~(sizeof(word) - 1);
1638 /* etext rounded to word boundary */
1639 volatile word next_page = (text_end + (word)max_page_size - 1)
1640 & ~((word)max_page_size - 1);
1641 volatile ptr_t result = (ptr_t)text_end;
1642 GC_setup_temporary_fault_handler();
1643 if (SETJMP(GC_jmp_buf) == 0) {
1644 /* Try reading at the address. */
1645 /* This should happen before there is another thread. */
1646 for (; next_page < (word)(DATAEND); next_page += (word)max_page_size)
1647 *(volatile char *)next_page;
1648 GC_reset_fault_handler();
1650 GC_reset_fault_handler();
1651 /* As above, we go to plan B */
1652 result = GC_find_limit((ptr_t)(DATAEND), FALSE);
1662 # define GC_AMIGA_DS
1663 # include "AmigaOS.c"
1666 #else /* !OS2 && !Windows && !AMIGA */
1668 void GC_register_data_segments(void)
1670 # if !defined(PCR) && !defined(MACOS)
1671 # if defined(REDIRECT_MALLOC) && defined(GC_SOLARIS_THREADS)
1672 /* As of Solaris 2.3, the Solaris threads implementation */
1673 /* allocates the data structure for the initial thread with */
1674 /* sbrk at process startup. It needs to be scanned, so that */
1675 /* we don't lose some malloc allocated data structures */
1676 /* hanging from it. We're on thin ice here ... */
1677 extern caddr_t sbrk();
1679 GC_add_roots_inner(DATASTART, (ptr_t)sbrk(0), FALSE);
1681 GC_add_roots_inner(DATASTART, (ptr_t)(DATAEND), FALSE);
1682 # if defined(DATASTART2)
1683 GC_add_roots_inner(DATASTART2, (ptr_t)(DATAEND2), FALSE);
1689 # if defined(THINK_C)
1690 extern void* GC_MacGetDataStart(void);
1691 /* globals begin above stack and end at a5. */
1692 GC_add_roots_inner((ptr_t)GC_MacGetDataStart(),
1693 (ptr_t)LMGetCurrentA5(), FALSE);
1695 # if defined(__MWERKS__)
1697 extern void* GC_MacGetDataStart(void);
1698 /* MATTHEW: Function to handle Far Globals (CW Pro 3) */
1699 # if __option(far_data)
1700 extern void* GC_MacGetDataEnd(void);
1702 /* globals begin above stack and end at a5. */
1703 GC_add_roots_inner((ptr_t)GC_MacGetDataStart(),
1704 (ptr_t)LMGetCurrentA5(), FALSE);
1705 /* MATTHEW: Handle Far Globals */
1706 # if __option(far_data)
1707 /* Far globals follow he QD globals: */
1708 GC_add_roots_inner((ptr_t)LMGetCurrentA5(),
1709 (ptr_t)GC_MacGetDataEnd(), FALSE);
1712 extern char __data_start__[], __data_end__[];
1713 GC_add_roots_inner((ptr_t)&__data_start__,
1714 (ptr_t)&__data_end__, FALSE);
1715 # endif /* __POWERPC__ */
1716 # endif /* __MWERKS__ */
1717 # endif /* !THINK_C */
1721 /* Dynamic libraries are added at every collection, since they may */
1725 # endif /* ! AMIGA */
1726 # endif /* ! MSWIN32 && ! MSWINCE*/
1730 * Auxiliary routines for obtaining memory from OS.
1733 # if !defined(OS2) && !defined(PCR) && !defined(AMIGA) \
1734 && !defined(MSWIN32) && !defined(MSWINCE) \
1735 && !defined(MACOS) && !defined(DOS4GW) && !defined(NONSTOP)
1737 # define SBRK_ARG_T ptrdiff_t
1739 #if defined(MMAP_SUPPORTED)
1741 #ifdef USE_MMAP_FIXED
1742 # define GC_MMAP_FLAGS MAP_FIXED | MAP_PRIVATE
1743 /* Seems to yield better performance on Solaris 2, but can */
1744 /* be unreliable if something is already mapped at the address. */
1746 # define GC_MMAP_FLAGS MAP_PRIVATE
1749 #ifdef USE_MMAP_ANON
1751 # if defined(MAP_ANONYMOUS)
1752 # define OPT_MAP_ANON MAP_ANONYMOUS
1754 # define OPT_MAP_ANON MAP_ANON
1758 # define OPT_MAP_ANON 0
1762 # define HEAP_START 0
1765 ptr_t GC_unix_mmap_get_mem(word bytes)
1768 static ptr_t last_addr = HEAP_START;
1770 # ifndef USE_MMAP_ANON
1771 static GC_bool initialized = FALSE;
1774 zero_fd = open("/dev/zero", O_RDONLY);
1775 fcntl(zero_fd, F_SETFD, FD_CLOEXEC);
1780 if (bytes & (GC_page_size -1)) ABORT("Bad GET_MEM arg");
1781 result = mmap(last_addr, bytes, PROT_READ | PROT_WRITE | OPT_PROT_EXEC,
1782 GC_MMAP_FLAGS | OPT_MAP_ANON, zero_fd, 0/* offset */);
1783 if (result == MAP_FAILED) return(0);
1784 last_addr = (ptr_t)result + bytes + GC_page_size - 1;
1785 last_addr = (ptr_t)((word)last_addr & ~(GC_page_size - 1));
1786 # if !defined(LINUX)
1787 if (last_addr == 0) {
1788 /* Oops. We got the end of the address space. This isn't */
1789 /* usable by arbitrary C code, since one-past-end pointers */
1790 /* don't work, so we discard it and try again. */
1791 munmap(result, (size_t)(-GC_page_size) - (size_t)result);
1792 /* Leave last page mapped, so we can't repeat. */
1793 return GC_unix_mmap_get_mem(bytes);
1796 GC_ASSERT(last_addr != 0);
1798 return((ptr_t)result);
1801 # endif /* MMAP_SUPPORTED */
1803 #if defined(USE_MMAP)
1805 ptr_t GC_unix_get_mem(word bytes)
1807 return GC_unix_mmap_get_mem(bytes);
1810 #else /* Not USE_MMAP */
1812 ptr_t GC_unix_sbrk_get_mem(word bytes)
1816 /* Bare sbrk isn't thread safe. Play by malloc rules. */
1817 /* The equivalent may be needed on other systems as well. */
1821 ptr_t cur_brk = (ptr_t)sbrk(0);
1822 SBRK_ARG_T lsbs = (word)cur_brk & (GC_page_size-1);
1824 if ((SBRK_ARG_T)bytes < 0) {
1825 result = 0; /* too big */
1829 if((ptr_t)sbrk(GC_page_size - lsbs) == (ptr_t)(-1)) {
1834 # ifdef ADD_HEAP_GUARD_PAGES
1835 /* This is useful for catching severe memory overwrite problems that */
1836 /* span heap sections. It shouldn't otherwise be turned on. */
1838 ptr_t guard = (ptr_t)sbrk((SBRK_ARG_T)GC_page_size);
1839 if (mprotect(guard, GC_page_size, PROT_NONE) != 0)
1840 ABORT("ADD_HEAP_GUARD_PAGES: mprotect failed");
1842 # endif /* ADD_HEAP_GUARD_PAGES */
1843 result = (ptr_t)sbrk((SBRK_ARG_T)bytes);
1844 if (result == (ptr_t)(-1)) result = 0;
1853 #if defined(MMAP_SUPPORTED)
1855 /* By default, we try both sbrk and mmap, in that order. */
1856 ptr_t GC_unix_get_mem(word bytes)
1858 static GC_bool sbrk_failed = FALSE;
1861 if (!sbrk_failed) result = GC_unix_sbrk_get_mem(bytes);
1864 result = GC_unix_mmap_get_mem(bytes);
1867 /* Try sbrk again, in case sbrk memory became available. */
1868 result = GC_unix_sbrk_get_mem(bytes);
1873 #else /* !MMAP_SUPPORTED */
1875 ptr_t GC_unix_get_mem(word bytes)
1877 return GC_unix_sbrk_get_mem(bytes);
1882 #endif /* Not USE_MMAP */
1888 void * os2_alloc(size_t bytes)
1892 if (DosAllocMem(&result, bytes, PAG_EXECUTE | PAG_READ |
1893 PAG_WRITE | PAG_COMMIT)
1897 if (result == 0) return(os2_alloc(bytes));
1904 # if defined(MSWIN32) || defined(MSWINCE)
1905 SYSTEM_INFO GC_sysinfo;
1910 # ifdef USE_GLOBAL_ALLOC
1911 # define GLOBAL_ALLOC_TEST 1
1913 # define GLOBAL_ALLOC_TEST GC_no_win32_dlls
1916 word GC_n_heap_bases = 0;
1918 word GC_mem_top_down = 0; /* Change to MEM_TOP_DOWN for better 64-bit */
1919 /* testing. Otherwise all addresses tend to */
1920 /* end up in first 4GB, hiding bugs. */
1922 ptr_t GC_win32_get_mem(word bytes)
1926 if (GLOBAL_ALLOC_TEST) {
1927 /* VirtualAlloc doesn't like PAGE_EXECUTE_READWRITE. */
1928 /* There are also unconfirmed rumors of other */
1929 /* problems, so we dodge the issue. */
1930 result = (ptr_t) GlobalAlloc(0, bytes + HBLKSIZE);
1931 result = (ptr_t)(((word)result + HBLKSIZE - 1) & ~(HBLKSIZE-1));
1933 /* VirtualProtect only works on regions returned by a */
1934 /* single VirtualAlloc call. Thus we allocate one */
1935 /* extra page, which will prevent merging of blocks */
1936 /* in separate regions, and eliminate any temptation */
1937 /* to call VirtualProtect on a range spanning regions. */
1938 /* This wastes a small amount of memory, and risks */
1939 /* increased fragmentation. But better alternatives */
1940 /* would require effort. */
1941 /* Pass the MEM_WRITE_WATCH only if GetWriteWatch-based */
1942 /* VDBs are enabled and the GetWriteWatch function is */
1943 /* available. Otherwise we waste resources or possibly */
1944 /* cause VirtualAlloc to fail (observed in Windows 2000 */
1946 result = (ptr_t) VirtualAlloc(NULL, bytes + 1,
1948 GetWriteWatch_alloc_flag |
1950 MEM_COMMIT | MEM_RESERVE
1952 PAGE_EXECUTE_READWRITE);
1954 if (HBLKDISPL(result) != 0) ABORT("Bad VirtualAlloc result");
1955 /* If I read the documentation correctly, this can */
1956 /* only happen if HBLKSIZE > 64k or not a power of 2. */
1957 if (GC_n_heap_bases >= MAX_HEAP_SECTS) ABORT("Too many heap sections");
1958 if (0 != result) GC_heap_bases[GC_n_heap_bases++] = result;
1962 void GC_win32_free_heap(void)
1964 if (GC_no_win32_dlls) {
1965 while (GC_n_heap_bases > 0) {
1966 GlobalFree (GC_heap_bases[--GC_n_heap_bases]);
1967 GC_heap_bases[GC_n_heap_bases] = 0;
1974 # define GC_AMIGA_AM
1975 # include "AmigaOS.c"
1981 word GC_n_heap_bases = 0;
1983 ptr_t GC_wince_get_mem(word bytes)
1988 /* Round up allocation size to multiple of page size */
1989 bytes = (bytes + GC_page_size-1) & ~(GC_page_size-1);
1991 /* Try to find reserved, uncommitted pages */
1992 for (i = 0; i < GC_n_heap_bases; i++) {
1993 if (((word)(-(signed_word)GC_heap_lengths[i])
1994 & (GC_sysinfo.dwAllocationGranularity-1))
1996 result = GC_heap_bases[i] + GC_heap_lengths[i];
2001 if (i == GC_n_heap_bases) {
2002 /* Reserve more pages */
2003 word res_bytes = (bytes + GC_sysinfo.dwAllocationGranularity-1)
2004 & ~(GC_sysinfo.dwAllocationGranularity-1);
2005 /* If we ever support MPROTECT_VDB here, we will probably need to */
2006 /* ensure that res_bytes is strictly > bytes, so that VirtualProtect */
2007 /* never spans regions. It seems to be OK for a VirtualFree */
2008 /* argument to span regions, so we should be OK for now. */
2009 result = (ptr_t) VirtualAlloc(NULL, res_bytes,
2010 MEM_RESERVE | MEM_TOP_DOWN,
2011 PAGE_EXECUTE_READWRITE);
2012 if (HBLKDISPL(result) != 0) ABORT("Bad VirtualAlloc result");
2013 /* If I read the documentation correctly, this can */
2014 /* only happen if HBLKSIZE > 64k or not a power of 2. */
2015 if (GC_n_heap_bases >= MAX_HEAP_SECTS) ABORT("Too many heap sections");
2016 GC_heap_bases[GC_n_heap_bases] = result;
2017 GC_heap_lengths[GC_n_heap_bases] = 0;
2022 result = (ptr_t) VirtualAlloc(result, bytes,
2024 PAGE_EXECUTE_READWRITE);
2025 if (result != NULL) {
2026 if (HBLKDISPL(result) != 0) ABORT("Bad VirtualAlloc result");
2027 GC_heap_lengths[i] += bytes;
2036 /* For now, this only works on Win32/WinCE and some Unix-like */
2037 /* systems. If you have something else, don't define */
2039 /* We assume ANSI C to support this feature. */
2041 #if !defined(MSWIN32) && !defined(MSWINCE)
2044 #include <sys/mman.h>
2045 #include <sys/stat.h>
2046 #include <sys/types.h>
2050 /* Compute a page aligned starting address for the unmap */
2051 /* operation on a block of size bytes starting at start. */
2052 /* Return 0 if the block is too small to make this feasible. */
2053 ptr_t GC_unmap_start(ptr_t start, size_t bytes)
2055 ptr_t result = start;
2056 /* Round start to next page boundary. */
2057 result += GC_page_size - 1;
2058 result = (ptr_t)((word)result & ~(GC_page_size - 1));
2059 if (result + GC_page_size > start + bytes) return 0;
2063 /* Compute end address for an unmap operation on the indicated */
2065 ptr_t GC_unmap_end(ptr_t start, size_t bytes)
2067 ptr_t end_addr = start + bytes;
2068 end_addr = (ptr_t)((word)end_addr & ~(GC_page_size - 1));
2072 /* Under Win32/WinCE we commit (map) and decommit (unmap) */
2073 /* memory using VirtualAlloc and VirtualFree. These functions */
2074 /* work on individual allocations of virtual memory, made */
2075 /* previously using VirtualAlloc with the MEM_RESERVE flag. */
2076 /* The ranges we need to (de)commit may span several of these */
2077 /* allocations; therefore we use VirtualQuery to check */
2078 /* allocation lengths, and split up the range as necessary. */
2080 /* We assume that GC_remap is called on exactly the same range */
2081 /* as a previous call to GC_unmap. It is safe to consistently */
2082 /* round the endpoints in both places. */
2083 void GC_unmap(ptr_t start, size_t bytes)
2085 ptr_t start_addr = GC_unmap_start(start, bytes);
2086 ptr_t end_addr = GC_unmap_end(start, bytes);
2087 word len = end_addr - start_addr;
2088 if (0 == start_addr) return;
2089 # if defined(MSWIN32) || defined(MSWINCE)
2091 MEMORY_BASIC_INFORMATION mem_info;
2093 if (VirtualQuery(start_addr, &mem_info, sizeof(mem_info))
2094 != sizeof(mem_info))
2095 ABORT("Weird VirtualQuery result");
2096 free_len = (len < mem_info.RegionSize) ? len : mem_info.RegionSize;
2097 if (!VirtualFree(start_addr, free_len, MEM_DECOMMIT))
2098 ABORT("VirtualFree failed");
2099 GC_unmapped_bytes += free_len;
2100 start_addr += free_len;
2104 /* We immediately remap it to prevent an intervening mmap from */
2105 /* accidentally grabbing the same address space. */
2108 result = mmap(start_addr, len, PROT_NONE,
2109 MAP_PRIVATE | MAP_FIXED | OPT_MAP_ANON,
2110 zero_fd, 0/* offset */);
2111 if (result != (void *)start_addr) ABORT("mmap(...PROT_NONE...) failed");
2113 GC_unmapped_bytes += len;
2118 void GC_remap(ptr_t start, size_t bytes)
2120 ptr_t start_addr = GC_unmap_start(start, bytes);
2121 ptr_t end_addr = GC_unmap_end(start, bytes);
2122 word len = end_addr - start_addr;
2124 # if defined(MSWIN32) || defined(MSWINCE)
2127 if (0 == start_addr) return;
2129 MEMORY_BASIC_INFORMATION mem_info;
2131 if (VirtualQuery(start_addr, &mem_info, sizeof(mem_info))
2132 != sizeof(mem_info))
2133 ABORT("Weird VirtualQuery result");
2134 alloc_len = (len < mem_info.RegionSize) ? len : mem_info.RegionSize;
2135 result = VirtualAlloc(start_addr, alloc_len,
2137 PAGE_EXECUTE_READWRITE);
2138 if (result != start_addr) {
2139 ABORT("VirtualAlloc remapping failed");
2141 GC_unmapped_bytes -= alloc_len;
2142 start_addr += alloc_len;
2146 /* It was already remapped with PROT_NONE. */
2149 if (0 == start_addr) return;
2150 result = mprotect(start_addr, len,
2151 PROT_READ | PROT_WRITE | OPT_PROT_EXEC);
2154 "Mprotect failed at %p (length %ld) with errno %d\n",
2155 start_addr, (unsigned long)len, errno);
2156 ABORT("Mprotect remapping failed");
2158 GC_unmapped_bytes -= len;
2162 /* Two adjacent blocks have already been unmapped and are about to */
2163 /* be merged. Unmap the whole block. This typically requires */
2164 /* that we unmap a small section in the middle that was not previously */
2165 /* unmapped due to alignment constraints. */
2166 void GC_unmap_gap(ptr_t start1, size_t bytes1, ptr_t start2, size_t bytes2)
2168 ptr_t start1_addr = GC_unmap_start(start1, bytes1);
2169 ptr_t end1_addr = GC_unmap_end(start1, bytes1);
2170 ptr_t start2_addr = GC_unmap_start(start2, bytes2);
2171 ptr_t end2_addr = GC_unmap_end(start2, bytes2);
2172 ptr_t start_addr = end1_addr;
2173 ptr_t end_addr = start2_addr;
2175 GC_ASSERT(start1 + bytes1 == start2);
2176 if (0 == start1_addr) start_addr = GC_unmap_start(start1, bytes1 + bytes2);
2177 if (0 == start2_addr) end_addr = GC_unmap_end(start1, bytes1 + bytes2);
2178 if (0 == start_addr) return;
2179 len = end_addr - start_addr;
2180 # if defined(MSWIN32) || defined(MSWINCE)
2182 MEMORY_BASIC_INFORMATION mem_info;
2184 if (VirtualQuery(start_addr, &mem_info, sizeof(mem_info))
2185 != sizeof(mem_info))
2186 ABORT("Weird VirtualQuery result");
2187 free_len = (len < mem_info.RegionSize) ? len : mem_info.RegionSize;
2188 if (!VirtualFree(start_addr, free_len, MEM_DECOMMIT))
2189 ABORT("VirtualFree failed");
2190 GC_unmapped_bytes += free_len;
2191 start_addr += free_len;
2195 if (len != 0 && munmap(start_addr, len) != 0) ABORT("munmap failed");
2196 GC_unmapped_bytes += len;
2200 #endif /* USE_MUNMAP */
2202 /* Routine for pushing any additional roots. In THREADS */
2203 /* environment, this is also responsible for marking from */
2204 /* thread stacks. */
2206 void (*GC_push_other_roots)(void) = 0;
2210 PCR_ERes GC_push_thread_stack(PCR_Th_T *t, PCR_Any dummy)
2212 struct PCR_ThCtl_TInfoRep info;
2215 info.ti_stkLow = info.ti_stkHi = 0;
2216 result = PCR_ThCtl_GetInfo(t, &info);
2217 GC_push_all_stack((ptr_t)(info.ti_stkLow), (ptr_t)(info.ti_stkHi));
2221 /* Push the contents of an old object. We treat this as stack */
2222 /* data only becasue that makes it robust against mark stack */
2224 PCR_ERes GC_push_old_obj(void *p, size_t size, PCR_Any data)
2226 GC_push_all_stack((ptr_t)p, (ptr_t)p + size);
2227 return(PCR_ERes_okay);
2231 void GC_default_push_other_roots(void)
2233 /* Traverse data allocated by previous memory managers. */
2235 extern struct PCR_MM_ProcsRep * GC_old_allocator;
2237 if ((*(GC_old_allocator->mmp_enumerate))(PCR_Bool_false,
2240 ABORT("Old object enumeration failed");
2243 /* Traverse all thread stacks. */
2245 PCR_ThCtl_ApplyToAllOtherThreads(GC_push_thread_stack,0))
2246 || PCR_ERes_IsErr(GC_push_thread_stack(PCR_Th_CurrThread(), 0))) {
2247 ABORT("Thread stack marking failed\n");
2254 # if defined(GC_PTHREADS) || defined(GC_WIN32_THREADS)
2256 extern void GC_push_all_stacks(void);
2258 void GC_default_push_other_roots(void)
2260 GC_push_all_stacks();
2263 # endif /* GC_WIN32_THREADS || GC_PTHREADS */
2265 void (*GC_push_other_roots)(void) = GC_default_push_other_roots;
2267 #endif /* THREADS */
2270 * Routines for accessing dirty bits on virtual pages.
2271 * There are six ways to maintain this information:
2272 * DEFAULT_VDB: A simple dummy implementation that treats every page
2273 * as possibly dirty. This makes incremental collection
2274 * useless, but the implementation is still correct.
2275 * MANUAL_VDB: Stacks and static data are always considered dirty.
2276 * Heap pages are considered dirty if GC_dirty(p) has been
2277 * called on some pointer p pointing to somewhere inside
2278 * an object on that page. A GC_dirty() call on a large
2279 * object directly dirties only a single page, but for
2280 * MANUAL_VDB we are careful to treat an object with a dirty
2281 * page as completely dirty.
2282 * In order to avoid races, an object must be marked dirty
2283 * after it is written, and a reference to the object
2284 * must be kept on a stack or in a register in the interim.
2285 * With threads enabled, an object directly reachable from the
2286 * stack at the time of a collection is treated as dirty.
2287 * In single-threaded mode, it suffices to ensure that no
2288 * collection can take place between the pointer assignment
2289 * and the GC_dirty() call.
2290 * PCR_VDB: Use PPCRs virtual dirty bit facility.
2291 * PROC_VDB: Use the /proc facility for reading dirty bits. Only
2292 * works under some SVR4 variants. Even then, it may be
2293 * too slow to be entirely satisfactory. Requires reading
2294 * dirty bits for entire address space. Implementations tend
2295 * to assume that the client is a (slow) debugger.
2296 * MPROTECT_VDB:Protect pages and then catch the faults to keep track of
2297 * dirtied pages. The implementation (and implementability)
2298 * is highly system dependent. This usually fails when system
2299 * calls write to a protected page. We prevent the read system
2300 * call from doing so. It is the clients responsibility to
2301 * make sure that other system calls are similarly protected
2302 * or write only to the stack.
2303 * GWW_VDB: Use the Win32 GetWriteWatch functions, if available, to
2304 * read dirty bits. In case it is not available (because we
2305 * are running on Windows 95, Windows 2000 or earlier),
2306 * MPROTECT_VDB may be defined as a fallback strategy.
2308 GC_bool GC_dirty_maintained = FALSE;
2310 #if defined(PROC_VDB) || defined(GWW_VDB)
2312 /* Add all pages in pht2 to pht1 */
2313 void GC_or_pages(page_hash_table pht1, page_hash_table pht2)
2317 for (i = 0; i < PHT_SIZE; i++) pht1[i] |= pht2[i];
2324 # define GC_GWW_BUF_LEN 1024
2325 static PVOID gww_buf[GC_GWW_BUF_LEN];
2327 # ifdef MPROTECT_VDB
2328 GC_bool GC_gww_dirty_init(void)
2330 detect_GetWriteWatch();
2331 return GC_GWW_AVAILABLE();
2334 void GC_dirty_init(void)
2336 detect_GetWriteWatch();
2337 GC_dirty_maintained = GC_GWW_AVAILABLE();
2341 # ifdef MPROTECT_VDB
2342 static void GC_gww_read_dirty(void)
2344 void GC_read_dirty(void)
2349 BZERO(GC_grungy_pages, sizeof(GC_grungy_pages));
2351 for (i = 0; i != GC_n_heap_sects; ++i) {
2355 PVOID * pages, * pages_end;
2359 count = GC_GWW_BUF_LEN;
2361 * GetWriteWatch is documented as returning non-zero when it fails,
2362 * but the documentation doesn't explicitly say why it would fail or
2363 * what its behaviour will be if it fails.
2364 * It does appear to fail, at least on recent W2K instances, if
2365 * the underlying memory was not allocated with the appropriate
2366 * flag. This is common if GC_enable_incremental is called
2367 * shortly after GC initialization. To avoid modifying the
2368 * interface, we silently work around such a failure, it it only
2369 * affects the initial (small) heap allocation.
2370 * If there are more dirty
2371 * pages than will fit in the buffer, this is not treated as a
2372 * failure; we must check the page count in the loop condition.
2373 * Since each partial call will reset the status of some
2374 * pages, this should eventually terminate even in the overflow
2377 if (GetWriteWatch_func(WRITE_WATCH_FLAG_RESET,
2378 GC_heap_sects[i].hs_start,
2379 GC_heap_sects[i].hs_bytes,
2383 static int warn_count = 0;
2385 struct hblk * start = (struct hblk *)GC_heap_sects[i].hs_start;
2386 static struct hblk *last_warned = 0;
2387 size_t nblocks = divHBLKSZ(GC_heap_sects[i].hs_bytes);
2389 if ( i != 0 && last_warned != start && warn_count++ < 5) {
2390 last_warned = start;
2392 "GC_gww_read_dirty unexpectedly failed at %ld: "
2393 "Falling back to marking all pages dirty\n", start);
2395 for (j = 0; j < nblocks; ++j) {
2396 word hash = PHT_HASH(start + j);
2397 set_pht_entry_from_index(GC_grungy_pages, hash);
2399 count = 1; /* Done with this section. */
2400 } else /* succeeded */{
2401 pages_end = pages + count;
2402 while (pages != pages_end) {
2403 struct hblk * h = (struct hblk *) *pages++;
2404 struct hblk * h_end = (struct hblk *) ((char *) h + page_size);
2406 set_pht_entry_from_index(GC_grungy_pages, PHT_HASH(h));
2407 while (++h < h_end);
2410 } while (count == GC_GWW_BUF_LEN);
2413 GC_or_pages(GC_written_pages, GC_grungy_pages);
2416 # ifdef MPROTECT_VDB
2417 static GC_bool GC_gww_page_was_dirty(struct hblk * h)
2419 GC_bool GC_page_was_dirty(struct hblk * h)
2422 return HDR(h) == 0 || get_pht_entry_from_index(GC_grungy_pages, PHT_HASH(h));
2425 # ifdef MPROTECT_VDB
2426 static GC_bool GC_gww_page_was_ever_dirty(struct hblk * h)
2428 GC_bool GC_page_was_ever_dirty(struct hblk * h)
2431 return HDR(h) == 0 || get_pht_entry_from_index(GC_written_pages, PHT_HASH(h));
2434 # ifndef MPROTECT_VDB
2435 void GC_remove_protection(struct hblk *h, word nblocks, GC_bool is_ptrfree)
2439 # endif /* GWW_VDB */
2443 /* All of the following assume the allocation lock is held, and */
2444 /* signals are disabled. */
2446 /* The client asserts that unallocated pages in the heap are never */
2449 /* Initialize virtual dirty bit implementation. */
2450 void GC_dirty_init(void)
2452 if (GC_print_stats == VERBOSE)
2453 GC_log_printf("Initializing DEFAULT_VDB...\n");
2454 GC_dirty_maintained = TRUE;
2457 /* Retrieve system dirty bits for heap to a local buffer. */
2458 /* Restore the systems notion of which pages are dirty. */
2459 void GC_read_dirty(void)
2462 /* Is the HBLKSIZE sized page at h marked dirty in the local buffer? */
2463 /* If the actual page size is different, this returns TRUE if any */
2464 /* of the pages overlapping h are dirty. This routine may err on the */
2465 /* side of labelling pages as dirty (and this implementation does). */
2467 GC_bool GC_page_was_dirty(struct hblk *h)
2473 * The following two routines are typically less crucial. They matter
2474 * most with large dynamic libraries, or if we can't accurately identify
2475 * stacks, e.g. under Solaris 2.X. Otherwise the following default
2476 * versions are adequate.
2479 /* Could any valid GC heap pointer ever have been written to this page? */
2481 GC_bool GC_page_was_ever_dirty(struct hblk *h)
2487 /* I) hints that [h, h+nblocks) is about to be written. */
2488 /* II) guarantees that protection is removed. */
2489 /* (I) may speed up some dirty bit implementations. */
2490 /* (II) may be essential if we need to ensure that */
2491 /* pointer-free system call buffers in the heap are */
2492 /* not protected. */
2494 void GC_remove_protection(struct hblk *h, word nblocks, GC_bool is_ptrfree)
2498 # endif /* DEFAULT_VDB */
2502 /* Initialize virtual dirty bit implementation. */
2503 void GC_dirty_init(void)
2505 if (GC_print_stats == VERBOSE)
2506 GC_log_printf("Initializing MANUAL_VDB...\n");
2507 /* GC_dirty_pages and GC_grungy_pages are already cleared. */
2508 GC_dirty_maintained = TRUE;
2511 /* Retrieve system dirty bits for heap to a local buffer. */
2512 /* Restore the systems notion of which pages are dirty. */
2513 void GC_read_dirty(void)
2515 BCOPY((word *)GC_dirty_pages, GC_grungy_pages,
2516 (sizeof GC_dirty_pages));
2517 BZERO((word *)GC_dirty_pages, (sizeof GC_dirty_pages));
2520 /* Is the HBLKSIZE sized page at h marked dirty in the local buffer? */
2521 /* If the actual page size is different, this returns TRUE if any */
2522 /* of the pages overlapping h are dirty. This routine may err on the */
2523 /* side of labelling pages as dirty (and this implementation does). */
2525 GC_bool GC_page_was_dirty(struct hblk *h)
2527 register word index;
2529 index = PHT_HASH(h);
2530 return(HDR(h) == 0 || get_pht_entry_from_index(GC_grungy_pages, index));
2533 /* Could any valid GC heap pointer ever have been written to this page? */
2535 GC_bool GC_page_was_ever_dirty(struct hblk *h)
2537 /* FIXME - implement me. */
2541 /* Mark the page containing p as dirty. Logically, this dirties the */
2542 /* entire object. */
2543 void GC_dirty(ptr_t p)
2545 word index = PHT_HASH(p);
2546 async_set_pht_entry_from_index(GC_dirty_pages, index);
2550 void GC_remove_protection(struct hblk *h, word nblocks, GC_bool is_ptrfree)
2554 # endif /* MANUAL_VDB */
2557 # ifdef MPROTECT_VDB
2560 * See DEFAULT_VDB for interface descriptions.
2564 * This implementation maintains dirty bits itself by catching write
2565 * faults and keeping track of them. We assume nobody else catches
2566 * SIGBUS or SIGSEGV. We assume no write faults occur in system calls.
2567 * This means that clients must ensure that system calls don't write
2568 * to the write-protected heap. Probably the best way to do this is to
2569 * ensure that system calls write at most to POINTERFREE objects in the
2570 * heap, and do even that only if we are on a platform on which those
2571 * are not protected. Another alternative is to wrap system calls
2572 * (see example for read below), but the current implementation holds
2574 * We assume the page size is a multiple of HBLKSIZE.
2575 * We prefer them to be the same. We avoid protecting POINTERFREE
2576 * objects only if they are the same.
2579 # if !defined(MSWIN32) && !defined(MSWINCE) && !defined(DARWIN)
2581 # include <sys/mman.h>
2582 # include <signal.h>
2583 # include <sys/syscall.h>
2585 # define PROTECT(addr, len) \
2586 if (mprotect((caddr_t)(addr), (size_t)(len), \
2587 PROT_READ | OPT_PROT_EXEC) < 0) { \
2588 ABORT("mprotect failed"); \
2590 # define UNPROTECT(addr, len) \
2591 if (mprotect((caddr_t)(addr), (size_t)(len), \
2592 PROT_WRITE | PROT_READ | OPT_PROT_EXEC ) < 0) { \
2593 ABORT("un-mprotect failed"); \
2599 /* Using vm_protect (mach syscall) over mprotect (BSD syscall) seems to
2600 decrease the likelihood of some of the problems described below. */
2601 #include <mach/vm_map.h>
2602 static mach_port_t GC_task_self;
2603 #define PROTECT(addr,len) \
2604 if(vm_protect(GC_task_self,(vm_address_t)(addr),(vm_size_t)(len), \
2605 FALSE,VM_PROT_READ) != KERN_SUCCESS) { \
2606 ABORT("vm_portect failed"); \
2608 #define UNPROTECT(addr,len) \
2609 if(vm_protect(GC_task_self,(vm_address_t)(addr),(vm_size_t)(len), \
2610 FALSE,VM_PROT_READ|VM_PROT_WRITE) != KERN_SUCCESS) { \
2611 ABORT("vm_portect failed"); \
2616 # include <signal.h>
2619 static DWORD protect_junk;
2620 # define PROTECT(addr, len) \
2621 if (!VirtualProtect((addr), (len), PAGE_EXECUTE_READ, \
2623 DWORD last_error = GetLastError(); \
2624 GC_printf("Last error code: %lx\n", last_error); \
2625 ABORT("VirtualProtect failed"); \
2627 # define UNPROTECT(addr, len) \
2628 if (!VirtualProtect((addr), (len), PAGE_EXECUTE_READWRITE, \
2630 ABORT("un-VirtualProtect failed"); \
2632 # endif /* !DARWIN */
2633 # endif /* MSWIN32 || MSWINCE || DARWIN */
2635 #if defined(MSWIN32)
2636 typedef LPTOP_LEVEL_EXCEPTION_FILTER SIG_HNDLR_PTR;
2638 # define SIG_DFL (LPTOP_LEVEL_EXCEPTION_FILTER) (-1)
2639 #elif defined(MSWINCE)
2640 typedef LONG (WINAPI *SIG_HNDLR_PTR)(struct _EXCEPTION_POINTERS *);
2642 # define SIG_DFL (SIG_HNDLR_PTR) (-1)
2643 #elif defined(DARWIN)
2644 typedef void (* SIG_HNDLR_PTR)();
2646 typedef void (* SIG_HNDLR_PTR)(int, siginfo_t *, void *);
2647 typedef void (* PLAIN_HNDLR_PTR)(int);
2650 #if defined(__GLIBC__)
2651 # if __GLIBC__ < 2 || __GLIBC__ == 2 && __GLIBC_MINOR__ < 2
2652 # error glibc too old?
2657 SIG_HNDLR_PTR GC_old_bus_handler;
2658 GC_bool GC_old_bus_handler_used_si;
2659 SIG_HNDLR_PTR GC_old_segv_handler;
2660 /* Also old MSWIN32 ACCESS_VIOLATION filter */
2661 GC_bool GC_old_segv_handler_used_si;
2662 #endif /* !DARWIN */
2664 #if defined(THREADS)
2665 /* We need to lock around the bitmap update in the write fault handler */
2666 /* in order to avoid the risk of losing a bit. We do this with a */
2667 /* test-and-set spin lock if we know how to do that. Otherwise we */
2668 /* check whether we are already in the handler and use the dumb but */
2669 /* safe fallback algorithm of setting all bits in the word. */
2670 /* Contention should be very rare, so we do the minimum to handle it */
2672 #ifdef AO_HAVE_test_and_set_acquire
2673 static volatile AO_TS_t fault_handler_lock = 0;
2674 void async_set_pht_entry_from_index(volatile page_hash_table db, size_t index) {
2675 while (AO_test_and_set_acquire(&fault_handler_lock) == AO_TS_SET) {}
2676 /* Could also revert to set_pht_entry_from_index_safe if initial */
2677 /* GC_test_and_set fails. */
2678 set_pht_entry_from_index(db, index);
2679 AO_CLEAR(&fault_handler_lock);
2681 #else /* !AO_have_test_and_set_acquire */
2682 # error No test_and_set operation: Introduces a race.
2683 /* THIS WOULD BE INCORRECT! */
2684 /* The dirty bit vector may be temporarily wrong, */
2685 /* just before we notice the conflict and correct it. We may end up */
2686 /* looking at it while it's wrong. But this requires contention */
2687 /* exactly when a GC is triggered, which seems far less likely to */
2688 /* fail than the old code, which had no reported failures. Thus we */
2689 /* leave it this way while we think of something better, or support */
2690 /* GC_test_and_set on the remaining platforms. */
2691 static volatile word currently_updating = 0;
2692 void async_set_pht_entry_from_index(volatile page_hash_table db, size_t index) {
2693 unsigned int update_dummy;
2694 currently_updating = (word)(&update_dummy);
2695 set_pht_entry_from_index(db, index);
2696 /* If we get contention in the 10 or so instruction window here, */
2697 /* and we get stopped by a GC between the two updates, we lose! */
2698 if (currently_updating != (word)(&update_dummy)) {
2699 set_pht_entry_from_index_safe(db, index);
2700 /* We claim that if two threads concurrently try to update the */
2701 /* dirty bit vector, the first one to execute UPDATE_START */
2702 /* will see it changed when UPDATE_END is executed. (Note that */
2703 /* &update_dummy must differ in two distinct threads.) It */
2704 /* will then execute set_pht_entry_from_index_safe, thus */
2705 /* returning us to a safe state, though not soon enough. */
2708 #endif /* !AO_HAVE_test_and_set_acquire */
2709 #else /* !THREADS */
2710 # define async_set_pht_entry_from_index(db, index) \
2711 set_pht_entry_from_index(db, index)
2712 #endif /* !THREADS */
2714 #if !defined(DARWIN)
2716 # if defined(FREEBSD)
2717 # define SIG_OK TRUE
2718 # define CODE_OK (code == BUS_PAGE_FAULT)
2719 # elif defined(OSF1)
2720 # define SIG_OK (sig == SIGSEGV)
2721 # define CODE_OK (code == 2 /* experimentally determined */)
2722 # elif defined(IRIX5)
2723 # define SIG_OK (sig == SIGSEGV)
2724 # define CODE_OK (code == EACCES)
2725 # elif defined(HURD)
2726 # define SIG_OK (sig == SIGBUS || sig == SIGSEGV)
2727 # define CODE_OK TRUE
2728 # elif defined(LINUX)
2729 # define SIG_OK (sig == SIGSEGV)
2730 # define CODE_OK TRUE
2731 /* Empirically c.trapno == 14, on IA32, but is that useful? */
2732 /* Should probably consider alignment issues on other */
2733 /* architectures. */
2734 # elif defined(HPUX)
2735 # define SIG_OK (sig == SIGSEGV || sig == SIGBUS)
2736 # define CODE_OK (si -> si_code == SEGV_ACCERR) \
2737 || (si -> si_code == BUS_ADRERR) \
2738 || (si -> si_code == BUS_UNKNOWN) \
2739 || (si -> si_code == SEGV_UNKNOWN) \
2740 || (si -> si_code == BUS_OBJERR)
2741 # elif defined(FREEBSD)
2742 # define SIG_OK (sig == SIGBUS)
2743 # define CODE_OK (si -> si_code == BUS_PAGE_FAULT)
2744 # elif defined(SUNOS5SIGS)
2745 # define SIG_OK (sig == SIGSEGV)
2746 # define CODE_OK (si -> si_code == SEGV_ACCERR)
2747 # elif defined(MSWIN32) || defined(MSWINCE)
2748 # define SIG_OK (exc_info -> ExceptionRecord -> ExceptionCode \
2749 == STATUS_ACCESS_VIOLATION)
2750 # define CODE_OK (exc_info -> ExceptionRecord -> ExceptionInformation[0] \
2751 == 1) /* Write fault */
2754 # if defined(MSWIN32) || defined(MSWINCE)
2755 LONG WINAPI GC_write_fault_handler(struct _EXCEPTION_POINTERS *exc_info)
2757 # include <ucontext.h>
2759 void GC_write_fault_handler(int sig, siginfo_t *si, void *raw_sc)
2760 # endif /* MSWIN32 || MSWINCE */
2762 # if !defined(MSWIN32) && !defined(MSWINCE)
2763 int code = si -> si_code; /* Ignore gcc unused var. warning. */
2764 ucontext_t * scp = (ucontext_t *)raw_sc;
2765 /* Ignore gcc unused var. warning. */
2766 char *addr = si -> si_addr;
2768 # if defined(MSWIN32) || defined(MSWINCE)
2769 char * addr = (char *) (exc_info -> ExceptionRecord
2770 -> ExceptionInformation[1]);
2771 # define sig SIGSEGV
2775 if (SIG_OK && CODE_OK) {
2776 register struct hblk * h =
2777 (struct hblk *)((word)addr & ~(GC_page_size-1));
2778 GC_bool in_allocd_block;
2781 /* Address is only within the correct physical page. */
2782 in_allocd_block = FALSE;
2783 for (i = 0; i < divHBLKSZ(GC_page_size); i++) {
2784 if (HDR(h+i) != 0) {
2785 in_allocd_block = TRUE;
2789 in_allocd_block = (HDR(addr) != 0);
2791 if (!in_allocd_block) {
2792 /* FIXME - We should make sure that we invoke the */
2793 /* old handler with the appropriate calling */
2794 /* sequence, which often depends on SA_SIGINFO. */
2796 /* Heap blocks now begin and end on page boundaries */
2797 SIG_HNDLR_PTR old_handler;
2800 if (sig == SIGSEGV) {
2801 old_handler = GC_old_segv_handler;
2802 used_si = GC_old_segv_handler_used_si;
2804 old_handler = GC_old_bus_handler;
2805 used_si = GC_old_bus_handler_used_si;
2807 if (old_handler == (SIG_HNDLR_PTR)SIG_DFL) {
2808 # if !defined(MSWIN32) && !defined(MSWINCE)
2809 GC_err_printf("Segfault at %p\n", addr);
2810 ABORT("Unexpected bus error or segmentation fault");
2812 return(EXCEPTION_CONTINUE_SEARCH);
2816 * FIXME: This code should probably check if the
2817 * old signal handler used the traditional style and
2818 * if so call it using that style.
2821 return((*old_handler)(exc_info));
2824 ((SIG_HNDLR_PTR)old_handler) (sig, si, raw_sc);
2826 /* FIXME: should pass nonstandard args as well. */
2827 ((PLAIN_HNDLR_PTR)old_handler) (sig);
2832 UNPROTECT(h, GC_page_size);
2833 /* We need to make sure that no collection occurs between */
2834 /* the UNPROTECT and the setting of the dirty bit. Otherwise */
2835 /* a write by a third thread might go unnoticed. Reversing */
2836 /* the order is just as bad, since we would end up unprotecting */
2837 /* a page in a GC cycle during which it's not marked. */
2838 /* Currently we do this by disabling the thread stopping */
2839 /* signals while this handler is running. An alternative might */
2840 /* be to record the fact that we're about to unprotect, or */
2841 /* have just unprotected a page in the GC's thread structure, */
2842 /* and then to have the thread stopping code set the dirty */
2843 /* flag, if necessary. */
2844 for (i = 0; i < divHBLKSZ(GC_page_size); i++) {
2845 size_t index = PHT_HASH(h+i);
2847 async_set_pht_entry_from_index(GC_dirty_pages, index);
2849 /* The write may not take place before dirty bits are read. */
2850 /* But then we'll fault again ... */
2851 # if defined(MSWIN32) || defined(MSWINCE)
2852 return(EXCEPTION_CONTINUE_EXECUTION);
2857 #if defined(MSWIN32) || defined(MSWINCE)
2858 return EXCEPTION_CONTINUE_SEARCH;
2860 GC_err_printf("Segfault at %p\n", addr);
2861 ABORT("Unexpected bus error or segmentation fault");
2864 #endif /* !DARWIN */
2867 * We hold the allocation lock. We expect block h to be written
2868 * shortly. Ensure that all pages containing any part of the n hblks
2869 * starting at h are no longer protected. If is_ptrfree is false,
2870 * also ensure that they will subsequently appear to be dirty.
2872 void GC_remove_protection(struct hblk *h, word nblocks, GC_bool is_ptrfree)
2874 struct hblk * h_trunc; /* Truncated to page boundary */
2875 struct hblk * h_end; /* Page boundary following block end */
2876 struct hblk * current;
2877 GC_bool found_clean;
2879 # if defined(GWW_VDB)
2880 if (GC_GWW_AVAILABLE()) return;
2882 if (!GC_dirty_maintained) return;
2883 h_trunc = (struct hblk *)((word)h & ~(GC_page_size-1));
2884 h_end = (struct hblk *)(((word)(h + nblocks) + GC_page_size-1)
2885 & ~(GC_page_size-1));
2886 found_clean = FALSE;
2887 for (current = h_trunc; current < h_end; ++current) {
2888 size_t index = PHT_HASH(current);
2890 if (!is_ptrfree || current < h || current >= h + nblocks) {
2891 async_set_pht_entry_from_index(GC_dirty_pages, index);
2894 UNPROTECT(h_trunc, (ptr_t)h_end - (ptr_t)h_trunc);
2897 #if !defined(DARWIN)
2898 void GC_dirty_init(void)
2900 # if !defined(MSWIN32) && !defined(MSWINCE)
2901 struct sigaction act, oldact;
2902 act.sa_flags = SA_RESTART | SA_SIGINFO;
2903 act.sa_sigaction = GC_write_fault_handler;
2904 (void)sigemptyset(&act.sa_mask);
2906 /* Arrange to postpone SIG_SUSPEND while we're in a write fault */
2907 /* handler. This effectively makes the handler atomic w.r.t. */
2908 /* stopping the world for GC. */
2909 (void)sigaddset(&act.sa_mask, SIG_SUSPEND);
2910 # endif /* SIG_SUSPEND */
2912 if (GC_print_stats == VERBOSE)
2914 "Initializing mprotect virtual dirty bit implementation\n");
2915 GC_dirty_maintained = TRUE;
2916 if (GC_page_size % HBLKSIZE != 0) {
2917 GC_err_printf("Page size not multiple of HBLKSIZE\n");
2918 ABORT("Page size not multiple of HBLKSIZE");
2920 # if !defined(MSWIN32) && !defined(MSWINCE)
2921 # if defined(GC_IRIX_THREADS)
2922 sigaction(SIGSEGV, 0, &oldact);
2923 sigaction(SIGSEGV, &act, 0);
2926 int res = sigaction(SIGSEGV, &act, &oldact);
2927 if (res != 0) ABORT("Sigaction failed");
2930 if (oldact.sa_flags & SA_SIGINFO) {
2931 GC_old_segv_handler = oldact.sa_sigaction;
2932 GC_old_segv_handler_used_si = TRUE;
2934 GC_old_segv_handler = (SIG_HNDLR_PTR)oldact.sa_handler;
2935 GC_old_segv_handler_used_si = FALSE;
2937 if (GC_old_segv_handler == (SIG_HNDLR_PTR)SIG_IGN) {
2938 GC_err_printf("Previously ignored segmentation violation!?");
2939 GC_old_segv_handler = (SIG_HNDLR_PTR)SIG_DFL;
2941 if (GC_old_segv_handler != (SIG_HNDLR_PTR)SIG_DFL) {
2942 if (GC_print_stats == VERBOSE)
2943 GC_log_printf("Replaced other SIGSEGV handler\n");
2945 # endif /* ! MS windows */
2946 # if defined(HPUX) || defined(LINUX) || defined(HURD) \
2947 || (defined(FREEBSD) && defined(SUNOS5SIGS))
2948 sigaction(SIGBUS, &act, &oldact);
2949 if (oldact.sa_flags & SA_SIGINFO) {
2950 GC_old_bus_handler = oldact.sa_sigaction;
2951 GC_old_bus_handler_used_si = TRUE;
2953 GC_old_bus_handler = (SIG_HNDLR_PTR)oldact.sa_handler;
2954 GC_old_bus_handler_used_si = FALSE;
2956 if (GC_old_bus_handler == (SIG_HNDLR_PTR)SIG_IGN) {
2957 GC_err_printf("Previously ignored bus error!?");
2958 GC_old_bus_handler = (SIG_HNDLR_PTR)SIG_DFL;
2960 if (GC_old_bus_handler != (SIG_HNDLR_PTR)SIG_DFL) {
2961 if (GC_print_stats == VERBOSE)
2962 GC_log_printf("Replaced other SIGBUS handler\n");
2964 # endif /* HPUX || LINUX || HURD || (FREEBSD && SUNOS5SIGS) */
2965 # if defined(MSWIN32)
2966 # if defined(GWW_VDB)
2967 if (GC_gww_dirty_init())
2970 GC_old_segv_handler = SetUnhandledExceptionFilter(GC_write_fault_handler);
2971 if (GC_old_segv_handler != NULL) {
2973 GC_log_printf("Replaced other UnhandledExceptionFilter\n");
2975 GC_old_segv_handler = SIG_DFL;
2979 #endif /* !DARWIN */
2981 int GC_incremental_protection_needs(void)
2983 if (GC_page_size == HBLKSIZE) {
2984 return GC_PROTECTS_POINTER_HEAP;
2986 return GC_PROTECTS_POINTER_HEAP | GC_PROTECTS_PTRFREE_HEAP;
2990 #define HAVE_INCREMENTAL_PROTECTION_NEEDS
2992 #define IS_PTRFREE(hhdr) ((hhdr)->hb_descr == 0)
2994 #define PAGE_ALIGNED(x) !((word)(x) & (GC_page_size - 1))
2995 void GC_protect_heap(void)
2999 struct hblk * current;
3000 struct hblk * current_start; /* Start of block to be protected. */
3001 struct hblk * limit;
3003 GC_bool protect_all =
3004 (0 != (GC_incremental_protection_needs() & GC_PROTECTS_PTRFREE_HEAP));
3005 for (i = 0; i < GC_n_heap_sects; i++) {
3006 start = GC_heap_sects[i].hs_start;
3007 len = GC_heap_sects[i].hs_bytes;
3009 PROTECT(start, len);
3011 GC_ASSERT(PAGE_ALIGNED(len))
3012 GC_ASSERT(PAGE_ALIGNED(start))
3013 current_start = current = (struct hblk *)start;
3014 limit = (struct hblk *)(start + len);
3015 while (current < limit) {
3020 GC_ASSERT(PAGE_ALIGNED(current));
3021 GET_HDR(current, hhdr);
3022 if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {
3023 /* This can happen only if we're at the beginning of a */
3024 /* heap segment, and a block spans heap segments. */
3025 /* We will handle that block as part of the preceding */
3027 GC_ASSERT(current_start == current);
3028 current_start = ++current;
3031 if (HBLK_IS_FREE(hhdr)) {
3032 GC_ASSERT(PAGE_ALIGNED(hhdr -> hb_sz));
3033 nhblks = divHBLKSZ(hhdr -> hb_sz);
3034 is_ptrfree = TRUE; /* dirty on alloc */
3036 nhblks = OBJ_SZ_TO_BLOCKS(hhdr -> hb_sz);
3037 is_ptrfree = IS_PTRFREE(hhdr);
3040 if (current_start < current) {
3041 PROTECT(current_start, (ptr_t)current - (ptr_t)current_start);
3043 current_start = (current += nhblks);
3048 if (current_start < current) {
3049 PROTECT(current_start, (ptr_t)current - (ptr_t)current_start);
3055 /* We assume that either the world is stopped or its OK to lose dirty */
3056 /* bits while this is happenning (as in GC_enable_incremental). */
3057 void GC_read_dirty(void)
3059 # if defined(GWW_VDB)
3060 if (GC_GWW_AVAILABLE()) {
3061 GC_gww_read_dirty();
3065 BCOPY((word *)GC_dirty_pages, GC_grungy_pages,
3066 (sizeof GC_dirty_pages));
3067 BZERO((word *)GC_dirty_pages, (sizeof GC_dirty_pages));
3071 GC_bool GC_page_was_dirty(struct hblk *h)
3073 register word index;
3075 # if defined(GWW_VDB)
3076 if (GC_GWW_AVAILABLE())
3077 return GC_gww_page_was_dirty(h);
3080 index = PHT_HASH(h);
3081 return(HDR(h) == 0 || get_pht_entry_from_index(GC_grungy_pages, index));
3085 * Acquiring the allocation lock here is dangerous, since this
3086 * can be called from within GC_call_with_alloc_lock, and the cord
3087 * package does so. On systems that allow nested lock acquisition, this
3089 * On other systems, SET_LOCK_HOLDER and friends must be suitably defined.
3092 static GC_bool syscall_acquired_lock = FALSE; /* Protected by GC lock. */
3095 void GC_begin_syscall(void)
3097 /* FIXME: Resurrecting this code would require fixing the */
3098 /* test, which can spuriously return TRUE. */
3099 if (!I_HOLD_LOCK()) {
3101 syscall_acquired_lock = TRUE;
3105 void GC_end_syscall(void)
3107 if (syscall_acquired_lock) {
3108 syscall_acquired_lock = FALSE;
3113 void GC_unprotect_range(ptr_t addr, word len)
3115 struct hblk * start_block;
3116 struct hblk * end_block;
3117 register struct hblk *h;
3120 if (!GC_dirty_maintained) return;
3121 obj_start = GC_base(addr);
3122 if (obj_start == 0) return;
3123 if (GC_base(addr + len - 1) != obj_start) {
3124 ABORT("GC_unprotect_range(range bigger than object)");
3126 start_block = (struct hblk *)((word)addr & ~(GC_page_size - 1));
3127 end_block = (struct hblk *)((word)(addr + len - 1) & ~(GC_page_size - 1));
3128 end_block += GC_page_size/HBLKSIZE - 1;
3129 for (h = start_block; h <= end_block; h++) {
3130 register word index = PHT_HASH(h);
3132 async_set_pht_entry_from_index(GC_dirty_pages, index);
3134 UNPROTECT(start_block,
3135 ((ptr_t)end_block - (ptr_t)start_block) + HBLKSIZE);
3139 /* We no longer wrap read by default, since that was causing too many */
3140 /* problems. It is preferred that the client instead avoids writing */
3141 /* to the write-protected heap with a system call. */
3142 /* This still serves as sample code if you do want to wrap system calls.*/
3144 #if !defined(MSWIN32) && !defined(MSWINCE) && !defined(GC_USE_LD_WRAP)
3145 /* Replacement for UNIX system call. */
3146 /* Other calls that write to the heap should be handled similarly. */
3147 /* Note that this doesn't work well for blocking reads: It will hold */
3148 /* the allocation lock for the entire duration of the call. Multithreaded */
3149 /* clients should really ensure that it won't block, either by setting */
3150 /* the descriptor nonblocking, or by calling select or poll first, to */
3151 /* make sure that input is available. */
3152 /* Another, preferred alternative is to ensure that system calls never */
3153 /* write to the protected heap (see above). */
3154 # include <unistd.h>
3155 # include <sys/uio.h>
3156 ssize_t read(int fd, void *buf, size_t nbyte)
3161 GC_unprotect_range(buf, (word)nbyte);
3162 # if defined(IRIX5) || defined(GC_LINUX_THREADS)
3163 /* Indirect system call may not always be easily available. */
3164 /* We could call _read, but that would interfere with the */
3165 /* libpthread interception of read. */
3166 /* On Linux, we have to be careful with the linuxthreads */
3167 /* read interception. */
3172 iov.iov_len = nbyte;
3173 result = readv(fd, &iov, 1);
3177 result = __read(fd, buf, nbyte);
3179 /* The two zero args at the end of this list are because one
3180 IA-64 syscall() implementation actually requires six args
3181 to be passed, even though they aren't always used. */
3182 result = syscall(SYS_read, fd, buf, nbyte, 0, 0);
3188 #endif /* !MSWIN32 && !MSWINCE && !GC_LINUX_THREADS */
3190 #if defined(GC_USE_LD_WRAP) && !defined(THREADS)
3191 /* We use the GNU ld call wrapping facility. */
3192 /* This requires that the linker be invoked with "--wrap read". */
3193 /* This can be done by passing -Wl,"--wrap read" to gcc. */
3194 /* I'm not sure that this actually wraps whatever version of read */
3195 /* is called by stdio. That code also mentions __read. */
3196 # include <unistd.h>
3197 ssize_t __wrap_read(int fd, void *buf, size_t nbyte)
3202 GC_unprotect_range(buf, (word)nbyte);
3203 result = __real_read(fd, buf, nbyte);
3208 /* We should probably also do this for __read, or whatever stdio */
3209 /* actually calls. */
3215 GC_bool GC_page_was_ever_dirty(struct hblk *h)
3217 # if defined(GWW_VDB)
3218 if (GC_GWW_AVAILABLE())
3219 return GC_gww_page_was_ever_dirty(h);
3224 # endif /* MPROTECT_VDB */
3229 * See DEFAULT_VDB for interface descriptions.
3233 * This implementaion assumes a Solaris 2.X like /proc pseudo-file-system
3234 * from which we can read page modified bits. This facility is far from
3235 * optimal (e.g. we would like to get the info for only some of the
3236 * address space), but it avoids intercepting system calls.
3240 #include <sys/types.h>
3241 #include <sys/signal.h>
3242 #include <sys/fault.h>
3243 #include <sys/syscall.h>
3244 #include <sys/procfs.h>
3245 #include <sys/stat.h>
3247 #define INITIAL_BUF_SZ 16384
3248 word GC_proc_buf_size = INITIAL_BUF_SZ;
3253 void GC_dirty_init(void)
3258 GC_dirty_maintained = TRUE;
3259 if (GC_bytes_allocd != 0 || GC_bytes_allocd_before_gc != 0) {
3262 for (i = 0; i < PHT_SIZE; i++) GC_written_pages[i] = (word)(-1);
3263 if (GC_print_stats == VERBOSE)
3265 "Allocated bytes:%lu:all pages may have been written\n",
3267 (GC_bytes_allocd + GC_bytes_allocd_before_gc));
3269 sprintf(buf, "/proc/%d", getpid());
3270 fd = open(buf, O_RDONLY);
3272 ABORT("/proc open failed");
3274 GC_proc_fd = syscall(SYS_ioctl, fd, PIOCOPENPD, 0);
3276 syscall(SYS_fcntl, GC_proc_fd, F_SETFD, FD_CLOEXEC);
3277 if (GC_proc_fd < 0) {
3278 ABORT("/proc ioctl failed");
3280 GC_proc_buf = GC_scratch_alloc(GC_proc_buf_size);
3283 /* Ignore write hints. They don't help us here. */
3285 void GC_remove_protection(h, nblocks, is_ptrfree)
3292 # define READ(fd,buf,nbytes) read(fd, buf, nbytes)
3294 void GC_read_dirty(void)
3296 unsigned long ps, np;
3299 struct prasmap * map;
3301 ptr_t current_addr, limit;
3304 BZERO(GC_grungy_pages, (sizeof GC_grungy_pages));
3307 if (READ(GC_proc_fd, bufp, GC_proc_buf_size) <= 0) {
3309 GC_log_printf("/proc read failed: GC_proc_buf_size = %lu\n",
3310 (unsigned long)GC_proc_buf_size);
3312 /* Retry with larger buffer. */
3313 word new_size = 2 * GC_proc_buf_size;
3314 char * new_buf = GC_scratch_alloc(new_size);
3317 GC_proc_buf = bufp = new_buf;
3318 GC_proc_buf_size = new_size;
3320 if (READ(GC_proc_fd, bufp, GC_proc_buf_size) <= 0) {
3321 WARN("Insufficient space for /proc read\n", 0);
3323 memset(GC_grungy_pages, 0xff, sizeof (page_hash_table));
3324 memset(GC_written_pages, 0xff, sizeof(page_hash_table));
3329 /* Copy dirty bits into GC_grungy_pages */
3330 nmaps = ((struct prpageheader *)bufp) -> pr_nmap;
3331 /* printf( "nmaps = %d, PG_REFERENCED = %d, PG_MODIFIED = %d\n",
3332 nmaps, PG_REFERENCED, PG_MODIFIED); */
3333 bufp = bufp + sizeof(struct prpageheader);
3334 for (i = 0; i < nmaps; i++) {
3335 map = (struct prasmap *)bufp;
3336 vaddr = (ptr_t)(map -> pr_vaddr);
3337 ps = map -> pr_pagesize;
3338 np = map -> pr_npage;
3339 /* printf("vaddr = 0x%X, ps = 0x%X, np = 0x%X\n", vaddr, ps, np); */
3340 limit = vaddr + ps * np;
3341 bufp += sizeof (struct prasmap);
3342 for (current_addr = vaddr;
3343 current_addr < limit; current_addr += ps){
3344 if ((*bufp++) & PG_MODIFIED) {
3345 register struct hblk * h = (struct hblk *) current_addr;
3347 while ((ptr_t)h < current_addr + ps) {
3348 register word index = PHT_HASH(h);
3350 set_pht_entry_from_index(GC_grungy_pages, index);
3355 bufp += sizeof(long) - 1;
3356 bufp = (char *)((unsigned long)bufp & ~(sizeof(long)-1));
3358 /* Update GC_written_pages. */
3359 GC_or_pages(GC_written_pages, GC_grungy_pages);
3364 GC_bool GC_page_was_dirty(struct hblk *h)
3366 register word index = PHT_HASH(h);
3367 register GC_bool result;
3369 result = get_pht_entry_from_index(GC_grungy_pages, index);
3373 GC_bool GC_page_was_ever_dirty(struct hblk *h)
3375 register word index = PHT_HASH(h);
3376 register GC_bool result;
3378 result = get_pht_entry_from_index(GC_written_pages, index);
3382 # endif /* PROC_VDB */
3387 # include "vd/PCR_VD.h"
3389 # define NPAGES (32*1024) /* 128 MB */
3391 PCR_VD_DB GC_grungy_bits[NPAGES];
3393 ptr_t GC_vd_base; /* Address corresponding to GC_grungy_bits[0] */
3394 /* HBLKSIZE aligned. */
3396 void GC_dirty_init(void)
3398 GC_dirty_maintained = TRUE;
3399 /* For the time being, we assume the heap generally grows up */
3400 GC_vd_base = GC_heap_sects[0].hs_start;
3401 if (GC_vd_base == 0) {
3402 ABORT("Bad initial heap segment");
3404 if (PCR_VD_Start(HBLKSIZE, GC_vd_base, NPAGES*HBLKSIZE)
3406 ABORT("dirty bit initialization failed");
3410 void GC_read_dirty(void)
3412 /* lazily enable dirty bits on newly added heap sects */
3414 static int onhs = 0;
3415 int nhs = GC_n_heap_sects;
3416 for( ; onhs < nhs; onhs++ ) {
3417 PCR_VD_WriteProtectEnable(
3418 GC_heap_sects[onhs].hs_start,
3419 GC_heap_sects[onhs].hs_bytes );
3424 if (PCR_VD_Clear(GC_vd_base, NPAGES*HBLKSIZE, GC_grungy_bits)
3426 ABORT("dirty bit read failed");
3430 GC_bool GC_page_was_dirty(struct hblk *h)
3432 if((ptr_t)h < GC_vd_base || (ptr_t)h >= GC_vd_base + NPAGES*HBLKSIZE) {
3435 return(GC_grungy_bits[h - (struct hblk *)GC_vd_base] & PCR_VD_DB_dirtyBit);
3439 void GC_remove_protection(struct hblk *h, word nblocks, GC_bool is_ptrfree)
3441 PCR_VD_WriteProtectDisable(h, nblocks*HBLKSIZE);
3442 PCR_VD_WriteProtectEnable(h, nblocks*HBLKSIZE);
3445 # endif /* PCR_VDB */
3447 #if defined(MPROTECT_VDB) && defined(DARWIN)
3448 /* The following sources were used as a *reference* for this exception handling
3450 1. Apple's mach/xnu documentation
3451 2. Timothy J. Wood's "Mach Exception Handlers 101" post to the
3452 omnigroup's macosx-dev list.
3453 www.omnigroup.com/mailman/archive/macosx-dev/2000-June/014178.html
3454 3. macosx-nat.c from Apple's GDB source code.
3457 /* The bug that caused all this trouble should now be fixed. This should
3458 eventually be removed if all goes well. */
3460 /* #define BROKEN_EXCEPTION_HANDLING */
3462 #include <mach/mach.h>
3463 #include <mach/mach_error.h>
3464 #include <mach/thread_status.h>
3465 #include <mach/exception.h>
3466 #include <mach/task.h>
3467 #include <pthread.h>
3469 extern void GC_darwin_register_mach_handler_thread(mach_port_t);
3471 /* These are not defined in any header, although they are documented */
3473 exc_server(mach_msg_header_t *, mach_msg_header_t *);
3475 extern kern_return_t
3476 exception_raise(mach_port_t, mach_port_t, mach_port_t, exception_type_t,
3477 exception_data_t, mach_msg_type_number_t);
3479 extern kern_return_t
3480 exception_raise_state(mach_port_t, mach_port_t, mach_port_t, exception_type_t,
3481 exception_data_t, mach_msg_type_number_t,
3482 thread_state_flavor_t*, thread_state_t,
3483 mach_msg_type_number_t, thread_state_t,
3484 mach_msg_type_number_t*);
3486 extern kern_return_t
3487 exception_raise_state_identity(mach_port_t, mach_port_t, mach_port_t,
3488 exception_type_t, exception_data_t,
3489 mach_msg_type_number_t, thread_state_flavor_t*,
3490 thread_state_t, mach_msg_type_number_t,
3491 thread_state_t, mach_msg_type_number_t*);
3494 #define MAX_EXCEPTION_PORTS 16
3497 mach_msg_type_number_t count;
3498 exception_mask_t masks[MAX_EXCEPTION_PORTS];
3499 exception_handler_t ports[MAX_EXCEPTION_PORTS];
3500 exception_behavior_t behaviors[MAX_EXCEPTION_PORTS];
3501 thread_state_flavor_t flavors[MAX_EXCEPTION_PORTS];
3505 mach_port_t exception;
3506 #if defined(THREADS)
3512 mach_msg_header_t head;
3516 GC_MP_NORMAL, GC_MP_DISCARDING, GC_MP_STOPPED
3517 } GC_mprotect_state_t;
3519 /* FIXME: 1 and 2 seem to be safe to use in the msgh_id field,
3520 but it isn't documented. Use the source and see if they
3525 /* These values are only used on the reply port */
3528 #if defined(THREADS)
3530 GC_mprotect_state_t GC_mprotect_state;
3532 /* The following should ONLY be called when the world is stopped */
3533 static void GC_mprotect_thread_notify(mach_msg_id_t id)
3538 mach_msg_trailer_t trailer;
3541 mach_msg_return_t r;
3543 buf.msg.head.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0);
3544 buf.msg.head.msgh_size = sizeof(buf.msg);
3545 buf.msg.head.msgh_remote_port = GC_ports.exception;
3546 buf.msg.head.msgh_local_port = MACH_PORT_NULL;
3547 buf.msg.head.msgh_id = id;
3549 r = mach_msg(&buf.msg.head, MACH_SEND_MSG | MACH_RCV_MSG | MACH_RCV_LARGE,
3550 sizeof(buf.msg), sizeof(buf), GC_ports.reply,
3551 MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
3552 if(r != MACH_MSG_SUCCESS)
3553 ABORT("mach_msg failed in GC_mprotect_thread_notify");
3554 if(buf.msg.head.msgh_id != ID_ACK)
3555 ABORT("invalid ack in GC_mprotect_thread_notify");
3558 /* Should only be called by the mprotect thread */
3559 static void GC_mprotect_thread_reply(void)
3563 mach_msg_return_t r;
3565 msg.head.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0);
3566 msg.head.msgh_size = sizeof(msg);
3567 msg.head.msgh_remote_port = GC_ports.reply;
3568 msg.head.msgh_local_port = MACH_PORT_NULL;
3569 msg.head.msgh_id = ID_ACK;
3571 r = mach_msg(&msg.head, MACH_SEND_MSG, sizeof(msg), 0, MACH_PORT_NULL,
3572 MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
3573 if(r != MACH_MSG_SUCCESS)
3574 ABORT("mach_msg failed in GC_mprotect_thread_reply");
3577 void GC_mprotect_stop(void)
3579 GC_mprotect_thread_notify(ID_STOP);
3581 void GC_mprotect_resume(void)
3583 GC_mprotect_thread_notify(ID_RESUME);
3586 #else /* !THREADS */
3587 /* The compiler should optimize away any GC_mprotect_state computations */
3588 #define GC_mprotect_state GC_MP_NORMAL
3591 static void *GC_mprotect_thread(void *arg)
3593 mach_msg_return_t r;
3594 /* These two structures contain some private kernel data. We don't need to
3595 access any of it so we don't bother defining a proper struct. The
3596 correct definitions are in the xnu source code. */
3598 mach_msg_header_t head;
3602 mach_msg_header_t head;
3603 mach_msg_body_t msgh_body;
3609 GC_darwin_register_mach_handler_thread(mach_thread_self());
3612 r = mach_msg(&msg.head, MACH_RCV_MSG | MACH_RCV_LARGE |
3613 (GC_mprotect_state == GC_MP_DISCARDING ? MACH_RCV_TIMEOUT : 0),
3614 0, sizeof(msg), GC_ports.exception,
3615 GC_mprotect_state == GC_MP_DISCARDING ? 0
3616 : MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
3618 id = r == MACH_MSG_SUCCESS ? msg.head.msgh_id : -1;
3620 # if defined(THREADS)
3621 if(GC_mprotect_state == GC_MP_DISCARDING) {
3622 if(r == MACH_RCV_TIMED_OUT) {
3623 GC_mprotect_state = GC_MP_STOPPED;
3624 GC_mprotect_thread_reply();
3627 if(r == MACH_MSG_SUCCESS && (id == ID_STOP || id == ID_RESUME))
3628 ABORT("out of order mprotect thread request");
3630 # endif /* THREADS */
3632 if(r != MACH_MSG_SUCCESS) {
3633 GC_err_printf("mach_msg failed with %d %s\n", (int)r,
3634 mach_error_string(r));
3635 ABORT("mach_msg failed");
3639 # if defined(THREADS)
3641 if(GC_mprotect_state != GC_MP_NORMAL)
3642 ABORT("Called mprotect_stop when state wasn't normal");
3643 GC_mprotect_state = GC_MP_DISCARDING;
3646 if(GC_mprotect_state != GC_MP_STOPPED)
3647 ABORT("Called mprotect_resume when state wasn't stopped");
3648 GC_mprotect_state = GC_MP_NORMAL;
3649 GC_mprotect_thread_reply();
3651 # endif /* THREADS */
3653 /* Handle the message (calls catch_exception_raise) */
3654 if(!exc_server(&msg.head, &reply.head))
3655 ABORT("exc_server failed");
3656 /* Send the reply */
3657 r = mach_msg(&reply.head, MACH_SEND_MSG, reply.head.msgh_size, 0,
3658 MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE,
3660 if(r != MACH_MSG_SUCCESS) {
3661 /* This will fail if the thread dies, but the thread */
3662 /* shouldn't die... */
3663 # ifdef BROKEN_EXCEPTION_HANDLING
3664 GC_err_printf("mach_msg failed with %d %s while sending"
3665 "exc reply\n", (int)r,mach_error_string(r));
3667 ABORT("mach_msg failed while sending exception reply");
3676 /* All this SIGBUS code shouldn't be necessary. All protection faults should
3677 be going throught the mach exception handler. However, it seems a SIGBUS is
3678 occasionally sent for some unknown reason. Even more odd, it seems to be
3679 meaningless and safe to ignore. */
3680 #ifdef BROKEN_EXCEPTION_HANDLING
3682 static SIG_HNDLR_PTR GC_old_bus_handler;
3684 /* Updates to this aren't atomic, but the SIGBUSs seem pretty rare.
3685 Even if this doesn't get updated property, it isn't really a problem */
3686 static int GC_sigbus_count;
3688 static void GC_darwin_sigbus(int num, siginfo_t *sip, void *context)
3691 ABORT("Got a non-sigbus signal in the sigbus handler");
3693 /* Ugh... some seem safe to ignore, but too many in a row probably means
3694 trouble. GC_sigbus_count is reset for each mach exception that is
3696 if(GC_sigbus_count >= 8) {
3697 ABORT("Got more than 8 SIGBUSs in a row!");
3700 WARN("Ignoring SIGBUS.\n", 0);
3703 #endif /* BROKEN_EXCEPTION_HANDLING */
3705 void GC_dirty_init(void)
3710 pthread_attr_t attr;
3711 exception_mask_t mask;
3713 if (GC_print_stats == VERBOSE)
3714 GC_log_printf("Inititalizing mach/darwin mprotect virtual dirty bit "
3715 "implementation\n");
3716 # ifdef BROKEN_EXCEPTION_HANDLING
3717 WARN("Enabling workarounds for various darwin "
3718 "exception handling bugs.\n", 0);
3720 GC_dirty_maintained = TRUE;
3721 if (GC_page_size % HBLKSIZE != 0) {
3722 GC_err_printf("Page size not multiple of HBLKSIZE\n");
3723 ABORT("Page size not multiple of HBLKSIZE");
3726 GC_task_self = me = mach_task_self();
3728 r = mach_port_allocate(me, MACH_PORT_RIGHT_RECEIVE, &GC_ports.exception);
3729 if(r != KERN_SUCCESS)
3730 ABORT("mach_port_allocate failed (exception port)");
3732 r = mach_port_insert_right(me, GC_ports.exception, GC_ports.exception,
3733 MACH_MSG_TYPE_MAKE_SEND);
3734 if(r != KERN_SUCCESS)
3735 ABORT("mach_port_insert_right failed (exception port)");
3737 # if defined(THREADS)
3738 r = mach_port_allocate(me, MACH_PORT_RIGHT_RECEIVE, &GC_ports.reply);
3739 if(r != KERN_SUCCESS)
3740 ABORT("mach_port_allocate failed (reply port)");
3743 /* The exceptions we want to catch */
3744 mask = EXC_MASK_BAD_ACCESS;
3746 r = task_get_exception_ports(me, mask, GC_old_exc_ports.masks,
3747 &GC_old_exc_ports.count, GC_old_exc_ports.ports,
3748 GC_old_exc_ports.behaviors,
3749 GC_old_exc_ports.flavors);
3750 if(r != KERN_SUCCESS)
3751 ABORT("task_get_exception_ports failed");
3753 r = task_set_exception_ports(me, mask, GC_ports.exception, EXCEPTION_DEFAULT,
3754 GC_MACH_THREAD_STATE);
3755 if(r != KERN_SUCCESS)
3756 ABORT("task_set_exception_ports failed");
3757 if(pthread_attr_init(&attr) != 0)
3758 ABORT("pthread_attr_init failed");
3759 if(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0)
3760 ABORT("pthread_attr_setdetachedstate failed");
3762 # undef pthread_create
3763 /* This will call the real pthread function, not our wrapper */
3764 if(pthread_create(&thread, &attr, GC_mprotect_thread, NULL) != 0)
3765 ABORT("pthread_create failed");
3766 pthread_attr_destroy(&attr);
3768 /* Setup the sigbus handler for ignoring the meaningless SIGBUSs */
3769 # ifdef BROKEN_EXCEPTION_HANDLING
3771 struct sigaction sa, oldsa;
3772 sa.sa_handler = (SIG_HNDLR_PTR)GC_darwin_sigbus;
3773 sigemptyset(&sa.sa_mask);
3774 sa.sa_flags = SA_RESTART|SA_SIGINFO;
3775 if(sigaction(SIGBUS, &sa, &oldsa) < 0)
3777 GC_old_bus_handler = (SIG_HNDLR_PTR)oldsa.sa_handler;
3778 if (GC_old_bus_handler != SIG_DFL) {
3779 if (GC_print_stats == VERBOSE)
3780 GC_err_printf("Replaced other SIGBUS handler\n");
3783 # endif /* BROKEN_EXCEPTION_HANDLING */
3786 /* The source code for Apple's GDB was used as a reference for the exception
3787 forwarding code. This code is similar to be GDB code only because there is
3788 only one way to do it. */
3789 static kern_return_t GC_forward_exception(mach_port_t thread, mach_port_t task,
3790 exception_type_t exception,
3791 exception_data_t data,
3792 mach_msg_type_number_t data_count)
3797 exception_behavior_t behavior;
3798 thread_state_flavor_t flavor;
3800 thread_state_t thread_state = NULL;
3801 mach_msg_type_number_t thread_state_count = THREAD_STATE_MAX;
3803 for(i=0; i < GC_old_exc_ports.count; i++)
3804 if(GC_old_exc_ports.masks[i] & (1 << exception))
3806 if(i==GC_old_exc_ports.count)
3807 ABORT("No handler for exception!");
3809 port = GC_old_exc_ports.ports[i];
3810 behavior = GC_old_exc_ports.behaviors[i];
3811 flavor = GC_old_exc_ports.flavors[i];
3813 if(behavior != EXCEPTION_DEFAULT) {
3814 r = thread_get_state(thread, flavor, thread_state, &thread_state_count);
3815 if(r != KERN_SUCCESS)
3816 ABORT("thread_get_state failed in forward_exception");
3820 case EXCEPTION_DEFAULT:
3821 r = exception_raise(port, thread, task, exception, data, data_count);
3823 case EXCEPTION_STATE:
3824 r = exception_raise_state(port, thread, task, exception, data, data_count,
3825 &flavor, thread_state, thread_state_count,
3826 thread_state, &thread_state_count);
3828 case EXCEPTION_STATE_IDENTITY:
3829 r = exception_raise_state_identity(port, thread, task, exception, data,
3830 data_count, &flavor, thread_state,
3831 thread_state_count, thread_state,
3832 &thread_state_count);
3835 r = KERN_FAILURE; /* make gcc happy */
3836 ABORT("forward_exception: unknown behavior");
3840 if(behavior != EXCEPTION_DEFAULT) {
3841 r = thread_set_state(thread, flavor, thread_state, thread_state_count);
3842 if(r != KERN_SUCCESS)
3843 ABORT("thread_set_state failed in forward_exception");
3849 #define FWD() GC_forward_exception(thread, task, exception, code, code_count)
3851 /* This violates the namespace rules but there isn't anything that can be done
3852 about it. The exception handling stuff is hard coded to call this */
3854 catch_exception_raise(mach_port_t exception_port, mach_port_t thread,
3855 mach_port_t task, exception_type_t exception,
3856 exception_data_t code, mach_msg_type_number_t code_count)
3862 # if defined(POWERPC)
3863 # if CPP_WORDSZ == 32
3864 thread_state_flavor_t flavor = PPC_EXCEPTION_STATE;
3865 mach_msg_type_number_t exc_state_count = PPC_EXCEPTION_STATE_COUNT;
3866 ppc_exception_state_t exc_state;
3868 thread_state_flavor_t flavor = PPC_EXCEPTION_STATE64;
3869 mach_msg_type_number_t exc_state_count = PPC_EXCEPTION_STATE64_COUNT;
3870 ppc_exception_state64_t exc_state;
3872 # elif defined(I386) || defined(X86_64)
3873 # if CPP_WORDSZ == 32
3874 thread_state_flavor_t flavor = x86_EXCEPTION_STATE32;
3875 mach_msg_type_number_t exc_state_count = x86_EXCEPTION_STATE32_COUNT;
3876 x86_exception_state32_t exc_state;
3878 thread_state_flavor_t flavor = x86_EXCEPTION_STATE64;
3879 mach_msg_type_number_t exc_state_count = x86_EXCEPTION_STATE64_COUNT;
3880 x86_exception_state64_t exc_state;
3883 # error FIXME for non-ppc/x86 darwin
3887 if(exception != EXC_BAD_ACCESS || code[0] != KERN_PROTECTION_FAILURE) {
3888 # ifdef DEBUG_EXCEPTION_HANDLING
3889 /* We aren't interested, pass it on to the old handler */
3890 GC_printf("Exception: 0x%x Code: 0x%x 0x%x in catch....\n", exception,
3891 code_count > 0 ? code[0] : -1, code_count > 1 ? code[1] : -1);
3896 r = thread_get_state(thread, flavor, (natural_t*)&exc_state,
3898 if(r != KERN_SUCCESS) {
3899 /* The thread is supposed to be suspended while the exception handler
3900 is called. This shouldn't fail. */
3901 # ifdef BROKEN_EXCEPTION_HANDLING
3902 GC_err_printf("thread_get_state failed in catch_exception_raise\n");
3903 return KERN_SUCCESS;
3905 ABORT("thread_get_state failed in catch_exception_raise");
3909 /* This is the address that caused the fault */
3910 # if defined(POWERPC)
3911 addr = (char*) exc_state. THREAD_FLD(dar);
3912 # elif defined (I386) || defined (X86_64)
3913 addr = (char*) exc_state. THREAD_FLD(faultvaddr);
3915 # error FIXME for non POWERPC/I386
3918 if((HDR(addr)) == 0) {
3919 /* Ugh... just like the SIGBUS problem above, it seems we get a bogus
3920 KERN_PROTECTION_FAILURE every once and a while. We wait till we get
3921 a bunch in a row before doing anything about it. If a "real" fault
3922 ever occurres it'll just keep faulting over and over and we'll hit
3923 the limit pretty quickly. */
3924 # ifdef BROKEN_EXCEPTION_HANDLING
3925 static char *last_fault;
3926 static int last_fault_count;
3928 if(addr != last_fault) {
3930 last_fault_count = 0;
3932 if(++last_fault_count < 32) {
3933 if(last_fault_count == 1)
3934 WARN("Ignoring KERN_PROTECTION_FAILURE at %lx\n", (GC_word)addr);
3935 return KERN_SUCCESS;
3938 GC_err_printf("Unexpected KERN_PROTECTION_FAILURE at %p\n",addr);
3939 /* Can't pass it along to the signal handler because that is
3940 ignoring SIGBUS signals. We also shouldn't call ABORT here as
3941 signals don't always work too well from the exception handler. */
3942 GC_err_printf("Aborting\n");
3944 # else /* BROKEN_EXCEPTION_HANDLING */
3945 /* Pass it along to the next exception handler
3946 (which should call SIGBUS/SIGSEGV) */
3948 # endif /* !BROKEN_EXCEPTION_HANDLING */
3951 # ifdef BROKEN_EXCEPTION_HANDLING
3952 /* Reset the number of consecutive SIGBUSs */
3953 GC_sigbus_count = 0;
3956 if(GC_mprotect_state == GC_MP_NORMAL) { /* common case */
3957 h = (struct hblk*)((word)addr & ~(GC_page_size-1));
3958 UNPROTECT(h, GC_page_size);
3959 for (i = 0; i < divHBLKSZ(GC_page_size); i++) {
3960 register int index = PHT_HASH(h+i);
3961 async_set_pht_entry_from_index(GC_dirty_pages, index);
3963 } else if(GC_mprotect_state == GC_MP_DISCARDING) {
3964 /* Lie to the thread for now. No sense UNPROTECT()ing the memory
3965 when we're just going to PROTECT() it again later. The thread
3966 will just fault again once it resumes */
3968 /* Shouldn't happen, i don't think */
3969 GC_printf("KERN_PROTECTION_FAILURE while world is stopped\n");
3972 return KERN_SUCCESS;
3976 /* These should never be called, but just in case... */
3978 catch_exception_raise_state(mach_port_name_t exception_port, int exception,
3979 exception_data_t code,
3980 mach_msg_type_number_t codeCnt, int flavor,
3981 thread_state_t old_state, int old_stateCnt,
3982 thread_state_t new_state, int new_stateCnt)
3984 ABORT("catch_exception_raise_state");
3985 return(KERN_INVALID_ARGUMENT);
3989 catch_exception_raise_state_identity(mach_port_name_t exception_port,
3990 mach_port_t thread, mach_port_t task,
3991 int exception, exception_data_t code,
3992 mach_msg_type_number_t codeCnt, int flavor,
3993 thread_state_t old_state, int old_stateCnt,
3994 thread_state_t new_state, int new_stateCnt)
3996 ABORT("catch_exception_raise_state_identity");
3997 return(KERN_INVALID_ARGUMENT);
4001 #endif /* DARWIN && MPROTECT_VDB */
4003 # ifndef HAVE_INCREMENTAL_PROTECTION_NEEDS
4004 int GC_incremental_protection_needs()
4006 return GC_PROTECTS_NONE;
4008 # endif /* !HAVE_INCREMENTAL_PROTECTION_NEEDS */
4011 * Call stack save code for debugging.
4012 * Should probably be in mach_dep.c, but that requires reorganization.
4015 /* I suspect the following works for most X86 *nix variants, so */
4016 /* long as the frame pointer is explicitly stored. In the case of gcc, */
4017 /* compiler flags (e.g. -fomit-frame-pointer) determine whether it is. */
4018 #if defined(I386) && defined(LINUX) && defined(SAVE_CALL_CHAIN)
4019 # include <features.h>
4022 struct frame *fr_savfp;
4024 long fr_arg[NARGS]; /* All the arguments go here. */
4030 # include <features.h>
4035 struct frame *fr_savfp;
4043 # elif defined (DRSNX)
4044 # include <sys/sparc/frame.h>
4045 # elif defined(OPENBSD)
4047 # elif defined(FREEBSD) || defined(NETBSD)
4048 # include <machine/frame.h>
4050 # include <sys/frame.h>
4053 # error We only know how to to get the first 6 arguments
4057 #ifdef NEED_CALLINFO
4058 /* Fill in the pc and argument information for up to NFRAMES of my */
4059 /* callers. Ignore my frame and my callers frame. */
4062 # include <unistd.h>
4065 #endif /* NEED_CALLINFO */
4067 #if defined(GC_HAVE_BUILTIN_BACKTRACE)
4069 # include "private/msvc_dbg.h"
4071 # include <execinfo.h>
4075 #ifdef SAVE_CALL_CHAIN
4077 #if NARGS == 0 && NFRAMES % 2 == 0 /* No padding */ \
4078 && defined(GC_HAVE_BUILTIN_BACKTRACE)
4080 #ifdef REDIRECT_MALLOC
4081 /* Deal with possible malloc calls in backtrace by omitting */
4082 /* the infinitely recursing backtrace. */
4084 __thread /* If your compiler doesn't understand this */
4085 /* you could use something like pthread_getspecific. */
4087 GC_in_save_callers = FALSE;
4090 void GC_save_callers (struct callinfo info[NFRAMES])
4092 void * tmp_info[NFRAMES + 1];
4094 # define IGNORE_FRAMES 1
4096 /* We retrieve NFRAMES+1 pc values, but discard the first, since it */
4097 /* points to our own frame. */
4098 # ifdef REDIRECT_MALLOC
4099 if (GC_in_save_callers) {
4100 info[0].ci_pc = (word)(&GC_save_callers);
4101 for (i = 1; i < NFRAMES; ++i) info[i].ci_pc = 0;
4104 GC_in_save_callers = TRUE;
4106 GC_ASSERT(sizeof(struct callinfo) == sizeof(void *));
4107 npcs = backtrace((void **)tmp_info, NFRAMES + IGNORE_FRAMES);
4108 BCOPY(tmp_info+IGNORE_FRAMES, info, (npcs - IGNORE_FRAMES) * sizeof(void *));
4109 for (i = npcs - IGNORE_FRAMES; i < NFRAMES; ++i) info[i].ci_pc = 0;
4110 # ifdef REDIRECT_MALLOC
4111 GC_in_save_callers = FALSE;
4115 #else /* No builtin backtrace; do it ourselves */
4117 #if (defined(OPENBSD) || defined(NETBSD) || defined(FREEBSD)) && defined(SPARC)
4118 # define FR_SAVFP fr_fp
4119 # define FR_SAVPC fr_pc
4121 # define FR_SAVFP fr_savfp
4122 # define FR_SAVPC fr_savpc
4125 #if defined(SPARC) && (defined(__arch64__) || defined(__sparcv9))
4131 void GC_save_callers (struct callinfo info[NFRAMES])
4133 struct frame *frame;
4137 /* We assume this is turned on only with gcc as the compiler. */
4138 asm("movl %%ebp,%0" : "=r"(frame));
4141 frame = (struct frame *) GC_save_regs_in_stack ();
4142 fp = (struct frame *)((long) frame -> FR_SAVFP + BIAS);
4145 for (; (!(fp HOTTER_THAN frame) && !(GC_stackbottom HOTTER_THAN (ptr_t)fp)
4146 && (nframes < NFRAMES));
4147 fp = (struct frame *)((long) fp -> FR_SAVFP + BIAS), nframes++) {
4150 info[nframes].ci_pc = fp->FR_SAVPC;
4152 for (i = 0; i < NARGS; i++) {
4153 info[nframes].ci_arg[i] = ~(fp->fr_arg[i]);
4155 # endif /* NARGS > 0 */
4157 if (nframes < NFRAMES) info[nframes].ci_pc = 0;
4160 #endif /* No builtin backtrace */
4162 #endif /* SAVE_CALL_CHAIN */
4164 #ifdef NEED_CALLINFO
4166 /* Print info to stderr. We do NOT hold the allocation lock */
4167 void GC_print_callers (struct callinfo info[NFRAMES])
4170 static int reentry_count = 0;
4171 GC_bool stop = FALSE;
4173 /* FIXME: This should probably use a different lock, so that we */
4174 /* become callable with or without the allocation lock. */
4180 GC_err_printf("\tCaller at allocation:\n");
4182 GC_err_printf("\tCall chain at allocation:\n");
4184 for (i = 0; i < NFRAMES && !stop ; i++) {
4185 if (info[i].ci_pc == 0) break;
4190 GC_err_printf("\t\targs: ");
4191 for (j = 0; j < NARGS; j++) {
4192 if (j != 0) GC_err_printf(", ");
4193 GC_err_printf("%d (0x%X)", ~(info[i].ci_arg[j]),
4194 ~(info[i].ci_arg[j]));
4196 GC_err_printf("\n");
4199 if (reentry_count > 1) {
4200 /* We were called during an allocation during */
4201 /* a previous GC_print_callers call; punt. */
4202 GC_err_printf("\t\t##PC##= 0x%lx\n", info[i].ci_pc);
4209 # if defined(GC_HAVE_BUILTIN_BACKTRACE) \
4210 && !defined(GC_BACKTRACE_SYMBOLS_BROKEN)
4212 backtrace_symbols((void **)(&(info[i].ci_pc)), 1);
4213 char *name = sym_name[0];
4217 sprintf(buf, "##PC##= 0x%lx", info[i].ci_pc);
4219 # if defined(LINUX) && !defined(SMALL_CONFIG)
4220 /* Try for a line number. */
4223 static char exe_name[EXE_SZ];
4225 char cmd_buf[CMD_SZ];
4226 # define RESULT_SZ 200
4227 static char result_buf[RESULT_SZ];
4230 # define PRELOAD_SZ 200
4231 char preload_buf[PRELOAD_SZ];
4232 static GC_bool found_exe_name = FALSE;
4233 static GC_bool will_fail = FALSE;
4235 /* Try to get it via a hairy and expensive scheme. */
4236 /* First we get the name of the executable: */
4237 if (will_fail) goto out;
4238 if (!found_exe_name) {
4239 ret_code = readlink("/proc/self/exe", exe_name, EXE_SZ);
4240 if (ret_code < 0 || ret_code >= EXE_SZ
4241 || exe_name[0] != '/') {
4242 will_fail = TRUE; /* Dont try again. */
4245 exe_name[ret_code] = '\0';
4246 found_exe_name = TRUE;
4248 /* Then we use popen to start addr2line -e <exe> <addr> */
4249 /* There are faster ways to do this, but hopefully this */
4250 /* isn't time critical. */
4251 sprintf(cmd_buf, "/usr/bin/addr2line -f -e %s 0x%lx", exe_name,
4252 (unsigned long)info[i].ci_pc);
4253 old_preload = getenv ("LD_PRELOAD");
4254 if (0 != old_preload) {
4255 if (strlen (old_preload) >= PRELOAD_SZ) {
4259 strcpy (preload_buf, old_preload);
4260 unsetenv ("LD_PRELOAD");
4262 pipe = popen(cmd_buf, "r");
4263 if (0 != old_preload
4264 && 0 != setenv ("LD_PRELOAD", preload_buf, 0)) {
4265 WARN("Failed to reset LD_PRELOAD\n", 0);
4268 || (result_len = fread(result_buf, 1, RESULT_SZ - 1, pipe))
4270 if (pipe != NULL) pclose(pipe);
4274 if (result_buf[result_len - 1] == '\n') --result_len;
4275 result_buf[result_len] = 0;
4276 if (result_buf[0] == '?'
4277 || (result_buf[result_len-2] == ':'
4278 && result_buf[result_len-1] == '0')) {
4282 /* Get rid of embedded newline, if any. Test for "main" */
4284 char * nl = strchr(result_buf, '\n');
4285 if (nl != NULL && nl < result_buf + result_len) {
4288 if (strncmp(result_buf, "main", nl - result_buf) == 0) {
4292 if (result_len < RESULT_SZ - 25) {
4293 /* Add in hex address */
4294 sprintf(result_buf + result_len, " [0x%lx]",
4295 (unsigned long)info[i].ci_pc);
4302 GC_err_printf("\t\t%s\n", name);
4303 # if defined(GC_HAVE_BUILTIN_BACKTRACE) \
4304 && !defined(GC_BACKTRACE_SYMBOLS_BROKEN)
4305 free(sym_name); /* May call GC_free; that's OK */
4314 #endif /* NEED_CALLINFO */
4318 #if defined(LINUX) && defined(__ELF__) && !defined(SMALL_CONFIG)
4320 /* Dump /proc/self/maps to GC_stderr, to enable looking up names for
4321 addresses in FIND_LEAK output. */
4323 static word dump_maps(char *maps)
4325 GC_err_write(maps, strlen(maps));
4329 void GC_print_address_map(void)
4331 GC_err_printf("---------- Begin address map ----------\n");
4332 dump_maps(GC_get_maps());
4333 GC_err_printf("---------- End address map ----------\n");