2 * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
3 * Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved.
4 * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved.
5 * Copyright (c) 1999 by Hewlett-Packard Company. All rights reserved.
7 * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
8 * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
10 * Permission is hereby granted to use or copy this program
11 * for any purpose, provided the above notices are retained on all copies.
12 * Permission to modify the code and to distribute modified code is granted,
13 * provided the above notices are retained, and a notice that the code was
14 * modified is included with the above copyright notice.
17 # include "private/gc_priv.h"
19 # include "atomic_ops.h"
22 # if defined(LINUX) && !defined(POWERPC)
23 # include <linux/version.h>
24 # if (LINUX_VERSION_CODE <= 0x10400)
25 /* Ugly hack to get struct sigcontext_struct definition. Required */
26 /* for some early 1.3.X releases. Will hopefully go away soon. */
27 /* in some later Linux releases, asm/sigcontext.h may have to */
28 /* be included instead. */
30 # include <asm/signal.h>
33 /* Kernels prior to 2.1.1 defined struct sigcontext_struct instead of */
34 /* struct sigcontext. libc6 (glibc2) uses "struct sigcontext" in */
35 /* prototypes, so we have to include the top-level sigcontext.h to */
36 /* make sure the former gets defined to be the latter if appropriate. */
37 # include <features.h>
39 # if 2 == __GLIBC__ && 0 == __GLIBC_MINOR__
40 /* glibc 2.1 no longer has sigcontext.h. But signal.h */
41 /* has the right declaration for glibc 2.1. */
42 # include <sigcontext.h>
43 # endif /* 0 == __GLIBC_MINOR__ */
44 # else /* not 2 <= __GLIBC__ */
45 /* libc5 doesn't have <sigcontext.h>: go directly with the kernel */
46 /* one. Check LINUX_VERSION_CODE to see which we should reference. */
47 # include <asm/sigcontext.h>
48 # endif /* 2 <= __GLIBC__ */
51 # if !defined(OS2) && !defined(PCR) && !defined(AMIGA) && !defined(MACOS) \
53 # include <sys/types.h>
54 # if !defined(MSWIN32)
61 # define SIGSEGV 0 /* value is irrelevant */
70 #if defined(LINUX) || defined(LINUX_STACKBOTTOM)
74 /* Blatantly OS dependent routines, except for those that are related */
75 /* to dynamic loading. */
83 #if defined(MSWIN32) || defined(MSWINCE) || defined(CYGWIN32)
84 # define WIN32_LEAN_AND_MEAN
87 /* It's not clear this is completely kosher under Cygwin. But it */
88 /* allows us to get a working GC_get_stack_base. */
92 # include <Processes.h>
97 # include <malloc.h> /* for locking */
100 #if defined(LINUX) || defined(FREEBSD) || defined(SOLARIS) || defined(IRIX5) \
101 || defined(USE_MMAP) || defined(USE_MUNMAP)
102 # define MMAP_SUPPORTED
105 #if defined(MMAP_SUPPORTED) || defined(ADD_HEAP_GUARD_PAGES)
106 # if defined(USE_MUNMAP) && !defined(USE_MMAP)
107 --> USE_MUNMAP requires USE_MMAP
109 # include <sys/types.h>
110 # include <sys/mman.h>
111 # include <sys/stat.h>
116 /* for get_etext and friends */
117 #include <mach-o/getsect.h>
121 /* Apparently necessary for djgpp 2.01. May cause problems with */
122 /* other versions. */
123 typedef long unsigned int caddr_t;
127 # include "il/PCR_IL.h"
128 # include "th/PCR_ThCtl.h"
129 # include "mm/PCR_MM.h"
132 #if !defined(NO_EXECUTE_PERMISSION)
133 # define OPT_PROT_EXEC PROT_EXEC
135 # define OPT_PROT_EXEC 0
138 #if defined(LINUX) && \
139 (defined(USE_PROC_FOR_LIBRARIES) || defined(IA64) || !defined(SMALL_CONFIG))
140 # define NEED_PROC_MAPS
143 #ifdef NEED_PROC_MAPS
144 /* We need to parse /proc/self/maps, either to find dynamic libraries, */
145 /* and/or to find the register backing store base (IA64). Do it once */
150 /* Repeatedly perform a read call until the buffer is filled or */
151 /* we encounter EOF. */
152 ssize_t GC_repeat_read(int fd, char *buf, size_t count)
154 ssize_t num_read = 0;
157 while (num_read < count) {
158 result = READ(fd, buf + num_read, count - num_read);
159 if (result < 0) return result;
160 if (result == 0) break;
166 /* Determine the length of a file by incrementally reading it into a */
167 /* This would be sily to use on a file supporting lseek, but Linux */
168 /* /proc files usually do not. */
169 size_t GC_get_file_len(int f)
173 # define GET_FILE_LEN_BUF_SZ 500
174 char buf[GET_FILE_LEN_BUF_SZ];
177 result = read(f, buf, GET_FILE_LEN_BUF_SZ);
178 if (result == -1) return 0;
180 } while (result > 0);
184 size_t GC_get_maps_len(void)
186 int f = open("/proc/self/maps", O_RDONLY);
187 size_t result = GC_get_file_len(f);
193 * Copy the contents of /proc/self/maps to a buffer in our address space.
194 * Return the address of the buffer, or zero on failure.
195 * This code could be simplified if we could determine its size
198 char * GC_get_maps(void)
202 static char init_buf[1];
203 static char *maps_buf = init_buf;
204 static size_t maps_buf_sz = 1;
205 size_t maps_size, old_maps_size = 0;
207 /* The buffer is essentially static, so there must be a single client. */
208 GC_ASSERT(I_HOLD_LOCK());
210 /* Note that in the presence of threads, the maps file can */
211 /* essentially shrink asynchronously and unexpectedly as */
212 /* threads that we already think of as dead release their */
213 /* stacks. And there is no easy way to read the entire */
214 /* file atomically. This is arguably a misfeature of the */
215 /* /proc/.../maps interface. */
217 /* Since we dont believe the file can grow */
218 /* asynchronously, it should suffice to first determine */
219 /* the size (using lseek or read), and then to reread the */
220 /* file. If the size is inconsistent we have to retry. */
221 /* This only matters with threads enabled, and if we use */
222 /* this to locate roots (not the default). */
224 /* Determine the initial size of /proc/self/maps. */
225 /* Note that lseek doesn't work, at least as of 2.6.15. */
227 maps_size = GC_get_maps_len();
228 if (0 == maps_size) return 0;
230 maps_size = 4000; /* Guess */
233 /* Read /proc/self/maps, growing maps_buf as necessary. */
234 /* Note that we may not allocate conventionally, and */
235 /* thus can't use stdio. */
237 while (maps_size >= maps_buf_sz) {
238 /* Grow only by powers of 2, since we leak "too small" buffers. */
239 while (maps_size >= maps_buf_sz) maps_buf_sz *= 2;
240 maps_buf = GC_scratch_alloc(maps_buf_sz);
242 /* Recompute initial length, since we allocated. */
243 /* This can only happen a few times per program */
245 maps_size = GC_get_maps_len();
246 if (0 == maps_size) return 0;
248 if (maps_buf == 0) return 0;
250 GC_ASSERT(maps_buf_sz >= maps_size + 1);
251 f = open("/proc/self/maps", O_RDONLY);
252 if (-1 == f) return 0;
254 old_maps_size = maps_size;
258 result = GC_repeat_read(f, maps_buf, maps_buf_sz-1);
259 if (result <= 0) return 0;
261 } while (result == maps_buf_sz-1);
264 if (maps_size > old_maps_size) {
265 GC_err_printf("Old maps size = %d, new maps size = %d\n",
266 old_maps_size, maps_size);
267 ABORT("Unexpected asynchronous /proc/self/maps growth: "
268 "Unregistered thread?");
271 } while (maps_size >= maps_buf_sz || maps_size < old_maps_size);
272 /* In the single-threaded case, the second clause is false. */
273 maps_buf[maps_size] = '\0';
275 /* Apply fn to result. */
280 // GC_parse_map_entry parses an entry from /proc/self/maps so we can
281 // locate all writable data segments that belong to shared libraries.
282 // The format of one of these entries and the fields we care about
284 // XXXXXXXX-XXXXXXXX r-xp 00000000 30:05 260537 name of mapping...\n
285 // ^^^^^^^^ ^^^^^^^^ ^^^^ ^^
286 // start end prot maj_dev
288 // Note that since about august 2003 kernels, the columns no longer have
289 // fixed offsets on 64-bit kernels. Hence we no longer rely on fixed offsets
290 // anywhere, which is safer anyway.
294 * Assign various fields of the first line in buf_ptr to *start, *end,
295 * *prot, *maj_dev and *mapping_name. Mapping_name may be NULL.
296 * *prot and *mapping_name are assigned pointers into the original
299 char *GC_parse_map_entry(char *buf_ptr, ptr_t *start, ptr_t *end,
300 char **prot, unsigned int *maj_dev,
303 char *start_start, *end_start, *maj_dev_start;
307 if (buf_ptr == NULL || *buf_ptr == '\0') {
312 while (isspace(*p)) ++p;
314 GC_ASSERT(isxdigit(*start_start));
315 *start = (ptr_t)strtoul(start_start, &endp, 16); p = endp;
320 GC_ASSERT(isxdigit(*end_start));
321 *end = (ptr_t)strtoul(end_start, &endp, 16); p = endp;
322 GC_ASSERT(isspace(*p));
324 while (isspace(*p)) ++p;
325 GC_ASSERT(*p == 'r' || *p == '-');
327 /* Skip past protection field to offset field */
328 while (!isspace(*p)) ++p; while (isspace(*p)) ++p;
329 GC_ASSERT(isxdigit(*p));
330 /* Skip past offset field, which we ignore */
331 while (!isspace(*p)) ++p; while (isspace(*p)) ++p;
333 GC_ASSERT(isxdigit(*maj_dev_start));
334 *maj_dev = strtoul(maj_dev_start, NULL, 16);
336 if (mapping_name == 0) {
337 while (*p && *p++ != '\n');
339 while (*p && *p != '\n' && *p != '/' && *p != '[') p++;
341 while (*p && *p++ != '\n');
347 /* Try to read the backing store base from /proc/self/maps. */
348 /* Return the bounds of the writable mapping with a 0 major device, */
349 /* which includes the address passed as data. */
350 /* Return FALSE if there is no such mapping. */
351 GC_bool GC_enclosing_mapping(ptr_t addr, ptr_t *startp, ptr_t *endp)
354 ptr_t my_start, my_end;
355 unsigned int maj_dev;
356 char *maps = GC_get_maps();
357 char *buf_ptr = maps;
359 if (0 == maps) return(FALSE);
361 buf_ptr = GC_parse_map_entry(buf_ptr, &my_start, &my_end,
364 if (buf_ptr == NULL) return FALSE;
365 if (prot[1] == 'w' && maj_dev == 0) {
366 if (my_end > addr && my_start <= addr) {
376 #if defined(REDIRECT_MALLOC)
377 /* Find the text(code) mapping for the library whose name, after */
378 /* stripping the directory part, starts with nm. */
379 GC_bool GC_text_mapping(char *nm, ptr_t *startp, ptr_t *endp)
381 size_t nm_len = strlen(nm);
384 ptr_t my_start, my_end;
385 unsigned int maj_dev;
386 char *maps = GC_get_maps();
387 char *buf_ptr = maps;
389 if (0 == maps) return(FALSE);
391 buf_ptr = GC_parse_map_entry(buf_ptr, &my_start, &my_end,
392 &prot, &maj_dev, &map_path);
394 if (buf_ptr == NULL) return FALSE;
395 if (prot[0] == 'r' && prot[1] == '-' && prot[2] == 'x') {
397 /* Set p to point just past last slash, if any. */
398 while (*p != '\0' && *p != '\n' && *p != ' ' && *p != '\t') ++p;
399 while (*p != '/' && p >= map_path) --p;
401 if (strncmp(nm, p, nm_len) == 0) {
410 #endif /* REDIRECT_MALLOC */
413 static ptr_t backing_store_base_from_proc(void)
415 ptr_t my_start, my_end;
416 if (!GC_enclosing_mapping(GC_save_regs_in_stack(), &my_start, &my_end)) {
417 if (GC_print_stats) {
418 GC_log_printf("Failed to find backing store base from /proc\n");
426 #endif /* NEED_PROC_MAPS */
428 #if defined(SEARCH_FOR_DATA_START)
429 /* The I386 case can be handled without a search. The Alpha case */
430 /* used to be handled differently as well, but the rules changed */
431 /* for recent Linux versions. This seems to be the easiest way to */
432 /* cover all versions. */
434 # if defined(LINUX) || defined(HURD)
435 /* Some Linux distributions arrange to define __data_start. Some */
436 /* define data_start as a weak symbol. The latter is technically */
437 /* broken, since the user program may define data_start, in which */
438 /* case we lose. Nonetheless, we try both, prefering __data_start. */
439 /* We assume gcc-compatible pragmas. */
440 # pragma weak __data_start
441 extern int __data_start[];
442 # pragma weak data_start
443 extern int data_start[];
449 void GC_init_linux_data_start()
451 extern ptr_t GC_find_limit(ptr_t, GC_bool);
453 # if defined(LINUX) || defined(HURD)
454 /* Try the easy approaches first: */
455 if ((ptr_t)__data_start != 0) {
456 GC_data_start = (ptr_t)(__data_start);
459 if ((ptr_t)data_start != 0) {
460 GC_data_start = (ptr_t)(data_start);
464 GC_data_start = GC_find_limit((ptr_t)(_end), FALSE);
470 # ifndef ECOS_GC_MEMORY_SIZE
471 # define ECOS_GC_MEMORY_SIZE (448 * 1024)
472 # endif /* ECOS_GC_MEMORY_SIZE */
474 // FIXME: This is a simple way of allocating memory which is
475 // compatible with ECOS early releases. Later releases use a more
476 // sophisticated means of allocating memory than this simple static
477 // allocator, but this method is at least bound to work.
478 static char memory[ECOS_GC_MEMORY_SIZE];
479 static char *brk = memory;
481 static void *tiny_sbrk(ptrdiff_t increment)
487 if (brk > memory + sizeof memory)
495 #define sbrk tiny_sbrk
498 #if (defined(NETBSD) || defined(OPENBSD)) && defined(__ELF__)
501 void GC_init_netbsd_elf(void)
503 extern ptr_t GC_find_limit(ptr_t, GC_bool);
504 extern char **environ;
505 /* This may need to be environ, without the underscore, for */
507 GC_data_start = GC_find_limit((ptr_t)&environ, FALSE);
515 # if !defined(__IBMC__) && !defined(__WATCOMC__) /* e.g. EMX */
518 unsigned short magic_number;
519 unsigned short padding[29];
523 #define E_MAGIC(x) (x).magic_number
524 #define EMAGIC 0x5A4D
525 #define E_LFANEW(x) (x).new_exe_offset
528 unsigned char magic_number[2];
529 unsigned char byte_order;
530 unsigned char word_order;
531 unsigned long exe_format_level;
534 unsigned long padding1[13];
535 unsigned long object_table_offset;
536 unsigned long object_count;
537 unsigned long padding2[31];
540 #define E32_MAGIC1(x) (x).magic_number[0]
541 #define E32MAGIC1 'L'
542 #define E32_MAGIC2(x) (x).magic_number[1]
543 #define E32MAGIC2 'X'
544 #define E32_BORDER(x) (x).byte_order
546 #define E32_WORDER(x) (x).word_order
548 #define E32_CPU(x) (x).cpu
550 #define E32_OBJTAB(x) (x).object_table_offset
551 #define E32_OBJCNT(x) (x).object_count
557 unsigned long pagemap;
558 unsigned long mapsize;
559 unsigned long reserved;
562 #define O32_FLAGS(x) (x).flags
563 #define OBJREAD 0x0001L
564 #define OBJWRITE 0x0002L
565 #define OBJINVALID 0x0080L
566 #define O32_SIZE(x) (x).size
567 #define O32_BASE(x) (x).base
569 # else /* IBM's compiler */
571 /* A kludge to get around what appears to be a header file bug */
573 # define WORD unsigned short
576 # define DWORD unsigned long
583 # endif /* __IBMC__ */
585 # define INCL_DOSEXCEPTIONS
586 # define INCL_DOSPROCESS
587 # define INCL_DOSERRORS
588 # define INCL_DOSMODULEMGR
589 # define INCL_DOSMEMMGR
593 /* Disable and enable signals during nontrivial allocations */
595 void GC_disable_signals(void)
599 DosEnterMustComplete(&nest);
600 if (nest != 1) ABORT("nested GC_disable_signals");
603 void GC_enable_signals(void)
607 DosExitMustComplete(&nest);
608 if (nest != 0) ABORT("GC_enable_signals");
614 # if !defined(PCR) && !defined(AMIGA) && !defined(MSWIN32) \
615 && !defined(MSWINCE) \
616 && !defined(MACOS) && !defined(DJGPP) && !defined(DOS4GW) \
617 && !defined(NOSYS) && !defined(ECOS)
620 /* Use the traditional BSD interface */
621 # define SIGSET_T int
622 # define SIG_DEL(set, signal) (set) &= ~(sigmask(signal))
623 # define SIG_FILL(set) (set) = 0x7fffffff
624 /* Setting the leading bit appears to provoke a bug in some */
625 /* longjmp implementations. Most systems appear not to have */
627 # define SIGSETMASK(old, new) (old) = sigsetmask(new)
630 /* Use POSIX/SYSV interface */
631 # define SIGSET_T sigset_t
632 # define SIG_DEL(set, signal) sigdelset(&(set), (signal))
633 # define SIG_FILL(set) sigfillset(&set)
634 # define SIGSETMASK(old, new) sigprocmask(SIG_SETMASK, &(new), &(old))
637 static GC_bool mask_initialized = FALSE;
639 static SIGSET_T new_mask;
641 static SIGSET_T old_mask;
643 static SIGSET_T dummy;
645 #if defined(GC_ASSERTIONS) && !defined(THREADS)
646 # define CHECK_SIGNALS
647 int GC_sig_disabled = 0;
650 void GC_disable_signals(void)
652 if (!mask_initialized) {
655 SIG_DEL(new_mask, SIGSEGV);
656 SIG_DEL(new_mask, SIGILL);
657 SIG_DEL(new_mask, SIGQUIT);
659 SIG_DEL(new_mask, SIGBUS);
662 SIG_DEL(new_mask, SIGIOT);
665 SIG_DEL(new_mask, SIGEMT);
668 SIG_DEL(new_mask, SIGTRAP);
670 mask_initialized = TRUE;
672 # ifdef CHECK_SIGNALS
673 if (GC_sig_disabled != 0) ABORT("Nested disables");
676 SIGSETMASK(old_mask,new_mask);
679 void GC_enable_signals(void)
681 # ifdef CHECK_SIGNALS
682 if (GC_sig_disabled != 1) ABORT("Unmatched enable");
685 SIGSETMASK(dummy,old_mask);
692 /* Ivan Demakov: simplest way (to me) */
694 void GC_disable_signals() { }
695 void GC_enable_signals() { }
698 /* Find the page size */
701 # if defined(MSWIN32) || defined(MSWINCE)
702 void GC_setpagesize(void)
704 GetSystemInfo(&GC_sysinfo);
705 GC_page_size = GC_sysinfo.dwPageSize;
709 # if defined(MPROTECT_VDB) || defined(PROC_VDB) || defined(USE_MMAP)
710 void GC_setpagesize(void)
712 GC_page_size = GETPAGESIZE();
715 /* It's acceptable to fake it. */
716 void GC_setpagesize(void)
718 GC_page_size = HBLKSIZE;
724 * Find the base of the stack.
725 * Used only in single-threaded environment.
726 * With threads, GC_mark_roots needs to know how to do this.
727 * Called with allocator lock held.
729 # if defined(MSWIN32) || defined(MSWINCE) || defined(CYGWIN32)
730 # define is_writable(prot) ((prot) == PAGE_READWRITE \
731 || (prot) == PAGE_WRITECOPY \
732 || (prot) == PAGE_EXECUTE_READWRITE \
733 || (prot) == PAGE_EXECUTE_WRITECOPY)
734 /* Return the number of bytes that are writable starting at p. */
735 /* The pointer p is assumed to be page aligned. */
736 /* If base is not 0, *base becomes the beginning of the */
737 /* allocation region containing p. */
738 word GC_get_writable_length(ptr_t p, ptr_t *base)
740 MEMORY_BASIC_INFORMATION buf;
744 result = VirtualQuery(p, &buf, sizeof(buf));
745 if (result != sizeof(buf)) ABORT("Weird VirtualQuery result");
746 if (base != 0) *base = (ptr_t)(buf.AllocationBase);
747 protect = (buf.Protect & ~(PAGE_GUARD | PAGE_NOCACHE));
748 if (!is_writable(protect)) {
751 if (buf.State != MEM_COMMIT) return(0);
752 return(buf.RegionSize);
755 GC_API int GC_get_stack_base(struct GC_stack_base *sb)
758 ptr_t sp = (ptr_t)(&dummy);
759 ptr_t trunc_sp = (ptr_t)((word)sp & ~(GC_page_size - 1));
760 word size = GC_get_writable_length(trunc_sp, 0);
762 sb -> mem_base = trunc_sp + size;
766 #define HAVE_GET_STACK_BASE
768 /* This is always called from the main thread. */
769 ptr_t GC_get_main_stack_base(void)
771 struct GC_stack_base sb;
773 GC_get_stack_base(&sb);
774 return (ptr_t)sb.mem_base;
777 # endif /* MS Windows */
780 # include <kernel/OS.h>
781 ptr_t GC_get_main_stack_base(void){
783 get_thread_info(find_thread(NULL),&th);
791 ptr_t GC_get_main_stack_base(void)
796 if (DosGetInfoBlocks(&ptib, &ppib) != NO_ERROR) {
797 GC_err_printf("DosGetInfoBlocks failed\n");
798 ABORT("DosGetInfoBlocks failed\n");
800 return((ptr_t)(ptib -> tib_pstacklimit));
807 # include "AmigaOS.c"
811 # if defined(NEED_FIND_LIMIT) || defined(UNIX_LIKE)
813 typedef void (*handler)(int);
815 # if defined(SUNOS5SIGS) || defined(IRIX5) || defined(OSF1) \
816 || defined(HURD) || defined(NETBSD)
817 static struct sigaction old_segv_act;
818 # if defined(_sigargs) /* !Irix6.x */ || defined(HPUX) \
819 || defined(HURD) || defined(NETBSD)
820 static struct sigaction old_bus_act;
823 static handler old_segv_handler, old_bus_handler;
826 void GC_set_and_save_fault_handler(handler h)
828 # if defined(SUNOS5SIGS) || defined(IRIX5) \
829 || defined(OSF1) || defined(HURD) || defined(NETBSD)
830 struct sigaction act;
833 # if 0 /* Was necessary for Solaris 2.3 and very temporary */
835 act.sa_flags = SA_RESTART | SA_NODEFER;
837 act.sa_flags = SA_RESTART;
840 (void) sigemptyset(&act.sa_mask);
841 # ifdef GC_IRIX_THREADS
842 /* Older versions have a bug related to retrieving and */
843 /* and setting a handler at the same time. */
844 (void) sigaction(SIGSEGV, 0, &old_segv_act);
845 (void) sigaction(SIGSEGV, &act, 0);
847 (void) sigaction(SIGSEGV, &act, &old_segv_act);
848 # if defined(IRIX5) && defined(_sigargs) /* Irix 5.x, not 6.x */ \
849 || defined(HPUX) || defined(HURD) || defined(NETBSD)
850 /* Under Irix 5.x or HP/UX, we may get SIGBUS. */
851 /* Pthreads doesn't exist under Irix 5.x, so we */
852 /* don't have to worry in the threads case. */
853 (void) sigaction(SIGBUS, &act, &old_bus_act);
855 # endif /* GC_IRIX_THREADS */
857 old_segv_handler = signal(SIGSEGV, h);
859 old_bus_handler = signal(SIGBUS, h);
863 # endif /* NEED_FIND_LIMIT || UNIX_LIKE */
865 # if defined(NEED_FIND_LIMIT) || \
866 defined(USE_PROC_FOR_LIBRARIES) && defined(THREADS)
867 /* Some tools to implement HEURISTIC2 */
868 # define MIN_PAGE_SIZE 256 /* Smallest conceivable page size, bytes */
871 void GC_fault_handler(int sig)
873 LONGJMP(GC_jmp_buf, 1);
876 void GC_setup_temporary_fault_handler(void)
878 /* Handler is process-wide, so this should only happen in */
879 /* one thread at a time. */
880 GC_ASSERT(I_HOLD_LOCK());
881 GC_set_and_save_fault_handler(GC_fault_handler);
884 void GC_reset_fault_handler(void)
886 # if defined(SUNOS5SIGS) || defined(IRIX5) \
887 || defined(OSF1) || defined(HURD) || defined(NETBSD)
888 (void) sigaction(SIGSEGV, &old_segv_act, 0);
889 # if defined(IRIX5) && defined(_sigargs) /* Irix 5.x, not 6.x */ \
890 || defined(HPUX) || defined(HURD) || defined(NETBSD)
891 (void) sigaction(SIGBUS, &old_bus_act, 0);
894 (void) signal(SIGSEGV, old_segv_handler);
896 (void) signal(SIGBUS, old_bus_handler);
901 /* Return the first nonaddressible location > p (up) or */
902 /* the smallest location q s.t. [q,p) is addressable (!up). */
903 /* We assume that p (up) or p-1 (!up) is addressable. */
904 /* Requires allocation lock. */
905 ptr_t GC_find_limit_with_bound(ptr_t p, GC_bool up, ptr_t bound)
907 static volatile ptr_t result;
908 /* Safer if static, since otherwise it may not be */
909 /* preserved across the longjmp. Can safely be */
910 /* static since it's only called with the */
911 /* allocation lock held. */
913 GC_ASSERT(I_HOLD_LOCK());
914 GC_setup_temporary_fault_handler();
915 if (SETJMP(GC_jmp_buf) == 0) {
916 result = (ptr_t)(((word)(p))
917 & ~(MIN_PAGE_SIZE-1));
920 result += MIN_PAGE_SIZE;
921 if (result >= bound) return bound;
923 result -= MIN_PAGE_SIZE;
924 if (result <= bound) return bound;
926 GC_noop1((word)(*result));
929 GC_reset_fault_handler();
931 result += MIN_PAGE_SIZE;
936 ptr_t GC_find_limit(ptr_t p, GC_bool up)
939 return GC_find_limit_with_bound(p, up, (ptr_t)(word)(-1));
941 return GC_find_limit_with_bound(p, up, 0);
946 #if defined(ECOS) || defined(NOSYS)
947 ptr_t GC_get_main_stack_base(void)
953 #ifdef HPUX_STACKBOTTOM
955 #include <sys/param.h>
956 #include <sys/pstat.h>
958 ptr_t GC_get_register_stack_base(void)
960 struct pst_vm_status vm_status;
963 while (pstat_getprocvm(&vm_status, sizeof(vm_status), 0, i++) == 1) {
964 if (vm_status.pst_type == PS_RSESTACK) {
965 return (ptr_t) vm_status.pst_vaddr;
969 /* old way to get the register stackbottom */
970 return (ptr_t)(((word)GC_stackbottom - BACKING_STORE_DISPLACEMENT - 1)
971 & ~(BACKING_STORE_ALIGNMENT - 1));
974 #endif /* HPUX_STACK_BOTTOM */
976 #ifdef LINUX_STACKBOTTOM
978 #include <sys/types.h>
979 #include <sys/stat.h>
981 # define STAT_SKIP 27 /* Number of fields preceding startstack */
982 /* field in /proc/self/stat */
984 #ifdef USE_LIBC_PRIVATES
985 # pragma weak __libc_stack_end
986 extern ptr_t __libc_stack_end;
990 # ifdef USE_LIBC_PRIVATES
991 # pragma weak __libc_ia64_register_backing_store_base
992 extern ptr_t __libc_ia64_register_backing_store_base;
995 ptr_t GC_get_register_stack_base(void)
999 # ifdef USE_LIBC_PRIVATES
1000 if (0 != &__libc_ia64_register_backing_store_base
1001 && 0 != __libc_ia64_register_backing_store_base) {
1002 /* Glibc 2.2.4 has a bug such that for dynamically linked */
1003 /* executables __libc_ia64_register_backing_store_base is */
1004 /* defined but uninitialized during constructor calls. */
1005 /* Hence we check for both nonzero address and value. */
1006 return __libc_ia64_register_backing_store_base;
1009 result = backing_store_base_from_proc();
1011 result = GC_find_limit(GC_save_regs_in_stack(), FALSE);
1012 /* Now seems to work better than constant displacement */
1013 /* heuristic used in 6.X versions. The latter seems to */
1014 /* fail for 2.6 kernels. */
1020 ptr_t GC_linux_stack_base(void)
1022 /* We read the stack base value from /proc/self/stat. We do this */
1023 /* using direct I/O system calls in order to avoid calling malloc */
1024 /* in case REDIRECT_MALLOC is defined. */
1025 # define STAT_BUF_SIZE 4096
1026 # define STAT_READ read
1027 /* Should probably call the real read, if read is wrapped. */
1028 char stat_buf[STAT_BUF_SIZE];
1032 size_t i, buf_offset = 0;
1034 /* First try the easy way. This should work for glibc 2.2 */
1035 /* This fails in a prelinked ("prelink" command) executable */
1036 /* since the correct value of __libc_stack_end never */
1037 /* becomes visible to us. The second test works around */
1039 # ifdef USE_LIBC_PRIVATES
1040 if (0 != &__libc_stack_end && 0 != __libc_stack_end ) {
1042 /* Some versions of glibc set the address 16 bytes too */
1043 /* low while the initialization code is running. */
1044 if (((word)__libc_stack_end & 0xfff) + 0x10 < 0x1000) {
1045 return __libc_stack_end + 0x10;
1046 } /* Otherwise it's not safe to add 16 bytes and we fall */
1047 /* back to using /proc. */
1048 # elif defined(SPARC)
1049 /* Older versions of glibc for 64-bit Sparc do not set
1050 * this variable correctly, it gets set to either zero
1053 if (__libc_stack_end != (ptr_t) (unsigned long)0x1)
1054 return __libc_stack_end;
1056 return __libc_stack_end;
1060 f = open("/proc/self/stat", O_RDONLY);
1061 if (f < 0 || STAT_READ(f, stat_buf, STAT_BUF_SIZE) < 2 * STAT_SKIP) {
1062 ABORT("Couldn't read /proc/self/stat");
1064 c = stat_buf[buf_offset++];
1065 /* Skip the required number of fields. This number is hopefully */
1066 /* constant across all Linux implementations. */
1067 for (i = 0; i < STAT_SKIP; ++i) {
1068 while (isspace(c)) c = stat_buf[buf_offset++];
1069 while (!isspace(c)) c = stat_buf[buf_offset++];
1071 while (isspace(c)) c = stat_buf[buf_offset++];
1072 while (isdigit(c)) {
1075 c = stat_buf[buf_offset++];
1078 if (result < 0x10000000) ABORT("Absurd stack bottom value");
1079 return (ptr_t)result;
1082 #endif /* LINUX_STACKBOTTOM */
1084 #ifdef FREEBSD_STACKBOTTOM
1086 /* This uses an undocumented sysctl call, but at least one expert */
1087 /* believes it will stay. */
1090 #include <sys/types.h>
1091 #include <sys/sysctl.h>
1093 ptr_t GC_freebsd_stack_base(void)
1095 int nm[2] = {CTL_KERN, KERN_USRSTACK};
1097 size_t len = sizeof(ptr_t);
1098 int r = sysctl(nm, 2, &base, &len, NULL, 0);
1100 if (r) ABORT("Error getting stack base");
1105 #endif /* FREEBSD_STACKBOTTOM */
1107 #if !defined(BEOS) && !defined(AMIGA) && !defined(MSWIN32) \
1108 && !defined(MSWINCE) && !defined(OS2) && !defined(NOSYS) && !defined(ECOS) \
1109 && !defined(CYGWIN32)
1111 ptr_t GC_get_main_stack_base(void)
1113 # if defined(HEURISTIC1) || defined(HEURISTIC2)
1118 # define STACKBOTTOM_ALIGNMENT_M1 ((word)STACK_GRAN - 1)
1121 return(STACKBOTTOM);
1124 # ifdef STACK_GROWS_DOWN
1125 result = (ptr_t)((((word)(&dummy))
1126 + STACKBOTTOM_ALIGNMENT_M1)
1127 & ~STACKBOTTOM_ALIGNMENT_M1);
1129 result = (ptr_t)(((word)(&dummy))
1130 & ~STACKBOTTOM_ALIGNMENT_M1);
1132 # endif /* HEURISTIC1 */
1133 # ifdef LINUX_STACKBOTTOM
1134 result = GC_linux_stack_base();
1136 # ifdef FREEBSD_STACKBOTTOM
1137 result = GC_freebsd_stack_base();
1140 # ifdef STACK_GROWS_DOWN
1141 result = GC_find_limit((ptr_t)(&dummy), TRUE);
1142 # ifdef HEURISTIC2_LIMIT
1143 if (result > HEURISTIC2_LIMIT
1144 && (ptr_t)(&dummy) < HEURISTIC2_LIMIT) {
1145 result = HEURISTIC2_LIMIT;
1149 result = GC_find_limit((ptr_t)(&dummy), FALSE);
1150 # ifdef HEURISTIC2_LIMIT
1151 if (result < HEURISTIC2_LIMIT
1152 && (ptr_t)(&dummy) > HEURISTIC2_LIMIT) {
1153 result = HEURISTIC2_LIMIT;
1158 # endif /* HEURISTIC2 */
1159 # ifdef STACK_GROWS_DOWN
1160 if (result == 0) result = (ptr_t)(signed_word)(-sizeof(ptr_t));
1163 # endif /* STACKBOTTOM */
1166 # endif /* ! AMIGA, !OS 2, ! MS Windows, !BEOS, !NOSYS, !ECOS */
1168 #if defined(GC_LINUX_THREADS) && !defined(HAVE_GET_STACK_BASE)
1170 #include <pthread.h>
1173 ptr_t GC_greatest_stack_base_below(ptr_t bound);
1174 /* From pthread_support.c */
1177 int GC_get_stack_base(struct GC_stack_base *b)
1179 pthread_attr_t attr;
1182 if (pthread_getattr_np(pthread_self(), &attr) != 0) {
1183 WARN("pthread_getattr_np failed\n", 0);
1184 return GC_UNIMPLEMENTED;
1186 if (pthread_attr_getstack(&attr, &(b -> mem_base), &size) != 0) {
1187 ABORT("pthread_attr_getstack failed");
1189 # ifdef STACK_GROWS_DOWN
1190 b -> mem_base = (char *)(b -> mem_base) + size;
1193 /* We could try backing_store_base_from_proc, but that's safe */
1194 /* only if no mappings are being asynchronously created. */
1195 /* Subtracting the size from the stack base doesn't work for at */
1196 /* least the main thread. */
1199 ptr_t bsp = GC_save_regs_in_stack();
1200 ptr_t next_stack = GC_greatest_stack_base_below(bsp);
1201 if (0 == next_stack) {
1202 b -> reg_base = GC_find_limit(bsp, FALSE);
1204 /* Avoid walking backwards into preceding memory stack and */
1206 b -> reg_base = GC_find_limit_with_bound(bsp, FALSE, next_stack);
1214 #define HAVE_GET_STACK_BASE
1216 #endif /* GC_LINUX_THREADS */
1218 #ifndef HAVE_GET_STACK_BASE
1219 /* Retrieve stack base. */
1220 /* Using the GC_find_limit version is risky. */
1221 /* On IA64, for example, there is no guard page between the */
1222 /* stack of one thread and the register backing store of the */
1223 /* next. Thus this is likely to identify way too large a */
1224 /* "stack" and thus at least result in disastrous performance. */
1225 /* FIXME - Implement better strategies here. */
1226 int GC_get_stack_base(struct GC_stack_base *b)
1230 # ifdef NEED_FIND_LIMIT
1231 # ifdef STACK_GROWS_DOWN
1232 b -> mem_base = GC_find_limit((ptr_t)(&dummy), TRUE);
1234 b -> reg_base = GC_find_limit(GC_save_regs_in_stack(), FALSE);
1237 b -> mem_base = GC_find_limit(&dummy, FALSE);
1241 return GC_UNIMPLEMENTED;
1247 * Register static data segment(s) as roots.
1248 * If more data segments are added later then they need to be registered
1249 * add that point (as we do with SunOS dynamic loading),
1250 * or GC_mark_roots needs to check for them (as we do with PCR).
1251 * Called with allocator lock held.
1256 void GC_register_data_segments(void)
1260 HMODULE module_handle;
1261 # define PBUFSIZ 512
1262 UCHAR path[PBUFSIZ];
1264 struct exe_hdr hdrdos; /* MSDOS header. */
1265 struct e32_exe hdr386; /* Real header for my executable */
1266 struct o32_obj seg; /* Currrent segment */
1270 if (DosGetInfoBlocks(&ptib, &ppib) != NO_ERROR) {
1271 GC_err_printf("DosGetInfoBlocks failed\n");
1272 ABORT("DosGetInfoBlocks failed\n");
1274 module_handle = ppib -> pib_hmte;
1275 if (DosQueryModuleName(module_handle, PBUFSIZ, path) != NO_ERROR) {
1276 GC_err_printf("DosQueryModuleName failed\n");
1277 ABORT("DosGetInfoBlocks failed\n");
1279 myexefile = fopen(path, "rb");
1280 if (myexefile == 0) {
1281 GC_err_puts("Couldn't open executable ");
1282 GC_err_puts(path); GC_err_puts("\n");
1283 ABORT("Failed to open executable\n");
1285 if (fread((char *)(&hdrdos), 1, sizeof hdrdos, myexefile) < sizeof hdrdos) {
1286 GC_err_puts("Couldn't read MSDOS header from ");
1287 GC_err_puts(path); GC_err_puts("\n");
1288 ABORT("Couldn't read MSDOS header");
1290 if (E_MAGIC(hdrdos) != EMAGIC) {
1291 GC_err_puts("Executable has wrong DOS magic number: ");
1292 GC_err_puts(path); GC_err_puts("\n");
1293 ABORT("Bad DOS magic number");
1295 if (fseek(myexefile, E_LFANEW(hdrdos), SEEK_SET) != 0) {
1296 GC_err_puts("Seek to new header failed in ");
1297 GC_err_puts(path); GC_err_puts("\n");
1298 ABORT("Bad DOS magic number");
1300 if (fread((char *)(&hdr386), 1, sizeof hdr386, myexefile) < sizeof hdr386) {
1301 GC_err_puts("Couldn't read MSDOS header from ");
1302 GC_err_puts(path); GC_err_puts("\n");
1303 ABORT("Couldn't read OS/2 header");
1305 if (E32_MAGIC1(hdr386) != E32MAGIC1 || E32_MAGIC2(hdr386) != E32MAGIC2) {
1306 GC_err_puts("Executable has wrong OS/2 magic number:");
1307 GC_err_puts(path); GC_err_puts("\n");
1308 ABORT("Bad OS/2 magic number");
1310 if ( E32_BORDER(hdr386) != E32LEBO || E32_WORDER(hdr386) != E32LEWO) {
1311 GC_err_puts("Executable %s has wrong byte order: ");
1312 GC_err_puts(path); GC_err_puts("\n");
1313 ABORT("Bad byte order");
1315 if ( E32_CPU(hdr386) == E32CPU286) {
1316 GC_err_puts("GC can't handle 80286 executables: ");
1317 GC_err_puts(path); GC_err_puts("\n");
1320 if (fseek(myexefile, E_LFANEW(hdrdos) + E32_OBJTAB(hdr386),
1322 GC_err_puts("Seek to object table failed: ");
1323 GC_err_puts(path); GC_err_puts("\n");
1324 ABORT("Seek to object table failed");
1326 for (nsegs = E32_OBJCNT(hdr386); nsegs > 0; nsegs--) {
1328 if (fread((char *)(&seg), 1, sizeof seg, myexefile) < sizeof seg) {
1329 GC_err_puts("Couldn't read obj table entry from ");
1330 GC_err_puts(path); GC_err_puts("\n");
1331 ABORT("Couldn't read obj table entry");
1333 flags = O32_FLAGS(seg);
1334 if (!(flags & OBJWRITE)) continue;
1335 if (!(flags & OBJREAD)) continue;
1336 if (flags & OBJINVALID) {
1337 GC_err_printf("Object with invalid pages?\n");
1340 GC_add_roots_inner(O32_BASE(seg), O32_BASE(seg)+O32_SIZE(seg), FALSE);
1346 # if defined(MSWIN32) || defined(MSWINCE)
1349 /* Unfortunately, we have to handle win32s very differently from NT, */
1350 /* Since VirtualQuery has very different semantics. In particular, */
1351 /* under win32s a VirtualQuery call on an unmapped page returns an */
1352 /* invalid result. Under NT, GC_register_data_segments is a noop and */
1353 /* all real work is done by GC_register_dynamic_libraries. Under */
1354 /* win32s, we cannot find the data segments associated with dll's. */
1355 /* We register the main data segment here. */
1356 GC_bool GC_no_win32_dlls = FALSE;
1357 /* This used to be set for gcc, to avoid dealing with */
1358 /* the structured exception handling issues. But we now have */
1359 /* assembly code to do that right. */
1361 # if defined(GWW_VDB)
1363 # ifndef _BASETSD_H_
1364 typedef ULONG * PULONG_PTR;
1366 typedef UINT (WINAPI * GetWriteWatch_type)(
1367 DWORD, PVOID, SIZE_T, PVOID*, PULONG_PTR, PULONG);
1368 static GetWriteWatch_type GetWriteWatch_func;
1369 static DWORD GetWriteWatch_alloc_flag;
1371 # define GC_GWW_AVAILABLE() (GetWriteWatch_func != NULL)
1373 static void detect_GetWriteWatch(void)
1375 static GC_bool done;
1379 GetWriteWatch_func = (GetWriteWatch_type)
1380 GetProcAddress(GetModuleHandle("kernel32.dll"), "GetWriteWatch");
1381 if (GetWriteWatch_func != NULL) {
1382 /* Also check whether VirtualAlloc accepts MEM_WRITE_WATCH, */
1383 /* as some versions of kernel32.dll have one but not the */
1384 /* other, making the feature completely broken. */
1385 void * page = VirtualAlloc(NULL, GC_page_size,
1386 MEM_WRITE_WATCH | MEM_RESERVE,
1390 ULONG_PTR count = 16;
1392 /* Check that it actually works. In spite of some */
1393 /* documentation it actually seems to exist on W2K. */
1394 /* This test may be unnecessary, but ... */
1395 if (GetWriteWatch_func(WRITE_WATCH_FLAG_RESET,
1400 /* GetWriteWatch always fails. */
1401 GetWriteWatch_func = NULL;
1403 GetWriteWatch_alloc_flag = MEM_WRITE_WATCH;
1405 VirtualFree(page, GC_page_size, MEM_RELEASE);
1407 /* GetWriteWatch will be useless. */
1408 GetWriteWatch_func = NULL;
1411 if (GC_print_stats) {
1412 if (GetWriteWatch_func == NULL) {
1413 GC_log_printf("Did not find a usable GetWriteWatch()\n");
1415 GC_log_printf("Using GetWriteWatch()\n");
1421 # endif /* GWW_VDB */
1423 GC_bool GC_wnt = FALSE;
1424 /* This is a Windows NT derivative, i.e. NT, W2K, XP or later. */
1426 void GC_init_win32(void)
1429 /* If we're running under win32s, assume that no DLLs will be loaded */
1430 /* I doubt anyone still runs win32s, but ... */
1431 DWORD v = GetVersion();
1432 GC_wnt = !(v & 0x80000000);
1433 GC_no_win32_dlls |= ((!GC_wnt) && (v & 0xff) <= 3);
1436 /* Return the smallest address a such that VirtualQuery */
1437 /* returns correct results for all addresses between a and start. */
1438 /* Assumes VirtualQuery returns correct information for start. */
1439 ptr_t GC_least_described_address(ptr_t start)
1441 MEMORY_BASIC_INFORMATION buf;
1447 limit = GC_sysinfo.lpMinimumApplicationAddress;
1448 p = (ptr_t)((word)start & ~(GC_page_size - 1));
1450 q = (LPVOID)(p - GC_page_size);
1451 if ((ptr_t)q > (ptr_t)p /* underflow */ || q < limit) break;
1452 result = VirtualQuery(q, &buf, sizeof(buf));
1453 if (result != sizeof(buf) || buf.AllocationBase == 0) break;
1454 p = (ptr_t)(buf.AllocationBase);
1460 # ifndef REDIRECT_MALLOC
1461 /* We maintain a linked list of AllocationBase values that we know */
1462 /* correspond to malloc heap sections. Currently this is only called */
1463 /* during a GC. But there is some hope that for long running */
1464 /* programs we will eventually see most heap sections. */
1466 /* In the long run, it would be more reliable to occasionally walk */
1467 /* the malloc heap with HeapWalk on the default heap. But that */
1468 /* apparently works only for NT-based Windows. */
1470 /* In the long run, a better data structure would also be nice ... */
1471 struct GC_malloc_heap_list {
1472 void * allocation_base;
1473 struct GC_malloc_heap_list *next;
1474 } *GC_malloc_heap_l = 0;
1476 /* Is p the base of one of the malloc heap sections we already know */
1478 GC_bool GC_is_malloc_heap_base(ptr_t p)
1480 struct GC_malloc_heap_list *q = GC_malloc_heap_l;
1483 if (q -> allocation_base == p) return TRUE;
1489 void *GC_get_allocation_base(void *p)
1491 MEMORY_BASIC_INFORMATION buf;
1492 size_t result = VirtualQuery(p, &buf, sizeof(buf));
1493 if (result != sizeof(buf)) {
1494 ABORT("Weird VirtualQuery result");
1496 return buf.AllocationBase;
1499 size_t GC_max_root_size = 100000; /* Appr. largest root size. */
1501 void GC_add_current_malloc_heap()
1503 struct GC_malloc_heap_list *new_l =
1504 malloc(sizeof(struct GC_malloc_heap_list));
1505 void * candidate = GC_get_allocation_base(new_l);
1507 if (new_l == 0) return;
1508 if (GC_is_malloc_heap_base(candidate)) {
1509 /* Try a little harder to find malloc heap. */
1510 size_t req_size = 10000;
1512 void *p = malloc(req_size);
1513 if (0 == p) { free(new_l); return; }
1514 candidate = GC_get_allocation_base(p);
1517 } while (GC_is_malloc_heap_base(candidate)
1518 && req_size < GC_max_root_size/10 && req_size < 500000);
1519 if (GC_is_malloc_heap_base(candidate)) {
1520 free(new_l); return;
1524 GC_log_printf("Found new system malloc AllocationBase at %p\n",
1526 new_l -> allocation_base = candidate;
1527 new_l -> next = GC_malloc_heap_l;
1528 GC_malloc_heap_l = new_l;
1530 # endif /* REDIRECT_MALLOC */
1532 /* Is p the start of either the malloc heap, or of one of our */
1533 /* heap sections? */
1534 GC_bool GC_is_heap_base (ptr_t p)
1539 # ifndef REDIRECT_MALLOC
1540 if (GC_root_size > GC_max_root_size) GC_max_root_size = GC_root_size;
1541 if (GC_is_malloc_heap_base(p)) return TRUE;
1543 for (i = 0; i < GC_n_heap_bases; i++) {
1544 if (GC_heap_bases[i] == p) return TRUE;
1550 void GC_register_root_section(ptr_t static_root)
1552 MEMORY_BASIC_INFORMATION buf;
1557 char * limit, * new_limit;
1559 if (!GC_no_win32_dlls) return;
1560 p = base = limit = GC_least_described_address(static_root);
1561 while (p < GC_sysinfo.lpMaximumApplicationAddress) {
1562 result = VirtualQuery(p, &buf, sizeof(buf));
1563 if (result != sizeof(buf) || buf.AllocationBase == 0
1564 || GC_is_heap_base(buf.AllocationBase)) break;
1565 new_limit = (char *)p + buf.RegionSize;
1566 protect = buf.Protect;
1567 if (buf.State == MEM_COMMIT
1568 && is_writable(protect)) {
1569 if ((char *)p == limit) {
1572 if (base != limit) GC_add_roots_inner(base, limit, FALSE);
1577 if (p > (LPVOID)new_limit /* overflow */) break;
1578 p = (LPVOID)new_limit;
1580 if (base != limit) GC_add_roots_inner(base, limit, FALSE);
1584 void GC_register_data_segments()
1588 GC_register_root_section((ptr_t)(&dummy));
1592 # else /* !OS2 && !Windows */
1594 # if (defined(SVR4) || defined(AUX) || defined(DGUX) \
1595 || (defined(LINUX) && defined(SPARC))) && !defined(PCR)
1596 ptr_t GC_SysVGetDataStart(size_t max_page_size, ptr_t etext_addr)
1598 word text_end = ((word)(etext_addr) + sizeof(word) - 1)
1599 & ~(sizeof(word) - 1);
1600 /* etext rounded to word boundary */
1601 word next_page = ((text_end + (word)max_page_size - 1)
1602 & ~((word)max_page_size - 1));
1603 word page_offset = (text_end & ((word)max_page_size - 1));
1604 volatile char * result = (char *)(next_page + page_offset);
1605 /* Note that this isnt equivalent to just adding */
1606 /* max_page_size to &etext if &etext is at a page boundary */
1608 GC_setup_temporary_fault_handler();
1609 if (SETJMP(GC_jmp_buf) == 0) {
1610 /* Try writing to the address. */
1612 GC_reset_fault_handler();
1614 GC_reset_fault_handler();
1615 /* We got here via a longjmp. The address is not readable. */
1616 /* This is known to happen under Solaris 2.4 + gcc, which place */
1617 /* string constants in the text segment, but after etext. */
1618 /* Use plan B. Note that we now know there is a gap between */
1619 /* text and data segments, so plan A bought us something. */
1620 result = (char *)GC_find_limit((ptr_t)(DATAEND), FALSE);
1622 return((ptr_t)result);
1626 # if defined(FREEBSD) && (defined(I386) || defined(X86_64) || defined(powerpc) || defined(__powerpc__)) && !defined(PCR)
1627 /* Its unclear whether this should be identical to the above, or */
1628 /* whether it should apply to non-X86 architectures. */
1629 /* For now we don't assume that there is always an empty page after */
1630 /* etext. But in some cases there actually seems to be slightly more. */
1631 /* This also deals with holes between read-only data and writable data. */
1632 ptr_t GC_FreeBSDGetDataStart(size_t max_page_size, ptr_t etext_addr)
1634 word text_end = ((word)(etext_addr) + sizeof(word) - 1)
1635 & ~(sizeof(word) - 1);
1636 /* etext rounded to word boundary */
1637 volatile word next_page = (text_end + (word)max_page_size - 1)
1638 & ~((word)max_page_size - 1);
1639 volatile ptr_t result = (ptr_t)text_end;
1640 GC_setup_temporary_fault_handler();
1641 if (SETJMP(GC_jmp_buf) == 0) {
1642 /* Try reading at the address. */
1643 /* This should happen before there is another thread. */
1644 for (; next_page < (word)(DATAEND); next_page += (word)max_page_size)
1645 *(volatile char *)next_page;
1646 GC_reset_fault_handler();
1648 GC_reset_fault_handler();
1649 /* As above, we go to plan B */
1650 result = GC_find_limit((ptr_t)(DATAEND), FALSE);
1660 # define GC_AMIGA_DS
1661 # include "AmigaOS.c"
1664 #else /* !OS2 && !Windows && !AMIGA */
1666 void GC_register_data_segments(void)
1668 # if !defined(PCR) && !defined(MACOS)
1669 # if defined(REDIRECT_MALLOC) && defined(GC_SOLARIS_THREADS)
1670 /* As of Solaris 2.3, the Solaris threads implementation */
1671 /* allocates the data structure for the initial thread with */
1672 /* sbrk at process startup. It needs to be scanned, so that */
1673 /* we don't lose some malloc allocated data structures */
1674 /* hanging from it. We're on thin ice here ... */
1675 extern caddr_t sbrk();
1677 GC_add_roots_inner(DATASTART, (ptr_t)sbrk(0), FALSE);
1679 GC_add_roots_inner(DATASTART, (ptr_t)(DATAEND), FALSE);
1680 # if defined(DATASTART2)
1681 GC_add_roots_inner(DATASTART2, (ptr_t)(DATAEND2), FALSE);
1687 # if defined(THINK_C)
1688 extern void* GC_MacGetDataStart(void);
1689 /* globals begin above stack and end at a5. */
1690 GC_add_roots_inner((ptr_t)GC_MacGetDataStart(),
1691 (ptr_t)LMGetCurrentA5(), FALSE);
1693 # if defined(__MWERKS__)
1695 extern void* GC_MacGetDataStart(void);
1696 /* MATTHEW: Function to handle Far Globals (CW Pro 3) */
1697 # if __option(far_data)
1698 extern void* GC_MacGetDataEnd(void);
1700 /* globals begin above stack and end at a5. */
1701 GC_add_roots_inner((ptr_t)GC_MacGetDataStart(),
1702 (ptr_t)LMGetCurrentA5(), FALSE);
1703 /* MATTHEW: Handle Far Globals */
1704 # if __option(far_data)
1705 /* Far globals follow he QD globals: */
1706 GC_add_roots_inner((ptr_t)LMGetCurrentA5(),
1707 (ptr_t)GC_MacGetDataEnd(), FALSE);
1710 extern char __data_start__[], __data_end__[];
1711 GC_add_roots_inner((ptr_t)&__data_start__,
1712 (ptr_t)&__data_end__, FALSE);
1713 # endif /* __POWERPC__ */
1714 # endif /* __MWERKS__ */
1715 # endif /* !THINK_C */
1719 /* Dynamic libraries are added at every collection, since they may */
1723 # endif /* ! AMIGA */
1724 # endif /* ! MSWIN32 && ! MSWINCE*/
1728 * Auxiliary routines for obtaining memory from OS.
1731 # if !defined(OS2) && !defined(PCR) && !defined(AMIGA) \
1732 && !defined(MSWIN32) && !defined(MSWINCE) \
1733 && !defined(MACOS) && !defined(DOS4GW) && !defined(NONSTOP)
1735 # define SBRK_ARG_T ptrdiff_t
1737 #if defined(MMAP_SUPPORTED)
1739 #ifdef USE_MMAP_FIXED
1740 # define GC_MMAP_FLAGS MAP_FIXED | MAP_PRIVATE
1741 /* Seems to yield better performance on Solaris 2, but can */
1742 /* be unreliable if something is already mapped at the address. */
1744 # define GC_MMAP_FLAGS MAP_PRIVATE
1747 #ifdef USE_MMAP_ANON
1749 # if defined(MAP_ANONYMOUS)
1750 # define OPT_MAP_ANON MAP_ANONYMOUS
1752 # define OPT_MAP_ANON MAP_ANON
1756 # define OPT_MAP_ANON 0
1760 # define HEAP_START 0
1763 ptr_t GC_unix_mmap_get_mem(word bytes)
1766 static ptr_t last_addr = HEAP_START;
1768 # ifndef USE_MMAP_ANON
1769 static GC_bool initialized = FALSE;
1772 zero_fd = open("/dev/zero", O_RDONLY);
1773 fcntl(zero_fd, F_SETFD, FD_CLOEXEC);
1778 if (bytes & (GC_page_size -1)) ABORT("Bad GET_MEM arg");
1779 result = mmap(last_addr, bytes, PROT_READ | PROT_WRITE | OPT_PROT_EXEC,
1780 GC_MMAP_FLAGS | OPT_MAP_ANON, zero_fd, 0/* offset */);
1781 if (result == MAP_FAILED) return(0);
1782 last_addr = (ptr_t)result + bytes + GC_page_size - 1;
1783 last_addr = (ptr_t)((word)last_addr & ~(GC_page_size - 1));
1784 # if !defined(LINUX)
1785 if (last_addr == 0) {
1786 /* Oops. We got the end of the address space. This isn't */
1787 /* usable by arbitrary C code, since one-past-end pointers */
1788 /* don't work, so we discard it and try again. */
1789 munmap(result, (size_t)(-GC_page_size) - (size_t)result);
1790 /* Leave last page mapped, so we can't repeat. */
1791 return GC_unix_mmap_get_mem(bytes);
1794 GC_ASSERT(last_addr != 0);
1796 return((ptr_t)result);
1799 # endif /* MMAP_SUPPORTED */
1801 #if defined(USE_MMAP)
1803 ptr_t GC_unix_get_mem(word bytes)
1805 return GC_unix_mmap_get_mem(bytes);
1808 #else /* Not USE_MMAP */
1810 ptr_t GC_unix_sbrk_get_mem(word bytes)
1814 /* Bare sbrk isn't thread safe. Play by malloc rules. */
1815 /* The equivalent may be needed on other systems as well. */
1819 ptr_t cur_brk = (ptr_t)sbrk(0);
1820 SBRK_ARG_T lsbs = (word)cur_brk & (GC_page_size-1);
1822 if ((SBRK_ARG_T)bytes < 0) {
1823 result = 0; /* too big */
1827 if((ptr_t)sbrk(GC_page_size - lsbs) == (ptr_t)(-1)) {
1832 # ifdef ADD_HEAP_GUARD_PAGES
1833 /* This is useful for catching severe memory overwrite problems that */
1834 /* span heap sections. It shouldn't otherwise be turned on. */
1836 ptr_t guard = (ptr_t)sbrk((SBRK_ARG_T)GC_page_size);
1837 if (mprotect(guard, GC_page_size, PROT_NONE) != 0)
1838 ABORT("ADD_HEAP_GUARD_PAGES: mprotect failed");
1840 # endif /* ADD_HEAP_GUARD_PAGES */
1841 result = (ptr_t)sbrk((SBRK_ARG_T)bytes);
1842 if (result == (ptr_t)(-1)) result = 0;
1851 #if defined(MMAP_SUPPORTED)
1853 /* By default, we try both sbrk and mmap, in that order. */
1854 ptr_t GC_unix_get_mem(word bytes)
1856 static GC_bool sbrk_failed = FALSE;
1859 if (!sbrk_failed) result = GC_unix_sbrk_get_mem(bytes);
1862 result = GC_unix_mmap_get_mem(bytes);
1865 /* Try sbrk again, in case sbrk memory became available. */
1866 result = GC_unix_sbrk_get_mem(bytes);
1871 #else /* !MMAP_SUPPORTED */
1873 ptr_t GC_unix_get_mem(word bytes)
1875 return GC_unix_sbrk_get_mem(bytes);
1880 #endif /* Not USE_MMAP */
1886 void * os2_alloc(size_t bytes)
1890 if (DosAllocMem(&result, bytes, PAG_EXECUTE | PAG_READ |
1891 PAG_WRITE | PAG_COMMIT)
1895 if (result == 0) return(os2_alloc(bytes));
1902 # if defined(MSWIN32) || defined(MSWINCE)
1903 SYSTEM_INFO GC_sysinfo;
1908 # ifdef USE_GLOBAL_ALLOC
1909 # define GLOBAL_ALLOC_TEST 1
1911 # define GLOBAL_ALLOC_TEST GC_no_win32_dlls
1914 word GC_n_heap_bases = 0;
1916 word GC_mem_top_down = 0; /* Change to MEM_TOP_DOWN for better 64-bit */
1917 /* testing. Otherwise all addresses tend to */
1918 /* end up in first 4GB, hiding bugs. */
1920 ptr_t GC_win32_get_mem(word bytes)
1924 if (GLOBAL_ALLOC_TEST) {
1925 /* VirtualAlloc doesn't like PAGE_EXECUTE_READWRITE. */
1926 /* There are also unconfirmed rumors of other */
1927 /* problems, so we dodge the issue. */
1928 result = (ptr_t) GlobalAlloc(0, bytes + HBLKSIZE);
1929 result = (ptr_t)(((word)result + HBLKSIZE - 1) & ~(HBLKSIZE-1));
1931 /* VirtualProtect only works on regions returned by a */
1932 /* single VirtualAlloc call. Thus we allocate one */
1933 /* extra page, which will prevent merging of blocks */
1934 /* in separate regions, and eliminate any temptation */
1935 /* to call VirtualProtect on a range spanning regions. */
1936 /* This wastes a small amount of memory, and risks */
1937 /* increased fragmentation. But better alternatives */
1938 /* would require effort. */
1939 /* Pass the MEM_WRITE_WATCH only if GetWriteWatch-based */
1940 /* VDBs are enabled and the GetWriteWatch function is */
1941 /* available. Otherwise we waste resources or possibly */
1942 /* cause VirtualAlloc to fail (observed in Windows 2000 */
1944 result = (ptr_t) VirtualAlloc(NULL, bytes + 1,
1946 GetWriteWatch_alloc_flag |
1948 MEM_COMMIT | MEM_RESERVE
1950 PAGE_EXECUTE_READWRITE);
1952 if (HBLKDISPL(result) != 0) ABORT("Bad VirtualAlloc result");
1953 /* If I read the documentation correctly, this can */
1954 /* only happen if HBLKSIZE > 64k or not a power of 2. */
1955 if (GC_n_heap_bases >= MAX_HEAP_SECTS) ABORT("Too many heap sections");
1956 if (0 != result) GC_heap_bases[GC_n_heap_bases++] = result;
1960 void GC_win32_free_heap(void)
1962 if (GC_no_win32_dlls) {
1963 while (GC_n_heap_bases > 0) {
1964 GlobalFree (GC_heap_bases[--GC_n_heap_bases]);
1965 GC_heap_bases[GC_n_heap_bases] = 0;
1972 # define GC_AMIGA_AM
1973 # include "AmigaOS.c"
1979 word GC_n_heap_bases = 0;
1981 ptr_t GC_wince_get_mem(word bytes)
1986 /* Round up allocation size to multiple of page size */
1987 bytes = (bytes + GC_page_size-1) & ~(GC_page_size-1);
1989 /* Try to find reserved, uncommitted pages */
1990 for (i = 0; i < GC_n_heap_bases; i++) {
1991 if (((word)(-(signed_word)GC_heap_lengths[i])
1992 & (GC_sysinfo.dwAllocationGranularity-1))
1994 result = GC_heap_bases[i] + GC_heap_lengths[i];
1999 if (i == GC_n_heap_bases) {
2000 /* Reserve more pages */
2001 word res_bytes = (bytes + GC_sysinfo.dwAllocationGranularity-1)
2002 & ~(GC_sysinfo.dwAllocationGranularity-1);
2003 /* If we ever support MPROTECT_VDB here, we will probably need to */
2004 /* ensure that res_bytes is strictly > bytes, so that VirtualProtect */
2005 /* never spans regions. It seems to be OK for a VirtualFree */
2006 /* argument to span regions, so we should be OK for now. */
2007 result = (ptr_t) VirtualAlloc(NULL, res_bytes,
2008 MEM_RESERVE | MEM_TOP_DOWN,
2009 PAGE_EXECUTE_READWRITE);
2010 if (HBLKDISPL(result) != 0) ABORT("Bad VirtualAlloc result");
2011 /* If I read the documentation correctly, this can */
2012 /* only happen if HBLKSIZE > 64k or not a power of 2. */
2013 if (GC_n_heap_bases >= MAX_HEAP_SECTS) ABORT("Too many heap sections");
2014 GC_heap_bases[GC_n_heap_bases] = result;
2015 GC_heap_lengths[GC_n_heap_bases] = 0;
2020 result = (ptr_t) VirtualAlloc(result, bytes,
2022 PAGE_EXECUTE_READWRITE);
2023 if (result != NULL) {
2024 if (HBLKDISPL(result) != 0) ABORT("Bad VirtualAlloc result");
2025 GC_heap_lengths[i] += bytes;
2034 /* For now, this only works on Win32/WinCE and some Unix-like */
2035 /* systems. If you have something else, don't define */
2037 /* We assume ANSI C to support this feature. */
2039 #if !defined(MSWIN32) && !defined(MSWINCE)
2042 #include <sys/mman.h>
2043 #include <sys/stat.h>
2044 #include <sys/types.h>
2048 /* Compute a page aligned starting address for the unmap */
2049 /* operation on a block of size bytes starting at start. */
2050 /* Return 0 if the block is too small to make this feasible. */
2051 ptr_t GC_unmap_start(ptr_t start, size_t bytes)
2053 ptr_t result = start;
2054 /* Round start to next page boundary. */
2055 result += GC_page_size - 1;
2056 result = (ptr_t)((word)result & ~(GC_page_size - 1));
2057 if (result + GC_page_size > start + bytes) return 0;
2061 /* Compute end address for an unmap operation on the indicated */
2063 ptr_t GC_unmap_end(ptr_t start, size_t bytes)
2065 ptr_t end_addr = start + bytes;
2066 end_addr = (ptr_t)((word)end_addr & ~(GC_page_size - 1));
2070 /* Under Win32/WinCE we commit (map) and decommit (unmap) */
2071 /* memory using VirtualAlloc and VirtualFree. These functions */
2072 /* work on individual allocations of virtual memory, made */
2073 /* previously using VirtualAlloc with the MEM_RESERVE flag. */
2074 /* The ranges we need to (de)commit may span several of these */
2075 /* allocations; therefore we use VirtualQuery to check */
2076 /* allocation lengths, and split up the range as necessary. */
2078 /* We assume that GC_remap is called on exactly the same range */
2079 /* as a previous call to GC_unmap. It is safe to consistently */
2080 /* round the endpoints in both places. */
2081 void GC_unmap(ptr_t start, size_t bytes)
2083 ptr_t start_addr = GC_unmap_start(start, bytes);
2084 ptr_t end_addr = GC_unmap_end(start, bytes);
2085 word len = end_addr - start_addr;
2086 if (0 == start_addr) return;
2087 # if defined(MSWIN32) || defined(MSWINCE)
2089 MEMORY_BASIC_INFORMATION mem_info;
2091 if (VirtualQuery(start_addr, &mem_info, sizeof(mem_info))
2092 != sizeof(mem_info))
2093 ABORT("Weird VirtualQuery result");
2094 free_len = (len < mem_info.RegionSize) ? len : mem_info.RegionSize;
2095 if (!VirtualFree(start_addr, free_len, MEM_DECOMMIT))
2096 ABORT("VirtualFree failed");
2097 GC_unmapped_bytes += free_len;
2098 start_addr += free_len;
2102 /* We immediately remap it to prevent an intervening mmap from */
2103 /* accidentally grabbing the same address space. */
2106 result = mmap(start_addr, len, PROT_NONE,
2107 MAP_PRIVATE | MAP_FIXED | OPT_MAP_ANON,
2108 zero_fd, 0/* offset */);
2109 if (result != (void *)start_addr) ABORT("mmap(...PROT_NONE...) failed");
2111 GC_unmapped_bytes += len;
2116 void GC_remap(ptr_t start, size_t bytes)
2118 ptr_t start_addr = GC_unmap_start(start, bytes);
2119 ptr_t end_addr = GC_unmap_end(start, bytes);
2120 word len = end_addr - start_addr;
2122 # if defined(MSWIN32) || defined(MSWINCE)
2125 if (0 == start_addr) return;
2127 MEMORY_BASIC_INFORMATION mem_info;
2129 if (VirtualQuery(start_addr, &mem_info, sizeof(mem_info))
2130 != sizeof(mem_info))
2131 ABORT("Weird VirtualQuery result");
2132 alloc_len = (len < mem_info.RegionSize) ? len : mem_info.RegionSize;
2133 result = VirtualAlloc(start_addr, alloc_len,
2135 PAGE_EXECUTE_READWRITE);
2136 if (result != start_addr) {
2137 ABORT("VirtualAlloc remapping failed");
2139 GC_unmapped_bytes -= alloc_len;
2140 start_addr += alloc_len;
2144 /* It was already remapped with PROT_NONE. */
2147 if (0 == start_addr) return;
2148 result = mprotect(start_addr, len,
2149 PROT_READ | PROT_WRITE | OPT_PROT_EXEC);
2152 "Mprotect failed at %p (length %ld) with errno %d\n",
2153 start_addr, (unsigned long)len, errno);
2154 ABORT("Mprotect remapping failed");
2156 GC_unmapped_bytes -= len;
2160 /* Two adjacent blocks have already been unmapped and are about to */
2161 /* be merged. Unmap the whole block. This typically requires */
2162 /* that we unmap a small section in the middle that was not previously */
2163 /* unmapped due to alignment constraints. */
2164 void GC_unmap_gap(ptr_t start1, size_t bytes1, ptr_t start2, size_t bytes2)
2166 ptr_t start1_addr = GC_unmap_start(start1, bytes1);
2167 ptr_t end1_addr = GC_unmap_end(start1, bytes1);
2168 ptr_t start2_addr = GC_unmap_start(start2, bytes2);
2169 ptr_t end2_addr = GC_unmap_end(start2, bytes2);
2170 ptr_t start_addr = end1_addr;
2171 ptr_t end_addr = start2_addr;
2173 GC_ASSERT(start1 + bytes1 == start2);
2174 if (0 == start1_addr) start_addr = GC_unmap_start(start1, bytes1 + bytes2);
2175 if (0 == start2_addr) end_addr = GC_unmap_end(start1, bytes1 + bytes2);
2176 if (0 == start_addr) return;
2177 len = end_addr - start_addr;
2178 # if defined(MSWIN32) || defined(MSWINCE)
2180 MEMORY_BASIC_INFORMATION mem_info;
2182 if (VirtualQuery(start_addr, &mem_info, sizeof(mem_info))
2183 != sizeof(mem_info))
2184 ABORT("Weird VirtualQuery result");
2185 free_len = (len < mem_info.RegionSize) ? len : mem_info.RegionSize;
2186 if (!VirtualFree(start_addr, free_len, MEM_DECOMMIT))
2187 ABORT("VirtualFree failed");
2188 GC_unmapped_bytes += free_len;
2189 start_addr += free_len;
2193 if (len != 0 && munmap(start_addr, len) != 0) ABORT("munmap failed");
2194 GC_unmapped_bytes += len;
2198 #endif /* USE_MUNMAP */
2200 /* Routine for pushing any additional roots. In THREADS */
2201 /* environment, this is also responsible for marking from */
2202 /* thread stacks. */
2204 void (*GC_push_other_roots)(void) = 0;
2208 PCR_ERes GC_push_thread_stack(PCR_Th_T *t, PCR_Any dummy)
2210 struct PCR_ThCtl_TInfoRep info;
2213 info.ti_stkLow = info.ti_stkHi = 0;
2214 result = PCR_ThCtl_GetInfo(t, &info);
2215 GC_push_all_stack((ptr_t)(info.ti_stkLow), (ptr_t)(info.ti_stkHi));
2219 /* Push the contents of an old object. We treat this as stack */
2220 /* data only becasue that makes it robust against mark stack */
2222 PCR_ERes GC_push_old_obj(void *p, size_t size, PCR_Any data)
2224 GC_push_all_stack((ptr_t)p, (ptr_t)p + size);
2225 return(PCR_ERes_okay);
2229 void GC_default_push_other_roots(void)
2231 /* Traverse data allocated by previous memory managers. */
2233 extern struct PCR_MM_ProcsRep * GC_old_allocator;
2235 if ((*(GC_old_allocator->mmp_enumerate))(PCR_Bool_false,
2238 ABORT("Old object enumeration failed");
2241 /* Traverse all thread stacks. */
2243 PCR_ThCtl_ApplyToAllOtherThreads(GC_push_thread_stack,0))
2244 || PCR_ERes_IsErr(GC_push_thread_stack(PCR_Th_CurrThread(), 0))) {
2245 ABORT("Thread stack marking failed\n");
2252 # if defined(GC_PTHREADS) || defined(GC_WIN32_THREADS)
2254 extern void GC_push_all_stacks(void);
2256 void GC_default_push_other_roots(void)
2258 GC_push_all_stacks();
2261 # endif /* GC_WIN32_THREADS || GC_PTHREADS */
2263 void (*GC_push_other_roots)(void) = GC_default_push_other_roots;
2265 #endif /* THREADS */
2268 * Routines for accessing dirty bits on virtual pages.
2269 * There are six ways to maintain this information:
2270 * DEFAULT_VDB: A simple dummy implementation that treats every page
2271 * as possibly dirty. This makes incremental collection
2272 * useless, but the implementation is still correct.
2273 * MANUAL_VDB: Stacks and static data are always considered dirty.
2274 * Heap pages are considered dirty if GC_dirty(p) has been
2275 * called on some pointer p pointing to somewhere inside
2276 * an object on that page. A GC_dirty() call on a large
2277 * object directly dirties only a single page, but for
2278 * MANUAL_VDB we are careful to treat an object with a dirty
2279 * page as completely dirty.
2280 * In order to avoid races, an object must be marked dirty
2281 * after it is written, and a reference to the object
2282 * must be kept on a stack or in a register in the interim.
2283 * With threads enabled, an object directly reachable from the
2284 * stack at the time of a collection is treated as dirty.
2285 * In single-threaded mode, it suffices to ensure that no
2286 * collection can take place between the pointer assignment
2287 * and the GC_dirty() call.
2288 * PCR_VDB: Use PPCRs virtual dirty bit facility.
2289 * PROC_VDB: Use the /proc facility for reading dirty bits. Only
2290 * works under some SVR4 variants. Even then, it may be
2291 * too slow to be entirely satisfactory. Requires reading
2292 * dirty bits for entire address space. Implementations tend
2293 * to assume that the client is a (slow) debugger.
2294 * MPROTECT_VDB:Protect pages and then catch the faults to keep track of
2295 * dirtied pages. The implementation (and implementability)
2296 * is highly system dependent. This usually fails when system
2297 * calls write to a protected page. We prevent the read system
2298 * call from doing so. It is the clients responsibility to
2299 * make sure that other system calls are similarly protected
2300 * or write only to the stack.
2301 * GWW_VDB: Use the Win32 GetWriteWatch functions, if available, to
2302 * read dirty bits. In case it is not available (because we
2303 * are running on Windows 95, Windows 2000 or earlier),
2304 * MPROTECT_VDB may be defined as a fallback strategy.
2306 GC_bool GC_dirty_maintained = FALSE;
2308 #if defined(PROC_VDB) || defined(GWW_VDB)
2310 /* Add all pages in pht2 to pht1 */
2311 void GC_or_pages(page_hash_table pht1, page_hash_table pht2)
2315 for (i = 0; i < PHT_SIZE; i++) pht1[i] |= pht2[i];
2322 # define GC_GWW_BUF_LEN 1024
2323 static PVOID gww_buf[GC_GWW_BUF_LEN];
2325 # ifdef MPROTECT_VDB
2326 GC_bool GC_gww_dirty_init(void)
2328 detect_GetWriteWatch();
2329 return GC_GWW_AVAILABLE();
2332 void GC_dirty_init(void)
2334 detect_GetWriteWatch();
2335 GC_dirty_maintained = GC_GWW_AVAILABLE();
2339 # ifdef MPROTECT_VDB
2340 static void GC_gww_read_dirty(void)
2342 void GC_read_dirty(void)
2347 BZERO(GC_grungy_pages, sizeof(GC_grungy_pages));
2349 for (i = 0; i != GC_n_heap_sects; ++i) {
2353 PVOID * pages, * pages_end;
2357 count = GC_GWW_BUF_LEN;
2359 * GetWriteWatch is documented as returning non-zero when it fails,
2360 * but the documentation doesn't explicitly say why it would fail or
2361 * what its behaviour will be if it fails.
2362 * It does appear to fail, at least on recent W2K instances, if
2363 * the underlying memory was not allocated with the appropriate
2364 * flag. This is common if GC_enable_incremental is called
2365 * shortly after GC initialization. To avoid modifying the
2366 * interface, we silently work around such a failure, it it only
2367 * affects the initial (small) heap allocation.
2368 * If there are more dirty
2369 * pages than will fit in the buffer, this is not treated as a
2370 * failure; we must check the page count in the loop condition.
2371 * Since each partial call will reset the status of some
2372 * pages, this should eventually terminate even in the overflow
2375 if (GetWriteWatch_func(WRITE_WATCH_FLAG_RESET,
2376 GC_heap_sects[i].hs_start,
2377 GC_heap_sects[i].hs_bytes,
2381 static int warn_count = 0;
2383 struct hblk * start = (struct hblk *)GC_heap_sects[i].hs_start;
2384 static struct hblk *last_warned = 0;
2385 size_t nblocks = divHBLKSZ(GC_heap_sects[i].hs_bytes);
2387 if ( i != 0 && last_warned != start && warn_count++ < 5) {
2388 last_warned = start;
2390 "GC_gww_read_dirty unexpectedly failed at %ld: "
2391 "Falling back to marking all pages dirty\n", start);
2393 for (j = 0; j < nblocks; ++j) {
2394 word hash = PHT_HASH(start + j);
2395 set_pht_entry_from_index(GC_grungy_pages, hash);
2397 count = 1; /* Done with this section. */
2398 } else /* succeeded */{
2399 pages_end = pages + count;
2400 while (pages != pages_end) {
2401 struct hblk * h = (struct hblk *) *pages++;
2402 struct hblk * h_end = (struct hblk *) ((char *) h + page_size);
2404 set_pht_entry_from_index(GC_grungy_pages, PHT_HASH(h));
2405 while (++h < h_end);
2408 } while (count == GC_GWW_BUF_LEN);
2411 GC_or_pages(GC_written_pages, GC_grungy_pages);
2414 # ifdef MPROTECT_VDB
2415 static GC_bool GC_gww_page_was_dirty(struct hblk * h)
2417 GC_bool GC_page_was_dirty(struct hblk * h)
2420 return HDR(h) == 0 || get_pht_entry_from_index(GC_grungy_pages, PHT_HASH(h));
2423 # ifdef MPROTECT_VDB
2424 static GC_bool GC_gww_page_was_ever_dirty(struct hblk * h)
2426 GC_bool GC_page_was_ever_dirty(struct hblk * h)
2429 return HDR(h) == 0 || get_pht_entry_from_index(GC_written_pages, PHT_HASH(h));
2432 # ifndef MPROTECT_VDB
2433 void GC_remove_protection(struct hblk *h, word nblocks, GC_bool is_ptrfree)
2437 # endif /* GWW_VDB */
2441 /* All of the following assume the allocation lock is held, and */
2442 /* signals are disabled. */
2444 /* The client asserts that unallocated pages in the heap are never */
2447 /* Initialize virtual dirty bit implementation. */
2448 void GC_dirty_init(void)
2450 if (GC_print_stats == VERBOSE)
2451 GC_log_printf("Initializing DEFAULT_VDB...\n");
2452 GC_dirty_maintained = TRUE;
2455 /* Retrieve system dirty bits for heap to a local buffer. */
2456 /* Restore the systems notion of which pages are dirty. */
2457 void GC_read_dirty(void)
2460 /* Is the HBLKSIZE sized page at h marked dirty in the local buffer? */
2461 /* If the actual page size is different, this returns TRUE if any */
2462 /* of the pages overlapping h are dirty. This routine may err on the */
2463 /* side of labelling pages as dirty (and this implementation does). */
2465 GC_bool GC_page_was_dirty(struct hblk *h)
2471 * The following two routines are typically less crucial. They matter
2472 * most with large dynamic libraries, or if we can't accurately identify
2473 * stacks, e.g. under Solaris 2.X. Otherwise the following default
2474 * versions are adequate.
2477 /* Could any valid GC heap pointer ever have been written to this page? */
2479 GC_bool GC_page_was_ever_dirty(struct hblk *h)
2485 /* I) hints that [h, h+nblocks) is about to be written. */
2486 /* II) guarantees that protection is removed. */
2487 /* (I) may speed up some dirty bit implementations. */
2488 /* (II) may be essential if we need to ensure that */
2489 /* pointer-free system call buffers in the heap are */
2490 /* not protected. */
2492 void GC_remove_protection(struct hblk *h, word nblocks, GC_bool is_ptrfree)
2496 # endif /* DEFAULT_VDB */
2500 /* Initialize virtual dirty bit implementation. */
2501 void GC_dirty_init(void)
2503 if (GC_print_stats == VERBOSE)
2504 GC_log_printf("Initializing MANUAL_VDB...\n");
2505 /* GC_dirty_pages and GC_grungy_pages are already cleared. */
2506 GC_dirty_maintained = TRUE;
2509 /* Retrieve system dirty bits for heap to a local buffer. */
2510 /* Restore the systems notion of which pages are dirty. */
2511 void GC_read_dirty(void)
2513 BCOPY((word *)GC_dirty_pages, GC_grungy_pages,
2514 (sizeof GC_dirty_pages));
2515 BZERO((word *)GC_dirty_pages, (sizeof GC_dirty_pages));
2518 /* Is the HBLKSIZE sized page at h marked dirty in the local buffer? */
2519 /* If the actual page size is different, this returns TRUE if any */
2520 /* of the pages overlapping h are dirty. This routine may err on the */
2521 /* side of labelling pages as dirty (and this implementation does). */
2523 GC_bool GC_page_was_dirty(struct hblk *h)
2525 register word index;
2527 index = PHT_HASH(h);
2528 return(HDR(h) == 0 || get_pht_entry_from_index(GC_grungy_pages, index));
2531 /* Could any valid GC heap pointer ever have been written to this page? */
2533 GC_bool GC_page_was_ever_dirty(struct hblk *h)
2535 /* FIXME - implement me. */
2539 /* Mark the page containing p as dirty. Logically, this dirties the */
2540 /* entire object. */
2541 void GC_dirty(ptr_t p)
2543 word index = PHT_HASH(p);
2544 async_set_pht_entry_from_index(GC_dirty_pages, index);
2548 void GC_remove_protection(struct hblk *h, word nblocks, GC_bool is_ptrfree)
2552 # endif /* MANUAL_VDB */
2555 # ifdef MPROTECT_VDB
2558 * See DEFAULT_VDB for interface descriptions.
2562 * This implementation maintains dirty bits itself by catching write
2563 * faults and keeping track of them. We assume nobody else catches
2564 * SIGBUS or SIGSEGV. We assume no write faults occur in system calls.
2565 * This means that clients must ensure that system calls don't write
2566 * to the write-protected heap. Probably the best way to do this is to
2567 * ensure that system calls write at most to POINTERFREE objects in the
2568 * heap, and do even that only if we are on a platform on which those
2569 * are not protected. Another alternative is to wrap system calls
2570 * (see example for read below), but the current implementation holds
2572 * We assume the page size is a multiple of HBLKSIZE.
2573 * We prefer them to be the same. We avoid protecting POINTERFREE
2574 * objects only if they are the same.
2577 # if !defined(MSWIN32) && !defined(MSWINCE) && !defined(DARWIN)
2579 # include <sys/mman.h>
2580 # include <signal.h>
2581 # include <sys/syscall.h>
2583 # define PROTECT(addr, len) \
2584 if (mprotect((caddr_t)(addr), (size_t)(len), \
2585 PROT_READ | OPT_PROT_EXEC) < 0) { \
2586 ABORT("mprotect failed"); \
2588 # define UNPROTECT(addr, len) \
2589 if (mprotect((caddr_t)(addr), (size_t)(len), \
2590 PROT_WRITE | PROT_READ | OPT_PROT_EXEC ) < 0) { \
2591 ABORT("un-mprotect failed"); \
2597 /* Using vm_protect (mach syscall) over mprotect (BSD syscall) seems to
2598 decrease the likelihood of some of the problems described below. */
2599 #include <mach/vm_map.h>
2600 static mach_port_t GC_task_self;
2601 #define PROTECT(addr,len) \
2602 if(vm_protect(GC_task_self,(vm_address_t)(addr),(vm_size_t)(len), \
2603 FALSE,VM_PROT_READ) != KERN_SUCCESS) { \
2604 ABORT("vm_portect failed"); \
2606 #define UNPROTECT(addr,len) \
2607 if(vm_protect(GC_task_self,(vm_address_t)(addr),(vm_size_t)(len), \
2608 FALSE,VM_PROT_READ|VM_PROT_WRITE) != KERN_SUCCESS) { \
2609 ABORT("vm_portect failed"); \
2614 # include <signal.h>
2617 static DWORD protect_junk;
2618 # define PROTECT(addr, len) \
2619 if (!VirtualProtect((addr), (len), PAGE_EXECUTE_READ, \
2621 DWORD last_error = GetLastError(); \
2622 GC_printf("Last error code: %lx\n", last_error); \
2623 ABORT("VirtualProtect failed"); \
2625 # define UNPROTECT(addr, len) \
2626 if (!VirtualProtect((addr), (len), PAGE_EXECUTE_READWRITE, \
2628 ABORT("un-VirtualProtect failed"); \
2630 # endif /* !DARWIN */
2631 # endif /* MSWIN32 || MSWINCE || DARWIN */
2633 #if defined(MSWIN32)
2634 typedef LPTOP_LEVEL_EXCEPTION_FILTER SIG_HNDLR_PTR;
2636 # define SIG_DFL (LPTOP_LEVEL_EXCEPTION_FILTER) (-1)
2637 #elif defined(MSWINCE)
2638 typedef LONG (WINAPI *SIG_HNDLR_PTR)(struct _EXCEPTION_POINTERS *);
2640 # define SIG_DFL (SIG_HNDLR_PTR) (-1)
2641 #elif defined(DARWIN)
2642 typedef void (* SIG_HNDLR_PTR)();
2644 typedef void (* SIG_HNDLR_PTR)(int, siginfo_t *, void *);
2645 typedef void (* PLAIN_HNDLR_PTR)(int);
2648 #if defined(__GLIBC__)
2649 # if __GLIBC__ < 2 || __GLIBC__ == 2 && __GLIBC_MINOR__ < 2
2650 # error glibc too old?
2655 SIG_HNDLR_PTR GC_old_bus_handler;
2656 GC_bool GC_old_bus_handler_used_si;
2657 SIG_HNDLR_PTR GC_old_segv_handler;
2658 /* Also old MSWIN32 ACCESS_VIOLATION filter */
2659 GC_bool GC_old_segv_handler_used_si;
2660 #endif /* !DARWIN */
2662 #if defined(THREADS)
2663 /* We need to lock around the bitmap update in the write fault handler */
2664 /* in order to avoid the risk of losing a bit. We do this with a */
2665 /* test-and-set spin lock if we know how to do that. Otherwise we */
2666 /* check whether we are already in the handler and use the dumb but */
2667 /* safe fallback algorithm of setting all bits in the word. */
2668 /* Contention should be very rare, so we do the minimum to handle it */
2670 #ifdef AO_HAVE_test_and_set_acquire
2671 static volatile AO_TS_t fault_handler_lock = 0;
2672 void async_set_pht_entry_from_index(volatile page_hash_table db, size_t index) {
2673 while (AO_test_and_set_acquire(&fault_handler_lock) == AO_TS_SET) {}
2674 /* Could also revert to set_pht_entry_from_index_safe if initial */
2675 /* GC_test_and_set fails. */
2676 set_pht_entry_from_index(db, index);
2677 AO_CLEAR(&fault_handler_lock);
2679 #else /* !AO_have_test_and_set_acquire */
2680 # error No test_and_set operation: Introduces a race.
2681 /* THIS WOULD BE INCORRECT! */
2682 /* The dirty bit vector may be temporarily wrong, */
2683 /* just before we notice the conflict and correct it. We may end up */
2684 /* looking at it while it's wrong. But this requires contention */
2685 /* exactly when a GC is triggered, which seems far less likely to */
2686 /* fail than the old code, which had no reported failures. Thus we */
2687 /* leave it this way while we think of something better, or support */
2688 /* GC_test_and_set on the remaining platforms. */
2689 static volatile word currently_updating = 0;
2690 void async_set_pht_entry_from_index(volatile page_hash_table db, size_t index) {
2691 unsigned int update_dummy;
2692 currently_updating = (word)(&update_dummy);
2693 set_pht_entry_from_index(db, index);
2694 /* If we get contention in the 10 or so instruction window here, */
2695 /* and we get stopped by a GC between the two updates, we lose! */
2696 if (currently_updating != (word)(&update_dummy)) {
2697 set_pht_entry_from_index_safe(db, index);
2698 /* We claim that if two threads concurrently try to update the */
2699 /* dirty bit vector, the first one to execute UPDATE_START */
2700 /* will see it changed when UPDATE_END is executed. (Note that */
2701 /* &update_dummy must differ in two distinct threads.) It */
2702 /* will then execute set_pht_entry_from_index_safe, thus */
2703 /* returning us to a safe state, though not soon enough. */
2706 #endif /* !AO_HAVE_test_and_set_acquire */
2707 #else /* !THREADS */
2708 # define async_set_pht_entry_from_index(db, index) \
2709 set_pht_entry_from_index(db, index)
2710 #endif /* !THREADS */
2712 #if !defined(DARWIN)
2714 # if defined(FREEBSD)
2715 # define SIG_OK TRUE
2716 # define CODE_OK (code == BUS_PAGE_FAULT)
2717 # elif defined(OSF1)
2718 # define SIG_OK (sig == SIGSEGV)
2719 # define CODE_OK (code == 2 /* experimentally determined */)
2720 # elif defined(IRIX5)
2721 # define SIG_OK (sig == SIGSEGV)
2722 # define CODE_OK (code == EACCES)
2723 # elif defined(HURD)
2724 # define SIG_OK (sig == SIGBUS || sig == SIGSEGV)
2725 # define CODE_OK TRUE
2726 # elif defined(LINUX)
2727 # define SIG_OK (sig == SIGSEGV)
2728 # define CODE_OK TRUE
2729 /* Empirically c.trapno == 14, on IA32, but is that useful? */
2730 /* Should probably consider alignment issues on other */
2731 /* architectures. */
2732 # elif defined(HPUX)
2733 # define SIG_OK (sig == SIGSEGV || sig == SIGBUS)
2734 # define CODE_OK (si -> si_code == SEGV_ACCERR) \
2735 || (si -> si_code == BUS_ADRERR) \
2736 || (si -> si_code == BUS_UNKNOWN) \
2737 || (si -> si_code == SEGV_UNKNOWN) \
2738 || (si -> si_code == BUS_OBJERR)
2739 # elif defined(FREEBSD)
2740 # define SIG_OK (sig == SIGBUS)
2741 # define CODE_OK (si -> si_code == BUS_PAGE_FAULT)
2742 # elif defined(SUNOS5SIGS)
2743 # define SIG_OK (sig == SIGSEGV)
2744 # define CODE_OK (si -> si_code == SEGV_ACCERR)
2745 # elif defined(MSWIN32) || defined(MSWINCE)
2746 # define SIG_OK (exc_info -> ExceptionRecord -> ExceptionCode \
2747 == STATUS_ACCESS_VIOLATION)
2748 # define CODE_OK (exc_info -> ExceptionRecord -> ExceptionInformation[0] \
2749 == 1) /* Write fault */
2752 # if defined(MSWIN32) || defined(MSWINCE)
2753 LONG WINAPI GC_write_fault_handler(struct _EXCEPTION_POINTERS *exc_info)
2755 # include <ucontext.h>
2757 void GC_write_fault_handler(int sig, siginfo_t *si, void *raw_sc)
2758 # endif /* MSWIN32 || MSWINCE */
2760 # if !defined(MSWIN32) && !defined(MSWINCE)
2761 int code = si -> si_code; /* Ignore gcc unused var. warning. */
2762 ucontext_t * scp = (ucontext_t *)raw_sc;
2763 /* Ignore gcc unused var. warning. */
2764 char *addr = si -> si_addr;
2766 # if defined(MSWIN32) || defined(MSWINCE)
2767 char * addr = (char *) (exc_info -> ExceptionRecord
2768 -> ExceptionInformation[1]);
2769 # define sig SIGSEGV
2773 if (SIG_OK && CODE_OK) {
2774 register struct hblk * h =
2775 (struct hblk *)((word)addr & ~(GC_page_size-1));
2776 GC_bool in_allocd_block;
2779 /* Address is only within the correct physical page. */
2780 in_allocd_block = FALSE;
2781 for (i = 0; i < divHBLKSZ(GC_page_size); i++) {
2782 if (HDR(h+i) != 0) {
2783 in_allocd_block = TRUE;
2787 in_allocd_block = (HDR(addr) != 0);
2789 if (!in_allocd_block) {
2790 /* FIXME - We should make sure that we invoke the */
2791 /* old handler with the appropriate calling */
2792 /* sequence, which often depends on SA_SIGINFO. */
2794 /* Heap blocks now begin and end on page boundaries */
2795 SIG_HNDLR_PTR old_handler;
2798 if (sig == SIGSEGV) {
2799 old_handler = GC_old_segv_handler;
2800 used_si = GC_old_segv_handler_used_si;
2802 old_handler = GC_old_bus_handler;
2803 used_si = GC_old_bus_handler_used_si;
2805 if (old_handler == (SIG_HNDLR_PTR)SIG_DFL) {
2806 # if !defined(MSWIN32) && !defined(MSWINCE)
2807 GC_err_printf("Segfault at %p\n", addr);
2808 ABORT("Unexpected bus error or segmentation fault");
2810 return(EXCEPTION_CONTINUE_SEARCH);
2814 * FIXME: This code should probably check if the
2815 * old signal handler used the traditional style and
2816 * if so call it using that style.
2819 return((*old_handler)(exc_info));
2822 ((SIG_HNDLR_PTR)old_handler) (sig, si, raw_sc);
2824 /* FIXME: should pass nonstandard args as well. */
2825 ((PLAIN_HNDLR_PTR)old_handler) (sig);
2830 UNPROTECT(h, GC_page_size);
2831 /* We need to make sure that no collection occurs between */
2832 /* the UNPROTECT and the setting of the dirty bit. Otherwise */
2833 /* a write by a third thread might go unnoticed. Reversing */
2834 /* the order is just as bad, since we would end up unprotecting */
2835 /* a page in a GC cycle during which it's not marked. */
2836 /* Currently we do this by disabling the thread stopping */
2837 /* signals while this handler is running. An alternative might */
2838 /* be to record the fact that we're about to unprotect, or */
2839 /* have just unprotected a page in the GC's thread structure, */
2840 /* and then to have the thread stopping code set the dirty */
2841 /* flag, if necessary. */
2842 for (i = 0; i < divHBLKSZ(GC_page_size); i++) {
2843 size_t index = PHT_HASH(h+i);
2845 async_set_pht_entry_from_index(GC_dirty_pages, index);
2847 /* The write may not take place before dirty bits are read. */
2848 /* But then we'll fault again ... */
2849 # if defined(MSWIN32) || defined(MSWINCE)
2850 return(EXCEPTION_CONTINUE_EXECUTION);
2855 #if defined(MSWIN32) || defined(MSWINCE)
2856 return EXCEPTION_CONTINUE_SEARCH;
2858 GC_err_printf("Segfault at %p\n", addr);
2859 ABORT("Unexpected bus error or segmentation fault");
2862 #endif /* !DARWIN */
2865 * We hold the allocation lock. We expect block h to be written
2866 * shortly. Ensure that all pages containing any part of the n hblks
2867 * starting at h are no longer protected. If is_ptrfree is false,
2868 * also ensure that they will subsequently appear to be dirty.
2870 void GC_remove_protection(struct hblk *h, word nblocks, GC_bool is_ptrfree)
2872 struct hblk * h_trunc; /* Truncated to page boundary */
2873 struct hblk * h_end; /* Page boundary following block end */
2874 struct hblk * current;
2875 GC_bool found_clean;
2877 # if defined(GWW_VDB)
2878 if (GC_GWW_AVAILABLE()) return;
2880 if (!GC_dirty_maintained) return;
2881 h_trunc = (struct hblk *)((word)h & ~(GC_page_size-1));
2882 h_end = (struct hblk *)(((word)(h + nblocks) + GC_page_size-1)
2883 & ~(GC_page_size-1));
2884 found_clean = FALSE;
2885 for (current = h_trunc; current < h_end; ++current) {
2886 size_t index = PHT_HASH(current);
2888 if (!is_ptrfree || current < h || current >= h + nblocks) {
2889 async_set_pht_entry_from_index(GC_dirty_pages, index);
2892 UNPROTECT(h_trunc, (ptr_t)h_end - (ptr_t)h_trunc);
2895 #if !defined(DARWIN)
2896 void GC_dirty_init(void)
2898 # if !defined(MSWIN32) && !defined(MSWINCE)
2899 struct sigaction act, oldact;
2900 act.sa_flags = SA_RESTART | SA_SIGINFO;
2901 act.sa_sigaction = GC_write_fault_handler;
2902 (void)sigemptyset(&act.sa_mask);
2904 /* Arrange to postpone SIG_SUSPEND while we're in a write fault */
2905 /* handler. This effectively makes the handler atomic w.r.t. */
2906 /* stopping the world for GC. */
2907 (void)sigaddset(&act.sa_mask, SIG_SUSPEND);
2908 # endif /* SIG_SUSPEND */
2910 if (GC_print_stats == VERBOSE)
2912 "Initializing mprotect virtual dirty bit implementation\n");
2913 GC_dirty_maintained = TRUE;
2914 if (GC_page_size % HBLKSIZE != 0) {
2915 GC_err_printf("Page size not multiple of HBLKSIZE\n");
2916 ABORT("Page size not multiple of HBLKSIZE");
2918 # if !defined(MSWIN32) && !defined(MSWINCE)
2919 # if defined(GC_IRIX_THREADS)
2920 sigaction(SIGSEGV, 0, &oldact);
2921 sigaction(SIGSEGV, &act, 0);
2924 int res = sigaction(SIGSEGV, &act, &oldact);
2925 if (res != 0) ABORT("Sigaction failed");
2928 if (oldact.sa_flags & SA_SIGINFO) {
2929 GC_old_segv_handler = oldact.sa_sigaction;
2930 GC_old_segv_handler_used_si = TRUE;
2932 GC_old_segv_handler = (SIG_HNDLR_PTR)oldact.sa_handler;
2933 GC_old_segv_handler_used_si = FALSE;
2935 if (GC_old_segv_handler == (SIG_HNDLR_PTR)SIG_IGN) {
2936 GC_err_printf("Previously ignored segmentation violation!?");
2937 GC_old_segv_handler = (SIG_HNDLR_PTR)SIG_DFL;
2939 if (GC_old_segv_handler != (SIG_HNDLR_PTR)SIG_DFL) {
2940 if (GC_print_stats == VERBOSE)
2941 GC_log_printf("Replaced other SIGSEGV handler\n");
2943 # endif /* ! MS windows */
2944 # if defined(HPUX) || defined(LINUX) || defined(HURD) \
2945 || (defined(FREEBSD) && defined(SUNOS5SIGS))
2946 sigaction(SIGBUS, &act, &oldact);
2947 if (oldact.sa_flags & SA_SIGINFO) {
2948 GC_old_bus_handler = oldact.sa_sigaction;
2949 GC_old_bus_handler_used_si = TRUE;
2951 GC_old_bus_handler = (SIG_HNDLR_PTR)oldact.sa_handler;
2952 GC_old_bus_handler_used_si = FALSE;
2954 if (GC_old_bus_handler == (SIG_HNDLR_PTR)SIG_IGN) {
2955 GC_err_printf("Previously ignored bus error!?");
2956 GC_old_bus_handler = (SIG_HNDLR_PTR)SIG_DFL;
2958 if (GC_old_bus_handler != (SIG_HNDLR_PTR)SIG_DFL) {
2959 if (GC_print_stats == VERBOSE)
2960 GC_log_printf("Replaced other SIGBUS handler\n");
2962 # endif /* HPUX || LINUX || HURD || (FREEBSD && SUNOS5SIGS) */
2963 # if defined(MSWIN32)
2964 # if defined(GWW_VDB)
2965 if (GC_gww_dirty_init())
2968 GC_old_segv_handler = SetUnhandledExceptionFilter(GC_write_fault_handler);
2969 if (GC_old_segv_handler != NULL) {
2971 GC_log_printf("Replaced other UnhandledExceptionFilter\n");
2973 GC_old_segv_handler = SIG_DFL;
2977 #endif /* !DARWIN */
2979 int GC_incremental_protection_needs(void)
2981 if (GC_page_size == HBLKSIZE) {
2982 return GC_PROTECTS_POINTER_HEAP;
2984 return GC_PROTECTS_POINTER_HEAP | GC_PROTECTS_PTRFREE_HEAP;
2988 #define HAVE_INCREMENTAL_PROTECTION_NEEDS
2990 #define IS_PTRFREE(hhdr) ((hhdr)->hb_descr == 0)
2992 #define PAGE_ALIGNED(x) !((word)(x) & (GC_page_size - 1))
2993 void GC_protect_heap(void)
2997 struct hblk * current;
2998 struct hblk * current_start; /* Start of block to be protected. */
2999 struct hblk * limit;
3001 GC_bool protect_all =
3002 (0 != (GC_incremental_protection_needs() & GC_PROTECTS_PTRFREE_HEAP));
3003 for (i = 0; i < GC_n_heap_sects; i++) {
3004 start = GC_heap_sects[i].hs_start;
3005 len = GC_heap_sects[i].hs_bytes;
3007 PROTECT(start, len);
3009 GC_ASSERT(PAGE_ALIGNED(len))
3010 GC_ASSERT(PAGE_ALIGNED(start))
3011 current_start = current = (struct hblk *)start;
3012 limit = (struct hblk *)(start + len);
3013 while (current < limit) {
3018 GC_ASSERT(PAGE_ALIGNED(current));
3019 GET_HDR(current, hhdr);
3020 if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {
3021 /* This can happen only if we're at the beginning of a */
3022 /* heap segment, and a block spans heap segments. */
3023 /* We will handle that block as part of the preceding */
3025 GC_ASSERT(current_start == current);
3026 current_start = ++current;
3029 if (HBLK_IS_FREE(hhdr)) {
3030 GC_ASSERT(PAGE_ALIGNED(hhdr -> hb_sz));
3031 nhblks = divHBLKSZ(hhdr -> hb_sz);
3032 is_ptrfree = TRUE; /* dirty on alloc */
3034 nhblks = OBJ_SZ_TO_BLOCKS(hhdr -> hb_sz);
3035 is_ptrfree = IS_PTRFREE(hhdr);
3038 if (current_start < current) {
3039 PROTECT(current_start, (ptr_t)current - (ptr_t)current_start);
3041 current_start = (current += nhblks);
3046 if (current_start < current) {
3047 PROTECT(current_start, (ptr_t)current - (ptr_t)current_start);
3053 /* We assume that either the world is stopped or its OK to lose dirty */
3054 /* bits while this is happenning (as in GC_enable_incremental). */
3055 void GC_read_dirty(void)
3057 # if defined(GWW_VDB)
3058 if (GC_GWW_AVAILABLE()) {
3059 GC_gww_read_dirty();
3063 BCOPY((word *)GC_dirty_pages, GC_grungy_pages,
3064 (sizeof GC_dirty_pages));
3065 BZERO((word *)GC_dirty_pages, (sizeof GC_dirty_pages));
3069 GC_bool GC_page_was_dirty(struct hblk *h)
3071 register word index;
3073 # if defined(GWW_VDB)
3074 if (GC_GWW_AVAILABLE())
3075 return GC_gww_page_was_dirty(h);
3078 index = PHT_HASH(h);
3079 return(HDR(h) == 0 || get_pht_entry_from_index(GC_grungy_pages, index));
3083 * Acquiring the allocation lock here is dangerous, since this
3084 * can be called from within GC_call_with_alloc_lock, and the cord
3085 * package does so. On systems that allow nested lock acquisition, this
3087 * On other systems, SET_LOCK_HOLDER and friends must be suitably defined.
3090 static GC_bool syscall_acquired_lock = FALSE; /* Protected by GC lock. */
3093 void GC_begin_syscall(void)
3095 /* FIXME: Resurrecting this code would require fixing the */
3096 /* test, which can spuriously return TRUE. */
3097 if (!I_HOLD_LOCK()) {
3099 syscall_acquired_lock = TRUE;
3103 void GC_end_syscall(void)
3105 if (syscall_acquired_lock) {
3106 syscall_acquired_lock = FALSE;
3111 void GC_unprotect_range(ptr_t addr, word len)
3113 struct hblk * start_block;
3114 struct hblk * end_block;
3115 register struct hblk *h;
3118 if (!GC_dirty_maintained) return;
3119 obj_start = GC_base(addr);
3120 if (obj_start == 0) return;
3121 if (GC_base(addr + len - 1) != obj_start) {
3122 ABORT("GC_unprotect_range(range bigger than object)");
3124 start_block = (struct hblk *)((word)addr & ~(GC_page_size - 1));
3125 end_block = (struct hblk *)((word)(addr + len - 1) & ~(GC_page_size - 1));
3126 end_block += GC_page_size/HBLKSIZE - 1;
3127 for (h = start_block; h <= end_block; h++) {
3128 register word index = PHT_HASH(h);
3130 async_set_pht_entry_from_index(GC_dirty_pages, index);
3132 UNPROTECT(start_block,
3133 ((ptr_t)end_block - (ptr_t)start_block) + HBLKSIZE);
3137 /* We no longer wrap read by default, since that was causing too many */
3138 /* problems. It is preferred that the client instead avoids writing */
3139 /* to the write-protected heap with a system call. */
3140 /* This still serves as sample code if you do want to wrap system calls.*/
3142 #if !defined(MSWIN32) && !defined(MSWINCE) && !defined(GC_USE_LD_WRAP)
3143 /* Replacement for UNIX system call. */
3144 /* Other calls that write to the heap should be handled similarly. */
3145 /* Note that this doesn't work well for blocking reads: It will hold */
3146 /* the allocation lock for the entire duration of the call. Multithreaded */
3147 /* clients should really ensure that it won't block, either by setting */
3148 /* the descriptor nonblocking, or by calling select or poll first, to */
3149 /* make sure that input is available. */
3150 /* Another, preferred alternative is to ensure that system calls never */
3151 /* write to the protected heap (see above). */
3152 # include <unistd.h>
3153 # include <sys/uio.h>
3154 ssize_t read(int fd, void *buf, size_t nbyte)
3159 GC_unprotect_range(buf, (word)nbyte);
3160 # if defined(IRIX5) || defined(GC_LINUX_THREADS)
3161 /* Indirect system call may not always be easily available. */
3162 /* We could call _read, but that would interfere with the */
3163 /* libpthread interception of read. */
3164 /* On Linux, we have to be careful with the linuxthreads */
3165 /* read interception. */
3170 iov.iov_len = nbyte;
3171 result = readv(fd, &iov, 1);
3175 result = __read(fd, buf, nbyte);
3177 /* The two zero args at the end of this list are because one
3178 IA-64 syscall() implementation actually requires six args
3179 to be passed, even though they aren't always used. */
3180 result = syscall(SYS_read, fd, buf, nbyte, 0, 0);
3186 #endif /* !MSWIN32 && !MSWINCE && !GC_LINUX_THREADS */
3188 #if defined(GC_USE_LD_WRAP) && !defined(THREADS)
3189 /* We use the GNU ld call wrapping facility. */
3190 /* This requires that the linker be invoked with "--wrap read". */
3191 /* This can be done by passing -Wl,"--wrap read" to gcc. */
3192 /* I'm not sure that this actually wraps whatever version of read */
3193 /* is called by stdio. That code also mentions __read. */
3194 # include <unistd.h>
3195 ssize_t __wrap_read(int fd, void *buf, size_t nbyte)
3200 GC_unprotect_range(buf, (word)nbyte);
3201 result = __real_read(fd, buf, nbyte);
3206 /* We should probably also do this for __read, or whatever stdio */
3207 /* actually calls. */
3213 GC_bool GC_page_was_ever_dirty(struct hblk *h)
3215 # if defined(GWW_VDB)
3216 if (GC_GWW_AVAILABLE())
3217 return GC_gww_page_was_ever_dirty(h);
3222 # endif /* MPROTECT_VDB */
3227 * See DEFAULT_VDB for interface descriptions.
3231 * This implementaion assumes a Solaris 2.X like /proc pseudo-file-system
3232 * from which we can read page modified bits. This facility is far from
3233 * optimal (e.g. we would like to get the info for only some of the
3234 * address space), but it avoids intercepting system calls.
3238 #include <sys/types.h>
3239 #include <sys/signal.h>
3240 #include <sys/fault.h>
3241 #include <sys/syscall.h>
3242 #include <sys/procfs.h>
3243 #include <sys/stat.h>
3245 #define INITIAL_BUF_SZ 16384
3246 word GC_proc_buf_size = INITIAL_BUF_SZ;
3251 void GC_dirty_init(void)
3256 GC_dirty_maintained = TRUE;
3257 if (GC_bytes_allocd != 0 || GC_bytes_allocd_before_gc != 0) {
3260 for (i = 0; i < PHT_SIZE; i++) GC_written_pages[i] = (word)(-1);
3261 if (GC_print_stats == VERBOSE)
3263 "Allocated bytes:%lu:all pages may have been written\n",
3265 (GC_bytes_allocd + GC_bytes_allocd_before_gc));
3267 sprintf(buf, "/proc/%d", getpid());
3268 fd = open(buf, O_RDONLY);
3270 ABORT("/proc open failed");
3272 GC_proc_fd = syscall(SYS_ioctl, fd, PIOCOPENPD, 0);
3274 syscall(SYS_fcntl, GC_proc_fd, F_SETFD, FD_CLOEXEC);
3275 if (GC_proc_fd < 0) {
3276 ABORT("/proc ioctl failed");
3278 GC_proc_buf = GC_scratch_alloc(GC_proc_buf_size);
3281 /* Ignore write hints. They don't help us here. */
3283 void GC_remove_protection(h, nblocks, is_ptrfree)
3290 # define READ(fd,buf,nbytes) read(fd, buf, nbytes)
3292 void GC_read_dirty(void)
3294 unsigned long ps, np;
3297 struct prasmap * map;
3299 ptr_t current_addr, limit;
3302 BZERO(GC_grungy_pages, (sizeof GC_grungy_pages));
3305 if (READ(GC_proc_fd, bufp, GC_proc_buf_size) <= 0) {
3307 GC_log_printf("/proc read failed: GC_proc_buf_size = %lu\n",
3308 (unsigned long)GC_proc_buf_size);
3310 /* Retry with larger buffer. */
3311 word new_size = 2 * GC_proc_buf_size;
3312 char * new_buf = GC_scratch_alloc(new_size);
3315 GC_proc_buf = bufp = new_buf;
3316 GC_proc_buf_size = new_size;
3318 if (READ(GC_proc_fd, bufp, GC_proc_buf_size) <= 0) {
3319 WARN("Insufficient space for /proc read\n", 0);
3321 memset(GC_grungy_pages, 0xff, sizeof (page_hash_table));
3322 memset(GC_written_pages, 0xff, sizeof(page_hash_table));
3327 /* Copy dirty bits into GC_grungy_pages */
3328 nmaps = ((struct prpageheader *)bufp) -> pr_nmap;
3329 /* printf( "nmaps = %d, PG_REFERENCED = %d, PG_MODIFIED = %d\n",
3330 nmaps, PG_REFERENCED, PG_MODIFIED); */
3331 bufp = bufp + sizeof(struct prpageheader);
3332 for (i = 0; i < nmaps; i++) {
3333 map = (struct prasmap *)bufp;
3334 vaddr = (ptr_t)(map -> pr_vaddr);
3335 ps = map -> pr_pagesize;
3336 np = map -> pr_npage;
3337 /* printf("vaddr = 0x%X, ps = 0x%X, np = 0x%X\n", vaddr, ps, np); */
3338 limit = vaddr + ps * np;
3339 bufp += sizeof (struct prasmap);
3340 for (current_addr = vaddr;
3341 current_addr < limit; current_addr += ps){
3342 if ((*bufp++) & PG_MODIFIED) {
3343 register struct hblk * h = (struct hblk *) current_addr;
3345 while ((ptr_t)h < current_addr + ps) {
3346 register word index = PHT_HASH(h);
3348 set_pht_entry_from_index(GC_grungy_pages, index);
3353 bufp += sizeof(long) - 1;
3354 bufp = (char *)((unsigned long)bufp & ~(sizeof(long)-1));
3356 /* Update GC_written_pages. */
3357 GC_or_pages(GC_written_pages, GC_grungy_pages);
3362 GC_bool GC_page_was_dirty(struct hblk *h)
3364 register word index = PHT_HASH(h);
3365 register GC_bool result;
3367 result = get_pht_entry_from_index(GC_grungy_pages, index);
3371 GC_bool GC_page_was_ever_dirty(struct hblk *h)
3373 register word index = PHT_HASH(h);
3374 register GC_bool result;
3376 result = get_pht_entry_from_index(GC_written_pages, index);
3380 # endif /* PROC_VDB */
3385 # include "vd/PCR_VD.h"
3387 # define NPAGES (32*1024) /* 128 MB */
3389 PCR_VD_DB GC_grungy_bits[NPAGES];
3391 ptr_t GC_vd_base; /* Address corresponding to GC_grungy_bits[0] */
3392 /* HBLKSIZE aligned. */
3394 void GC_dirty_init(void)
3396 GC_dirty_maintained = TRUE;
3397 /* For the time being, we assume the heap generally grows up */
3398 GC_vd_base = GC_heap_sects[0].hs_start;
3399 if (GC_vd_base == 0) {
3400 ABORT("Bad initial heap segment");
3402 if (PCR_VD_Start(HBLKSIZE, GC_vd_base, NPAGES*HBLKSIZE)
3404 ABORT("dirty bit initialization failed");
3408 void GC_read_dirty(void)
3410 /* lazily enable dirty bits on newly added heap sects */
3412 static int onhs = 0;
3413 int nhs = GC_n_heap_sects;
3414 for( ; onhs < nhs; onhs++ ) {
3415 PCR_VD_WriteProtectEnable(
3416 GC_heap_sects[onhs].hs_start,
3417 GC_heap_sects[onhs].hs_bytes );
3422 if (PCR_VD_Clear(GC_vd_base, NPAGES*HBLKSIZE, GC_grungy_bits)
3424 ABORT("dirty bit read failed");
3428 GC_bool GC_page_was_dirty(struct hblk *h)
3430 if((ptr_t)h < GC_vd_base || (ptr_t)h >= GC_vd_base + NPAGES*HBLKSIZE) {
3433 return(GC_grungy_bits[h - (struct hblk *)GC_vd_base] & PCR_VD_DB_dirtyBit);
3437 void GC_remove_protection(struct hblk *h, word nblocks, GC_bool is_ptrfree)
3439 PCR_VD_WriteProtectDisable(h, nblocks*HBLKSIZE);
3440 PCR_VD_WriteProtectEnable(h, nblocks*HBLKSIZE);
3443 # endif /* PCR_VDB */
3445 #if defined(MPROTECT_VDB) && defined(DARWIN)
3446 /* The following sources were used as a *reference* for this exception handling
3448 1. Apple's mach/xnu documentation
3449 2. Timothy J. Wood's "Mach Exception Handlers 101" post to the
3450 omnigroup's macosx-dev list.
3451 www.omnigroup.com/mailman/archive/macosx-dev/2000-June/014178.html
3452 3. macosx-nat.c from Apple's GDB source code.
3455 /* The bug that caused all this trouble should now be fixed. This should
3456 eventually be removed if all goes well. */
3458 /* #define BROKEN_EXCEPTION_HANDLING */
3460 #include <mach/mach.h>
3461 #include <mach/mach_error.h>
3462 #include <mach/thread_status.h>
3463 #include <mach/exception.h>
3464 #include <mach/task.h>
3465 #include <pthread.h>
3467 extern void GC_darwin_register_mach_handler_thread(mach_port_t);
3469 /* These are not defined in any header, although they are documented */
3471 exc_server(mach_msg_header_t *, mach_msg_header_t *);
3473 extern kern_return_t
3474 exception_raise(mach_port_t, mach_port_t, mach_port_t, exception_type_t,
3475 exception_data_t, mach_msg_type_number_t);
3477 extern kern_return_t
3478 exception_raise_state(mach_port_t, mach_port_t, mach_port_t, exception_type_t,
3479 exception_data_t, mach_msg_type_number_t,
3480 thread_state_flavor_t*, thread_state_t,
3481 mach_msg_type_number_t, thread_state_t,
3482 mach_msg_type_number_t*);
3484 extern kern_return_t
3485 exception_raise_state_identity(mach_port_t, mach_port_t, mach_port_t,
3486 exception_type_t, exception_data_t,
3487 mach_msg_type_number_t, thread_state_flavor_t*,
3488 thread_state_t, mach_msg_type_number_t,
3489 thread_state_t, mach_msg_type_number_t*);
3492 #define MAX_EXCEPTION_PORTS 16
3495 mach_msg_type_number_t count;
3496 exception_mask_t masks[MAX_EXCEPTION_PORTS];
3497 exception_handler_t ports[MAX_EXCEPTION_PORTS];
3498 exception_behavior_t behaviors[MAX_EXCEPTION_PORTS];
3499 thread_state_flavor_t flavors[MAX_EXCEPTION_PORTS];
3503 mach_port_t exception;
3504 #if defined(THREADS)
3510 mach_msg_header_t head;
3514 GC_MP_NORMAL, GC_MP_DISCARDING, GC_MP_STOPPED
3515 } GC_mprotect_state_t;
3517 /* FIXME: 1 and 2 seem to be safe to use in the msgh_id field,
3518 but it isn't documented. Use the source and see if they
3523 /* These values are only used on the reply port */
3526 #if defined(THREADS)
3528 GC_mprotect_state_t GC_mprotect_state;
3530 /* The following should ONLY be called when the world is stopped */
3531 static void GC_mprotect_thread_notify(mach_msg_id_t id)
3536 mach_msg_trailer_t trailer;
3539 mach_msg_return_t r;
3541 buf.msg.head.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0);
3542 buf.msg.head.msgh_size = sizeof(buf.msg);
3543 buf.msg.head.msgh_remote_port = GC_ports.exception;
3544 buf.msg.head.msgh_local_port = MACH_PORT_NULL;
3545 buf.msg.head.msgh_id = id;
3547 r = mach_msg(&buf.msg.head, MACH_SEND_MSG | MACH_RCV_MSG | MACH_RCV_LARGE,
3548 sizeof(buf.msg), sizeof(buf), GC_ports.reply,
3549 MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
3550 if(r != MACH_MSG_SUCCESS)
3551 ABORT("mach_msg failed in GC_mprotect_thread_notify");
3552 if(buf.msg.head.msgh_id != ID_ACK)
3553 ABORT("invalid ack in GC_mprotect_thread_notify");
3556 /* Should only be called by the mprotect thread */
3557 static void GC_mprotect_thread_reply(void)
3561 mach_msg_return_t r;
3563 msg.head.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0);
3564 msg.head.msgh_size = sizeof(msg);
3565 msg.head.msgh_remote_port = GC_ports.reply;
3566 msg.head.msgh_local_port = MACH_PORT_NULL;
3567 msg.head.msgh_id = ID_ACK;
3569 r = mach_msg(&msg.head, MACH_SEND_MSG, sizeof(msg), 0, MACH_PORT_NULL,
3570 MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
3571 if(r != MACH_MSG_SUCCESS)
3572 ABORT("mach_msg failed in GC_mprotect_thread_reply");
3575 void GC_mprotect_stop(void)
3577 GC_mprotect_thread_notify(ID_STOP);
3579 void GC_mprotect_resume(void)
3581 GC_mprotect_thread_notify(ID_RESUME);
3584 #else /* !THREADS */
3585 /* The compiler should optimize away any GC_mprotect_state computations */
3586 #define GC_mprotect_state GC_MP_NORMAL
3589 static void *GC_mprotect_thread(void *arg)
3591 mach_msg_return_t r;
3592 /* These two structures contain some private kernel data. We don't need to
3593 access any of it so we don't bother defining a proper struct. The
3594 correct definitions are in the xnu source code. */
3596 mach_msg_header_t head;
3600 mach_msg_header_t head;
3601 mach_msg_body_t msgh_body;
3607 GC_darwin_register_mach_handler_thread(mach_thread_self());
3610 r = mach_msg(&msg.head, MACH_RCV_MSG | MACH_RCV_LARGE |
3611 (GC_mprotect_state == GC_MP_DISCARDING ? MACH_RCV_TIMEOUT : 0),
3612 0, sizeof(msg), GC_ports.exception,
3613 GC_mprotect_state == GC_MP_DISCARDING ? 0
3614 : MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
3616 id = r == MACH_MSG_SUCCESS ? msg.head.msgh_id : -1;
3618 # if defined(THREADS)
3619 if(GC_mprotect_state == GC_MP_DISCARDING) {
3620 if(r == MACH_RCV_TIMED_OUT) {
3621 GC_mprotect_state = GC_MP_STOPPED;
3622 GC_mprotect_thread_reply();
3625 if(r == MACH_MSG_SUCCESS && (id == ID_STOP || id == ID_RESUME))
3626 ABORT("out of order mprotect thread request");
3628 # endif /* THREADS */
3630 if(r != MACH_MSG_SUCCESS) {
3631 GC_err_printf("mach_msg failed with %d %s\n", (int)r,
3632 mach_error_string(r));
3633 ABORT("mach_msg failed");
3637 # if defined(THREADS)
3639 if(GC_mprotect_state != GC_MP_NORMAL)
3640 ABORT("Called mprotect_stop when state wasn't normal");
3641 GC_mprotect_state = GC_MP_DISCARDING;
3644 if(GC_mprotect_state != GC_MP_STOPPED)
3645 ABORT("Called mprotect_resume when state wasn't stopped");
3646 GC_mprotect_state = GC_MP_NORMAL;
3647 GC_mprotect_thread_reply();
3649 # endif /* THREADS */
3651 /* Handle the message (calls catch_exception_raise) */
3652 if(!exc_server(&msg.head, &reply.head))
3653 ABORT("exc_server failed");
3654 /* Send the reply */
3655 r = mach_msg(&reply.head, MACH_SEND_MSG, reply.head.msgh_size, 0,
3656 MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE,
3658 if(r != MACH_MSG_SUCCESS) {
3659 /* This will fail if the thread dies, but the thread */
3660 /* shouldn't die... */
3661 # ifdef BROKEN_EXCEPTION_HANDLING
3662 GC_err_printf("mach_msg failed with %d %s while sending"
3663 "exc reply\n", (int)r,mach_error_string(r));
3665 ABORT("mach_msg failed while sending exception reply");
3674 /* All this SIGBUS code shouldn't be necessary. All protection faults should
3675 be going throught the mach exception handler. However, it seems a SIGBUS is
3676 occasionally sent for some unknown reason. Even more odd, it seems to be
3677 meaningless and safe to ignore. */
3678 #ifdef BROKEN_EXCEPTION_HANDLING
3680 static SIG_HNDLR_PTR GC_old_bus_handler;
3682 /* Updates to this aren't atomic, but the SIGBUSs seem pretty rare.
3683 Even if this doesn't get updated property, it isn't really a problem */
3684 static int GC_sigbus_count;
3686 static void GC_darwin_sigbus(int num, siginfo_t *sip, void *context)
3689 ABORT("Got a non-sigbus signal in the sigbus handler");
3691 /* Ugh... some seem safe to ignore, but too many in a row probably means
3692 trouble. GC_sigbus_count is reset for each mach exception that is
3694 if(GC_sigbus_count >= 8) {
3695 ABORT("Got more than 8 SIGBUSs in a row!");
3698 WARN("Ignoring SIGBUS.\n", 0);
3701 #endif /* BROKEN_EXCEPTION_HANDLING */
3703 void GC_dirty_init(void)
3708 pthread_attr_t attr;
3709 exception_mask_t mask;
3711 if (GC_print_stats == VERBOSE)
3712 GC_log_printf("Inititalizing mach/darwin mprotect virtual dirty bit "
3713 "implementation\n");
3714 # ifdef BROKEN_EXCEPTION_HANDLING
3715 WARN("Enabling workarounds for various darwin "
3716 "exception handling bugs.\n", 0);
3718 GC_dirty_maintained = TRUE;
3719 if (GC_page_size % HBLKSIZE != 0) {
3720 GC_err_printf("Page size not multiple of HBLKSIZE\n");
3721 ABORT("Page size not multiple of HBLKSIZE");
3724 GC_task_self = me = mach_task_self();
3726 r = mach_port_allocate(me, MACH_PORT_RIGHT_RECEIVE, &GC_ports.exception);
3727 if(r != KERN_SUCCESS)
3728 ABORT("mach_port_allocate failed (exception port)");
3730 r = mach_port_insert_right(me, GC_ports.exception, GC_ports.exception,
3731 MACH_MSG_TYPE_MAKE_SEND);
3732 if(r != KERN_SUCCESS)
3733 ABORT("mach_port_insert_right failed (exception port)");
3735 # if defined(THREADS)
3736 r = mach_port_allocate(me, MACH_PORT_RIGHT_RECEIVE, &GC_ports.reply);
3737 if(r != KERN_SUCCESS)
3738 ABORT("mach_port_allocate failed (reply port)");
3741 /* The exceptions we want to catch */
3742 mask = EXC_MASK_BAD_ACCESS;
3744 r = task_get_exception_ports(me, mask, GC_old_exc_ports.masks,
3745 &GC_old_exc_ports.count, GC_old_exc_ports.ports,
3746 GC_old_exc_ports.behaviors,
3747 GC_old_exc_ports.flavors);
3748 if(r != KERN_SUCCESS)
3749 ABORT("task_get_exception_ports failed");
3751 r = task_set_exception_ports(me, mask, GC_ports.exception, EXCEPTION_DEFAULT,
3752 GC_MACH_THREAD_STATE);
3753 if(r != KERN_SUCCESS)
3754 ABORT("task_set_exception_ports failed");
3755 if(pthread_attr_init(&attr) != 0)
3756 ABORT("pthread_attr_init failed");
3757 if(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0)
3758 ABORT("pthread_attr_setdetachedstate failed");
3760 # undef pthread_create
3761 /* This will call the real pthread function, not our wrapper */
3762 if(pthread_create(&thread, &attr, GC_mprotect_thread, NULL) != 0)
3763 ABORT("pthread_create failed");
3764 pthread_attr_destroy(&attr);
3766 /* Setup the sigbus handler for ignoring the meaningless SIGBUSs */
3767 # ifdef BROKEN_EXCEPTION_HANDLING
3769 struct sigaction sa, oldsa;
3770 sa.sa_handler = (SIG_HNDLR_PTR)GC_darwin_sigbus;
3771 sigemptyset(&sa.sa_mask);
3772 sa.sa_flags = SA_RESTART|SA_SIGINFO;
3773 if(sigaction(SIGBUS, &sa, &oldsa) < 0)
3775 GC_old_bus_handler = (SIG_HNDLR_PTR)oldsa.sa_handler;
3776 if (GC_old_bus_handler != SIG_DFL) {
3777 if (GC_print_stats == VERBOSE)
3778 GC_err_printf("Replaced other SIGBUS handler\n");
3781 # endif /* BROKEN_EXCEPTION_HANDLING */
3784 /* The source code for Apple's GDB was used as a reference for the exception
3785 forwarding code. This code is similar to be GDB code only because there is
3786 only one way to do it. */
3787 static kern_return_t GC_forward_exception(mach_port_t thread, mach_port_t task,
3788 exception_type_t exception,
3789 exception_data_t data,
3790 mach_msg_type_number_t data_count)
3795 exception_behavior_t behavior;
3796 thread_state_flavor_t flavor;
3798 thread_state_t thread_state = NULL;
3799 mach_msg_type_number_t thread_state_count = THREAD_STATE_MAX;
3801 for(i=0; i < GC_old_exc_ports.count; i++)
3802 if(GC_old_exc_ports.masks[i] & (1 << exception))
3804 if(i==GC_old_exc_ports.count)
3805 ABORT("No handler for exception!");
3807 port = GC_old_exc_ports.ports[i];
3808 behavior = GC_old_exc_ports.behaviors[i];
3809 flavor = GC_old_exc_ports.flavors[i];
3811 if(behavior != EXCEPTION_DEFAULT) {
3812 r = thread_get_state(thread, flavor, thread_state, &thread_state_count);
3813 if(r != KERN_SUCCESS)
3814 ABORT("thread_get_state failed in forward_exception");
3818 case EXCEPTION_DEFAULT:
3819 r = exception_raise(port, thread, task, exception, data, data_count);
3821 case EXCEPTION_STATE:
3822 r = exception_raise_state(port, thread, task, exception, data, data_count,
3823 &flavor, thread_state, thread_state_count,
3824 thread_state, &thread_state_count);
3826 case EXCEPTION_STATE_IDENTITY:
3827 r = exception_raise_state_identity(port, thread, task, exception, data,
3828 data_count, &flavor, thread_state,
3829 thread_state_count, thread_state,
3830 &thread_state_count);
3833 r = KERN_FAILURE; /* make gcc happy */
3834 ABORT("forward_exception: unknown behavior");
3838 if(behavior != EXCEPTION_DEFAULT) {
3839 r = thread_set_state(thread, flavor, thread_state, thread_state_count);
3840 if(r != KERN_SUCCESS)
3841 ABORT("thread_set_state failed in forward_exception");
3847 #define FWD() GC_forward_exception(thread, task, exception, code, code_count)
3849 /* This violates the namespace rules but there isn't anything that can be done
3850 about it. The exception handling stuff is hard coded to call this */
3852 catch_exception_raise(mach_port_t exception_port, mach_port_t thread,
3853 mach_port_t task, exception_type_t exception,
3854 exception_data_t code, mach_msg_type_number_t code_count)
3860 # if defined(POWERPC)
3861 # if CPP_WORDSZ == 32
3862 thread_state_flavor_t flavor = PPC_EXCEPTION_STATE;
3863 mach_msg_type_number_t exc_state_count = PPC_EXCEPTION_STATE_COUNT;
3864 ppc_exception_state_t exc_state;
3866 thread_state_flavor_t flavor = PPC_EXCEPTION_STATE64;
3867 mach_msg_type_number_t exc_state_count = PPC_EXCEPTION_STATE64_COUNT;
3868 ppc_exception_state64_t exc_state;
3870 # elif defined(I386) || defined(X86_64)
3871 # if CPP_WORDSZ == 32
3872 thread_state_flavor_t flavor = x86_EXCEPTION_STATE32;
3873 mach_msg_type_number_t exc_state_count = x86_EXCEPTION_STATE32_COUNT;
3874 x86_exception_state32_t exc_state;
3876 thread_state_flavor_t flavor = x86_EXCEPTION_STATE64;
3877 mach_msg_type_number_t exc_state_count = x86_EXCEPTION_STATE64_COUNT;
3878 x86_exception_state64_t exc_state;
3881 # error FIXME for non-ppc/x86 darwin
3885 if(exception != EXC_BAD_ACCESS || code[0] != KERN_PROTECTION_FAILURE) {
3886 # ifdef DEBUG_EXCEPTION_HANDLING
3887 /* We aren't interested, pass it on to the old handler */
3888 GC_printf("Exception: 0x%x Code: 0x%x 0x%x in catch....\n", exception,
3889 code_count > 0 ? code[0] : -1, code_count > 1 ? code[1] : -1);
3894 r = thread_get_state(thread, flavor, (natural_t*)&exc_state,
3896 if(r != KERN_SUCCESS) {
3897 /* The thread is supposed to be suspended while the exception handler
3898 is called. This shouldn't fail. */
3899 # ifdef BROKEN_EXCEPTION_HANDLING
3900 GC_err_printf("thread_get_state failed in catch_exception_raise\n");
3901 return KERN_SUCCESS;
3903 ABORT("thread_get_state failed in catch_exception_raise");
3907 /* This is the address that caused the fault */
3908 # if defined(POWERPC)
3909 addr = (char*) exc_state. THREAD_FLD(dar);
3910 # elif defined (I386) || defined (X86_64)
3911 addr = (char*) exc_state. THREAD_FLD(faultvaddr);
3913 # error FIXME for non POWERPC/I386
3916 if((HDR(addr)) == 0) {
3917 /* Ugh... just like the SIGBUS problem above, it seems we get a bogus
3918 KERN_PROTECTION_FAILURE every once and a while. We wait till we get
3919 a bunch in a row before doing anything about it. If a "real" fault
3920 ever occurres it'll just keep faulting over and over and we'll hit
3921 the limit pretty quickly. */
3922 # ifdef BROKEN_EXCEPTION_HANDLING
3923 static char *last_fault;
3924 static int last_fault_count;
3926 if(addr != last_fault) {
3928 last_fault_count = 0;
3930 if(++last_fault_count < 32) {
3931 if(last_fault_count == 1)
3932 WARN("Ignoring KERN_PROTECTION_FAILURE at %lx\n", (GC_word)addr);
3933 return KERN_SUCCESS;
3936 GC_err_printf("Unexpected KERN_PROTECTION_FAILURE at %p\n",addr);
3937 /* Can't pass it along to the signal handler because that is
3938 ignoring SIGBUS signals. We also shouldn't call ABORT here as
3939 signals don't always work too well from the exception handler. */
3940 GC_err_printf("Aborting\n");
3942 # else /* BROKEN_EXCEPTION_HANDLING */
3943 /* Pass it along to the next exception handler
3944 (which should call SIGBUS/SIGSEGV) */
3946 # endif /* !BROKEN_EXCEPTION_HANDLING */
3949 # ifdef BROKEN_EXCEPTION_HANDLING
3950 /* Reset the number of consecutive SIGBUSs */
3951 GC_sigbus_count = 0;
3954 if(GC_mprotect_state == GC_MP_NORMAL) { /* common case */
3955 h = (struct hblk*)((word)addr & ~(GC_page_size-1));
3956 UNPROTECT(h, GC_page_size);
3957 for (i = 0; i < divHBLKSZ(GC_page_size); i++) {
3958 register int index = PHT_HASH(h+i);
3959 async_set_pht_entry_from_index(GC_dirty_pages, index);
3961 } else if(GC_mprotect_state == GC_MP_DISCARDING) {
3962 /* Lie to the thread for now. No sense UNPROTECT()ing the memory
3963 when we're just going to PROTECT() it again later. The thread
3964 will just fault again once it resumes */
3966 /* Shouldn't happen, i don't think */
3967 GC_printf("KERN_PROTECTION_FAILURE while world is stopped\n");
3970 return KERN_SUCCESS;
3974 /* These should never be called, but just in case... */
3976 catch_exception_raise_state(mach_port_name_t exception_port, int exception,
3977 exception_data_t code,
3978 mach_msg_type_number_t codeCnt, int flavor,
3979 thread_state_t old_state, int old_stateCnt,
3980 thread_state_t new_state, int new_stateCnt)
3982 ABORT("catch_exception_raise_state");
3983 return(KERN_INVALID_ARGUMENT);
3987 catch_exception_raise_state_identity(mach_port_name_t exception_port,
3988 mach_port_t thread, mach_port_t task,
3989 int exception, exception_data_t code,
3990 mach_msg_type_number_t codeCnt, int flavor,
3991 thread_state_t old_state, int old_stateCnt,
3992 thread_state_t new_state, int new_stateCnt)
3994 ABORT("catch_exception_raise_state_identity");
3995 return(KERN_INVALID_ARGUMENT);
3999 #endif /* DARWIN && MPROTECT_VDB */
4001 # ifndef HAVE_INCREMENTAL_PROTECTION_NEEDS
4002 int GC_incremental_protection_needs()
4004 return GC_PROTECTS_NONE;
4006 # endif /* !HAVE_INCREMENTAL_PROTECTION_NEEDS */
4009 * Call stack save code for debugging.
4010 * Should probably be in mach_dep.c, but that requires reorganization.
4013 /* I suspect the following works for most X86 *nix variants, so */
4014 /* long as the frame pointer is explicitly stored. In the case of gcc, */
4015 /* compiler flags (e.g. -fomit-frame-pointer) determine whether it is. */
4016 #if defined(I386) && defined(LINUX) && defined(SAVE_CALL_CHAIN)
4017 # include <features.h>
4020 struct frame *fr_savfp;
4022 long fr_arg[NARGS]; /* All the arguments go here. */
4028 # include <features.h>
4033 struct frame *fr_savfp;
4041 # elif defined (DRSNX)
4042 # include <sys/sparc/frame.h>
4043 # elif defined(OPENBSD)
4045 # elif defined(FREEBSD) || defined(NETBSD)
4046 # include <machine/frame.h>
4048 # include <sys/frame.h>
4051 # error We only know how to to get the first 6 arguments
4055 #ifdef NEED_CALLINFO
4056 /* Fill in the pc and argument information for up to NFRAMES of my */
4057 /* callers. Ignore my frame and my callers frame. */
4060 # include <unistd.h>
4063 #endif /* NEED_CALLINFO */
4065 #if defined(GC_HAVE_BUILTIN_BACKTRACE)
4067 # include "private/msvc_dbg.h"
4069 # include <execinfo.h>
4073 #ifdef SAVE_CALL_CHAIN
4075 #if NARGS == 0 && NFRAMES % 2 == 0 /* No padding */ \
4076 && defined(GC_HAVE_BUILTIN_BACKTRACE)
4078 #ifdef REDIRECT_MALLOC
4079 /* Deal with possible malloc calls in backtrace by omitting */
4080 /* the infinitely recursing backtrace. */
4082 __thread /* If your compiler doesn't understand this */
4083 /* you could use something like pthread_getspecific. */
4085 GC_in_save_callers = FALSE;
4088 void GC_save_callers (struct callinfo info[NFRAMES])
4090 void * tmp_info[NFRAMES + 1];
4092 # define IGNORE_FRAMES 1
4094 /* We retrieve NFRAMES+1 pc values, but discard the first, since it */
4095 /* points to our own frame. */
4096 # ifdef REDIRECT_MALLOC
4097 if (GC_in_save_callers) {
4098 info[0].ci_pc = (word)(&GC_save_callers);
4099 for (i = 1; i < NFRAMES; ++i) info[i].ci_pc = 0;
4102 GC_in_save_callers = TRUE;
4104 GC_ASSERT(sizeof(struct callinfo) == sizeof(void *));
4105 npcs = backtrace((void **)tmp_info, NFRAMES + IGNORE_FRAMES);
4106 BCOPY(tmp_info+IGNORE_FRAMES, info, (npcs - IGNORE_FRAMES) * sizeof(void *));
4107 for (i = npcs - IGNORE_FRAMES; i < NFRAMES; ++i) info[i].ci_pc = 0;
4108 # ifdef REDIRECT_MALLOC
4109 GC_in_save_callers = FALSE;
4113 #else /* No builtin backtrace; do it ourselves */
4115 #if (defined(OPENBSD) || defined(NETBSD) || defined(FREEBSD)) && defined(SPARC)
4116 # define FR_SAVFP fr_fp
4117 # define FR_SAVPC fr_pc
4119 # define FR_SAVFP fr_savfp
4120 # define FR_SAVPC fr_savpc
4123 #if defined(SPARC) && (defined(__arch64__) || defined(__sparcv9))
4129 void GC_save_callers (struct callinfo info[NFRAMES])
4131 struct frame *frame;
4135 /* We assume this is turned on only with gcc as the compiler. */
4136 asm("movl %%ebp,%0" : "=r"(frame));
4139 frame = (struct frame *) GC_save_regs_in_stack ();
4140 fp = (struct frame *)((long) frame -> FR_SAVFP + BIAS);
4143 for (; (!(fp HOTTER_THAN frame) && !(GC_stackbottom HOTTER_THAN (ptr_t)fp)
4144 && (nframes < NFRAMES));
4145 fp = (struct frame *)((long) fp -> FR_SAVFP + BIAS), nframes++) {
4148 info[nframes].ci_pc = fp->FR_SAVPC;
4150 for (i = 0; i < NARGS; i++) {
4151 info[nframes].ci_arg[i] = ~(fp->fr_arg[i]);
4153 # endif /* NARGS > 0 */
4155 if (nframes < NFRAMES) info[nframes].ci_pc = 0;
4158 #endif /* No builtin backtrace */
4160 #endif /* SAVE_CALL_CHAIN */
4162 #ifdef NEED_CALLINFO
4164 /* Print info to stderr. We do NOT hold the allocation lock */
4165 void GC_print_callers (struct callinfo info[NFRAMES])
4168 static int reentry_count = 0;
4169 GC_bool stop = FALSE;
4171 /* FIXME: This should probably use a different lock, so that we */
4172 /* become callable with or without the allocation lock. */
4178 GC_err_printf("\tCaller at allocation:\n");
4180 GC_err_printf("\tCall chain at allocation:\n");
4182 for (i = 0; i < NFRAMES && !stop ; i++) {
4183 if (info[i].ci_pc == 0) break;
4188 GC_err_printf("\t\targs: ");
4189 for (j = 0; j < NARGS; j++) {
4190 if (j != 0) GC_err_printf(", ");
4191 GC_err_printf("%d (0x%X)", ~(info[i].ci_arg[j]),
4192 ~(info[i].ci_arg[j]));
4194 GC_err_printf("\n");
4197 if (reentry_count > 1) {
4198 /* We were called during an allocation during */
4199 /* a previous GC_print_callers call; punt. */
4200 GC_err_printf("\t\t##PC##= 0x%lx\n", info[i].ci_pc);
4207 # if defined(GC_HAVE_BUILTIN_BACKTRACE) \
4208 && !defined(GC_BACKTRACE_SYMBOLS_BROKEN)
4210 backtrace_symbols((void **)(&(info[i].ci_pc)), 1);
4211 char *name = sym_name[0];
4215 sprintf(buf, "##PC##= 0x%lx", info[i].ci_pc);
4217 # if defined(LINUX) && !defined(SMALL_CONFIG)
4218 /* Try for a line number. */
4221 static char exe_name[EXE_SZ];
4223 char cmd_buf[CMD_SZ];
4224 # define RESULT_SZ 200
4225 static char result_buf[RESULT_SZ];
4228 # define PRELOAD_SZ 200
4229 char preload_buf[PRELOAD_SZ];
4230 static GC_bool found_exe_name = FALSE;
4231 static GC_bool will_fail = FALSE;
4233 /* Try to get it via a hairy and expensive scheme. */
4234 /* First we get the name of the executable: */
4235 if (will_fail) goto out;
4236 if (!found_exe_name) {
4237 ret_code = readlink("/proc/self/exe", exe_name, EXE_SZ);
4238 if (ret_code < 0 || ret_code >= EXE_SZ
4239 || exe_name[0] != '/') {
4240 will_fail = TRUE; /* Dont try again. */
4243 exe_name[ret_code] = '\0';
4244 found_exe_name = TRUE;
4246 /* Then we use popen to start addr2line -e <exe> <addr> */
4247 /* There are faster ways to do this, but hopefully this */
4248 /* isn't time critical. */
4249 sprintf(cmd_buf, "/usr/bin/addr2line -f -e %s 0x%lx", exe_name,
4250 (unsigned long)info[i].ci_pc);
4251 old_preload = getenv ("LD_PRELOAD");
4252 if (0 != old_preload) {
4253 if (strlen (old_preload) >= PRELOAD_SZ) {
4257 strcpy (preload_buf, old_preload);
4258 unsetenv ("LD_PRELOAD");
4260 pipe = popen(cmd_buf, "r");
4261 if (0 != old_preload
4262 && 0 != setenv ("LD_PRELOAD", preload_buf, 0)) {
4263 WARN("Failed to reset LD_PRELOAD\n", 0);
4266 || (result_len = fread(result_buf, 1, RESULT_SZ - 1, pipe))
4268 if (pipe != NULL) pclose(pipe);
4272 if (result_buf[result_len - 1] == '\n') --result_len;
4273 result_buf[result_len] = 0;
4274 if (result_buf[0] == '?'
4275 || (result_buf[result_len-2] == ':'
4276 && result_buf[result_len-1] == '0')) {
4280 /* Get rid of embedded newline, if any. Test for "main" */
4282 char * nl = strchr(result_buf, '\n');
4283 if (nl != NULL && nl < result_buf + result_len) {
4286 if (strncmp(result_buf, "main", nl - result_buf) == 0) {
4290 if (result_len < RESULT_SZ - 25) {
4291 /* Add in hex address */
4292 sprintf(result_buf + result_len, " [0x%lx]",
4293 (unsigned long)info[i].ci_pc);
4300 GC_err_printf("\t\t%s\n", name);
4301 # if defined(GC_HAVE_BUILTIN_BACKTRACE) \
4302 && !defined(GC_BACKTRACE_SYMBOLS_BROKEN)
4303 free(sym_name); /* May call GC_free; that's OK */
4312 #endif /* NEED_CALLINFO */
4316 #if defined(LINUX) && defined(__ELF__) && !defined(SMALL_CONFIG)
4318 /* Dump /proc/self/maps to GC_stderr, to enable looking up names for
4319 addresses in FIND_LEAK output. */
4321 static word dump_maps(char *maps)
4323 GC_err_write(maps, strlen(maps));
4327 void GC_print_address_map(void)
4329 GC_err_printf("---------- Begin address map ----------\n");
4330 dump_maps(GC_get_maps());
4331 GC_err_printf("---------- End address map ----------\n");