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 */
66 #if defined(UNIX_LIKE) || defined(CYGWIN32)
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 && !defined(MSWIN32) && !defined(MSWINCE))
103 # define MMAP_SUPPORTED
106 #if defined(MMAP_SUPPORTED) || defined(ADD_HEAP_GUARD_PAGES)
107 # if defined(USE_MUNMAP) && !defined(USE_MMAP)
108 --> USE_MUNMAP requires USE_MMAP
110 # include <sys/types.h>
111 # include <sys/mman.h>
112 # include <sys/stat.h>
117 /* for get_etext and friends */
118 #include <mach-o/getsect.h>
122 /* Apparently necessary for djgpp 2.01. May cause problems with */
123 /* other versions. */
124 typedef long unsigned int caddr_t;
128 # include "il/PCR_IL.h"
129 # include "th/PCR_ThCtl.h"
130 # include "mm/PCR_MM.h"
133 #if !defined(NO_EXECUTE_PERMISSION)
134 # define OPT_PROT_EXEC PROT_EXEC
136 # define OPT_PROT_EXEC 0
139 #if defined(LINUX) && \
140 (defined(USE_PROC_FOR_LIBRARIES) || defined(IA64) || !defined(SMALL_CONFIG))
141 # define NEED_PROC_MAPS
144 #ifdef NEED_PROC_MAPS
145 /* We need to parse /proc/self/maps, either to find dynamic libraries, */
146 /* and/or to find the register backing store base (IA64). Do it once */
151 /* Repeatedly perform a read call until the buffer is filled or */
152 /* we encounter EOF. */
153 ssize_t GC_repeat_read(int fd, char *buf, size_t count)
155 ssize_t num_read = 0;
158 while (num_read < count) {
159 result = READ(fd, buf + num_read, count - num_read);
160 if (result < 0) return result;
161 if (result == 0) break;
168 /* Determine the length of a file by incrementally reading it into a */
169 /* This would be silly to use on a file supporting lseek, but Linux */
170 /* /proc files usually do not. */
171 STATIC size_t GC_get_file_len(int f)
175 # define GET_FILE_LEN_BUF_SZ 500
176 char buf[GET_FILE_LEN_BUF_SZ];
179 result = read(f, buf, GET_FILE_LEN_BUF_SZ);
180 if (result == -1) return 0;
182 } while (result > 0);
186 STATIC size_t GC_get_maps_len(void)
188 int f = open("/proc/self/maps", O_RDONLY);
189 size_t result = GC_get_file_len(f);
196 * Copy the contents of /proc/self/maps to a buffer in our address space.
197 * Return the address of the buffer, or zero on failure.
198 * This code could be simplified if we could determine its size
201 char * GC_get_maps(void)
205 static char init_buf[1];
206 static char *maps_buf = init_buf;
207 static size_t maps_buf_sz = 1;
208 size_t maps_size, old_maps_size = 0;
210 /* The buffer is essentially static, so there must be a single client. */
211 GC_ASSERT(I_HOLD_LOCK());
213 /* Note that in the presence of threads, the maps file can */
214 /* essentially shrink asynchronously and unexpectedly as */
215 /* threads that we already think of as dead release their */
216 /* stacks. And there is no easy way to read the entire */
217 /* file atomically. This is arguably a misfeature of the */
218 /* /proc/.../maps interface. */
220 /* Since we dont believe the file can grow */
221 /* asynchronously, it should suffice to first determine */
222 /* the size (using lseek or read), and then to reread the */
223 /* file. If the size is inconsistent we have to retry. */
224 /* This only matters with threads enabled, and if we use */
225 /* this to locate roots (not the default). */
227 /* Determine the initial size of /proc/self/maps. */
228 /* Note that lseek doesn't work, at least as of 2.6.15. */
230 maps_size = GC_get_maps_len();
231 if (0 == maps_size) return 0;
233 maps_size = 4000; /* Guess */
236 /* Read /proc/self/maps, growing maps_buf as necessary. */
237 /* Note that we may not allocate conventionally, and */
238 /* thus can't use stdio. */
240 while (maps_size >= maps_buf_sz) {
241 /* Grow only by powers of 2, since we leak "too small" buffers. */
242 while (maps_size >= maps_buf_sz) maps_buf_sz *= 2;
243 maps_buf = GC_scratch_alloc(maps_buf_sz);
245 /* Recompute initial length, since we allocated. */
246 /* This can only happen a few times per program */
248 maps_size = GC_get_maps_len();
249 if (0 == maps_size) return 0;
251 if (maps_buf == 0) return 0;
253 GC_ASSERT(maps_buf_sz >= maps_size + 1);
254 f = open("/proc/self/maps", O_RDONLY);
255 if (-1 == f) return 0;
257 old_maps_size = maps_size;
261 result = GC_repeat_read(f, maps_buf, maps_buf_sz-1);
262 if (result <= 0) return 0;
264 } while (result == maps_buf_sz-1);
267 if (maps_size > old_maps_size) {
268 GC_err_printf("Old maps size = %lu, new maps size = %lu\n",
269 (unsigned long)old_maps_size,
270 (unsigned long)maps_size);
271 ABORT("Unexpected asynchronous /proc/self/maps growth: "
272 "Unregistered thread?");
275 } while (maps_size >= maps_buf_sz || maps_size < old_maps_size);
276 /* In the single-threaded case, the second clause is false. */
277 maps_buf[maps_size] = '\0';
279 /* Apply fn to result. */
284 * GC_parse_map_entry parses an entry from /proc/self/maps so we can
285 * locate all writable data segments that belong to shared libraries.
286 * The format of one of these entries and the fields we care about
288 * XXXXXXXX-XXXXXXXX r-xp 00000000 30:05 260537 name of mapping...\n
289 * ^^^^^^^^ ^^^^^^^^ ^^^^ ^^
290 * start end prot maj_dev
292 * Note that since about august 2003 kernels, the columns no longer have
293 * fixed offsets on 64-bit kernels. Hence we no longer rely on fixed offsets
294 * anywhere, which is safer anyway.
298 * Assign various fields of the first line in buf_ptr to *start, *end,
299 * *prot, *maj_dev and *mapping_name. Mapping_name may be NULL.
300 * *prot and *mapping_name are assigned pointers into the original
303 char *GC_parse_map_entry(char *buf_ptr, ptr_t *start, ptr_t *end,
304 char **prot, unsigned int *maj_dev,
307 char *start_start, *end_start, *maj_dev_start;
311 if (buf_ptr == NULL || *buf_ptr == '\0') {
316 while (isspace(*p)) ++p;
318 GC_ASSERT(isxdigit(*start_start));
319 *start = (ptr_t)strtoul(start_start, &endp, 16); p = endp;
324 GC_ASSERT(isxdigit(*end_start));
325 *end = (ptr_t)strtoul(end_start, &endp, 16); p = endp;
326 GC_ASSERT(isspace(*p));
328 while (isspace(*p)) ++p;
329 GC_ASSERT(*p == 'r' || *p == '-');
331 /* Skip past protection field to offset field */
332 while (!isspace(*p)) ++p; while (isspace(*p)) ++p;
333 GC_ASSERT(isxdigit(*p));
334 /* Skip past offset field, which we ignore */
335 while (!isspace(*p)) ++p; while (isspace(*p)) ++p;
337 GC_ASSERT(isxdigit(*maj_dev_start));
338 *maj_dev = strtoul(maj_dev_start, NULL, 16);
340 if (mapping_name == 0) {
341 while (*p && *p++ != '\n');
343 while (*p && *p != '\n' && *p != '/' && *p != '[') p++;
345 while (*p && *p++ != '\n');
351 /* Try to read the backing store base from /proc/self/maps. */
352 /* Return the bounds of the writable mapping with a 0 major device, */
353 /* which includes the address passed as data. */
354 /* Return FALSE if there is no such mapping. */
355 GC_bool GC_enclosing_mapping(ptr_t addr, ptr_t *startp, ptr_t *endp)
358 ptr_t my_start, my_end;
359 unsigned int maj_dev;
360 char *maps = GC_get_maps();
361 char *buf_ptr = maps;
363 if (0 == maps) return(FALSE);
365 buf_ptr = GC_parse_map_entry(buf_ptr, &my_start, &my_end,
368 if (buf_ptr == NULL) return FALSE;
369 if (prot[1] == 'w' && maj_dev == 0) {
370 if (my_end > addr && my_start <= addr) {
380 #if defined(REDIRECT_MALLOC)
381 /* Find the text(code) mapping for the library whose name, after */
382 /* stripping the directory part, starts with nm. */
383 GC_bool GC_text_mapping(char *nm, ptr_t *startp, ptr_t *endp)
385 size_t nm_len = strlen(nm);
388 ptr_t my_start, my_end;
389 unsigned int maj_dev;
390 char *maps = GC_get_maps();
391 char *buf_ptr = maps;
393 if (0 == maps) return(FALSE);
395 buf_ptr = GC_parse_map_entry(buf_ptr, &my_start, &my_end,
396 &prot, &maj_dev, &map_path);
398 if (buf_ptr == NULL) return FALSE;
399 if (prot[0] == 'r' && prot[1] == '-' && prot[2] == 'x') {
401 /* Set p to point just past last slash, if any. */
402 while (*p != '\0' && *p != '\n' && *p != ' ' && *p != '\t') ++p;
403 while (*p != '/' && p >= map_path) --p;
405 if (strncmp(nm, p, nm_len) == 0) {
414 #endif /* REDIRECT_MALLOC */
417 static ptr_t backing_store_base_from_proc(void)
419 ptr_t my_start, my_end;
420 if (!GC_enclosing_mapping(GC_save_regs_in_stack(), &my_start, &my_end)) {
421 if (GC_print_stats) {
422 GC_log_printf("Failed to find backing store base from /proc\n");
430 #endif /* NEED_PROC_MAPS */
432 #if defined(SEARCH_FOR_DATA_START)
433 /* The I386 case can be handled without a search. The Alpha case */
434 /* used to be handled differently as well, but the rules changed */
435 /* for recent Linux versions. This seems to be the easiest way to */
436 /* cover all versions. */
438 # if defined(LINUX) || defined(HURD)
439 /* Some Linux distributions arrange to define __data_start. Some */
440 /* define data_start as a weak symbol. The latter is technically */
441 /* broken, since the user program may define data_start, in which */
442 /* case we lose. Nonetheless, we try both, preferring __data_start.*/
443 /* We assume gcc-compatible pragmas. */
444 # pragma weak __data_start
445 extern int __data_start[];
446 # pragma weak data_start
447 extern int data_start[];
453 ptr_t GC_find_limit(ptr_t, GC_bool);
455 void GC_init_linux_data_start(void)
458 # if defined(LINUX) || defined(HURD)
459 /* Try the easy approaches first: */
460 if ((ptr_t)__data_start != 0) {
461 GC_data_start = (ptr_t)(__data_start);
464 if ((ptr_t)data_start != 0) {
465 GC_data_start = (ptr_t)(data_start);
469 GC_data_start = GC_find_limit((ptr_t)(_end), FALSE);
475 # ifndef ECOS_GC_MEMORY_SIZE
476 # define ECOS_GC_MEMORY_SIZE (448 * 1024)
477 # endif /* ECOS_GC_MEMORY_SIZE */
479 /* FIXME: This is a simple way of allocating memory which is */
480 /* compatible with ECOS early releases. Later releases use a more */
481 /* sophisticated means of allocating memory than this simple static */
482 /* allocator, but this method is at least bound to work. */
483 static char memory[ECOS_GC_MEMORY_SIZE];
484 static char *brk = memory;
486 static void *tiny_sbrk(ptrdiff_t increment)
492 if (brk > memory + sizeof memory)
500 #define sbrk tiny_sbrk
503 #if (defined(NETBSD) || defined(OPENBSD)) && defined(__ELF__)
505 ptr_t GC_find_limit(ptr_t, GC_bool);
506 extern char **environ;
508 void GC_init_netbsd_elf(void)
510 /* This may need to be environ, without the underscore, for */
512 GC_data_start = GC_find_limit((ptr_t)&environ, FALSE);
520 # if !defined(__IBMC__) && !defined(__WATCOMC__) /* e.g. EMX */
523 unsigned short magic_number;
524 unsigned short padding[29];
528 #define E_MAGIC(x) (x).magic_number
529 #define EMAGIC 0x5A4D
530 #define E_LFANEW(x) (x).new_exe_offset
533 unsigned char magic_number[2];
534 unsigned char byte_order;
535 unsigned char word_order;
536 unsigned long exe_format_level;
539 unsigned long padding1[13];
540 unsigned long object_table_offset;
541 unsigned long object_count;
542 unsigned long padding2[31];
545 #define E32_MAGIC1(x) (x).magic_number[0]
546 #define E32MAGIC1 'L'
547 #define E32_MAGIC2(x) (x).magic_number[1]
548 #define E32MAGIC2 'X'
549 #define E32_BORDER(x) (x).byte_order
551 #define E32_WORDER(x) (x).word_order
553 #define E32_CPU(x) (x).cpu
555 #define E32_OBJTAB(x) (x).object_table_offset
556 #define E32_OBJCNT(x) (x).object_count
562 unsigned long pagemap;
563 unsigned long mapsize;
564 unsigned long reserved;
567 #define O32_FLAGS(x) (x).flags
568 #define OBJREAD 0x0001L
569 #define OBJWRITE 0x0002L
570 #define OBJINVALID 0x0080L
571 #define O32_SIZE(x) (x).size
572 #define O32_BASE(x) (x).base
574 # else /* IBM's compiler */
576 /* A kludge to get around what appears to be a header file bug */
578 # define WORD unsigned short
581 # define DWORD unsigned long
588 # endif /* __IBMC__ */
590 # define INCL_DOSEXCEPTIONS
591 # define INCL_DOSPROCESS
592 # define INCL_DOSERRORS
593 # define INCL_DOSMODULEMGR
594 # define INCL_DOSMEMMGR
599 /* Find the page size */
602 # if defined(MSWIN32) || defined(MSWINCE)
603 void GC_setpagesize(void)
605 GetSystemInfo(&GC_sysinfo);
606 GC_page_size = GC_sysinfo.dwPageSize;
610 # if defined(MPROTECT_VDB) || defined(PROC_VDB) || defined(USE_MMAP)
611 void GC_setpagesize(void)
613 GC_page_size = GETPAGESIZE();
616 /* It's acceptable to fake it. */
617 void GC_setpagesize(void)
619 GC_page_size = HBLKSIZE;
624 # if defined(MSWIN32) || defined(MSWINCE) || defined(CYGWIN32)
628 # define is_writable(prot) ((prot) == PAGE_READWRITE \
629 || (prot) == PAGE_WRITECOPY \
630 || (prot) == PAGE_EXECUTE_READWRITE \
631 || (prot) == PAGE_EXECUTE_WRITECOPY)
632 /* Return the number of bytes that are writable starting at p. */
633 /* The pointer p is assumed to be page aligned. */
634 /* If base is not 0, *base becomes the beginning of the */
635 /* allocation region containing p. */
636 STATIC word GC_get_writable_length(ptr_t p, ptr_t *base)
638 MEMORY_BASIC_INFORMATION buf;
642 result = VirtualQuery(p, &buf, sizeof(buf));
643 if (result != sizeof(buf)) ABORT("Weird VirtualQuery result");
644 if (base != 0) *base = (ptr_t)(buf.AllocationBase);
645 protect = (buf.Protect & ~(PAGE_GUARD | PAGE_NOCACHE));
646 if (!is_writable(protect)) {
649 if (buf.State != MEM_COMMIT) return(0);
650 return(buf.RegionSize);
653 GC_API int GC_CALL GC_get_stack_base(struct GC_stack_base *sb)
656 ptr_t sp = (ptr_t)(&dummy);
657 ptr_t trunc_sp = (ptr_t)((word)sp & ~(GC_page_size - 1));
658 word size = GC_get_writable_length(trunc_sp, 0);
660 sb -> mem_base = trunc_sp + size;
666 /* An alternate version for Cygwin (adapted from Dave Korn's */
667 /* gcc version of boehm-gc). */
668 GC_API int GC_CALL GC_get_stack_base(struct GC_stack_base *sb)
670 extern void * _tlsbase __asm__ ("%fs:4");
671 sb -> mem_base = _tlsbase;
675 #endif /* CYGWIN32 */
678 #define HAVE_GET_STACK_BASE
680 /* This is always called from the main thread. */
681 ptr_t GC_get_main_stack_base(void)
683 struct GC_stack_base sb;
685 GC_get_stack_base(&sb);
686 return (ptr_t)sb.mem_base;
689 # endif /* MS Windows */
692 # include <kernel/OS.h>
693 ptr_t GC_get_main_stack_base(void){
695 get_thread_info(find_thread(NULL),&th);
703 ptr_t GC_get_main_stack_base(void)
708 if (DosGetInfoBlocks(&ptib, &ppib) != NO_ERROR) {
709 GC_err_printf("DosGetInfoBlocks failed\n");
710 ABORT("DosGetInfoBlocks failed\n");
712 return((ptr_t)(ptib -> tib_pstacklimit));
719 # include "AmigaOS.c"
723 # if defined(NEED_FIND_LIMIT) || defined(UNIX_LIKE)
725 typedef void (*handler)(int);
727 # if defined(SUNOS5SIGS) || defined(IRIX5) || defined(OSF1) \
728 || defined(HURD) || defined(NETBSD)
729 static struct sigaction old_segv_act;
730 # if defined(_sigargs) /* !Irix6.x */ || defined(HPUX) \
731 || defined(HURD) || defined(NETBSD) || defined(FREEBSD)
732 static struct sigaction old_bus_act;
735 static handler old_segv_handler, old_bus_handler;
738 void GC_set_and_save_fault_handler(handler h)
740 # if defined(SUNOS5SIGS) || defined(IRIX5) \
741 || defined(OSF1) || defined(HURD) || defined(NETBSD)
742 struct sigaction act;
745 # if 0 /* Was necessary for Solaris 2.3 and very temporary */
747 act.sa_flags = SA_RESTART | SA_NODEFER;
749 act.sa_flags = SA_RESTART;
752 (void) sigemptyset(&act.sa_mask);
753 # ifdef GC_IRIX_THREADS
754 /* Older versions have a bug related to retrieving and */
755 /* and setting a handler at the same time. */
756 (void) sigaction(SIGSEGV, 0, &old_segv_act);
757 (void) sigaction(SIGSEGV, &act, 0);
759 (void) sigaction(SIGSEGV, &act, &old_segv_act);
760 # if defined(IRIX5) && defined(_sigargs) /* Irix 5.x, not 6.x */ \
761 || defined(HPUX) || defined(HURD) || defined(NETBSD) \
763 /* Under Irix 5.x or HP/UX, we may get SIGBUS. */
764 /* Pthreads doesn't exist under Irix 5.x, so we */
765 /* don't have to worry in the threads case. */
766 (void) sigaction(SIGBUS, &act, &old_bus_act);
768 # endif /* GC_IRIX_THREADS */
770 old_segv_handler = signal(SIGSEGV, h);
772 old_bus_handler = signal(SIGBUS, h);
776 # endif /* NEED_FIND_LIMIT || UNIX_LIKE */
778 # if defined(NEED_FIND_LIMIT) || \
779 defined(USE_PROC_FOR_LIBRARIES) && defined(THREADS)
780 /* Some tools to implement HEURISTIC2 */
781 # define MIN_PAGE_SIZE 256 /* Smallest conceivable page size, bytes */
784 STATIC void GC_fault_handler(int sig)
786 LONGJMP(GC_jmp_buf, 1);
789 void GC_setup_temporary_fault_handler(void)
791 /* Handler is process-wide, so this should only happen in */
792 /* one thread at a time. */
793 GC_ASSERT(I_HOLD_LOCK());
794 GC_set_and_save_fault_handler(GC_fault_handler);
797 void GC_reset_fault_handler(void)
799 # if defined(SUNOS5SIGS) || defined(IRIX5) \
800 || defined(OSF1) || defined(HURD) || defined(NETBSD)
801 (void) sigaction(SIGSEGV, &old_segv_act, 0);
802 # if defined(IRIX5) && defined(_sigargs) /* Irix 5.x, not 6.x */ \
803 || defined(HPUX) || defined(HURD) || defined(NETBSD) \
805 (void) sigaction(SIGBUS, &old_bus_act, 0);
808 (void) signal(SIGSEGV, old_segv_handler);
810 (void) signal(SIGBUS, old_bus_handler);
815 /* Return the first non-addressable location > p (up) or */
816 /* the smallest location q s.t. [q,p) is addressable (!up). */
817 /* We assume that p (up) or p-1 (!up) is addressable. */
818 /* Requires allocation lock. */
819 STATIC ptr_t GC_find_limit_with_bound(ptr_t p, GC_bool up, ptr_t bound)
821 static volatile ptr_t result;
822 /* Safer if static, since otherwise it may not be */
823 /* preserved across the longjmp. Can safely be */
824 /* static since it's only called with the */
825 /* allocation lock held. */
827 GC_ASSERT(I_HOLD_LOCK());
828 GC_setup_temporary_fault_handler();
829 if (SETJMP(GC_jmp_buf) == 0) {
830 result = (ptr_t)(((word)(p))
831 & ~(MIN_PAGE_SIZE-1));
834 result += MIN_PAGE_SIZE;
835 if (result >= bound) return bound;
837 result -= MIN_PAGE_SIZE;
838 if (result <= bound) return bound;
840 GC_noop1((word)(*result));
843 GC_reset_fault_handler();
845 result += MIN_PAGE_SIZE;
850 ptr_t GC_find_limit(ptr_t p, GC_bool up)
852 return GC_find_limit_with_bound(p, up, up ? (ptr_t)(word)(-1) : 0);
856 #if defined(ECOS) || defined(NOSYS)
857 ptr_t GC_get_main_stack_base(void)
863 #ifdef HPUX_STACKBOTTOM
865 #include <sys/param.h>
866 #include <sys/pstat.h>
868 ptr_t GC_get_register_stack_base(void)
870 struct pst_vm_status vm_status;
873 while (pstat_getprocvm(&vm_status, sizeof(vm_status), 0, i++) == 1) {
874 if (vm_status.pst_type == PS_RSESTACK) {
875 return (ptr_t) vm_status.pst_vaddr;
879 /* old way to get the register stackbottom */
880 return (ptr_t)(((word)GC_stackbottom - BACKING_STORE_DISPLACEMENT - 1)
881 & ~(BACKING_STORE_ALIGNMENT - 1));
884 #endif /* HPUX_STACK_BOTTOM */
886 #ifdef LINUX_STACKBOTTOM
888 #include <sys/types.h>
889 #include <sys/stat.h>
891 # define STAT_SKIP 27 /* Number of fields preceding startstack */
892 /* field in /proc/self/stat */
894 #ifdef USE_LIBC_PRIVATES
895 # pragma weak __libc_stack_end
896 extern ptr_t __libc_stack_end;
900 # ifdef USE_LIBC_PRIVATES
901 # pragma weak __libc_ia64_register_backing_store_base
902 extern ptr_t __libc_ia64_register_backing_store_base;
905 ptr_t GC_get_register_stack_base(void)
909 # ifdef USE_LIBC_PRIVATES
910 if (0 != &__libc_ia64_register_backing_store_base
911 && 0 != __libc_ia64_register_backing_store_base) {
912 /* Glibc 2.2.4 has a bug such that for dynamically linked */
913 /* executables __libc_ia64_register_backing_store_base is */
914 /* defined but uninitialized during constructor calls. */
915 /* Hence we check for both nonzero address and value. */
916 return __libc_ia64_register_backing_store_base;
919 result = backing_store_base_from_proc();
921 result = GC_find_limit(GC_save_regs_in_stack(), FALSE);
922 /* Now seems to work better than constant displacement */
923 /* heuristic used in 6.X versions. The latter seems to */
924 /* fail for 2.6 kernels. */
930 STATIC ptr_t GC_linux_stack_base(void)
932 /* We read the stack base value from /proc/self/stat. We do this */
933 /* using direct I/O system calls in order to avoid calling malloc */
934 /* in case REDIRECT_MALLOC is defined. */
935 # define STAT_BUF_SIZE 4096
936 # define STAT_READ read
937 /* Should probably call the real read, if read is wrapped. */
938 char stat_buf[STAT_BUF_SIZE];
942 size_t i, buf_offset = 0;
944 /* First try the easy way. This should work for glibc 2.2 */
945 /* This fails in a prelinked ("prelink" command) executable */
946 /* since the correct value of __libc_stack_end never */
947 /* becomes visible to us. The second test works around */
949 # ifdef USE_LIBC_PRIVATES
950 if (0 != &__libc_stack_end && 0 != __libc_stack_end ) {
952 /* Some versions of glibc set the address 16 bytes too */
953 /* low while the initialization code is running. */
954 if (((word)__libc_stack_end & 0xfff) + 0x10 < 0x1000) {
955 return __libc_stack_end + 0x10;
956 } /* Otherwise it's not safe to add 16 bytes and we fall */
957 /* back to using /proc. */
958 # elif defined(SPARC)
959 /* Older versions of glibc for 64-bit Sparc do not set
960 * this variable correctly, it gets set to either zero
963 if (__libc_stack_end != (ptr_t) (unsigned long)0x1)
964 return __libc_stack_end;
966 return __libc_stack_end;
970 f = open("/proc/self/stat", O_RDONLY);
971 if (f < 0 || STAT_READ(f, stat_buf, STAT_BUF_SIZE) < 2 * STAT_SKIP) {
972 ABORT("Couldn't read /proc/self/stat");
974 c = stat_buf[buf_offset++];
975 /* Skip the required number of fields. This number is hopefully */
976 /* constant across all Linux implementations. */
977 for (i = 0; i < STAT_SKIP; ++i) {
978 while (isspace(c)) c = stat_buf[buf_offset++];
979 while (!isspace(c)) c = stat_buf[buf_offset++];
981 while (isspace(c)) c = stat_buf[buf_offset++];
985 c = stat_buf[buf_offset++];
988 if (result < 0x100000) ABORT("Absurd stack bottom value");
989 return (ptr_t)result;
992 #endif /* LINUX_STACKBOTTOM */
994 #ifdef FREEBSD_STACKBOTTOM
996 /* This uses an undocumented sysctl call, but at least one expert */
997 /* believes it will stay. */
1000 #include <sys/types.h>
1001 #include <sys/sysctl.h>
1003 STATIC ptr_t GC_freebsd_stack_base(void)
1005 int nm[2] = {CTL_KERN, KERN_USRSTACK};
1007 size_t len = sizeof(ptr_t);
1008 int r = sysctl(nm, 2, &base, &len, NULL, 0);
1010 if (r) ABORT("Error getting stack base");
1015 #endif /* FREEBSD_STACKBOTTOM */
1017 #if !defined(BEOS) && !defined(AMIGA) && !defined(MSWIN32) \
1018 && !defined(MSWINCE) && !defined(OS2) && !defined(NOSYS) && !defined(ECOS) \
1019 && !defined(CYGWIN32)
1021 ptr_t GC_get_main_stack_base(void)
1024 return(STACKBOTTOM);
1026 # if defined(HEURISTIC1) || defined(HEURISTIC2)
1030 # define STACKBOTTOM_ALIGNMENT_M1 ((word)STACK_GRAN - 1)
1032 # ifdef STACK_GROWS_DOWN
1033 result = (ptr_t)((((word)(&dummy))
1034 + STACKBOTTOM_ALIGNMENT_M1)
1035 & ~STACKBOTTOM_ALIGNMENT_M1);
1037 result = (ptr_t)(((word)(&dummy))
1038 & ~STACKBOTTOM_ALIGNMENT_M1);
1040 # endif /* HEURISTIC1 */
1041 # ifdef LINUX_STACKBOTTOM
1042 result = GC_linux_stack_base();
1044 # ifdef FREEBSD_STACKBOTTOM
1045 result = GC_freebsd_stack_base();
1048 # ifdef STACK_GROWS_DOWN
1049 result = GC_find_limit((ptr_t)(&dummy), TRUE);
1050 # ifdef HEURISTIC2_LIMIT
1051 if (result > HEURISTIC2_LIMIT
1052 && (ptr_t)(&dummy) < HEURISTIC2_LIMIT) {
1053 result = HEURISTIC2_LIMIT;
1057 result = GC_find_limit((ptr_t)(&dummy), FALSE);
1058 # ifdef HEURISTIC2_LIMIT
1059 if (result < HEURISTIC2_LIMIT
1060 && (ptr_t)(&dummy) > HEURISTIC2_LIMIT) {
1061 result = HEURISTIC2_LIMIT;
1066 # endif /* HEURISTIC2 */
1067 # ifdef STACK_GROWS_DOWN
1068 if (result == 0) result = (ptr_t)(signed_word)(-sizeof(ptr_t));
1071 # endif /* STACKBOTTOM */
1074 # endif /* ! AMIGA, !OS 2, ! MS Windows, !BEOS, !NOSYS, !ECOS */
1076 #if defined(GC_LINUX_THREADS) && !defined(HAVE_GET_STACK_BASE)
1078 #include <pthread.h>
1079 /* extern int pthread_getattr_np(pthread_t, pthread_attr_t *); */
1082 ptr_t GC_greatest_stack_base_below(ptr_t bound);
1083 /* From pthread_support.c */
1086 GC_API int GC_CALL GC_get_stack_base(struct GC_stack_base *b)
1088 pthread_attr_t attr;
1091 if (pthread_getattr_np(pthread_self(), &attr) != 0) {
1092 WARN("pthread_getattr_np failed\n", 0);
1093 return GC_UNIMPLEMENTED;
1095 if (pthread_attr_getstack(&attr, &(b -> mem_base), &size) != 0) {
1096 ABORT("pthread_attr_getstack failed");
1098 pthread_attr_destroy(&attr);
1099 # ifdef STACK_GROWS_DOWN
1100 b -> mem_base = (char *)(b -> mem_base) + size;
1103 /* We could try backing_store_base_from_proc, but that's safe */
1104 /* only if no mappings are being asynchronously created. */
1105 /* Subtracting the size from the stack base doesn't work for at */
1106 /* least the main thread. */
1109 ptr_t bsp = GC_save_regs_in_stack();
1110 ptr_t next_stack = GC_greatest_stack_base_below(bsp);
1111 if (0 == next_stack) {
1112 b -> reg_base = GC_find_limit(bsp, FALSE);
1114 /* Avoid walking backwards into preceding memory stack and */
1116 b -> reg_base = GC_find_limit_with_bound(bsp, FALSE, next_stack);
1124 #define HAVE_GET_STACK_BASE
1126 #endif /* GC_LINUX_THREADS */
1128 #ifndef HAVE_GET_STACK_BASE
1129 /* Retrieve stack base. */
1130 /* Using the GC_find_limit version is risky. */
1131 /* On IA64, for example, there is no guard page between the */
1132 /* stack of one thread and the register backing store of the */
1133 /* next. Thus this is likely to identify way too large a */
1134 /* "stack" and thus at least result in disastrous performance. */
1135 /* FIXME - Implement better strategies here. */
1136 GC_API int GC_CALL GC_get_stack_base(struct GC_stack_base *b)
1138 # ifdef NEED_FIND_LIMIT
1140 # ifdef STACK_GROWS_DOWN
1141 b -> mem_base = GC_find_limit((ptr_t)(&dummy), TRUE);
1143 b -> reg_base = GC_find_limit(GC_save_regs_in_stack(), FALSE);
1146 b -> mem_base = GC_find_limit(&dummy, FALSE);
1150 return GC_UNIMPLEMENTED;
1156 * Register static data segment(s) as roots.
1157 * If more data segments are added later then they need to be registered
1158 * add that point (as we do with SunOS dynamic loading),
1159 * or GC_mark_roots needs to check for them (as we do with PCR).
1160 * Called with allocator lock held.
1165 void GC_register_data_segments(void)
1169 HMODULE module_handle;
1170 # define PBUFSIZ 512
1171 UCHAR path[PBUFSIZ];
1173 struct exe_hdr hdrdos; /* MSDOS header. */
1174 struct e32_exe hdr386; /* Real header for my executable */
1175 struct o32_obj seg; /* Currrent segment */
1179 if (DosGetInfoBlocks(&ptib, &ppib) != NO_ERROR) {
1180 GC_err_printf("DosGetInfoBlocks failed\n");
1181 ABORT("DosGetInfoBlocks failed\n");
1183 module_handle = ppib -> pib_hmte;
1184 if (DosQueryModuleName(module_handle, PBUFSIZ, path) != NO_ERROR) {
1185 GC_err_printf("DosQueryModuleName failed\n");
1186 ABORT("DosGetInfoBlocks failed\n");
1188 myexefile = fopen(path, "rb");
1189 if (myexefile == 0) {
1190 GC_err_puts("Couldn't open executable ");
1191 GC_err_puts(path); GC_err_puts("\n");
1192 ABORT("Failed to open executable\n");
1194 if (fread((char *)(&hdrdos), 1, sizeof hdrdos, myexefile) < sizeof hdrdos) {
1195 GC_err_puts("Couldn't read MSDOS header from ");
1196 GC_err_puts(path); GC_err_puts("\n");
1197 ABORT("Couldn't read MSDOS header");
1199 if (E_MAGIC(hdrdos) != EMAGIC) {
1200 GC_err_puts("Executable has wrong DOS magic number: ");
1201 GC_err_puts(path); GC_err_puts("\n");
1202 ABORT("Bad DOS magic number");
1204 if (fseek(myexefile, E_LFANEW(hdrdos), SEEK_SET) != 0) {
1205 GC_err_puts("Seek to new header failed in ");
1206 GC_err_puts(path); GC_err_puts("\n");
1207 ABORT("Bad DOS magic number");
1209 if (fread((char *)(&hdr386), 1, sizeof hdr386, myexefile) < sizeof hdr386) {
1210 GC_err_puts("Couldn't read MSDOS header from ");
1211 GC_err_puts(path); GC_err_puts("\n");
1212 ABORT("Couldn't read OS/2 header");
1214 if (E32_MAGIC1(hdr386) != E32MAGIC1 || E32_MAGIC2(hdr386) != E32MAGIC2) {
1215 GC_err_puts("Executable has wrong OS/2 magic number:");
1216 GC_err_puts(path); GC_err_puts("\n");
1217 ABORT("Bad OS/2 magic number");
1219 if ( E32_BORDER(hdr386) != E32LEBO || E32_WORDER(hdr386) != E32LEWO) {
1220 GC_err_puts("Executable %s has wrong byte order: ");
1221 GC_err_puts(path); GC_err_puts("\n");
1222 ABORT("Bad byte order");
1224 if ( E32_CPU(hdr386) == E32CPU286) {
1225 GC_err_puts("GC can't handle 80286 executables: ");
1226 GC_err_puts(path); GC_err_puts("\n");
1229 if (fseek(myexefile, E_LFANEW(hdrdos) + E32_OBJTAB(hdr386),
1231 GC_err_puts("Seek to object table failed: ");
1232 GC_err_puts(path); GC_err_puts("\n");
1233 ABORT("Seek to object table failed");
1235 for (nsegs = E32_OBJCNT(hdr386); nsegs > 0; nsegs--) {
1237 if (fread((char *)(&seg), 1, sizeof seg, myexefile) < sizeof seg) {
1238 GC_err_puts("Couldn't read obj table entry from ");
1239 GC_err_puts(path); GC_err_puts("\n");
1240 ABORT("Couldn't read obj table entry");
1242 flags = O32_FLAGS(seg);
1243 if (!(flags & OBJWRITE)) continue;
1244 if (!(flags & OBJREAD)) continue;
1245 if (flags & OBJINVALID) {
1246 GC_err_printf("Object with invalid pages?\n");
1249 GC_add_roots_inner((ptr_t)O32_BASE(seg),
1250 (ptr_t)(O32_BASE(seg)+O32_SIZE(seg)), FALSE);
1256 # if defined(GWW_VDB)
1258 # ifndef MEM_WRITE_WATCH
1259 # define MEM_WRITE_WATCH 0x200000
1262 # ifndef WRITE_WATCH_FLAG_RESET
1263 # define WRITE_WATCH_FLAG_RESET 1
1266 # if !defined(_BASETSD_H_) && !defined(_BASETSD_H)
1268 typedef unsigned __int64 ULONG_PTR;
1270 typedef unsigned long ULONG_PTR;
1272 typedef ULONG_PTR SIZE_T;
1273 typedef ULONG_PTR * PULONG_PTR;
1276 typedef UINT (WINAPI * GetWriteWatch_type)(
1277 DWORD, PVOID, SIZE_T, PVOID*, PULONG_PTR, PULONG);
1278 static GetWriteWatch_type GetWriteWatch_func;
1279 static DWORD GetWriteWatch_alloc_flag;
1281 # define GC_GWW_AVAILABLE() (GetWriteWatch_func != NULL)
1283 static void detect_GetWriteWatch(void)
1285 static GC_bool done;
1289 # if defined(MPROTECT_VDB)
1291 char * str = GETENV("GC_USE_GETWRITEWATCH");
1292 # if defined(GC_PREFER_MPROTECT_VDB)
1293 if (str == NULL || (*str == '0' && *(str + 1) == '\0')) {
1294 /* GC_USE_GETWRITEWATCH is unset or set to "0". */
1295 done = TRUE; /* falling back to MPROTECT_VDB strategy. */
1296 /* This should work as if GWW_VDB is undefined. */
1300 if (str != NULL && *str == '0' && *(str + 1) == '\0') {
1301 /* GC_USE_GETWRITEWATCH is set "0". */
1302 done = TRUE; /* falling back to MPROTECT_VDB strategy. */
1309 GetWriteWatch_func = (GetWriteWatch_type)
1310 GetProcAddress(GetModuleHandle("kernel32.dll"), "GetWriteWatch");
1311 if (GetWriteWatch_func != NULL) {
1312 /* Also check whether VirtualAlloc accepts MEM_WRITE_WATCH, */
1313 /* as some versions of kernel32.dll have one but not the */
1314 /* other, making the feature completely broken. */
1315 void * page = VirtualAlloc(NULL, GC_page_size,
1316 MEM_WRITE_WATCH | MEM_RESERVE,
1320 ULONG_PTR count = 16;
1322 /* Check that it actually works. In spite of some */
1323 /* documentation it actually seems to exist on W2K. */
1324 /* This test may be unnecessary, but ... */
1325 if (GetWriteWatch_func(WRITE_WATCH_FLAG_RESET,
1330 /* GetWriteWatch always fails. */
1331 GetWriteWatch_func = NULL;
1333 GetWriteWatch_alloc_flag = MEM_WRITE_WATCH;
1335 VirtualFree(page, GC_page_size, MEM_RELEASE);
1337 /* GetWriteWatch will be useless. */
1338 GetWriteWatch_func = NULL;
1341 if (GC_print_stats) {
1342 if (GetWriteWatch_func == NULL) {
1343 GC_log_printf("Did not find a usable GetWriteWatch()\n");
1345 GC_log_printf("Using GetWriteWatch()\n");
1351 # endif /* GWW_VDB */
1353 # if defined(MSWIN32) || defined(MSWINCE)
1356 /* Unfortunately, we have to handle win32s very differently from NT, */
1357 /* Since VirtualQuery has very different semantics. In particular, */
1358 /* under win32s a VirtualQuery call on an unmapped page returns an */
1359 /* invalid result. Under NT, GC_register_data_segments is a no-op */
1360 /* and all real work is done by GC_register_dynamic_libraries. Under */
1361 /* win32s, we cannot find the data segments associated with dll's. */
1362 /* We register the main data segment here. */
1363 GC_bool GC_no_win32_dlls = FALSE;
1364 /* This used to be set for gcc, to avoid dealing with */
1365 /* the structured exception handling issues. But we now have */
1366 /* assembly code to do that right. */
1368 GC_bool GC_wnt = FALSE;
1369 /* This is a Windows NT derivative, i.e. NT, W2K, XP or later. */
1371 void GC_init_win32(void)
1374 /* If we're running under win32s, assume that no DLLs will be loaded */
1375 /* I doubt anyone still runs win32s, but ... */
1376 DWORD v = GetVersion();
1377 GC_wnt = !(v & 0x80000000);
1378 GC_no_win32_dlls |= ((!GC_wnt) && (v & 0xff) <= 3);
1381 /* Return the smallest address a such that VirtualQuery */
1382 /* returns correct results for all addresses between a and start. */
1383 /* Assumes VirtualQuery returns correct information for start. */
1384 ptr_t GC_least_described_address(ptr_t start)
1386 MEMORY_BASIC_INFORMATION buf;
1392 limit = GC_sysinfo.lpMinimumApplicationAddress;
1393 p = (ptr_t)((word)start & ~(GC_page_size - 1));
1395 q = (LPVOID)(p - GC_page_size);
1396 if ((ptr_t)q > (ptr_t)p /* underflow */ || q < limit) break;
1397 result = VirtualQuery(q, &buf, sizeof(buf));
1398 if (result != sizeof(buf) || buf.AllocationBase == 0) break;
1399 p = (ptr_t)(buf.AllocationBase);
1405 # ifndef REDIRECT_MALLOC
1406 /* We maintain a linked list of AllocationBase values that we know */
1407 /* correspond to malloc heap sections. Currently this is only called */
1408 /* during a GC. But there is some hope that for long running */
1409 /* programs we will eventually see most heap sections. */
1411 /* In the long run, it would be more reliable to occasionally walk */
1412 /* the malloc heap with HeapWalk on the default heap. But that */
1413 /* apparently works only for NT-based Windows. */
1415 /* In the long run, a better data structure would also be nice ... */
1416 STATIC struct GC_malloc_heap_list {
1417 void * allocation_base;
1418 struct GC_malloc_heap_list *next;
1419 } *GC_malloc_heap_l = 0;
1421 /* Is p the base of one of the malloc heap sections we already know */
1423 STATIC GC_bool GC_is_malloc_heap_base(ptr_t p)
1425 struct GC_malloc_heap_list *q = GC_malloc_heap_l;
1428 if (q -> allocation_base == p) return TRUE;
1434 STATIC void *GC_get_allocation_base(void *p)
1436 MEMORY_BASIC_INFORMATION buf;
1437 size_t result = VirtualQuery(p, &buf, sizeof(buf));
1438 if (result != sizeof(buf)) {
1439 ABORT("Weird VirtualQuery result");
1441 return buf.AllocationBase;
1444 STATIC size_t GC_max_root_size = 100000; /* Appr. largest root size. */
1446 void GC_add_current_malloc_heap(void)
1448 struct GC_malloc_heap_list *new_l =
1449 malloc(sizeof(struct GC_malloc_heap_list));
1450 void * candidate = GC_get_allocation_base(new_l);
1452 if (new_l == 0) return;
1453 if (GC_is_malloc_heap_base(candidate)) {
1454 /* Try a little harder to find malloc heap. */
1455 size_t req_size = 10000;
1457 void *p = malloc(req_size);
1458 if (0 == p) { free(new_l); return; }
1459 candidate = GC_get_allocation_base(p);
1462 } while (GC_is_malloc_heap_base(candidate)
1463 && req_size < GC_max_root_size/10 && req_size < 500000);
1464 if (GC_is_malloc_heap_base(candidate)) {
1465 free(new_l); return;
1469 GC_log_printf("Found new system malloc AllocationBase at %p\n",
1471 new_l -> allocation_base = candidate;
1472 new_l -> next = GC_malloc_heap_l;
1473 GC_malloc_heap_l = new_l;
1475 # endif /* REDIRECT_MALLOC */
1477 /* Is p the start of either the malloc heap, or of one of our */
1478 /* heap sections? */
1479 GC_bool GC_is_heap_base (ptr_t p)
1484 # ifndef REDIRECT_MALLOC
1485 if (GC_root_size > GC_max_root_size) GC_max_root_size = GC_root_size;
1486 if (GC_is_malloc_heap_base(p)) return TRUE;
1488 for (i = 0; i < GC_n_heap_bases; i++) {
1489 if (GC_heap_bases[i] == p) return TRUE;
1495 STATIC void GC_register_root_section(ptr_t static_root)
1497 MEMORY_BASIC_INFORMATION buf;
1502 char * limit, * new_limit;
1504 if (!GC_no_win32_dlls) return;
1505 p = base = limit = GC_least_described_address(static_root);
1506 while (p < GC_sysinfo.lpMaximumApplicationAddress) {
1507 result = VirtualQuery(p, &buf, sizeof(buf));
1508 if (result != sizeof(buf) || buf.AllocationBase == 0
1509 || GC_is_heap_base(buf.AllocationBase)) break;
1510 new_limit = (char *)p + buf.RegionSize;
1511 protect = buf.Protect;
1512 if (buf.State == MEM_COMMIT
1513 && is_writable(protect)) {
1514 if ((char *)p == limit) {
1517 if (base != limit) GC_add_roots_inner(base, limit, FALSE);
1522 if (p > (LPVOID)new_limit /* overflow */) break;
1523 p = (LPVOID)new_limit;
1525 if (base != limit) GC_add_roots_inner(base, limit, FALSE);
1529 void GC_register_data_segments(void)
1533 GC_register_root_section((ptr_t)(&dummy));
1537 # else /* !OS2 && !Windows */
1539 # if (defined(SVR4) || defined(AUX) || defined(DGUX) \
1540 || (defined(LINUX) && defined(SPARC))) && !defined(PCR)
1541 ptr_t GC_SysVGetDataStart(size_t max_page_size, ptr_t etext_addr)
1543 word text_end = ((word)(etext_addr) + sizeof(word) - 1)
1544 & ~(sizeof(word) - 1);
1545 /* etext rounded to word boundary */
1546 word next_page = ((text_end + (word)max_page_size - 1)
1547 & ~((word)max_page_size - 1));
1548 word page_offset = (text_end & ((word)max_page_size - 1));
1549 volatile char * result = (char *)(next_page + page_offset);
1550 /* Note that this isnt equivalent to just adding */
1551 /* max_page_size to &etext if &etext is at a page boundary */
1553 GC_setup_temporary_fault_handler();
1554 if (SETJMP(GC_jmp_buf) == 0) {
1555 /* Try writing to the address. */
1557 GC_reset_fault_handler();
1559 GC_reset_fault_handler();
1560 /* We got here via a longjmp. The address is not readable. */
1561 /* This is known to happen under Solaris 2.4 + gcc, which place */
1562 /* string constants in the text segment, but after etext. */
1563 /* Use plan B. Note that we now know there is a gap between */
1564 /* text and data segments, so plan A bought us something. */
1565 result = (char *)GC_find_limit((ptr_t)(DATAEND), FALSE);
1567 return((ptr_t)result);
1571 # if defined(FREEBSD) && (defined(I386) || defined(X86_64) || defined(powerpc) || defined(__powerpc__)) && !defined(PCR)
1572 /* Its unclear whether this should be identical to the above, or */
1573 /* whether it should apply to non-X86 architectures. */
1574 /* For now we don't assume that there is always an empty page after */
1575 /* etext. But in some cases there actually seems to be slightly more. */
1576 /* This also deals with holes between read-only data and writable data. */
1577 ptr_t GC_FreeBSDGetDataStart(size_t max_page_size, ptr_t etext_addr)
1579 word text_end = ((word)(etext_addr) + sizeof(word) - 1)
1580 & ~(sizeof(word) - 1);
1581 /* etext rounded to word boundary */
1582 volatile word next_page = (text_end + (word)max_page_size - 1)
1583 & ~((word)max_page_size - 1);
1584 volatile ptr_t result = (ptr_t)text_end;
1585 GC_setup_temporary_fault_handler();
1586 if (SETJMP(GC_jmp_buf) == 0) {
1587 /* Try reading at the address. */
1588 /* This should happen before there is another thread. */
1589 for (; next_page < (word)(DATAEND); next_page += (word)max_page_size)
1590 *(volatile char *)next_page;
1591 GC_reset_fault_handler();
1593 GC_reset_fault_handler();
1594 /* As above, we go to plan B */
1595 result = GC_find_limit((ptr_t)(DATAEND), FALSE);
1605 # define GC_AMIGA_DS
1606 # include "AmigaOS.c"
1609 #else /* !OS2 && !Windows && !AMIGA */
1611 void GC_register_data_segments(void)
1613 # if !defined(PCR) && !defined(MACOS)
1614 # if defined(REDIRECT_MALLOC) && defined(GC_SOLARIS_THREADS)
1615 /* As of Solaris 2.3, the Solaris threads implementation */
1616 /* allocates the data structure for the initial thread with */
1617 /* sbrk at process startup. It needs to be scanned, so that */
1618 /* we don't lose some malloc allocated data structures */
1619 /* hanging from it. We're on thin ice here ... */
1620 extern caddr_t sbrk(int);
1622 GC_add_roots_inner(DATASTART, (ptr_t)sbrk(0), FALSE);
1624 GC_add_roots_inner(DATASTART, (ptr_t)(DATAEND), FALSE);
1625 # if defined(DATASTART2)
1626 GC_add_roots_inner(DATASTART2, (ptr_t)(DATAEND2), FALSE);
1632 # if defined(THINK_C)
1633 extern void* GC_MacGetDataStart(void);
1634 /* globals begin above stack and end at a5. */
1635 GC_add_roots_inner((ptr_t)GC_MacGetDataStart(),
1636 (ptr_t)LMGetCurrentA5(), FALSE);
1638 # if defined(__MWERKS__)
1640 extern void* GC_MacGetDataStart(void);
1641 /* MATTHEW: Function to handle Far Globals (CW Pro 3) */
1642 # if __option(far_data)
1643 extern void* GC_MacGetDataEnd(void);
1645 /* globals begin above stack and end at a5. */
1646 GC_add_roots_inner((ptr_t)GC_MacGetDataStart(),
1647 (ptr_t)LMGetCurrentA5(), FALSE);
1648 /* MATTHEW: Handle Far Globals */
1649 # if __option(far_data)
1650 /* Far globals follow he QD globals: */
1651 GC_add_roots_inner((ptr_t)LMGetCurrentA5(),
1652 (ptr_t)GC_MacGetDataEnd(), FALSE);
1655 extern char __data_start__[], __data_end__[];
1656 GC_add_roots_inner((ptr_t)&__data_start__,
1657 (ptr_t)&__data_end__, FALSE);
1658 # endif /* __POWERPC__ */
1659 # endif /* __MWERKS__ */
1660 # endif /* !THINK_C */
1664 /* Dynamic libraries are added at every collection, since they may */
1668 # endif /* ! AMIGA */
1669 # endif /* ! MSWIN32 && ! MSWINCE*/
1673 * Auxiliary routines for obtaining memory from OS.
1676 # if !defined(OS2) && !defined(PCR) && !defined(AMIGA) \
1677 && !defined(MSWIN32) && !defined(MSWINCE) \
1678 && !defined(MACOS) && !defined(DOS4GW) && !defined(NONSTOP)
1680 # define SBRK_ARG_T ptrdiff_t
1682 #if defined(MMAP_SUPPORTED)
1684 #ifdef USE_MMAP_FIXED
1685 # define GC_MMAP_FLAGS MAP_FIXED | MAP_PRIVATE
1686 /* Seems to yield better performance on Solaris 2, but can */
1687 /* be unreliable if something is already mapped at the address. */
1689 # define GC_MMAP_FLAGS MAP_PRIVATE
1692 #ifdef USE_MMAP_ANON
1694 # if defined(MAP_ANONYMOUS)
1695 # define OPT_MAP_ANON MAP_ANONYMOUS
1697 # define OPT_MAP_ANON MAP_ANON
1701 # define OPT_MAP_ANON 0
1705 # define HEAP_START ((ptr_t)0)
1708 STATIC ptr_t GC_unix_mmap_get_mem(word bytes)
1711 static ptr_t last_addr = HEAP_START;
1713 # ifndef USE_MMAP_ANON
1714 static GC_bool initialized = FALSE;
1717 zero_fd = open("/dev/zero", O_RDONLY);
1718 fcntl(zero_fd, F_SETFD, FD_CLOEXEC);
1723 if (bytes & (GC_page_size -1)) ABORT("Bad GET_MEM arg");
1724 result = mmap(last_addr, bytes, PROT_READ | PROT_WRITE | OPT_PROT_EXEC,
1725 GC_MMAP_FLAGS | OPT_MAP_ANON, zero_fd, 0/* offset */);
1726 if (result == MAP_FAILED) return(0);
1727 last_addr = (ptr_t)result + bytes + GC_page_size - 1;
1728 last_addr = (ptr_t)((word)last_addr & ~(GC_page_size - 1));
1729 # if !defined(LINUX)
1730 if (last_addr == 0) {
1731 /* Oops. We got the end of the address space. This isn't */
1732 /* usable by arbitrary C code, since one-past-end pointers */
1733 /* don't work, so we discard it and try again. */
1734 munmap(result, (size_t)(-GC_page_size) - (size_t)result);
1735 /* Leave last page mapped, so we can't repeat. */
1736 return GC_unix_mmap_get_mem(bytes);
1739 GC_ASSERT(last_addr != 0);
1741 return((ptr_t)result);
1744 # endif /* MMAP_SUPPORTED */
1746 #if defined(USE_MMAP)
1748 ptr_t GC_unix_get_mem(word bytes)
1750 return GC_unix_mmap_get_mem(bytes);
1753 #else /* Not USE_MMAP */
1755 STATIC ptr_t GC_unix_sbrk_get_mem(word bytes)
1759 /* Bare sbrk isn't thread safe. Play by malloc rules. */
1760 /* The equivalent may be needed on other systems as well. */
1764 ptr_t cur_brk = (ptr_t)sbrk(0);
1765 SBRK_ARG_T lsbs = (word)cur_brk & (GC_page_size-1);
1767 if ((SBRK_ARG_T)bytes < 0) {
1768 result = 0; /* too big */
1772 if((ptr_t)sbrk(GC_page_size - lsbs) == (ptr_t)(-1)) {
1777 # ifdef ADD_HEAP_GUARD_PAGES
1778 /* This is useful for catching severe memory overwrite problems that */
1779 /* span heap sections. It shouldn't otherwise be turned on. */
1781 ptr_t guard = (ptr_t)sbrk((SBRK_ARG_T)GC_page_size);
1782 if (mprotect(guard, GC_page_size, PROT_NONE) != 0)
1783 ABORT("ADD_HEAP_GUARD_PAGES: mprotect failed");
1785 # endif /* ADD_HEAP_GUARD_PAGES */
1786 result = (ptr_t)sbrk((SBRK_ARG_T)bytes);
1787 if (result == (ptr_t)(-1)) result = 0;
1796 #if defined(MMAP_SUPPORTED)
1798 /* By default, we try both sbrk and mmap, in that order. */
1799 ptr_t GC_unix_get_mem(word bytes)
1801 static GC_bool sbrk_failed = FALSE;
1804 if (!sbrk_failed) result = GC_unix_sbrk_get_mem(bytes);
1807 result = GC_unix_mmap_get_mem(bytes);
1810 /* Try sbrk again, in case sbrk memory became available. */
1811 result = GC_unix_sbrk_get_mem(bytes);
1816 #else /* !MMAP_SUPPORTED */
1818 ptr_t GC_unix_get_mem(word bytes)
1820 return GC_unix_sbrk_get_mem(bytes);
1825 #endif /* Not USE_MMAP */
1831 void * os2_alloc(size_t bytes)
1835 if (DosAllocMem(&result, bytes, PAG_EXECUTE | PAG_READ |
1836 PAG_WRITE | PAG_COMMIT)
1840 if (result == 0) return(os2_alloc(bytes));
1847 # if defined(MSWIN32) || defined(MSWINCE)
1848 SYSTEM_INFO GC_sysinfo;
1853 # ifdef USE_GLOBAL_ALLOC
1854 # define GLOBAL_ALLOC_TEST 1
1856 # define GLOBAL_ALLOC_TEST GC_no_win32_dlls
1859 word GC_n_heap_bases = 0;
1861 #ifdef GC_USE_MEM_TOP_DOWN
1862 STATIC DWORD GC_mem_top_down = MEM_TOP_DOWN;
1863 /* Use GC_USE_MEM_TOP_DOWN for better 64-bit */
1864 /* testing. Otherwise all addresses tend to */
1865 /* end up in first 4GB, hiding bugs. */
1867 STATIC DWORD GC_mem_top_down = 0;
1870 ptr_t GC_win32_get_mem(word bytes)
1874 if (GLOBAL_ALLOC_TEST) {
1875 /* VirtualAlloc doesn't like PAGE_EXECUTE_READWRITE. */
1876 /* There are also unconfirmed rumors of other */
1877 /* problems, so we dodge the issue. */
1878 result = (ptr_t) GlobalAlloc(0, bytes + HBLKSIZE);
1879 result = (ptr_t)(((word)result + HBLKSIZE - 1) & ~(HBLKSIZE-1));
1881 /* VirtualProtect only works on regions returned by a */
1882 /* single VirtualAlloc call. Thus we allocate one */
1883 /* extra page, which will prevent merging of blocks */
1884 /* in separate regions, and eliminate any temptation */
1885 /* to call VirtualProtect on a range spanning regions. */
1886 /* This wastes a small amount of memory, and risks */
1887 /* increased fragmentation. But better alternatives */
1888 /* would require effort. */
1889 /* Pass the MEM_WRITE_WATCH only if GetWriteWatch-based */
1890 /* VDBs are enabled and the GetWriteWatch function is */
1891 /* available. Otherwise we waste resources or possibly */
1892 /* cause VirtualAlloc to fail (observed in Windows 2000 */
1894 result = (ptr_t) VirtualAlloc(NULL, bytes + 1,
1896 GetWriteWatch_alloc_flag |
1898 MEM_COMMIT | MEM_RESERVE
1900 PAGE_EXECUTE_READWRITE);
1902 if (HBLKDISPL(result) != 0) ABORT("Bad VirtualAlloc result");
1903 /* If I read the documentation correctly, this can */
1904 /* only happen if HBLKSIZE > 64k or not a power of 2. */
1905 if (GC_n_heap_bases >= MAX_HEAP_SECTS) ABORT("Too many heap sections");
1906 if (0 != result) GC_heap_bases[GC_n_heap_bases++] = result;
1910 GC_API void GC_CALL GC_win32_free_heap(void)
1912 if (GC_no_win32_dlls) {
1913 while (GC_n_heap_bases > 0) {
1914 GlobalFree (GC_heap_bases[--GC_n_heap_bases]);
1915 GC_heap_bases[GC_n_heap_bases] = 0;
1922 # define GC_AMIGA_AM
1923 # include "AmigaOS.c"
1929 word GC_n_heap_bases = 0;
1931 ptr_t GC_wince_get_mem(word bytes)
1936 /* Round up allocation size to multiple of page size */
1937 bytes = (bytes + GC_page_size-1) & ~(GC_page_size-1);
1939 /* Try to find reserved, uncommitted pages */
1940 for (i = 0; i < GC_n_heap_bases; i++) {
1941 if (((word)(-(signed_word)GC_heap_lengths[i])
1942 & (GC_sysinfo.dwAllocationGranularity-1))
1944 result = GC_heap_bases[i] + GC_heap_lengths[i];
1949 if (i == GC_n_heap_bases) {
1950 /* Reserve more pages */
1951 word res_bytes = (bytes + GC_sysinfo.dwAllocationGranularity-1)
1952 & ~(GC_sysinfo.dwAllocationGranularity-1);
1953 /* If we ever support MPROTECT_VDB here, we will probably need to */
1954 /* ensure that res_bytes is strictly > bytes, so that VirtualProtect */
1955 /* never spans regions. It seems to be OK for a VirtualFree */
1956 /* argument to span regions, so we should be OK for now. */
1957 result = (ptr_t) VirtualAlloc(NULL, res_bytes,
1958 MEM_RESERVE | MEM_TOP_DOWN,
1959 PAGE_EXECUTE_READWRITE);
1960 if (HBLKDISPL(result) != 0) ABORT("Bad VirtualAlloc result");
1961 /* If I read the documentation correctly, this can */
1962 /* only happen if HBLKSIZE > 64k or not a power of 2. */
1963 if (GC_n_heap_bases >= MAX_HEAP_SECTS) ABORT("Too many heap sections");
1964 GC_heap_bases[GC_n_heap_bases] = result;
1965 GC_heap_lengths[GC_n_heap_bases] = 0;
1970 result = (ptr_t) VirtualAlloc(result, bytes,
1972 PAGE_EXECUTE_READWRITE);
1973 if (result != NULL) {
1974 if (HBLKDISPL(result) != 0) ABORT("Bad VirtualAlloc result");
1975 GC_heap_lengths[i] += bytes;
1984 /* For now, this only works on Win32/WinCE and some Unix-like */
1985 /* systems. If you have something else, don't define */
1988 #if !defined(MSWIN32) && !defined(MSWINCE)
1991 #include <sys/mman.h>
1992 #include <sys/stat.h>
1993 #include <sys/types.h>
1997 /* Compute a page aligned starting address for the unmap */
1998 /* operation on a block of size bytes starting at start. */
1999 /* Return 0 if the block is too small to make this feasible. */
2000 STATIC ptr_t GC_unmap_start(ptr_t start, size_t bytes)
2003 /* Round start to next page boundary. */
2004 result = (ptr_t)((word)(start + GC_page_size - 1) & ~(GC_page_size - 1));
2005 if (result + GC_page_size > start + bytes) return 0;
2009 /* Compute end address for an unmap operation on the indicated */
2011 STATIC ptr_t GC_unmap_end(ptr_t start, size_t bytes)
2013 return (ptr_t)((word)(start + bytes) & ~(GC_page_size - 1));
2016 /* Under Win32/WinCE we commit (map) and decommit (unmap) */
2017 /* memory using VirtualAlloc and VirtualFree. These functions */
2018 /* work on individual allocations of virtual memory, made */
2019 /* previously using VirtualAlloc with the MEM_RESERVE flag. */
2020 /* The ranges we need to (de)commit may span several of these */
2021 /* allocations; therefore we use VirtualQuery to check */
2022 /* allocation lengths, and split up the range as necessary. */
2024 /* We assume that GC_remap is called on exactly the same range */
2025 /* as a previous call to GC_unmap. It is safe to consistently */
2026 /* round the endpoints in both places. */
2027 void GC_unmap(ptr_t start, size_t bytes)
2029 ptr_t start_addr = GC_unmap_start(start, bytes);
2030 ptr_t end_addr = GC_unmap_end(start, bytes);
2031 word len = end_addr - start_addr;
2032 if (0 == start_addr) return;
2033 # if defined(MSWIN32) || defined(MSWINCE)
2035 MEMORY_BASIC_INFORMATION mem_info;
2037 if (VirtualQuery(start_addr, &mem_info, sizeof(mem_info))
2038 != sizeof(mem_info))
2039 ABORT("Weird VirtualQuery result");
2040 free_len = (len < mem_info.RegionSize) ? len : mem_info.RegionSize;
2041 if (!VirtualFree(start_addr, free_len, MEM_DECOMMIT))
2042 ABORT("VirtualFree failed");
2043 GC_unmapped_bytes += free_len;
2044 start_addr += free_len;
2048 /* We immediately remap it to prevent an intervening mmap from */
2049 /* accidentally grabbing the same address space. */
2052 result = mmap(start_addr, len, PROT_NONE,
2053 MAP_PRIVATE | MAP_FIXED | OPT_MAP_ANON,
2054 zero_fd, 0/* offset */);
2055 if (result != (void *)start_addr) ABORT("mmap(...PROT_NONE...) failed");
2057 GC_unmapped_bytes += len;
2062 void GC_remap(ptr_t start, size_t bytes)
2064 ptr_t start_addr = GC_unmap_start(start, bytes);
2065 ptr_t end_addr = GC_unmap_end(start, bytes);
2066 word len = end_addr - start_addr;
2068 /* FIXME: Should we handle out-of-memory here? */
2069 # if defined(MSWIN32) || defined(MSWINCE)
2072 if (0 == start_addr) return;
2074 MEMORY_BASIC_INFORMATION mem_info;
2076 if (VirtualQuery(start_addr, &mem_info, sizeof(mem_info))
2077 != sizeof(mem_info))
2078 ABORT("Weird VirtualQuery result");
2079 alloc_len = (len < mem_info.RegionSize) ? len : mem_info.RegionSize;
2080 result = VirtualAlloc(start_addr, alloc_len,
2082 PAGE_EXECUTE_READWRITE);
2083 if (result != start_addr) {
2084 ABORT("VirtualAlloc remapping failed");
2086 GC_unmapped_bytes -= alloc_len;
2087 start_addr += alloc_len;
2091 /* It was already remapped with PROT_NONE. */
2094 if (0 == start_addr) return;
2095 result = mprotect(start_addr, len,
2096 PROT_READ | PROT_WRITE | OPT_PROT_EXEC);
2099 "Mprotect failed at %p (length %ld) with errno %d\n",
2100 start_addr, (unsigned long)len, errno);
2101 ABORT("Mprotect remapping failed");
2103 GC_unmapped_bytes -= len;
2107 /* Two adjacent blocks have already been unmapped and are about to */
2108 /* be merged. Unmap the whole block. This typically requires */
2109 /* that we unmap a small section in the middle that was not previously */
2110 /* unmapped due to alignment constraints. */
2111 void GC_unmap_gap(ptr_t start1, size_t bytes1, ptr_t start2, size_t bytes2)
2113 ptr_t start1_addr = GC_unmap_start(start1, bytes1);
2114 ptr_t end1_addr = GC_unmap_end(start1, bytes1);
2115 ptr_t start2_addr = GC_unmap_start(start2, bytes2);
2116 ptr_t start_addr = end1_addr;
2117 ptr_t end_addr = start2_addr;
2119 GC_ASSERT(start1 + bytes1 == start2);
2120 if (0 == start1_addr) start_addr = GC_unmap_start(start1, bytes1 + bytes2);
2121 if (0 == start2_addr) end_addr = GC_unmap_end(start1, bytes1 + bytes2);
2122 if (0 == start_addr) return;
2123 len = end_addr - start_addr;
2124 # if defined(MSWIN32) || defined(MSWINCE)
2126 MEMORY_BASIC_INFORMATION mem_info;
2128 if (VirtualQuery(start_addr, &mem_info, sizeof(mem_info))
2129 != sizeof(mem_info))
2130 ABORT("Weird VirtualQuery result");
2131 free_len = (len < mem_info.RegionSize) ? len : mem_info.RegionSize;
2132 if (!VirtualFree(start_addr, free_len, MEM_DECOMMIT))
2133 ABORT("VirtualFree failed");
2134 GC_unmapped_bytes += free_len;
2135 start_addr += free_len;
2140 /* Immediately remap as above. */
2142 result = mmap(start_addr, len, PROT_NONE,
2143 MAP_PRIVATE | MAP_FIXED | OPT_MAP_ANON,
2144 zero_fd, 0/* offset */);
2145 if (result != (void *)start_addr) ABORT("mmap(...PROT_NONE...) failed");
2147 GC_unmapped_bytes += len;
2151 #endif /* USE_MUNMAP */
2153 /* Routine for pushing any additional roots. In THREADS */
2154 /* environment, this is also responsible for marking from */
2155 /* thread stacks. */
2157 void (*GC_push_other_roots)(void) = 0;
2161 PCR_ERes GC_push_thread_stack(PCR_Th_T *t, PCR_Any dummy)
2163 struct PCR_ThCtl_TInfoRep info;
2166 info.ti_stkLow = info.ti_stkHi = 0;
2167 result = PCR_ThCtl_GetInfo(t, &info);
2168 GC_push_all_stack((ptr_t)(info.ti_stkLow), (ptr_t)(info.ti_stkHi));
2172 /* Push the contents of an old object. We treat this as stack */
2173 /* data only because that makes it robust against mark stack */
2175 PCR_ERes GC_push_old_obj(void *p, size_t size, PCR_Any data)
2177 GC_push_all_stack((ptr_t)p, (ptr_t)p + size);
2178 return(PCR_ERes_okay);
2182 void GC_default_push_other_roots(void)
2184 /* Traverse data allocated by previous memory managers. */
2186 extern struct PCR_MM_ProcsRep * GC_old_allocator;
2188 if ((*(GC_old_allocator->mmp_enumerate))(PCR_Bool_false,
2191 ABORT("Old object enumeration failed");
2194 /* Traverse all thread stacks. */
2196 PCR_ThCtl_ApplyToAllOtherThreads(GC_push_thread_stack,0))
2197 || PCR_ERes_IsErr(GC_push_thread_stack(PCR_Th_CurrThread(), 0))) {
2198 ABORT("Thread stack marking failed\n");
2205 # if defined(GC_PTHREADS) || defined(GC_WIN32_THREADS)
2207 extern void GC_push_all_stacks(void);
2209 STATIC void GC_default_push_other_roots(void)
2211 GC_push_all_stacks();
2214 # endif /* GC_WIN32_THREADS || GC_PTHREADS */
2216 void (*GC_push_other_roots)(void) = GC_default_push_other_roots;
2218 #endif /* THREADS */
2221 * Routines for accessing dirty bits on virtual pages.
2222 * There are six ways to maintain this information:
2223 * DEFAULT_VDB: A simple dummy implementation that treats every page
2224 * as possibly dirty. This makes incremental collection
2225 * useless, but the implementation is still correct.
2226 * MANUAL_VDB: Stacks and static data are always considered dirty.
2227 * Heap pages are considered dirty if GC_dirty(p) has been
2228 * called on some pointer p pointing to somewhere inside
2229 * an object on that page. A GC_dirty() call on a large
2230 * object directly dirties only a single page, but for
2231 * MANUAL_VDB we are careful to treat an object with a dirty
2232 * page as completely dirty.
2233 * In order to avoid races, an object must be marked dirty
2234 * after it is written, and a reference to the object
2235 * must be kept on a stack or in a register in the interim.
2236 * With threads enabled, an object directly reachable from the
2237 * stack at the time of a collection is treated as dirty.
2238 * In single-threaded mode, it suffices to ensure that no
2239 * collection can take place between the pointer assignment
2240 * and the GC_dirty() call.
2241 * PCR_VDB: Use PPCRs virtual dirty bit facility.
2242 * PROC_VDB: Use the /proc facility for reading dirty bits. Only
2243 * works under some SVR4 variants. Even then, it may be
2244 * too slow to be entirely satisfactory. Requires reading
2245 * dirty bits for entire address space. Implementations tend
2246 * to assume that the client is a (slow) debugger.
2247 * MPROTECT_VDB:Protect pages and then catch the faults to keep track of
2248 * dirtied pages. The implementation (and implementability)
2249 * is highly system dependent. This usually fails when system
2250 * calls write to a protected page. We prevent the read system
2251 * call from doing so. It is the clients responsibility to
2252 * make sure that other system calls are similarly protected
2253 * or write only to the stack.
2254 * GWW_VDB: Use the Win32 GetWriteWatch functions, if available, to
2255 * read dirty bits. In case it is not available (because we
2256 * are running on Windows 95, Windows 2000 or earlier),
2257 * MPROTECT_VDB may be defined as a fallback strategy.
2259 GC_bool GC_dirty_maintained = FALSE;
2261 #if defined(PROC_VDB) || defined(GWW_VDB)
2263 /* Add all pages in pht2 to pht1 */
2264 STATIC void GC_or_pages(page_hash_table pht1, page_hash_table pht2)
2268 for (i = 0; i < PHT_SIZE; i++) pht1[i] |= pht2[i];
2275 # define GC_GWW_BUF_LEN (MAXHINCR * HBLKSIZE / 4096 /* X86 page size */)
2276 /* Still susceptible to overflow, if there are very large allocations, */
2277 /* and everything is dirty. */
2278 static PVOID gww_buf[GC_GWW_BUF_LEN];
2280 # ifdef MPROTECT_VDB
2281 GC_bool GC_gww_dirty_init(void)
2283 detect_GetWriteWatch();
2284 return GC_GWW_AVAILABLE();
2287 void GC_dirty_init(void)
2289 detect_GetWriteWatch();
2290 GC_dirty_maintained = GC_GWW_AVAILABLE();
2294 # ifdef MPROTECT_VDB
2295 static void GC_gww_read_dirty(void)
2297 void GC_read_dirty(void)
2302 BZERO(GC_grungy_pages, sizeof(GC_grungy_pages));
2304 for (i = 0; i != GC_n_heap_sects; ++i) {
2308 PVOID * pages, * pages_end;
2312 count = GC_GWW_BUF_LEN;
2314 * GetWriteWatch is documented as returning non-zero when it fails,
2315 * but the documentation doesn't explicitly say why it would fail or
2316 * what its behaviour will be if it fails.
2317 * It does appear to fail, at least on recent W2K instances, if
2318 * the underlying memory was not allocated with the appropriate
2319 * flag. This is common if GC_enable_incremental is called
2320 * shortly after GC initialization. To avoid modifying the
2321 * interface, we silently work around such a failure, it it only
2322 * affects the initial (small) heap allocation.
2323 * If there are more dirty
2324 * pages than will fit in the buffer, this is not treated as a
2325 * failure; we must check the page count in the loop condition.
2326 * Since each partial call will reset the status of some
2327 * pages, this should eventually terminate even in the overflow
2330 if (GetWriteWatch_func(WRITE_WATCH_FLAG_RESET,
2331 GC_heap_sects[i].hs_start,
2332 GC_heap_sects[i].hs_bytes,
2336 static int warn_count = 0;
2338 struct hblk * start = (struct hblk *)GC_heap_sects[i].hs_start;
2339 static struct hblk *last_warned = 0;
2340 size_t nblocks = divHBLKSZ(GC_heap_sects[i].hs_bytes);
2342 if ( i != 0 && last_warned != start && warn_count++ < 5) {
2343 last_warned = start;
2345 "GC_gww_read_dirty unexpectedly failed at %p: "
2346 "Falling back to marking all pages dirty\n", start);
2348 for (j = 0; j < nblocks; ++j) {
2349 word hash = PHT_HASH(start + j);
2350 set_pht_entry_from_index(GC_grungy_pages, hash);
2352 count = 1; /* Done with this section. */
2353 } else /* succeeded */{
2354 pages_end = pages + count;
2355 while (pages != pages_end) {
2356 struct hblk * h = (struct hblk *) *pages++;
2357 struct hblk * h_end = (struct hblk *) ((char *) h + page_size);
2359 set_pht_entry_from_index(GC_grungy_pages, PHT_HASH(h));
2360 while (++h < h_end);
2363 } while (count == GC_GWW_BUF_LEN);
2364 /* FIXME: It's unclear from Microsoft's documentation if this loop */
2365 /* is useful. We suspect the call just fails if the buffer fills */
2366 /* up. But that should still be handled correctly. */
2369 GC_or_pages(GC_written_pages, GC_grungy_pages);
2372 # ifdef MPROTECT_VDB
2373 static GC_bool GC_gww_page_was_dirty(struct hblk * h)
2375 GC_bool GC_page_was_dirty(struct hblk * h)
2378 return HDR(h) == 0 || get_pht_entry_from_index(GC_grungy_pages, PHT_HASH(h));
2381 # ifdef MPROTECT_VDB
2382 static GC_bool GC_gww_page_was_ever_dirty(struct hblk * h)
2384 GC_bool GC_page_was_ever_dirty(struct hblk * h)
2387 return HDR(h) == 0 || get_pht_entry_from_index(GC_written_pages, PHT_HASH(h));
2390 # ifndef MPROTECT_VDB
2392 void GC_remove_protection(struct hblk *h, word nblocks, GC_bool is_ptrfree)
2396 # endif /* GWW_VDB */
2400 /* All of the following assume the allocation lock is held. */
2402 /* The client asserts that unallocated pages in the heap are never */
2405 /* Initialize virtual dirty bit implementation. */
2406 void GC_dirty_init(void)
2408 if (GC_print_stats == VERBOSE)
2409 GC_log_printf("Initializing DEFAULT_VDB...\n");
2410 GC_dirty_maintained = TRUE;
2413 /* Retrieve system dirty bits for heap to a local buffer. */
2414 /* Restore the systems notion of which pages are dirty. */
2415 void GC_read_dirty(void)
2418 /* Is the HBLKSIZE sized page at h marked dirty in the local buffer? */
2419 /* If the actual page size is different, this returns TRUE if any */
2420 /* of the pages overlapping h are dirty. This routine may err on the */
2421 /* side of labeling pages as dirty (and this implementation does). */
2423 GC_bool GC_page_was_dirty(struct hblk *h)
2429 * The following two routines are typically less crucial. They matter
2430 * most with large dynamic libraries, or if we can't accurately identify
2431 * stacks, e.g. under Solaris 2.X. Otherwise the following default
2432 * versions are adequate.
2435 /* Could any valid GC heap pointer ever have been written to this page? */
2437 GC_bool GC_page_was_ever_dirty(struct hblk *h)
2443 /* I) hints that [h, h+nblocks) is about to be written. */
2444 /* II) guarantees that protection is removed. */
2445 /* (I) may speed up some dirty bit implementations. */
2446 /* (II) may be essential if we need to ensure that */
2447 /* pointer-free system call buffers in the heap are */
2448 /* not protected. */
2450 void GC_remove_protection(struct hblk *h, word nblocks, GC_bool is_ptrfree)
2454 # endif /* DEFAULT_VDB */
2458 /* Initialize virtual dirty bit implementation. */
2459 void GC_dirty_init(void)
2461 if (GC_print_stats == VERBOSE)
2462 GC_log_printf("Initializing MANUAL_VDB...\n");
2463 /* GC_dirty_pages and GC_grungy_pages are already cleared. */
2464 GC_dirty_maintained = TRUE;
2467 /* Retrieve system dirty bits for heap to a local buffer. */
2468 /* Restore the systems notion of which pages are dirty. */
2469 void GC_read_dirty(void)
2471 BCOPY((word *)GC_dirty_pages, GC_grungy_pages,
2472 (sizeof GC_dirty_pages));
2473 BZERO((word *)GC_dirty_pages, (sizeof GC_dirty_pages));
2476 /* Is the HBLKSIZE sized page at h marked dirty in the local buffer? */
2477 /* If the actual page size is different, this returns TRUE if any */
2478 /* of the pages overlapping h are dirty. This routine may err on the */
2479 /* side of labeling pages as dirty (and this implementation does). */
2480 GC_bool GC_page_was_dirty(struct hblk *h)
2482 register word index;
2484 index = PHT_HASH(h);
2485 return(HDR(h) == 0 || get_pht_entry_from_index(GC_grungy_pages, index));
2488 /* Could any valid GC heap pointer ever have been written to this page? */
2490 GC_bool GC_page_was_ever_dirty(struct hblk *h)
2492 /* FIXME - implement me. */
2496 /* Mark the page containing p as dirty. Logically, this dirties the */
2497 /* entire object. */
2498 void GC_dirty(ptr_t p)
2500 word index = PHT_HASH(p);
2501 async_set_pht_entry_from_index(GC_dirty_pages, index);
2505 void GC_remove_protection(struct hblk *h, word nblocks, GC_bool is_ptrfree)
2509 # endif /* MANUAL_VDB */
2512 # ifdef MPROTECT_VDB
2515 * See DEFAULT_VDB for interface descriptions.
2519 * This implementation maintains dirty bits itself by catching write
2520 * faults and keeping track of them. We assume nobody else catches
2521 * SIGBUS or SIGSEGV. We assume no write faults occur in system calls.
2522 * This means that clients must ensure that system calls don't write
2523 * to the write-protected heap. Probably the best way to do this is to
2524 * ensure that system calls write at most to POINTERFREE objects in the
2525 * heap, and do even that only if we are on a platform on which those
2526 * are not protected. Another alternative is to wrap system calls
2527 * (see example for read below), but the current implementation holds
2529 * We assume the page size is a multiple of HBLKSIZE.
2530 * We prefer them to be the same. We avoid protecting POINTERFREE
2531 * objects only if they are the same.
2534 # if !defined(MSWIN32) && !defined(MSWINCE) && !defined(DARWIN)
2536 # include <sys/mman.h>
2537 # include <signal.h>
2538 # include <sys/syscall.h>
2540 # define PROTECT(addr, len) \
2541 if (mprotect((caddr_t)(addr), (size_t)(len), \
2542 PROT_READ | OPT_PROT_EXEC) < 0) { \
2543 ABORT("mprotect failed"); \
2545 # define UNPROTECT(addr, len) \
2546 if (mprotect((caddr_t)(addr), (size_t)(len), \
2547 PROT_WRITE | PROT_READ | OPT_PROT_EXEC ) < 0) { \
2548 ABORT("un-mprotect failed"); \
2554 /* Using vm_protect (mach syscall) over mprotect (BSD syscall) seems to
2555 decrease the likelihood of some of the problems described below. */
2556 #include <mach/vm_map.h>
2557 static mach_port_t GC_task_self;
2558 # define PROTECT(addr,len) \
2559 if(vm_protect(GC_task_self,(vm_address_t)(addr),(vm_size_t)(len), \
2560 FALSE,VM_PROT_READ) != KERN_SUCCESS) { \
2561 ABORT("vm_portect failed"); \
2563 # define UNPROTECT(addr,len) \
2564 if(vm_protect(GC_task_self,(vm_address_t)(addr),(vm_size_t)(len), \
2565 FALSE,VM_PROT_READ|VM_PROT_WRITE) != KERN_SUCCESS) { \
2566 ABORT("vm_portect failed"); \
2571 # include <signal.h>
2574 static DWORD protect_junk;
2575 # define PROTECT(addr, len) \
2576 if (!VirtualProtect((addr), (len), PAGE_EXECUTE_READ, \
2578 GC_printf("Last error code: %lx\n", (long)GetLastError()); \
2579 ABORT("VirtualProtect failed"); \
2581 # define UNPROTECT(addr, len) \
2582 if (!VirtualProtect((addr), (len), PAGE_EXECUTE_READWRITE, \
2584 ABORT("un-VirtualProtect failed"); \
2586 # endif /* !DARWIN */
2587 # endif /* MSWIN32 || MSWINCE || DARWIN */
2589 #if defined(MSWIN32)
2590 typedef LPTOP_LEVEL_EXCEPTION_FILTER SIG_HNDLR_PTR;
2592 # define SIG_DFL (LPTOP_LEVEL_EXCEPTION_FILTER)((signed_word)-1)
2593 #elif defined(MSWINCE)
2594 typedef LONG (WINAPI *SIG_HNDLR_PTR)(struct _EXCEPTION_POINTERS *);
2596 # define SIG_DFL (SIG_HNDLR_PTR) (-1)
2597 #elif defined(DARWIN)
2598 typedef void (* SIG_HNDLR_PTR)();
2600 typedef void (* SIG_HNDLR_PTR)(int, siginfo_t *, void *);
2601 typedef void (* PLAIN_HNDLR_PTR)(int);
2604 #if defined(__GLIBC__)
2605 # if __GLIBC__ < 2 || __GLIBC__ == 2 && __GLIBC_MINOR__ < 2
2606 # error glibc too old?
2611 STATIC SIG_HNDLR_PTR GC_old_segv_handler;
2612 /* Also old MSWIN32 ACCESS_VIOLATION filter */
2613 #if !defined(MSWIN32) && !defined(MSWINCE)
2614 STATIC SIG_HNDLR_PTR GC_old_bus_handler;
2615 STATIC GC_bool GC_old_bus_handler_used_si;
2616 STATIC GC_bool GC_old_segv_handler_used_si;
2618 #endif /* !DARWIN */
2620 #if defined(THREADS)
2621 /* We need to lock around the bitmap update in the write fault handler */
2622 /* in order to avoid the risk of losing a bit. We do this with a */
2623 /* test-and-set spin lock if we know how to do that. Otherwise we */
2624 /* check whether we are already in the handler and use the dumb but */
2625 /* safe fallback algorithm of setting all bits in the word. */
2626 /* Contention should be very rare, so we do the minimum to handle it */
2628 #ifdef AO_HAVE_test_and_set_acquire
2629 volatile AO_TS_t GC_fault_handler_lock = 0;
2630 void async_set_pht_entry_from_index(volatile page_hash_table db, size_t index) {
2631 while (AO_test_and_set_acquire(&GC_fault_handler_lock) == AO_TS_SET) {}
2632 /* Could also revert to set_pht_entry_from_index_safe if initial */
2633 /* GC_test_and_set fails. */
2634 set_pht_entry_from_index(db, index);
2635 AO_CLEAR(&GC_fault_handler_lock);
2637 #else /* !AO_have_test_and_set_acquire */
2638 # error No test_and_set operation: Introduces a race.
2639 /* THIS WOULD BE INCORRECT! */
2640 /* The dirty bit vector may be temporarily wrong, */
2641 /* just before we notice the conflict and correct it. We may end up */
2642 /* looking at it while it's wrong. But this requires contention */
2643 /* exactly when a GC is triggered, which seems far less likely to */
2644 /* fail than the old code, which had no reported failures. Thus we */
2645 /* leave it this way while we think of something better, or support */
2646 /* GC_test_and_set on the remaining platforms. */
2647 static volatile word currently_updating = 0;
2648 void async_set_pht_entry_from_index(volatile page_hash_table db, size_t index) {
2649 unsigned int update_dummy;
2650 currently_updating = (word)(&update_dummy);
2651 set_pht_entry_from_index(db, index);
2652 /* If we get contention in the 10 or so instruction window here, */
2653 /* and we get stopped by a GC between the two updates, we lose! */
2654 if (currently_updating != (word)(&update_dummy)) {
2655 set_pht_entry_from_index_safe(db, index);
2656 /* We claim that if two threads concurrently try to update the */
2657 /* dirty bit vector, the first one to execute UPDATE_START */
2658 /* will see it changed when UPDATE_END is executed. (Note that */
2659 /* &update_dummy must differ in two distinct threads.) It */
2660 /* will then execute set_pht_entry_from_index_safe, thus */
2661 /* returning us to a safe state, though not soon enough. */
2664 #endif /* !AO_HAVE_test_and_set_acquire */
2665 #else /* !THREADS */
2666 # define async_set_pht_entry_from_index(db, index) \
2667 set_pht_entry_from_index(db, index)
2668 #endif /* !THREADS */
2671 void GC_record_fault(struct hblk * h);
2672 /* From checksums.c */
2675 #if !defined(DARWIN)
2677 # if defined(FREEBSD)
2678 # define SIG_OK TRUE
2679 # define CODE_OK (si -> si_code == BUS_PAGE_FAULT)
2680 # elif defined(OSF1)
2681 # define SIG_OK (sig == SIGSEGV)
2682 # define CODE_OK (si -> si_code == 2 /* experimentally determined */)
2683 # elif defined(IRIX5)
2684 # define SIG_OK (sig == SIGSEGV)
2685 # define CODE_OK (si -> si_code == EACCES)
2686 # elif defined(HURD)
2687 # define SIG_OK (sig == SIGBUS || sig == SIGSEGV)
2688 # define CODE_OK TRUE
2689 # elif defined(LINUX)
2690 # define SIG_OK (sig == SIGSEGV)
2691 # define CODE_OK TRUE
2692 /* Empirically c.trapno == 14, on IA32, but is that useful? */
2693 /* Should probably consider alignment issues on other */
2694 /* architectures. */
2695 # elif defined(HPUX)
2696 # define SIG_OK (sig == SIGSEGV || sig == SIGBUS)
2697 # define CODE_OK (si -> si_code == SEGV_ACCERR) \
2698 || (si -> si_code == BUS_ADRERR) \
2699 || (si -> si_code == BUS_UNKNOWN) \
2700 || (si -> si_code == SEGV_UNKNOWN) \
2701 || (si -> si_code == BUS_OBJERR)
2702 # elif defined(SUNOS5SIGS)
2703 # define SIG_OK (sig == SIGSEGV)
2704 # define CODE_OK (si -> si_code == SEGV_ACCERR)
2705 # elif defined(MSWIN32) || defined(MSWINCE)
2706 # define SIG_OK (exc_info -> ExceptionRecord -> ExceptionCode \
2707 == STATUS_ACCESS_VIOLATION)
2708 # define CODE_OK (exc_info -> ExceptionRecord -> ExceptionInformation[0] \
2709 == 1) /* Write fault */
2712 # if defined(MSWIN32) || defined(MSWINCE)
2713 LONG WINAPI GC_write_fault_handler(struct _EXCEPTION_POINTERS *exc_info)
2715 # include <ucontext.h>
2717 STATIC void GC_write_fault_handler(int sig, siginfo_t *si, void *raw_sc)
2718 # endif /* MSWIN32 || MSWINCE */
2720 # if !defined(MSWIN32) && !defined(MSWINCE)
2721 char *addr = si -> si_addr;
2723 char * addr = (char *) (exc_info -> ExceptionRecord
2724 -> ExceptionInformation[1]);
2728 if (SIG_OK && CODE_OK) {
2729 register struct hblk * h =
2730 (struct hblk *)((word)addr & ~(GC_page_size-1));
2731 GC_bool in_allocd_block;
2734 # endif /* CHECKSUMS */
2737 /* Address is only within the correct physical page. */
2738 in_allocd_block = FALSE;
2739 for (i = 0; i < divHBLKSZ(GC_page_size); i++) {
2740 if (HDR(h+i) != 0) {
2741 in_allocd_block = TRUE;
2745 in_allocd_block = (HDR(addr) != 0);
2747 if (!in_allocd_block) {
2748 /* FIXME - We should make sure that we invoke the */
2749 /* old handler with the appropriate calling */
2750 /* sequence, which often depends on SA_SIGINFO. */
2752 /* Heap blocks now begin and end on page boundaries */
2753 SIG_HNDLR_PTR old_handler;
2755 # if defined(MSWIN32) || defined(MSWINCE)
2756 old_handler = GC_old_segv_handler;
2760 if (sig == SIGSEGV) {
2761 old_handler = GC_old_segv_handler;
2762 used_si = GC_old_segv_handler_used_si;
2764 old_handler = GC_old_bus_handler;
2765 used_si = GC_old_bus_handler_used_si;
2769 if (old_handler == (SIG_HNDLR_PTR)SIG_DFL) {
2770 # if !defined(MSWIN32) && !defined(MSWINCE)
2771 GC_err_printf("Segfault at %p\n", addr);
2772 ABORT("Unexpected bus error or segmentation fault");
2774 return(EXCEPTION_CONTINUE_SEARCH);
2778 * FIXME: This code should probably check if the
2779 * old signal handler used the traditional style and
2780 * if so call it using that style.
2782 # if defined(MSWIN32) || defined(MSWINCE)
2783 return((*old_handler)(exc_info));
2786 ((SIG_HNDLR_PTR)old_handler) (sig, si, raw_sc);
2788 /* FIXME: should pass nonstandard args as well. */
2789 ((PLAIN_HNDLR_PTR)old_handler) (sig);
2794 UNPROTECT(h, GC_page_size);
2795 /* We need to make sure that no collection occurs between */
2796 /* the UNPROTECT and the setting of the dirty bit. Otherwise */
2797 /* a write by a third thread might go unnoticed. Reversing */
2798 /* the order is just as bad, since we would end up unprotecting */
2799 /* a page in a GC cycle during which it's not marked. */
2800 /* Currently we do this by disabling the thread stopping */
2801 /* signals while this handler is running. An alternative might */
2802 /* be to record the fact that we're about to unprotect, or */
2803 /* have just unprotected a page in the GC's thread structure, */
2804 /* and then to have the thread stopping code set the dirty */
2805 /* flag, if necessary. */
2806 for (i = 0; i < divHBLKSZ(GC_page_size); i++) {
2807 size_t index = PHT_HASH(h+i);
2809 async_set_pht_entry_from_index(GC_dirty_pages, index);
2811 /* The write may not take place before dirty bits are read. */
2812 /* But then we'll fault again ... */
2813 # if defined(MSWIN32) || defined(MSWINCE)
2814 return(EXCEPTION_CONTINUE_EXECUTION);
2819 #if defined(MSWIN32) || defined(MSWINCE)
2820 return EXCEPTION_CONTINUE_SEARCH;
2822 GC_err_printf("Segfault at %p\n", addr);
2823 ABORT("Unexpected bus error or segmentation fault");
2826 #endif /* !DARWIN */
2829 * We hold the allocation lock. We expect block h to be written
2830 * shortly. Ensure that all pages containing any part of the n hblks
2831 * starting at h are no longer protected. If is_ptrfree is false,
2832 * also ensure that they will subsequently appear to be dirty.
2834 void GC_remove_protection(struct hblk *h, word nblocks, GC_bool is_ptrfree)
2836 struct hblk * h_trunc; /* Truncated to page boundary */
2837 struct hblk * h_end; /* Page boundary following block end */
2838 struct hblk * current;
2840 # if defined(GWW_VDB)
2841 if (GC_GWW_AVAILABLE()) return;
2843 if (!GC_dirty_maintained) return;
2844 h_trunc = (struct hblk *)((word)h & ~(GC_page_size-1));
2845 h_end = (struct hblk *)(((word)(h + nblocks) + GC_page_size-1)
2846 & ~(GC_page_size-1));
2847 if (h_end == h_trunc + 1 &&
2848 get_pht_entry_from_index(GC_dirty_pages, PHT_HASH(h_trunc))) {
2849 /* already marked dirty, and hence unprotected. */
2852 for (current = h_trunc; current < h_end; ++current) {
2853 size_t index = PHT_HASH(current);
2854 if (!is_ptrfree || current < h || current >= h + nblocks) {
2855 async_set_pht_entry_from_index(GC_dirty_pages, index);
2858 UNPROTECT(h_trunc, (ptr_t)h_end - (ptr_t)h_trunc);
2861 #if !defined(DARWIN)
2862 void GC_dirty_init(void)
2864 # if !defined(MSWIN32) && !defined(MSWINCE)
2865 struct sigaction act, oldact;
2866 act.sa_flags = SA_RESTART | SA_SIGINFO;
2867 act.sa_sigaction = GC_write_fault_handler;
2868 (void)sigemptyset(&act.sa_mask);
2870 /* Arrange to postpone SIG_SUSPEND while we're in a write fault */
2871 /* handler. This effectively makes the handler atomic w.r.t. */
2872 /* stopping the world for GC. */
2873 (void)sigaddset(&act.sa_mask, SIG_SUSPEND);
2874 # endif /* SIG_SUSPEND */
2876 if (GC_print_stats == VERBOSE)
2878 "Initializing mprotect virtual dirty bit implementation\n");
2879 GC_dirty_maintained = TRUE;
2880 if (GC_page_size % HBLKSIZE != 0) {
2881 GC_err_printf("Page size not multiple of HBLKSIZE\n");
2882 ABORT("Page size not multiple of HBLKSIZE");
2884 # if !defined(MSWIN32) && !defined(MSWINCE)
2885 # if defined(GC_IRIX_THREADS)
2886 sigaction(SIGSEGV, 0, &oldact);
2887 sigaction(SIGSEGV, &act, 0);
2890 int res = sigaction(SIGSEGV, &act, &oldact);
2891 if (res != 0) ABORT("Sigaction failed");
2894 if (oldact.sa_flags & SA_SIGINFO) {
2895 GC_old_segv_handler = oldact.sa_sigaction;
2896 GC_old_segv_handler_used_si = TRUE;
2898 GC_old_segv_handler = (SIG_HNDLR_PTR)oldact.sa_handler;
2899 GC_old_segv_handler_used_si = FALSE;
2901 if (GC_old_segv_handler == (SIG_HNDLR_PTR)SIG_IGN) {
2902 GC_err_printf("Previously ignored segmentation violation!?\n");
2903 GC_old_segv_handler = (SIG_HNDLR_PTR)SIG_DFL;
2905 if (GC_old_segv_handler != (SIG_HNDLR_PTR)SIG_DFL) {
2906 if (GC_print_stats == VERBOSE)
2907 GC_log_printf("Replaced other SIGSEGV handler\n");
2909 # if defined(HPUX) || defined(LINUX) || defined(HURD) \
2910 || (defined(FREEBSD) && defined(SUNOS5SIGS))
2911 sigaction(SIGBUS, &act, &oldact);
2912 if (oldact.sa_flags & SA_SIGINFO) {
2913 GC_old_bus_handler = oldact.sa_sigaction;
2914 GC_old_bus_handler_used_si = TRUE;
2916 GC_old_bus_handler = (SIG_HNDLR_PTR)oldact.sa_handler;
2917 GC_old_bus_handler_used_si = FALSE;
2919 if (GC_old_bus_handler == (SIG_HNDLR_PTR)SIG_IGN) {
2920 GC_err_printf("Previously ignored bus error!?\n");
2921 GC_old_bus_handler = (SIG_HNDLR_PTR)SIG_DFL;
2923 if (GC_old_bus_handler != (SIG_HNDLR_PTR)SIG_DFL) {
2924 if (GC_print_stats == VERBOSE)
2925 GC_log_printf("Replaced other SIGBUS handler\n");
2927 # endif /* HPUX || LINUX || HURD || (FREEBSD && SUNOS5SIGS) */
2928 # endif /* ! MS windows */
2929 # if defined(GWW_VDB)
2930 if (GC_gww_dirty_init())
2933 # if defined(MSWIN32)
2934 GC_old_segv_handler = SetUnhandledExceptionFilter(GC_write_fault_handler);
2935 if (GC_old_segv_handler != NULL) {
2937 GC_log_printf("Replaced other UnhandledExceptionFilter\n");
2939 GC_old_segv_handler = SIG_DFL;
2943 #endif /* !DARWIN */
2945 GC_API int GC_CALL GC_incremental_protection_needs(void)
2947 if (GC_page_size == HBLKSIZE) {
2948 return GC_PROTECTS_POINTER_HEAP;
2950 return GC_PROTECTS_POINTER_HEAP | GC_PROTECTS_PTRFREE_HEAP;
2954 #define HAVE_INCREMENTAL_PROTECTION_NEEDS
2956 #define IS_PTRFREE(hhdr) ((hhdr)->hb_descr == 0)
2958 #define PAGE_ALIGNED(x) !((word)(x) & (GC_page_size - 1))
2959 STATIC void GC_protect_heap(void)
2963 struct hblk * current;
2964 struct hblk * current_start; /* Start of block to be protected. */
2965 struct hblk * limit;
2967 GC_bool protect_all =
2968 (0 != (GC_incremental_protection_needs() & GC_PROTECTS_PTRFREE_HEAP));
2969 for (i = 0; i < GC_n_heap_sects; i++) {
2970 start = GC_heap_sects[i].hs_start;
2971 len = GC_heap_sects[i].hs_bytes;
2973 PROTECT(start, len);
2975 GC_ASSERT(PAGE_ALIGNED(len))
2976 GC_ASSERT(PAGE_ALIGNED(start))
2977 current_start = current = (struct hblk *)start;
2978 limit = (struct hblk *)(start + len);
2979 while (current < limit) {
2984 GC_ASSERT(PAGE_ALIGNED(current));
2985 GET_HDR(current, hhdr);
2986 if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {
2987 /* This can happen only if we're at the beginning of a */
2988 /* heap segment, and a block spans heap segments. */
2989 /* We will handle that block as part of the preceding */
2991 GC_ASSERT(current_start == current);
2992 current_start = ++current;
2995 if (HBLK_IS_FREE(hhdr)) {
2996 GC_ASSERT(PAGE_ALIGNED(hhdr -> hb_sz));
2997 nhblks = divHBLKSZ(hhdr -> hb_sz);
2998 is_ptrfree = TRUE; /* dirty on alloc */
3000 nhblks = OBJ_SZ_TO_BLOCKS(hhdr -> hb_sz);
3001 is_ptrfree = IS_PTRFREE(hhdr);
3004 if (current_start < current) {
3005 PROTECT(current_start, (ptr_t)current - (ptr_t)current_start);
3007 current_start = (current += nhblks);
3012 if (current_start < current) {
3013 PROTECT(current_start, (ptr_t)current - (ptr_t)current_start);
3019 /* We assume that either the world is stopped or its OK to lose dirty */
3020 /* bits while this is happenning (as in GC_enable_incremental). */
3021 void GC_read_dirty(void)
3023 # if defined(GWW_VDB)
3024 if (GC_GWW_AVAILABLE()) {
3025 GC_gww_read_dirty();
3029 BCOPY((word *)GC_dirty_pages, GC_grungy_pages,
3030 (sizeof GC_dirty_pages));
3031 BZERO((word *)GC_dirty_pages, (sizeof GC_dirty_pages));
3035 GC_bool GC_page_was_dirty(struct hblk *h)
3037 register word index;
3039 # if defined(GWW_VDB)
3040 if (GC_GWW_AVAILABLE())
3041 return GC_gww_page_was_dirty(h);
3044 index = PHT_HASH(h);
3045 return(HDR(h) == 0 || get_pht_entry_from_index(GC_grungy_pages, index));
3049 * Acquiring the allocation lock here is dangerous, since this
3050 * can be called from within GC_call_with_alloc_lock, and the cord
3051 * package does so. On systems that allow nested lock acquisition, this
3053 * On other systems, SET_LOCK_HOLDER and friends must be suitably defined.
3057 static GC_bool syscall_acquired_lock = FALSE; /* Protected by GC lock. */
3059 void GC_begin_syscall(void)
3061 /* FIXME: Resurrecting this code would require fixing the */
3062 /* test, which can spuriously return TRUE. */
3063 if (!I_HOLD_LOCK()) {
3065 syscall_acquired_lock = TRUE;
3069 void GC_end_syscall(void)
3071 if (syscall_acquired_lock) {
3072 syscall_acquired_lock = FALSE;
3077 void GC_unprotect_range(ptr_t addr, word len)
3079 struct hblk * start_block;
3080 struct hblk * end_block;
3081 register struct hblk *h;
3084 if (!GC_dirty_maintained) return;
3085 obj_start = GC_base(addr);
3086 if (obj_start == 0) return;
3087 if (GC_base(addr + len - 1) != obj_start) {
3088 ABORT("GC_unprotect_range(range bigger than object)");
3090 start_block = (struct hblk *)((word)addr & ~(GC_page_size - 1));
3091 end_block = (struct hblk *)((word)(addr + len - 1) & ~(GC_page_size - 1));
3092 end_block += GC_page_size/HBLKSIZE - 1;
3093 for (h = start_block; h <= end_block; h++) {
3094 register word index = PHT_HASH(h);
3096 async_set_pht_entry_from_index(GC_dirty_pages, index);
3098 UNPROTECT(start_block,
3099 ((ptr_t)end_block - (ptr_t)start_block) + HBLKSIZE);
3103 /* We no longer wrap read by default, since that was causing too many */
3104 /* problems. It is preferred that the client instead avoids writing */
3105 /* to the write-protected heap with a system call. */
3106 /* This still serves as sample code if you do want to wrap system calls.*/
3108 #if !defined(MSWIN32) && !defined(MSWINCE) && !defined(GC_USE_LD_WRAP)
3109 /* Replacement for UNIX system call. */
3110 /* Other calls that write to the heap should be handled similarly. */
3111 /* Note that this doesn't work well for blocking reads: It will hold */
3112 /* the allocation lock for the entire duration of the call. Multithreaded */
3113 /* clients should really ensure that it won't block, either by setting */
3114 /* the descriptor nonblocking, or by calling select or poll first, to */
3115 /* make sure that input is available. */
3116 /* Another, preferred alternative is to ensure that system calls never */
3117 /* write to the protected heap (see above). */
3118 # include <unistd.h>
3119 # include <sys/uio.h>
3120 ssize_t read(int fd, void *buf, size_t nbyte)
3125 GC_unprotect_range(buf, (word)nbyte);
3126 # if defined(IRIX5) || defined(GC_LINUX_THREADS)
3127 /* Indirect system call may not always be easily available. */
3128 /* We could call _read, but that would interfere with the */
3129 /* libpthread interception of read. */
3130 /* On Linux, we have to be careful with the linuxthreads */
3131 /* read interception. */
3136 iov.iov_len = nbyte;
3137 result = readv(fd, &iov, 1);
3141 result = __read(fd, buf, nbyte);
3143 /* The two zero args at the end of this list are because one
3144 IA-64 syscall() implementation actually requires six args
3145 to be passed, even though they aren't always used. */
3146 result = syscall(SYS_read, fd, buf, nbyte, 0, 0);
3152 #endif /* !MSWIN32 && !MSWINCE && !GC_LINUX_THREADS */
3154 #if defined(GC_USE_LD_WRAP) && !defined(THREADS)
3155 /* We use the GNU ld call wrapping facility. */
3156 /* This requires that the linker be invoked with "--wrap read". */
3157 /* This can be done by passing -Wl,"--wrap read" to gcc. */
3158 /* I'm not sure that this actually wraps whatever version of read */
3159 /* is called by stdio. That code also mentions __read. */
3160 # include <unistd.h>
3161 ssize_t __wrap_read(int fd, void *buf, size_t nbyte)
3166 GC_unprotect_range(buf, (word)nbyte);
3167 result = __real_read(fd, buf, nbyte);
3172 /* We should probably also do this for __read, or whatever stdio */
3173 /* actually calls. */
3179 GC_bool GC_page_was_ever_dirty(struct hblk *h)
3181 # if defined(GWW_VDB)
3182 if (GC_GWW_AVAILABLE())
3183 return GC_gww_page_was_ever_dirty(h);
3188 # endif /* MPROTECT_VDB */
3193 * See DEFAULT_VDB for interface descriptions.
3197 * This implementation assumes a Solaris 2.X like /proc pseudo-file-system
3198 * from which we can read page modified bits. This facility is far from
3199 * optimal (e.g. we would like to get the info for only some of the
3200 * address space), but it avoids intercepting system calls.
3204 #include <sys/types.h>
3205 #include <sys/signal.h>
3206 #include <sys/fault.h>
3207 #include <sys/syscall.h>
3208 #include <sys/procfs.h>
3209 #include <sys/stat.h>
3211 #define INITIAL_BUF_SZ 16384
3212 STATIC word GC_proc_buf_size = INITIAL_BUF_SZ;
3213 STATIC char *GC_proc_buf;
3215 STATIC int GC_proc_fd;
3217 void GC_dirty_init(void)
3222 GC_dirty_maintained = TRUE;
3223 if (GC_bytes_allocd != 0 || GC_bytes_allocd_before_gc != 0) {
3226 for (i = 0; i < PHT_SIZE; i++) GC_written_pages[i] = (word)(-1);
3227 if (GC_print_stats == VERBOSE)
3229 "Allocated bytes:%lu:all pages may have been written\n",
3231 (GC_bytes_allocd + GC_bytes_allocd_before_gc));
3233 sprintf(buf, "/proc/%ld", (long)getpid());
3234 fd = open(buf, O_RDONLY);
3236 ABORT("/proc open failed");
3238 GC_proc_fd = syscall(SYS_ioctl, fd, PIOCOPENPD, 0);
3240 syscall(SYS_fcntl, GC_proc_fd, F_SETFD, FD_CLOEXEC);
3241 if (GC_proc_fd < 0) {
3242 ABORT("/proc ioctl failed");
3244 GC_proc_buf = GC_scratch_alloc(GC_proc_buf_size);
3247 /* Ignore write hints. They don't help us here. */
3249 void GC_remove_protection(struct hblk *h, word nblocks, GC_bool is_ptrfree)
3253 # define READ(fd,buf,nbytes) read(fd, buf, nbytes)
3255 void GC_read_dirty(void)
3257 unsigned long ps, np;
3260 struct prasmap * map;
3262 ptr_t current_addr, limit;
3265 BZERO(GC_grungy_pages, (sizeof GC_grungy_pages));
3268 if (READ(GC_proc_fd, bufp, GC_proc_buf_size) <= 0) {
3270 GC_log_printf("/proc read failed: GC_proc_buf_size = %lu\n",
3271 (unsigned long)GC_proc_buf_size);
3273 /* Retry with larger buffer. */
3274 word new_size = 2 * GC_proc_buf_size;
3275 char * new_buf = GC_scratch_alloc(new_size);
3278 GC_proc_buf = bufp = new_buf;
3279 GC_proc_buf_size = new_size;
3281 if (READ(GC_proc_fd, bufp, GC_proc_buf_size) <= 0) {
3282 WARN("Insufficient space for /proc read\n", 0);
3284 memset(GC_grungy_pages, 0xff, sizeof (page_hash_table));
3285 memset(GC_written_pages, 0xff, sizeof(page_hash_table));
3290 /* Copy dirty bits into GC_grungy_pages */
3291 nmaps = ((struct prpageheader *)bufp) -> pr_nmap;
3292 /* printf( "nmaps = %d, PG_REFERENCED = %d, PG_MODIFIED = %d\n",
3293 nmaps, PG_REFERENCED, PG_MODIFIED); */
3294 bufp = bufp + sizeof(struct prpageheader);
3295 for (i = 0; i < nmaps; i++) {
3296 map = (struct prasmap *)bufp;
3297 vaddr = (ptr_t)(map -> pr_vaddr);
3298 ps = map -> pr_pagesize;
3299 np = map -> pr_npage;
3300 /* printf("vaddr = 0x%X, ps = 0x%X, np = 0x%X\n", vaddr, ps, np); */
3301 limit = vaddr + ps * np;
3302 bufp += sizeof (struct prasmap);
3303 for (current_addr = vaddr;
3304 current_addr < limit; current_addr += ps){
3305 if ((*bufp++) & PG_MODIFIED) {
3306 register struct hblk * h = (struct hblk *) current_addr;
3308 while ((ptr_t)h < current_addr + ps) {
3309 register word index = PHT_HASH(h);
3311 set_pht_entry_from_index(GC_grungy_pages, index);
3316 bufp += sizeof(long) - 1;
3317 bufp = (char *)((unsigned long)bufp & ~(sizeof(long)-1));
3319 /* Update GC_written_pages. */
3320 GC_or_pages(GC_written_pages, GC_grungy_pages);
3325 GC_bool GC_page_was_dirty(struct hblk *h)
3327 register word index = PHT_HASH(h);
3329 return get_pht_entry_from_index(GC_grungy_pages, index);
3332 GC_bool GC_page_was_ever_dirty(struct hblk *h)
3334 register word index = PHT_HASH(h);
3336 return get_pht_entry_from_index(GC_written_pages, index);
3339 # endif /* PROC_VDB */
3344 # include "vd/PCR_VD.h"
3346 # define NPAGES (32*1024) /* 128 MB */
3348 PCR_VD_DB GC_grungy_bits[NPAGES];
3350 ptr_t GC_vd_base; /* Address corresponding to GC_grungy_bits[0] */
3351 /* HBLKSIZE aligned. */
3353 void GC_dirty_init(void)
3355 GC_dirty_maintained = TRUE;
3356 /* For the time being, we assume the heap generally grows up */
3357 GC_vd_base = GC_heap_sects[0].hs_start;
3358 if (GC_vd_base == 0) {
3359 ABORT("Bad initial heap segment");
3361 if (PCR_VD_Start(HBLKSIZE, GC_vd_base, NPAGES*HBLKSIZE)
3363 ABORT("dirty bit initialization failed");
3367 void GC_read_dirty(void)
3369 /* lazily enable dirty bits on newly added heap sects */
3371 static int onhs = 0;
3372 int nhs = GC_n_heap_sects;
3373 for( ; onhs < nhs; onhs++ ) {
3374 PCR_VD_WriteProtectEnable(
3375 GC_heap_sects[onhs].hs_start,
3376 GC_heap_sects[onhs].hs_bytes );
3381 if (PCR_VD_Clear(GC_vd_base, NPAGES*HBLKSIZE, GC_grungy_bits)
3383 ABORT("dirty bit read failed");
3387 GC_bool GC_page_was_dirty(struct hblk *h)
3389 if((ptr_t)h < GC_vd_base || (ptr_t)h >= GC_vd_base + NPAGES*HBLKSIZE) {
3392 return(GC_grungy_bits[h - (struct hblk *)GC_vd_base] & PCR_VD_DB_dirtyBit);
3396 void GC_remove_protection(struct hblk *h, word nblocks, GC_bool is_ptrfree)
3398 PCR_VD_WriteProtectDisable(h, nblocks*HBLKSIZE);
3399 PCR_VD_WriteProtectEnable(h, nblocks*HBLKSIZE);
3402 # endif /* PCR_VDB */
3404 #if defined(MPROTECT_VDB) && defined(DARWIN)
3405 /* The following sources were used as a *reference* for this exception handling
3407 1. Apple's mach/xnu documentation
3408 2. Timothy J. Wood's "Mach Exception Handlers 101" post to the
3409 omnigroup's macosx-dev list.
3410 www.omnigroup.com/mailman/archive/macosx-dev/2000-June/014178.html
3411 3. macosx-nat.c from Apple's GDB source code.
3414 /* The bug that caused all this trouble should now be fixed. This should
3415 eventually be removed if all goes well. */
3417 /* #define BROKEN_EXCEPTION_HANDLING */
3419 #include <mach/mach.h>
3420 #include <mach/mach_error.h>
3421 #include <mach/thread_status.h>
3422 #include <mach/exception.h>
3423 #include <mach/task.h>
3424 #include <pthread.h>
3426 extern void GC_darwin_register_mach_handler_thread(mach_port_t);
3428 /* These are not defined in any header, although they are documented */
3430 exc_server(mach_msg_header_t *, mach_msg_header_t *);
3432 extern kern_return_t
3433 exception_raise(mach_port_t, mach_port_t, mach_port_t, exception_type_t,
3434 exception_data_t, mach_msg_type_number_t);
3436 extern kern_return_t
3437 exception_raise_state(mach_port_t, mach_port_t, mach_port_t, exception_type_t,
3438 exception_data_t, mach_msg_type_number_t,
3439 thread_state_flavor_t*, thread_state_t,
3440 mach_msg_type_number_t, thread_state_t,
3441 mach_msg_type_number_t*);
3443 extern kern_return_t
3444 exception_raise_state_identity(mach_port_t, mach_port_t, mach_port_t,
3445 exception_type_t, exception_data_t,
3446 mach_msg_type_number_t, thread_state_flavor_t*,
3447 thread_state_t, mach_msg_type_number_t,
3448 thread_state_t, mach_msg_type_number_t*);
3451 #define MAX_EXCEPTION_PORTS 16
3454 mach_msg_type_number_t count;
3455 exception_mask_t masks[MAX_EXCEPTION_PORTS];
3456 exception_handler_t ports[MAX_EXCEPTION_PORTS];
3457 exception_behavior_t behaviors[MAX_EXCEPTION_PORTS];
3458 thread_state_flavor_t flavors[MAX_EXCEPTION_PORTS];
3462 mach_port_t exception;
3463 #if defined(THREADS)
3469 mach_msg_header_t head;
3473 GC_MP_NORMAL, GC_MP_DISCARDING, GC_MP_STOPPED
3474 } GC_mprotect_state_t;
3476 /* FIXME: 1 and 2 seem to be safe to use in the msgh_id field,
3477 but it isn't documented. Use the source and see if they
3482 /* These values are only used on the reply port */
3485 #if defined(THREADS)
3487 GC_mprotect_state_t GC_mprotect_state;
3489 /* The following should ONLY be called when the world is stopped */
3490 static void GC_mprotect_thread_notify(mach_msg_id_t id)
3495 mach_msg_trailer_t trailer;
3498 mach_msg_return_t r;
3500 buf.msg.head.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0);
3501 buf.msg.head.msgh_size = sizeof(buf.msg);
3502 buf.msg.head.msgh_remote_port = GC_ports.exception;
3503 buf.msg.head.msgh_local_port = MACH_PORT_NULL;
3504 buf.msg.head.msgh_id = id;
3506 r = mach_msg(&buf.msg.head, MACH_SEND_MSG | MACH_RCV_MSG | MACH_RCV_LARGE,
3507 sizeof(buf.msg), sizeof(buf), GC_ports.reply,
3508 MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
3509 if(r != MACH_MSG_SUCCESS)
3510 ABORT("mach_msg failed in GC_mprotect_thread_notify");
3511 if(buf.msg.head.msgh_id != ID_ACK)
3512 ABORT("invalid ack in GC_mprotect_thread_notify");
3515 /* Should only be called by the mprotect thread */
3516 static void GC_mprotect_thread_reply(void)
3520 mach_msg_return_t r;
3522 msg.head.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0);
3523 msg.head.msgh_size = sizeof(msg);
3524 msg.head.msgh_remote_port = GC_ports.reply;
3525 msg.head.msgh_local_port = MACH_PORT_NULL;
3526 msg.head.msgh_id = ID_ACK;
3528 r = mach_msg(&msg.head, MACH_SEND_MSG, sizeof(msg), 0, MACH_PORT_NULL,
3529 MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
3530 if(r != MACH_MSG_SUCCESS)
3531 ABORT("mach_msg failed in GC_mprotect_thread_reply");
3534 void GC_mprotect_stop(void)
3536 GC_mprotect_thread_notify(ID_STOP);
3538 void GC_mprotect_resume(void)
3540 GC_mprotect_thread_notify(ID_RESUME);
3543 #else /* !THREADS */
3544 /* The compiler should optimize away any GC_mprotect_state computations */
3545 #define GC_mprotect_state GC_MP_NORMAL
3548 static void *GC_mprotect_thread(void *arg)
3550 mach_msg_return_t r;
3551 /* These two structures contain some private kernel data. We don't need to
3552 access any of it so we don't bother defining a proper struct. The
3553 correct definitions are in the xnu source code. */
3555 mach_msg_header_t head;
3559 mach_msg_header_t head;
3560 mach_msg_body_t msgh_body;
3566 GC_darwin_register_mach_handler_thread(mach_thread_self());
3569 r = mach_msg(&msg.head, MACH_RCV_MSG | MACH_RCV_LARGE |
3570 (GC_mprotect_state == GC_MP_DISCARDING ? MACH_RCV_TIMEOUT : 0),
3571 0, sizeof(msg), GC_ports.exception,
3572 GC_mprotect_state == GC_MP_DISCARDING ? 0
3573 : MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
3575 id = r == MACH_MSG_SUCCESS ? msg.head.msgh_id : -1;
3577 # if defined(THREADS)
3578 if(GC_mprotect_state == GC_MP_DISCARDING) {
3579 if(r == MACH_RCV_TIMED_OUT) {
3580 GC_mprotect_state = GC_MP_STOPPED;
3581 GC_mprotect_thread_reply();
3584 if(r == MACH_MSG_SUCCESS && (id == ID_STOP || id == ID_RESUME))
3585 ABORT("out of order mprotect thread request");
3587 # endif /* THREADS */
3589 if(r != MACH_MSG_SUCCESS) {
3590 GC_err_printf("mach_msg failed with %d %s\n", (int)r,
3591 mach_error_string(r));
3592 ABORT("mach_msg failed");
3596 # if defined(THREADS)
3598 if(GC_mprotect_state != GC_MP_NORMAL)
3599 ABORT("Called mprotect_stop when state wasn't normal");
3600 GC_mprotect_state = GC_MP_DISCARDING;
3603 if(GC_mprotect_state != GC_MP_STOPPED)
3604 ABORT("Called mprotect_resume when state wasn't stopped");
3605 GC_mprotect_state = GC_MP_NORMAL;
3606 GC_mprotect_thread_reply();
3608 # endif /* THREADS */
3610 /* Handle the message (calls catch_exception_raise) */
3611 if(!exc_server(&msg.head, &reply.head))
3612 ABORT("exc_server failed");
3613 /* Send the reply */
3614 r = mach_msg(&reply.head, MACH_SEND_MSG, reply.head.msgh_size, 0,
3615 MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE,
3617 if(r != MACH_MSG_SUCCESS) {
3618 /* This will fail if the thread dies, but the thread */
3619 /* shouldn't die... */
3620 # ifdef BROKEN_EXCEPTION_HANDLING
3621 GC_err_printf("mach_msg failed with %d %s while sending "
3622 "exc reply\n", (int)r,mach_error_string(r));
3624 ABORT("mach_msg failed while sending exception reply");
3633 /* All this SIGBUS code shouldn't be necessary. All protection faults should
3634 be going through the mach exception handler. However, it seems a SIGBUS is
3635 occasionally sent for some unknown reason. Even more odd, it seems to be
3636 meaningless and safe to ignore. */
3637 #ifdef BROKEN_EXCEPTION_HANDLING
3639 /* Updates to this aren't atomic, but the SIGBUSs seem pretty rare.
3640 Even if this doesn't get updated property, it isn't really a problem */
3641 static int GC_sigbus_count;
3643 static void GC_darwin_sigbus(int num, siginfo_t *sip, void *context)
3646 ABORT("Got a non-sigbus signal in the sigbus handler");
3648 /* Ugh... some seem safe to ignore, but too many in a row probably means
3649 trouble. GC_sigbus_count is reset for each mach exception that is
3651 if(GC_sigbus_count >= 8) {
3652 ABORT("Got more than 8 SIGBUSs in a row!");
3655 WARN("Ignoring SIGBUS.\n", 0);
3658 #endif /* BROKEN_EXCEPTION_HANDLING */
3660 void GC_dirty_init(void)
3665 pthread_attr_t attr;
3666 exception_mask_t mask;
3668 if (GC_print_stats == VERBOSE)
3669 GC_log_printf("Initializing mach/darwin mprotect virtual dirty bit "
3670 "implementation\n");
3671 # ifdef BROKEN_EXCEPTION_HANDLING
3672 WARN("Enabling workarounds for various darwin "
3673 "exception handling bugs.\n", 0);
3675 GC_dirty_maintained = TRUE;
3676 if (GC_page_size % HBLKSIZE != 0) {
3677 GC_err_printf("Page size not multiple of HBLKSIZE\n");
3678 ABORT("Page size not multiple of HBLKSIZE");
3681 GC_task_self = me = mach_task_self();
3683 r = mach_port_allocate(me, MACH_PORT_RIGHT_RECEIVE, &GC_ports.exception);
3684 if(r != KERN_SUCCESS)
3685 ABORT("mach_port_allocate failed (exception port)");
3687 r = mach_port_insert_right(me, GC_ports.exception, GC_ports.exception,
3688 MACH_MSG_TYPE_MAKE_SEND);
3689 if(r != KERN_SUCCESS)
3690 ABORT("mach_port_insert_right failed (exception port)");
3692 # if defined(THREADS)
3693 r = mach_port_allocate(me, MACH_PORT_RIGHT_RECEIVE, &GC_ports.reply);
3694 if(r != KERN_SUCCESS)
3695 ABORT("mach_port_allocate failed (reply port)");
3698 /* The exceptions we want to catch */
3699 mask = EXC_MASK_BAD_ACCESS;
3701 r = task_get_exception_ports(me, mask, GC_old_exc_ports.masks,
3702 &GC_old_exc_ports.count, GC_old_exc_ports.ports,
3703 GC_old_exc_ports.behaviors,
3704 GC_old_exc_ports.flavors);
3705 if(r != KERN_SUCCESS)
3706 ABORT("task_get_exception_ports failed");
3708 r = task_set_exception_ports(me, mask, GC_ports.exception, EXCEPTION_DEFAULT,
3709 GC_MACH_THREAD_STATE);
3710 if(r != KERN_SUCCESS)
3711 ABORT("task_set_exception_ports failed");
3712 if(pthread_attr_init(&attr) != 0)
3713 ABORT("pthread_attr_init failed");
3714 if(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0)
3715 ABORT("pthread_attr_setdetachedstate failed");
3717 # undef pthread_create
3718 /* This will call the real pthread function, not our wrapper */
3719 if(pthread_create(&thread, &attr, GC_mprotect_thread, NULL) != 0)
3720 ABORT("pthread_create failed");
3721 pthread_attr_destroy(&attr);
3723 /* Setup the sigbus handler for ignoring the meaningless SIGBUSs */
3724 # ifdef BROKEN_EXCEPTION_HANDLING
3726 struct sigaction sa, oldsa;
3727 sa.sa_handler = (SIG_HNDLR_PTR)GC_darwin_sigbus;
3728 sigemptyset(&sa.sa_mask);
3729 sa.sa_flags = SA_RESTART|SA_SIGINFO;
3730 if(sigaction(SIGBUS, &sa, &oldsa) < 0)
3732 if ((SIG_HNDLR_PTR)oldsa.sa_handler != SIG_DFL) {
3733 if (GC_print_stats == VERBOSE)
3734 GC_err_printf("Replaced other SIGBUS handler\n");
3737 # endif /* BROKEN_EXCEPTION_HANDLING */
3740 /* The source code for Apple's GDB was used as a reference for the exception
3741 forwarding code. This code is similar to be GDB code only because there is
3742 only one way to do it. */
3743 static kern_return_t GC_forward_exception(mach_port_t thread, mach_port_t task,
3744 exception_type_t exception,
3745 exception_data_t data,
3746 mach_msg_type_number_t data_count)
3751 exception_behavior_t behavior;
3752 thread_state_flavor_t flavor;
3754 thread_state_t thread_state = NULL;
3755 mach_msg_type_number_t thread_state_count = THREAD_STATE_MAX;
3757 for(i=0; i < GC_old_exc_ports.count; i++)
3758 if(GC_old_exc_ports.masks[i] & (1 << exception))
3760 if(i==GC_old_exc_ports.count)
3761 ABORT("No handler for exception!");
3763 port = GC_old_exc_ports.ports[i];
3764 behavior = GC_old_exc_ports.behaviors[i];
3765 flavor = GC_old_exc_ports.flavors[i];
3767 if(behavior != EXCEPTION_DEFAULT) {
3768 r = thread_get_state(thread, flavor, thread_state, &thread_state_count);
3769 if(r != KERN_SUCCESS)
3770 ABORT("thread_get_state failed in forward_exception");
3774 case EXCEPTION_DEFAULT:
3775 r = exception_raise(port, thread, task, exception, data, data_count);
3777 case EXCEPTION_STATE:
3778 r = exception_raise_state(port, thread, task, exception, data, data_count,
3779 &flavor, thread_state, thread_state_count,
3780 thread_state, &thread_state_count);
3782 case EXCEPTION_STATE_IDENTITY:
3783 r = exception_raise_state_identity(port, thread, task, exception, data,
3784 data_count, &flavor, thread_state,
3785 thread_state_count, thread_state,
3786 &thread_state_count);
3789 r = KERN_FAILURE; /* make gcc happy */
3790 ABORT("forward_exception: unknown behavior");
3794 if(behavior != EXCEPTION_DEFAULT) {
3795 r = thread_set_state(thread, flavor, thread_state, thread_state_count);
3796 if(r != KERN_SUCCESS)
3797 ABORT("thread_set_state failed in forward_exception");
3803 #define FWD() GC_forward_exception(thread, task, exception, code, code_count)
3805 /* This violates the namespace rules but there isn't anything that can be done
3806 about it. The exception handling stuff is hard coded to call this */
3808 catch_exception_raise(mach_port_t exception_port, mach_port_t thread,
3809 mach_port_t task, exception_type_t exception,
3810 exception_data_t code, mach_msg_type_number_t code_count)
3816 # if defined(POWERPC)
3817 # if CPP_WORDSZ == 32
3818 thread_state_flavor_t flavor = PPC_EXCEPTION_STATE;
3819 mach_msg_type_number_t exc_state_count = PPC_EXCEPTION_STATE_COUNT;
3820 ppc_exception_state_t exc_state;
3822 thread_state_flavor_t flavor = PPC_EXCEPTION_STATE64;
3823 mach_msg_type_number_t exc_state_count = PPC_EXCEPTION_STATE64_COUNT;
3824 ppc_exception_state64_t exc_state;
3826 # elif defined(I386) || defined(X86_64)
3827 # if CPP_WORDSZ == 32
3828 thread_state_flavor_t flavor = x86_EXCEPTION_STATE32;
3829 mach_msg_type_number_t exc_state_count = x86_EXCEPTION_STATE32_COUNT;
3830 x86_exception_state32_t exc_state;
3832 thread_state_flavor_t flavor = x86_EXCEPTION_STATE64;
3833 mach_msg_type_number_t exc_state_count = x86_EXCEPTION_STATE64_COUNT;
3834 x86_exception_state64_t exc_state;
3837 # error FIXME for non-ppc/x86 darwin
3841 if(exception != EXC_BAD_ACCESS || code[0] != KERN_PROTECTION_FAILURE) {
3842 # ifdef DEBUG_EXCEPTION_HANDLING
3843 /* We aren't interested, pass it on to the old handler */
3844 GC_printf("Exception: 0x%x Code: 0x%x 0x%x in catch....\n", exception,
3845 code_count > 0 ? code[0] : -1, code_count > 1 ? code[1] : -1);
3850 r = thread_get_state(thread, flavor, (natural_t*)&exc_state,
3852 if(r != KERN_SUCCESS) {
3853 /* The thread is supposed to be suspended while the exception handler
3854 is called. This shouldn't fail. */
3855 # ifdef BROKEN_EXCEPTION_HANDLING
3856 GC_err_printf("thread_get_state failed in catch_exception_raise\n");
3857 return KERN_SUCCESS;
3859 ABORT("thread_get_state failed in catch_exception_raise");
3863 /* This is the address that caused the fault */
3864 # if defined(POWERPC)
3865 addr = (char*) exc_state. THREAD_FLD(dar);
3866 # elif defined (I386) || defined (X86_64)
3867 addr = (char*) exc_state. THREAD_FLD(faultvaddr);
3869 # error FIXME for non POWERPC/I386
3872 if((HDR(addr)) == 0) {
3873 /* Ugh... just like the SIGBUS problem above, it seems we get a bogus
3874 KERN_PROTECTION_FAILURE every once and a while. We wait till we get
3875 a bunch in a row before doing anything about it. If a "real" fault
3876 ever occurs it'll just keep faulting over and over and we'll hit
3877 the limit pretty quickly. */
3878 # ifdef BROKEN_EXCEPTION_HANDLING
3879 static char *last_fault;
3880 static int last_fault_count;
3882 if(addr != last_fault) {
3884 last_fault_count = 0;
3886 if(++last_fault_count < 32) {
3887 if(last_fault_count == 1)
3888 WARN("Ignoring KERN_PROTECTION_FAILURE at %p\n", addr);
3889 return KERN_SUCCESS;
3892 GC_err_printf("Unexpected KERN_PROTECTION_FAILURE at %p\n",addr);
3893 /* Can't pass it along to the signal handler because that is
3894 ignoring SIGBUS signals. We also shouldn't call ABORT here as
3895 signals don't always work too well from the exception handler. */
3896 GC_err_printf("Aborting\n");
3898 # else /* BROKEN_EXCEPTION_HANDLING */
3899 /* Pass it along to the next exception handler
3900 (which should call SIGBUS/SIGSEGV) */
3902 # endif /* !BROKEN_EXCEPTION_HANDLING */
3905 # ifdef BROKEN_EXCEPTION_HANDLING
3906 /* Reset the number of consecutive SIGBUSs */
3907 GC_sigbus_count = 0;
3910 if(GC_mprotect_state == GC_MP_NORMAL) { /* common case */
3911 h = (struct hblk*)((word)addr & ~(GC_page_size-1));
3912 UNPROTECT(h, GC_page_size);
3913 for (i = 0; i < divHBLKSZ(GC_page_size); i++) {
3914 register int index = PHT_HASH(h+i);
3915 async_set_pht_entry_from_index(GC_dirty_pages, index);
3917 } else if(GC_mprotect_state == GC_MP_DISCARDING) {
3918 /* Lie to the thread for now. No sense UNPROTECT()ing the memory
3919 when we're just going to PROTECT() it again later. The thread
3920 will just fault again once it resumes */
3922 /* Shouldn't happen, i don't think */
3923 GC_printf("KERN_PROTECTION_FAILURE while world is stopped\n");
3926 return KERN_SUCCESS;
3930 /* These should never be called, but just in case... */
3932 catch_exception_raise_state(mach_port_name_t exception_port, int exception,
3933 exception_data_t code,
3934 mach_msg_type_number_t codeCnt, int flavor,
3935 thread_state_t old_state, int old_stateCnt,
3936 thread_state_t new_state, int new_stateCnt)
3938 ABORT("catch_exception_raise_state");
3939 return(KERN_INVALID_ARGUMENT);
3943 catch_exception_raise_state_identity(mach_port_name_t exception_port,
3944 mach_port_t thread, mach_port_t task,
3945 int exception, exception_data_t code,
3946 mach_msg_type_number_t codeCnt, int flavor,
3947 thread_state_t old_state, int old_stateCnt,
3948 thread_state_t new_state, int new_stateCnt)
3950 ABORT("catch_exception_raise_state_identity");
3951 return(KERN_INVALID_ARGUMENT);
3955 #endif /* DARWIN && MPROTECT_VDB */
3957 # ifndef HAVE_INCREMENTAL_PROTECTION_NEEDS
3958 GC_API int GC_CALL GC_incremental_protection_needs(void)
3960 return GC_PROTECTS_NONE;
3962 # endif /* !HAVE_INCREMENTAL_PROTECTION_NEEDS */
3965 * Call stack save code for debugging.
3966 * Should probably be in mach_dep.c, but that requires reorganization.
3969 /* I suspect the following works for most X86 *nix variants, so */
3970 /* long as the frame pointer is explicitly stored. In the case of gcc, */
3971 /* compiler flags (e.g. -fomit-frame-pointer) determine whether it is. */
3972 #if defined(I386) && defined(LINUX) && defined(SAVE_CALL_CHAIN)
3973 # include <features.h>
3976 struct frame *fr_savfp;
3978 long fr_arg[NARGS]; /* All the arguments go here. */
3984 # include <features.h>
3989 struct frame *fr_savfp;
3997 # elif defined (DRSNX)
3998 # include <sys/sparc/frame.h>
3999 # elif defined(OPENBSD)
4001 # elif defined(FREEBSD) || defined(NETBSD)
4002 # include <machine/frame.h>
4004 # include <sys/frame.h>
4007 # error We only know how to to get the first 6 arguments
4011 #ifdef NEED_CALLINFO
4012 /* Fill in the pc and argument information for up to NFRAMES of my */
4013 /* callers. Ignore my frame and my callers frame. */
4016 # include <unistd.h>
4019 #endif /* NEED_CALLINFO */
4021 #if defined(GC_HAVE_BUILTIN_BACKTRACE)
4023 # include "private/msvc_dbg.h"
4025 # include <execinfo.h>
4029 #ifdef SAVE_CALL_CHAIN
4031 #if NARGS == 0 && NFRAMES % 2 == 0 /* No padding */ \
4032 && defined(GC_HAVE_BUILTIN_BACKTRACE)
4034 #ifdef REDIRECT_MALLOC
4035 /* Deal with possible malloc calls in backtrace by omitting */
4036 /* the infinitely recursing backtrace. */
4038 __thread /* If your compiler doesn't understand this */
4039 /* you could use something like pthread_getspecific. */
4041 GC_in_save_callers = FALSE;
4044 void GC_save_callers (struct callinfo info[NFRAMES])
4046 void * tmp_info[NFRAMES + 1];
4048 # define IGNORE_FRAMES 1
4050 /* We retrieve NFRAMES+1 pc values, but discard the first, since it */
4051 /* points to our own frame. */
4052 # ifdef REDIRECT_MALLOC
4053 if (GC_in_save_callers) {
4054 info[0].ci_pc = (word)(&GC_save_callers);
4055 for (i = 1; i < NFRAMES; ++i) info[i].ci_pc = 0;
4058 GC_in_save_callers = TRUE;
4060 GC_STATIC_ASSERT(sizeof(struct callinfo) == sizeof(void *));
4061 npcs = backtrace((void **)tmp_info, NFRAMES + IGNORE_FRAMES);
4062 BCOPY(tmp_info+IGNORE_FRAMES, info, (npcs - IGNORE_FRAMES) * sizeof(void *));
4063 for (i = npcs - IGNORE_FRAMES; i < NFRAMES; ++i) info[i].ci_pc = 0;
4064 # ifdef REDIRECT_MALLOC
4065 GC_in_save_callers = FALSE;
4069 #else /* No builtin backtrace; do it ourselves */
4071 #if (defined(OPENBSD) || defined(NETBSD) || defined(FREEBSD)) && defined(SPARC)
4072 # define FR_SAVFP fr_fp
4073 # define FR_SAVPC fr_pc
4075 # define FR_SAVFP fr_savfp
4076 # define FR_SAVPC fr_savpc
4079 #if defined(SPARC) && (defined(__arch64__) || defined(__sparcv9))
4085 void GC_save_callers (struct callinfo info[NFRAMES])
4087 struct frame *frame;
4091 /* We assume this is turned on only with gcc as the compiler. */
4092 asm("movl %%ebp,%0" : "=r"(frame));
4095 frame = (struct frame *) GC_save_regs_in_stack ();
4096 fp = (struct frame *)((long) frame -> FR_SAVFP + BIAS);
4099 for (; (!(fp HOTTER_THAN frame) && !(GC_stackbottom HOTTER_THAN (ptr_t)fp)
4100 && (nframes < NFRAMES));
4101 fp = (struct frame *)((long) fp -> FR_SAVFP + BIAS), nframes++) {
4104 info[nframes].ci_pc = fp->FR_SAVPC;
4106 for (i = 0; i < NARGS; i++) {
4107 info[nframes].ci_arg[i] = ~(fp->fr_arg[i]);
4109 # endif /* NARGS > 0 */
4111 if (nframes < NFRAMES) info[nframes].ci_pc = 0;
4114 #endif /* No builtin backtrace */
4116 #endif /* SAVE_CALL_CHAIN */
4118 #ifdef NEED_CALLINFO
4120 /* Print info to stderr. We do NOT hold the allocation lock */
4121 void GC_print_callers (struct callinfo info[NFRAMES])
4124 static int reentry_count = 0;
4125 GC_bool stop = FALSE;
4127 /* FIXME: This should probably use a different lock, so that we */
4128 /* become callable with or without the allocation lock. */
4134 GC_err_printf("\tCaller at allocation:\n");
4136 GC_err_printf("\tCall chain at allocation:\n");
4138 for (i = 0; i < NFRAMES && !stop ; i++) {
4139 if (info[i].ci_pc == 0) break;
4144 GC_err_printf("\t\targs: ");
4145 for (j = 0; j < NARGS; j++) {
4146 if (j != 0) GC_err_printf(", ");
4147 GC_err_printf("%d (0x%X)", ~(info[i].ci_arg[j]),
4148 ~(info[i].ci_arg[j]));
4150 GC_err_printf("\n");
4153 if (reentry_count > 1) {
4154 /* We were called during an allocation during */
4155 /* a previous GC_print_callers call; punt. */
4156 GC_err_printf("\t\t##PC##= 0x%lx\n", info[i].ci_pc);
4163 # if defined(GC_HAVE_BUILTIN_BACKTRACE) \
4164 && !defined(GC_BACKTRACE_SYMBOLS_BROKEN)
4166 backtrace_symbols((void **)(&(info[i].ci_pc)), 1);
4167 char *name = sym_name[0];
4171 sprintf(buf, "##PC##= 0x%lx", info[i].ci_pc);
4173 # if defined(LINUX) && !defined(SMALL_CONFIG)
4174 /* Try for a line number. */
4177 static char exe_name[EXE_SZ];
4179 char cmd_buf[CMD_SZ];
4180 # define RESULT_SZ 200
4181 static char result_buf[RESULT_SZ];
4184 # define PRELOAD_SZ 200
4185 char preload_buf[PRELOAD_SZ];
4186 static GC_bool found_exe_name = FALSE;
4187 static GC_bool will_fail = FALSE;
4189 /* Try to get it via a hairy and expensive scheme. */
4190 /* First we get the name of the executable: */
4191 if (will_fail) goto out;
4192 if (!found_exe_name) {
4193 ret_code = readlink("/proc/self/exe", exe_name, EXE_SZ);
4194 if (ret_code < 0 || ret_code >= EXE_SZ
4195 || exe_name[0] != '/') {
4196 will_fail = TRUE; /* Dont try again. */
4199 exe_name[ret_code] = '\0';
4200 found_exe_name = TRUE;
4202 /* Then we use popen to start addr2line -e <exe> <addr> */
4203 /* There are faster ways to do this, but hopefully this */
4204 /* isn't time critical. */
4205 sprintf(cmd_buf, "/usr/bin/addr2line -f -e %s 0x%lx", exe_name,
4206 (unsigned long)info[i].ci_pc);
4207 old_preload = getenv ("LD_PRELOAD");
4208 if (0 != old_preload) {
4209 if (strlen (old_preload) >= PRELOAD_SZ) {
4213 strcpy (preload_buf, old_preload);
4214 unsetenv ("LD_PRELOAD");
4216 pipe = popen(cmd_buf, "r");
4217 if (0 != old_preload
4218 && 0 != setenv ("LD_PRELOAD", preload_buf, 0)) {
4219 WARN("Failed to reset LD_PRELOAD\n", 0);
4222 || (result_len = fread(result_buf, 1, RESULT_SZ - 1, pipe))
4224 if (pipe != NULL) pclose(pipe);
4228 if (result_buf[result_len - 1] == '\n') --result_len;
4229 result_buf[result_len] = 0;
4230 if (result_buf[0] == '?'
4231 || (result_buf[result_len-2] == ':'
4232 && result_buf[result_len-1] == '0')) {
4236 /* Get rid of embedded newline, if any. Test for "main" */
4238 char * nl = strchr(result_buf, '\n');
4239 if (nl != NULL && nl < result_buf + result_len) {
4242 if (strncmp(result_buf, "main", nl - result_buf) == 0) {
4246 if (result_len < RESULT_SZ - 25) {
4247 /* Add in hex address */
4248 sprintf(result_buf + result_len, " [0x%lx]",
4249 (unsigned long)info[i].ci_pc);
4256 GC_err_printf("\t\t%s\n", name);
4257 # if defined(GC_HAVE_BUILTIN_BACKTRACE) \
4258 && !defined(GC_BACKTRACE_SYMBOLS_BROKEN)
4259 free(sym_name); /* May call GC_free; that's OK */
4268 #endif /* NEED_CALLINFO */
4272 #if defined(LINUX) && defined(__ELF__) && !defined(SMALL_CONFIG)
4274 /* Dump /proc/self/maps to GC_stderr, to enable looking up names for
4275 addresses in FIND_LEAK output. */
4277 static word dump_maps(char *maps)
4279 GC_err_write(maps, strlen(maps));
4283 void GC_print_address_map(void)
4285 GC_err_printf("---------- Begin address map ----------\n");
4286 dump_maps(GC_get_maps());
4287 GC_err_printf("---------- End address map ----------\n");