2 * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
3 * Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved.
4 * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved.
5 * Copyright (c) 1999 by Hewlett-Packard Company. All rights reserved.
7 * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
8 * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
10 * Permission is hereby granted to use or copy this program
11 * for any purpose, provided the above notices are retained on all copies.
12 * Permission to modify the code and to distribute modified code is granted,
13 * provided the above notices are retained, and a notice that the code was
14 * modified is included with the above copyright notice.
17 #include "private/gc_priv.h"
19 #if defined(LINUX) && !defined(POWERPC)
20 # include <linux/version.h>
21 # if (LINUX_VERSION_CODE <= 0x10400)
22 /* Ugly hack to get struct sigcontext_struct definition. Required */
23 /* for some early 1.3.X releases. Will hopefully go away soon. */
24 /* in some later Linux releases, asm/sigcontext.h may have to */
25 /* be included instead. */
27 # include <asm/signal.h>
30 /* Kernels prior to 2.1.1 defined struct sigcontext_struct instead of */
31 /* struct sigcontext. libc6 (glibc2) uses "struct sigcontext" in */
32 /* prototypes, so we have to include the top-level sigcontext.h to */
33 /* make sure the former gets defined to be the latter if appropriate. */
34 # include <features.h>
36 # if 2 == __GLIBC__ && 0 == __GLIBC_MINOR__
37 /* glibc 2.1 no longer has sigcontext.h. But signal.h */
38 /* has the right declaration for glibc 2.1. */
39 # include <sigcontext.h>
40 # endif /* 0 == __GLIBC_MINOR__ */
41 # else /* not 2 <= __GLIBC__ */
42 /* libc5 doesn't have <sigcontext.h>: go directly with the kernel */
43 /* one. Check LINUX_VERSION_CODE to see which we should reference. */
44 # include <asm/sigcontext.h>
45 # endif /* 2 <= __GLIBC__ */
49 #if !defined(OS2) && !defined(PCR) && !defined(AMIGA) && !defined(MACOS) \
50 && !defined(MSWINCE) && !defined(__CC_ARM)
51 # include <sys/types.h>
52 # if !defined(MSWIN32)
58 #if defined(MSWINCE) || defined(SN_TARGET_PS3)
59 # define SIGSEGV 0 /* value is irrelevant */
64 #if defined(UNIX_LIKE) || defined(CYGWIN32) || defined(NACL)
68 #if defined(LINUX) || defined(LINUX_STACKBOTTOM)
72 /* Blatantly OS dependent routines, except for those that are related */
73 /* to dynamic loading. */
77 # include "extra/AmigaOS.c"
81 #if defined(MSWIN32) || defined(MSWINCE) || defined(CYGWIN32)
82 # ifndef WIN32_LEAN_AND_MEAN
83 # define WIN32_LEAN_AND_MEAN 1
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 # error "invalid config - 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 STATIC GC_bool GC_pages_executable = TRUE;
136 STATIC GC_bool GC_pages_executable = FALSE;
138 #define IGNORE_PAGES_EXECUTABLE 1
139 /* Undefined on GC_pages_executable real use. */
141 #ifdef NEED_PROC_MAPS
142 /* We need to parse /proc/self/maps, either to find dynamic libraries, */
143 /* and/or to find the register backing store base (IA64). Do it once */
148 /* Repeatedly perform a read call until the buffer is filled or */
149 /* we encounter EOF. */
150 STATIC ssize_t GC_repeat_read(int fd, char *buf, size_t count)
155 ASSERT_CANCEL_DISABLED();
156 while (num_read < count) {
157 result = READ(fd, buf + num_read, count - num_read);
158 if (result < 0) return result;
159 if (result == 0) break;
166 /* Determine the length of a file by incrementally reading it into a */
167 /* This would be silly to use on a file supporting lseek, but Linux */
168 /* /proc files usually do not. */
169 STATIC size_t GC_get_file_len(int f)
173 # define GET_FILE_LEN_BUF_SZ 500
174 char buf[GET_FILE_LEN_BUF_SZ];
177 result = read(f, buf, GET_FILE_LEN_BUF_SZ);
178 if (result == -1) return 0;
180 } while (result > 0);
184 STATIC size_t GC_get_maps_len(void)
186 int f = open("/proc/self/maps", O_RDONLY);
188 if (f < 0) return 0; /* treat missing file as empty */
189 result = GC_get_file_len(f);
195 /* Copy the contents of /proc/self/maps to a buffer in our address */
196 /* space. Return the address of the buffer, or zero on failure. */
197 /* This code could be simplified if we could determine its size ahead */
199 GC_INNER char * GC_get_maps(void)
203 static char *maps_buf = NULL;
204 static size_t maps_buf_sz = 1;
205 size_t maps_size, old_maps_size = 0;
207 /* The buffer is essentially static, so there must be a single client. */
208 GC_ASSERT(I_HOLD_LOCK());
210 /* Note that in the presence of threads, the maps file can */
211 /* essentially shrink asynchronously and unexpectedly as */
212 /* threads that we already think of as dead release their */
213 /* stacks. And there is no easy way to read the entire */
214 /* file atomically. This is arguably a misfeature of the */
215 /* /proc/.../maps interface. */
217 /* Since we don't believe the file can grow */
218 /* asynchronously, it should suffice to first determine */
219 /* the size (using lseek or read), and then to reread the */
220 /* file. If the size is inconsistent we have to retry. */
221 /* This only matters with threads enabled, and if we use */
222 /* this to locate roots (not the default). */
225 /* Determine the initial size of /proc/self/maps. */
226 /* Note that lseek doesn't work, at least as of 2.6.15. */
227 maps_size = GC_get_maps_len();
228 if (0 == maps_size) return 0;
230 maps_size = 4000; /* Guess */
233 /* Read /proc/self/maps, growing maps_buf as necessary. */
234 /* Note that we may not allocate conventionally, and */
235 /* thus can't use stdio. */
237 while (maps_size >= maps_buf_sz) {
238 /* Grow only by powers of 2, since we leak "too small" buffers.*/
239 while (maps_size >= maps_buf_sz) maps_buf_sz *= 2;
240 maps_buf = GC_scratch_alloc(maps_buf_sz);
242 /* Recompute initial length, since we allocated. */
243 /* This can only happen a few times per program */
245 maps_size = GC_get_maps_len();
246 if (0 == maps_size) return 0;
248 if (maps_buf == 0) return 0;
250 GC_ASSERT(maps_buf_sz >= maps_size + 1);
251 f = open("/proc/self/maps", O_RDONLY);
252 if (-1 == f) return 0;
254 old_maps_size = maps_size;
258 result = GC_repeat_read(f, maps_buf, maps_buf_sz-1);
262 } while ((size_t)result == maps_buf_sz-1);
267 if (maps_size > old_maps_size) {
270 "Unexpected maps size growth from %lu to %lu\n",
271 (unsigned long)old_maps_size,
272 (unsigned long)maps_size);
273 ABORT("Unexpected asynchronous /proc/self/maps growth: "
274 "unregistered thread?");
277 } while (maps_size >= maps_buf_sz || maps_size < old_maps_size);
278 /* In the single-threaded case, the second clause is false. */
279 maps_buf[maps_size] = '\0';
281 /* Apply fn to result. */
286 * GC_parse_map_entry parses an entry from /proc/self/maps so we can
287 * locate all writable data segments that belong to shared libraries.
288 * The format of one of these entries and the fields we care about
290 * XXXXXXXX-XXXXXXXX r-xp 00000000 30:05 260537 name of mapping...\n
291 * ^^^^^^^^ ^^^^^^^^ ^^^^ ^^
292 * start end prot maj_dev
294 * Note that since about august 2003 kernels, the columns no longer have
295 * fixed offsets on 64-bit kernels. Hence we no longer rely on fixed offsets
296 * anywhere, which is safer anyway.
299 /* Assign various fields of the first line in buf_ptr to (*start), */
300 /* (*end), (*prot), (*maj_dev) and (*mapping_name). mapping_name may */
301 /* be NULL. (*prot) and (*mapping_name) are assigned pointers into the */
302 /* original buffer. */
303 GC_INNER 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 #if defined(IA64) || defined(INCLUDE_LINUX_THREAD_DESCR)
352 /* Try to read the backing store base from /proc/self/maps. */
353 /* Return the bounds of the writable mapping with a 0 major device, */
354 /* which includes the address passed as data. */
355 /* Return FALSE if there is no such mapping. */
356 GC_INNER GC_bool GC_enclosing_mapping(ptr_t addr, ptr_t *startp,
360 ptr_t my_start, my_end;
361 unsigned int maj_dev;
362 char *maps = GC_get_maps();
363 char *buf_ptr = maps;
365 if (0 == maps) return(FALSE);
367 buf_ptr = GC_parse_map_entry(buf_ptr, &my_start, &my_end,
370 if (buf_ptr == NULL) return FALSE;
371 if (prot[1] == 'w' && maj_dev == 0) {
372 if (my_end > addr && my_start <= addr) {
381 #endif /* IA64 || INCLUDE_LINUX_THREAD_DESCR */
383 #if defined(REDIRECT_MALLOC)
384 /* Find the text(code) mapping for the library whose name, after */
385 /* stripping the directory part, starts with nm. */
386 GC_INNER GC_bool GC_text_mapping(char *nm, ptr_t *startp, ptr_t *endp)
388 size_t nm_len = strlen(nm);
391 ptr_t my_start, my_end;
392 unsigned int maj_dev;
393 char *maps = GC_get_maps();
394 char *buf_ptr = maps;
396 if (0 == maps) return(FALSE);
398 buf_ptr = GC_parse_map_entry(buf_ptr, &my_start, &my_end,
399 &prot, &maj_dev, &map_path);
401 if (buf_ptr == NULL) return FALSE;
402 if (prot[0] == 'r' && prot[1] == '-' && prot[2] == 'x') {
404 /* Set p to point just past last slash, if any. */
405 while (*p != '\0' && *p != '\n' && *p != ' ' && *p != '\t') ++p;
406 while (*p != '/' && p >= map_path) --p;
408 if (strncmp(nm, p, nm_len) == 0) {
417 #endif /* REDIRECT_MALLOC */
420 static ptr_t backing_store_base_from_proc(void)
422 ptr_t my_start, my_end;
423 if (!GC_enclosing_mapping(GC_save_regs_in_stack(), &my_start, &my_end)) {
424 if (GC_print_stats) {
425 GC_log_printf("Failed to find backing store base from /proc\n");
433 #endif /* NEED_PROC_MAPS */
435 #if defined(SEARCH_FOR_DATA_START)
436 /* The I386 case can be handled without a search. The Alpha case */
437 /* used to be handled differently as well, but the rules changed */
438 /* for recent Linux versions. This seems to be the easiest way to */
439 /* cover all versions. */
441 # if defined(LINUX) || defined(HURD)
442 /* Some Linux distributions arrange to define __data_start. Some */
443 /* define data_start as a weak symbol. The latter is technically */
444 /* broken, since the user program may define data_start, in which */
445 /* case we lose. Nonetheless, we try both, preferring __data_start.*/
446 /* We assume gcc-compatible pragmas. */
447 # pragma weak __data_start
448 extern int __data_start[];
449 # pragma weak data_start
450 extern int data_start[];
454 ptr_t GC_data_start = NULL;
456 ptr_t GC_find_limit(ptr_t, GC_bool);
458 GC_INNER void GC_init_linux_data_start(void)
461 # if defined(LINUX) || defined(HURD)
462 /* Try the easy approaches first: */
463 if ((ptr_t)__data_start != 0) {
464 GC_data_start = (ptr_t)(__data_start);
467 if ((ptr_t)data_start != 0) {
468 GC_data_start = (ptr_t)(data_start);
472 GC_data_start = GC_find_limit((ptr_t)(_end), FALSE);
474 #endif /* SEARCH_FOR_DATA_START */
478 # ifndef ECOS_GC_MEMORY_SIZE
479 # define ECOS_GC_MEMORY_SIZE (448 * 1024)
480 # endif /* ECOS_GC_MEMORY_SIZE */
482 /* FIXME: This is a simple way of allocating memory which is */
483 /* compatible with ECOS early releases. Later releases use a more */
484 /* sophisticated means of allocating memory than this simple static */
485 /* allocator, but this method is at least bound to work. */
486 static char ecos_gc_memory[ECOS_GC_MEMORY_SIZE];
487 static char *ecos_gc_brk = ecos_gc_memory;
489 static void *tiny_sbrk(ptrdiff_t increment)
491 void *p = ecos_gc_brk;
492 ecos_gc_brk += increment;
493 if (ecos_gc_brk > ecos_gc_memory + sizeof(ecos_gc_memory)) {
494 ecos_gc_brk -= increment;
499 # define sbrk tiny_sbrk
502 #if defined(NETBSD) && defined(__ELF__)
503 ptr_t GC_data_start = NULL;
504 ptr_t GC_find_limit(ptr_t, GC_bool);
506 extern char **environ;
508 GC_INNER 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);
517 static struct sigaction old_segv_act;
518 STATIC sigjmp_buf GC_jmp_buf_openbsd;
521 # include <sys/syscall.h>
522 extern sigset_t __syscall(quad_t, ...);
525 /* Don't use GC_find_limit() because siglongjmp() outside of the */
526 /* signal handler by-passes our userland pthreads lib, leaving */
527 /* SIGSEGV and SIGPROF masked. Instead, use this custom one that */
528 /* works-around the issues. */
531 STATIC void GC_fault_handler_openbsd(int sig)
533 siglongjmp(GC_jmp_buf_openbsd, 1);
536 /* Return the first non-addressible location > p or bound. */
537 /* Requires the allocation lock. */
538 STATIC ptr_t GC_find_limit_openbsd(ptr_t p, ptr_t bound)
540 static volatile ptr_t result;
541 /* Safer if static, since otherwise it may not be */
542 /* preserved across the longjmp. Can safely be */
543 /* static since it's only called with the */
544 /* allocation lock held. */
546 struct sigaction act;
547 size_t pgsz = (size_t)sysconf(_SC_PAGESIZE);
548 GC_ASSERT(I_HOLD_LOCK());
550 act.sa_handler = GC_fault_handler_openbsd;
551 sigemptyset(&act.sa_mask);
552 act.sa_flags = SA_NODEFER | SA_RESTART;
553 sigaction(SIGSEGV, &act, &old_segv_act);
555 if (sigsetjmp(GC_jmp_buf_openbsd, 1) == 0) {
556 result = (ptr_t)((word)p & ~(pgsz-1));
559 if (result >= bound) {
563 GC_noop1((word)(*result));
568 /* Due to the siglongjump we need to manually unmask SIGPROF. */
569 __syscall(SYS_sigprocmask, SIG_UNBLOCK, sigmask(SIGPROF));
572 sigaction(SIGSEGV, &old_segv_act, 0);
576 /* Return first addressable location > p or bound. */
577 /* Requires the allocation lock. */
578 STATIC ptr_t GC_skip_hole_openbsd(ptr_t p, ptr_t bound)
580 static volatile ptr_t result;
581 static volatile int firstpass;
583 struct sigaction act;
584 size_t pgsz = (size_t)sysconf(_SC_PAGESIZE);
585 GC_ASSERT(I_HOLD_LOCK());
587 act.sa_handler = GC_fault_handler_openbsd;
588 sigemptyset(&act.sa_mask);
589 act.sa_flags = SA_NODEFER | SA_RESTART;
590 sigaction(SIGSEGV, &act, &old_segv_act);
593 result = (ptr_t)((word)p & ~(pgsz-1));
594 if (sigsetjmp(GC_jmp_buf_openbsd, 1) != 0 || firstpass) {
597 if (result >= bound) {
600 GC_noop1((word)(*result));
604 sigaction(SIGSEGV, &old_segv_act, 0);
613 # if !defined(__IBMC__) && !defined(__WATCOMC__) /* e.g. EMX */
616 unsigned short magic_number;
617 unsigned short padding[29];
621 #define E_MAGIC(x) (x).magic_number
622 #define EMAGIC 0x5A4D
623 #define E_LFANEW(x) (x).new_exe_offset
626 unsigned char magic_number[2];
627 unsigned char byte_order;
628 unsigned char word_order;
629 unsigned long exe_format_level;
632 unsigned long padding1[13];
633 unsigned long object_table_offset;
634 unsigned long object_count;
635 unsigned long padding2[31];
638 #define E32_MAGIC1(x) (x).magic_number[0]
639 #define E32MAGIC1 'L'
640 #define E32_MAGIC2(x) (x).magic_number[1]
641 #define E32MAGIC2 'X'
642 #define E32_BORDER(x) (x).byte_order
644 #define E32_WORDER(x) (x).word_order
646 #define E32_CPU(x) (x).cpu
648 #define E32_OBJTAB(x) (x).object_table_offset
649 #define E32_OBJCNT(x) (x).object_count
655 unsigned long pagemap;
656 unsigned long mapsize;
657 unsigned long reserved;
660 #define O32_FLAGS(x) (x).flags
661 #define OBJREAD 0x0001L
662 #define OBJWRITE 0x0002L
663 #define OBJINVALID 0x0080L
664 #define O32_SIZE(x) (x).size
665 #define O32_BASE(x) (x).base
667 # else /* IBM's compiler */
669 /* A kludge to get around what appears to be a header file bug */
671 # define WORD unsigned short
674 # define DWORD unsigned long
681 # endif /* __IBMC__ */
683 # define INCL_DOSEXCEPTIONS
684 # define INCL_DOSPROCESS
685 # define INCL_DOSERRORS
686 # define INCL_DOSMODULEMGR
687 # define INCL_DOSMEMMGR
692 /* Find the page size */
693 GC_INNER word GC_page_size = 0;
695 #if defined(MSWIN32) || defined(MSWINCE) || defined(CYGWIN32)
696 # ifndef VER_PLATFORM_WIN32_CE
697 # define VER_PLATFORM_WIN32_CE 3
700 # if defined(MSWINCE) && defined(THREADS)
701 GC_INNER GC_bool GC_dont_query_stack_min = FALSE;
704 GC_INNER void GC_setpagesize(void)
706 GetSystemInfo(&GC_sysinfo);
707 GC_page_size = GC_sysinfo.dwPageSize;
708 # if defined(MSWINCE) && !defined(_WIN32_WCE_EMULATION)
710 OSVERSIONINFO verInfo;
711 /* Check the current WinCE version. */
712 verInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
713 if (!GetVersionEx(&verInfo))
714 ABORT("GetVersionEx failed");
715 if (verInfo.dwPlatformId == VER_PLATFORM_WIN32_CE &&
716 verInfo.dwMajorVersion < 6) {
717 /* Only the first 32 MB of address space belongs to the */
718 /* current process (unless WinCE 6.0+ or emulation). */
719 GC_sysinfo.lpMaximumApplicationAddress = (LPVOID)((word)32 << 20);
721 /* On some old WinCE versions, it's observed that */
722 /* VirtualQuery calls don't work properly when used to */
723 /* get thread current stack committed minimum. */
724 if (verInfo.dwMajorVersion < 5)
725 GC_dont_query_stack_min = TRUE;
733 # define is_writable(prot) ((prot) == PAGE_READWRITE \
734 || (prot) == PAGE_WRITECOPY \
735 || (prot) == PAGE_EXECUTE_READWRITE \
736 || (prot) == PAGE_EXECUTE_WRITECOPY)
737 /* Return the number of bytes that are writable starting at p. */
738 /* The pointer p is assumed to be page aligned. */
739 /* If base is not 0, *base becomes the beginning of the */
740 /* allocation region containing p. */
741 STATIC word GC_get_writable_length(ptr_t p, ptr_t *base)
743 MEMORY_BASIC_INFORMATION buf;
747 result = VirtualQuery(p, &buf, sizeof(buf));
748 if (result != sizeof(buf)) ABORT("Weird VirtualQuery result");
749 if (base != 0) *base = (ptr_t)(buf.AllocationBase);
750 protect = (buf.Protect & ~(PAGE_GUARD | PAGE_NOCACHE));
751 if (!is_writable(protect)) {
754 if (buf.State != MEM_COMMIT) return(0);
755 return(buf.RegionSize);
758 GC_API int GC_CALL GC_get_stack_base(struct GC_stack_base *sb)
760 ptr_t trunc_sp = (ptr_t)((word)GC_approx_sp() & ~(GC_page_size - 1));
761 /* FIXME: This won't work if called from a deeply recursive */
762 /* client code (and the committed stack space has grown). */
763 word size = GC_get_writable_length(trunc_sp, 0);
764 GC_ASSERT(size != 0);
765 sb -> mem_base = trunc_sp + size;
768 # else /* CYGWIN32 */
769 /* An alternate version for Cygwin (adapted from Dave Korn's */
770 /* gcc version of boehm-gc). */
771 GC_API int GC_CALL GC_get_stack_base(struct GC_stack_base *sb)
773 extern void * _tlsbase __asm__ ("%fs:4");
774 sb -> mem_base = _tlsbase;
777 # endif /* CYGWIN32 */
778 # define HAVE_GET_STACK_BASE
781 GC_INNER void GC_setpagesize(void)
783 # if defined(MPROTECT_VDB) || defined(PROC_VDB) || defined(USE_MMAP)
784 GC_page_size = GETPAGESIZE();
785 if (!GC_page_size) ABORT("getpagesize() failed");
787 /* It's acceptable to fake it. */
788 GC_page_size = HBLKSIZE;
791 #endif /* !MSWIN32 */
794 # include <kernel/OS.h>
796 GC_API int GC_CALL GC_get_stack_base(struct GC_stack_base *sb)
799 get_thread_info(find_thread(NULL),&th);
800 sb->mem_base = th.stack_end;
803 # define HAVE_GET_STACK_BASE
807 GC_API int GC_CALL GC_get_stack_base(struct GC_stack_base *sb)
809 PTIB ptib; /* thread information block */
811 if (DosGetInfoBlocks(&ptib, &ppib) != NO_ERROR) {
812 ABORT("DosGetInfoBlocks failed");
814 sb->mem_base = ptib->tib_pstacklimit;
817 # define HAVE_GET_STACK_BASE
822 # include "extra/AmigaOS.c"
826 # if defined(NEED_FIND_LIMIT) || defined(UNIX_LIKE)
828 typedef void (*GC_fault_handler_t)(int);
830 # if defined(SUNOS5SIGS) || defined(IRIX5) || defined(OSF1) \
831 || defined(HURD) || defined(NETBSD)
832 static struct sigaction old_segv_act;
833 # if defined(_sigargs) /* !Irix6.x */ || defined(HPUX) \
834 || defined(HURD) || defined(NETBSD) || defined(FREEBSD)
835 static struct sigaction old_bus_act;
838 static GC_fault_handler_t old_segv_handler, old_bus_handler;
841 GC_INNER void GC_set_and_save_fault_handler(GC_fault_handler_t h)
843 # if defined(SUNOS5SIGS) || defined(IRIX5) \
844 || defined(OSF1) || defined(HURD) || defined(NETBSD)
845 struct sigaction act;
848 # ifdef SIGACTION_FLAGS_NODEFER_HACK
849 /* Was necessary for Solaris 2.3 and very temporary */
851 act.sa_flags = SA_RESTART | SA_NODEFER;
853 act.sa_flags = SA_RESTART;
856 (void) sigemptyset(&act.sa_mask);
857 # ifdef GC_IRIX_THREADS
858 /* Older versions have a bug related to retrieving and */
859 /* and setting a handler at the same time. */
860 (void) sigaction(SIGSEGV, 0, &old_segv_act);
861 (void) sigaction(SIGSEGV, &act, 0);
863 (void) sigaction(SIGSEGV, &act, &old_segv_act);
864 # if defined(IRIX5) && defined(_sigargs) /* Irix 5.x, not 6.x */ \
865 || defined(HPUX) || defined(HURD) || defined(NETBSD) \
867 /* Under Irix 5.x or HP/UX, we may get SIGBUS. */
868 /* Pthreads doesn't exist under Irix 5.x, so we */
869 /* don't have to worry in the threads case. */
870 (void) sigaction(SIGBUS, &act, &old_bus_act);
872 # endif /* GC_IRIX_THREADS */
874 old_segv_handler = signal(SIGSEGV, h);
876 old_bus_handler = signal(SIGBUS, h);
880 # endif /* NEED_FIND_LIMIT || UNIX_LIKE */
882 # if defined(NEED_FIND_LIMIT) \
883 || (defined(USE_PROC_FOR_LIBRARIES) && defined(THREADS))
884 /* Some tools to implement HEURISTIC2 */
885 # define MIN_PAGE_SIZE 256 /* Smallest conceivable page size, bytes */
888 STATIC void GC_fault_handler(int sig)
890 LONGJMP(GC_jmp_buf, 1);
893 GC_INNER void GC_setup_temporary_fault_handler(void)
895 /* Handler is process-wide, so this should only happen in */
896 /* one thread at a time. */
897 GC_ASSERT(I_HOLD_LOCK());
898 GC_set_and_save_fault_handler(GC_fault_handler);
901 GC_INNER void GC_reset_fault_handler(void)
903 # if defined(SUNOS5SIGS) || defined(IRIX5) \
904 || defined(OSF1) || defined(HURD) || defined(NETBSD)
905 (void) sigaction(SIGSEGV, &old_segv_act, 0);
906 # if defined(IRIX5) && defined(_sigargs) /* Irix 5.x, not 6.x */ \
907 || defined(HPUX) || defined(HURD) || defined(NETBSD) \
909 (void) sigaction(SIGBUS, &old_bus_act, 0);
912 (void) signal(SIGSEGV, old_segv_handler);
914 (void) signal(SIGBUS, old_bus_handler);
919 /* Return the first non-addressable location > p (up) or */
920 /* the smallest location q s.t. [q,p) is addressable (!up). */
921 /* We assume that p (up) or p-1 (!up) is addressable. */
922 /* Requires allocation lock. */
923 STATIC ptr_t GC_find_limit_with_bound(ptr_t p, GC_bool up, ptr_t bound)
925 static volatile ptr_t result;
926 /* Safer if static, since otherwise it may not be */
927 /* preserved across the longjmp. Can safely be */
928 /* static since it's only called with the */
929 /* allocation lock held. */
931 GC_ASSERT(I_HOLD_LOCK());
932 GC_setup_temporary_fault_handler();
933 if (SETJMP(GC_jmp_buf) == 0) {
934 result = (ptr_t)(((word)(p))
935 & ~(MIN_PAGE_SIZE-1));
938 result += MIN_PAGE_SIZE;
939 if (result >= bound) {
944 result -= MIN_PAGE_SIZE;
945 if (result <= bound) {
946 result = bound - MIN_PAGE_SIZE;
947 /* This is to compensate */
948 /* further result increment (we */
949 /* do not modify "up" variable */
950 /* since it might be clobbered */
951 /* by setjmp otherwise). */
955 GC_noop1((word)(*result));
958 GC_reset_fault_handler();
960 result += MIN_PAGE_SIZE;
965 ptr_t GC_find_limit(ptr_t p, GC_bool up)
967 return GC_find_limit_with_bound(p, up, up ? (ptr_t)(word)(-1) : 0);
969 # endif /* NEED_FIND_LIMIT || USE_PROC_FOR_LIBRARIES */
971 #ifdef HPUX_STACKBOTTOM
973 #include <sys/param.h>
974 #include <sys/pstat.h>
976 GC_INNER ptr_t GC_get_register_stack_base(void)
978 struct pst_vm_status vm_status;
981 while (pstat_getprocvm(&vm_status, sizeof(vm_status), 0, i++) == 1) {
982 if (vm_status.pst_type == PS_RSESTACK) {
983 return (ptr_t) vm_status.pst_vaddr;
987 /* old way to get the register stackbottom */
988 return (ptr_t)(((word)GC_stackbottom - BACKING_STORE_DISPLACEMENT - 1)
989 & ~(BACKING_STORE_ALIGNMENT - 1));
992 #endif /* HPUX_STACK_BOTTOM */
994 #ifdef LINUX_STACKBOTTOM
996 # include <sys/types.h>
997 # include <sys/stat.h>
999 # define STAT_SKIP 27 /* Number of fields preceding startstack */
1000 /* field in /proc/self/stat */
1002 # ifdef USE_LIBC_PRIVATES
1003 # pragma weak __libc_stack_end
1004 extern ptr_t __libc_stack_end;
1008 # ifdef USE_LIBC_PRIVATES
1009 # pragma weak __libc_ia64_register_backing_store_base
1010 extern ptr_t __libc_ia64_register_backing_store_base;
1013 GC_INNER ptr_t GC_get_register_stack_base(void)
1017 # ifdef USE_LIBC_PRIVATES
1018 if (0 != &__libc_ia64_register_backing_store_base
1019 && 0 != __libc_ia64_register_backing_store_base) {
1020 /* Glibc 2.2.4 has a bug such that for dynamically linked */
1021 /* executables __libc_ia64_register_backing_store_base is */
1022 /* defined but uninitialized during constructor calls. */
1023 /* Hence we check for both nonzero address and value. */
1024 return __libc_ia64_register_backing_store_base;
1027 result = backing_store_base_from_proc();
1029 result = GC_find_limit(GC_save_regs_in_stack(), FALSE);
1030 /* Now seems to work better than constant displacement */
1031 /* heuristic used in 6.X versions. The latter seems to */
1032 /* fail for 2.6 kernels. */
1038 STATIC ptr_t GC_linux_main_stack_base(void)
1040 /* We read the stack base value from /proc/self/stat. We do this */
1041 /* using direct I/O system calls in order to avoid calling malloc */
1042 /* in case REDIRECT_MALLOC is defined. */
1044 /* Also defined in pthread_support.c. */
1045 # define STAT_BUF_SIZE 4096
1046 # define STAT_READ read
1048 /* Should probably call the real read, if read is wrapped. */
1049 char stat_buf[STAT_BUF_SIZE];
1052 int i, buf_offset = 0, len;
1054 /* First try the easy way. This should work for glibc 2.2 */
1055 /* This fails in a prelinked ("prelink" command) executable */
1056 /* since the correct value of __libc_stack_end never */
1057 /* becomes visible to us. The second test works around */
1059 # ifdef USE_LIBC_PRIVATES
1060 if (0 != &__libc_stack_end && 0 != __libc_stack_end ) {
1062 /* Some versions of glibc set the address 16 bytes too */
1063 /* low while the initialization code is running. */
1064 if (((word)__libc_stack_end & 0xfff) + 0x10 < 0x1000) {
1065 return __libc_stack_end + 0x10;
1066 } /* Otherwise it's not safe to add 16 bytes and we fall */
1067 /* back to using /proc. */
1068 # elif defined(SPARC)
1069 /* Older versions of glibc for 64-bit Sparc do not set
1070 * this variable correctly, it gets set to either zero
1073 if (__libc_stack_end != (ptr_t) (unsigned long)0x1)
1074 return __libc_stack_end;
1076 return __libc_stack_end;
1080 f = open("/proc/self/stat", O_RDONLY);
1082 ABORT("Couldn't read /proc/self/stat");
1083 len = STAT_READ(f, stat_buf, STAT_BUF_SIZE);
1086 /* Skip the required number of fields. This number is hopefully */
1087 /* constant across all Linux implementations. */
1088 for (i = 0; i < STAT_SKIP; ++i) {
1089 while (buf_offset < len && isspace(stat_buf[buf_offset++])) {
1092 while (buf_offset < len && !isspace(stat_buf[buf_offset++])) {
1097 while (buf_offset < len && isspace(stat_buf[buf_offset])) {
1100 /* Find the end of the number and cut the buffer there. */
1101 for (i = 0; buf_offset + i < len; i++) {
1102 if (!isdigit(stat_buf[buf_offset + i])) break;
1104 if (buf_offset + i >= len) ABORT("Could not parse /proc/self/stat");
1105 stat_buf[buf_offset + i] = '\0';
1107 result = (word)STRTOULL(&stat_buf[buf_offset], NULL, 10);
1108 if (result < 0x100000 || (result & (sizeof(word) - 1)) != 0)
1109 ABORT("Absurd stack bottom value");
1110 return (ptr_t)result;
1112 #endif /* LINUX_STACKBOTTOM */
1114 #ifdef FREEBSD_STACKBOTTOM
1115 /* This uses an undocumented sysctl call, but at least one expert */
1116 /* believes it will stay. */
1118 # include <unistd.h>
1119 # include <sys/types.h>
1120 # include <sys/sysctl.h>
1122 STATIC ptr_t GC_freebsd_main_stack_base(void)
1124 int nm[2] = {CTL_KERN, KERN_USRSTACK};
1126 size_t len = sizeof(ptr_t);
1127 int r = sysctl(nm, 2, &base, &len, NULL, 0);
1128 if (r) ABORT("Error getting main stack base");
1131 #endif /* FREEBSD_STACKBOTTOM */
1133 #if defined(ECOS) || defined(NOSYS)
1134 ptr_t GC_get_main_stack_base(void)
1138 # define GET_MAIN_STACKBASE_SPECIAL
1139 #elif !defined(BEOS) && !defined(AMIGA) && !defined(OS2) \
1140 && !defined(MSWIN32) && !defined(MSWINCE) && !defined(CYGWIN32) \
1141 && !defined(GC_OPENBSD_THREADS) \
1142 && (!defined(GC_SOLARIS_THREADS) || defined(_STRICT_STDC))
1144 # if defined(LINUX) && defined(USE_GET_STACKBASE_FOR_MAIN)
1145 # include <pthread.h>
1146 # elif defined(DARWIN) && !defined(NO_PTHREAD_GET_STACKADDR_NP)
1147 /* We could use pthread_get_stackaddr_np even in case of a */
1148 /* single-threaded gclib (there is no -lpthread on Darwin). */
1149 # include <pthread.h>
1151 # define STACKBOTTOM (ptr_t)pthread_get_stackaddr_np(pthread_self())
1154 ptr_t GC_get_main_stack_base(void)
1157 # if defined(LINUX) && !defined(NACL) \
1158 && (defined(USE_GET_STACKBASE_FOR_MAIN) \
1159 || (defined(THREADS) && !defined(REDIRECT_MALLOC)))
1160 pthread_attr_t attr;
1164 if (pthread_getattr_np(pthread_self(), &attr) == 0) {
1165 if (pthread_attr_getstack(&attr, &stackaddr, &size) == 0
1166 && stackaddr != NULL) {
1167 pthread_attr_destroy(&attr);
1168 # ifdef STACK_GROWS_DOWN
1169 stackaddr = (char *)stackaddr + size;
1171 return (ptr_t)stackaddr;
1173 pthread_attr_destroy(&attr);
1175 WARN("pthread_getattr_np or pthread_attr_getstack failed"
1176 " for main thread\n", 0);
1179 result = STACKBOTTOM;
1181 # define STACKBOTTOM_ALIGNMENT_M1 ((word)STACK_GRAN - 1)
1183 # ifdef STACK_GROWS_DOWN
1184 result = (ptr_t)(((word)GC_approx_sp() + STACKBOTTOM_ALIGNMENT_M1)
1185 & ~STACKBOTTOM_ALIGNMENT_M1);
1187 result = (ptr_t)((word)GC_approx_sp() & ~STACKBOTTOM_ALIGNMENT_M1);
1189 # endif /* HEURISTIC1 */
1190 # ifdef LINUX_STACKBOTTOM
1191 result = GC_linux_main_stack_base();
1193 # ifdef FREEBSD_STACKBOTTOM
1194 result = GC_freebsd_main_stack_base();
1198 ptr_t sp = GC_approx_sp();
1199 # ifdef STACK_GROWS_DOWN
1200 result = GC_find_limit(sp, TRUE);
1201 # ifdef HEURISTIC2_LIMIT
1202 if (result > HEURISTIC2_LIMIT
1203 && sp < HEURISTIC2_LIMIT) {
1204 result = HEURISTIC2_LIMIT;
1208 result = GC_find_limit(sp, FALSE);
1209 # ifdef HEURISTIC2_LIMIT
1210 if (result < HEURISTIC2_LIMIT
1211 && sp > HEURISTIC2_LIMIT) {
1212 result = HEURISTIC2_LIMIT;
1217 # endif /* HEURISTIC2 */
1218 # ifdef STACK_GROWS_DOWN
1220 result = (ptr_t)(signed_word)(-sizeof(ptr_t));
1223 GC_ASSERT(GC_approx_sp() HOTTER_THAN result);
1226 # define GET_MAIN_STACKBASE_SPECIAL
1227 #endif /* !AMIGA, !BEOS, !OPENBSD, !OS2, !Windows */
1229 #if (defined(GC_LINUX_THREADS) || defined(PLATFORM_ANDROID)) && !defined(NACL)
1231 # include <pthread.h>
1232 /* extern int pthread_getattr_np(pthread_t, pthread_attr_t *); */
1234 GC_API int GC_CALL GC_get_stack_base(struct GC_stack_base *b)
1236 pthread_attr_t attr;
1242 if (pthread_getattr_np(pthread_self(), &attr) != 0) {
1243 WARN("pthread_getattr_np failed\n", 0);
1244 return GC_UNIMPLEMENTED;
1246 if (pthread_attr_getstack(&attr, &(b -> mem_base), &size) != 0) {
1247 ABORT("pthread_attr_getstack failed");
1249 pthread_attr_destroy(&attr);
1250 # ifdef STACK_GROWS_DOWN
1251 b -> mem_base = (char *)(b -> mem_base) + size;
1254 /* We could try backing_store_base_from_proc, but that's safe */
1255 /* only if no mappings are being asynchronously created. */
1256 /* Subtracting the size from the stack base doesn't work for at */
1257 /* least the main thread. */
1260 IF_CANCEL(int cancel_state;)
1264 DISABLE_CANCEL(cancel_state);
1265 bsp = GC_save_regs_in_stack();
1266 next_stack = GC_greatest_stack_base_below(bsp);
1267 if (0 == next_stack) {
1268 b -> reg_base = GC_find_limit(bsp, FALSE);
1270 /* Avoid walking backwards into preceding memory stack and */
1272 b -> reg_base = GC_find_limit_with_bound(bsp, FALSE, next_stack);
1274 RESTORE_CANCEL(cancel_state);
1280 # define HAVE_GET_STACK_BASE
1281 #endif /* GC_LINUX_THREADS */
1283 #if defined(GC_DARWIN_THREADS) && !defined(NO_PTHREAD_GET_STACKADDR_NP)
1284 # include <pthread.h>
1286 GC_API int GC_CALL GC_get_stack_base(struct GC_stack_base *b)
1288 /* pthread_get_stackaddr_np() should return stack bottom (highest */
1289 /* stack address plus 1). */
1290 b->mem_base = pthread_get_stackaddr_np(pthread_self());
1291 GC_ASSERT((void *)GC_approx_sp() HOTTER_THAN b->mem_base);
1294 # define HAVE_GET_STACK_BASE
1295 #endif /* GC_DARWIN_THREADS */
1297 #ifdef GC_OPENBSD_THREADS
1298 # include <sys/signal.h>
1299 # include <pthread.h>
1300 # include <pthread_np.h>
1302 /* Find the stack using pthread_stackseg_np(). */
1303 GC_API int GC_CALL GC_get_stack_base(struct GC_stack_base *sb)
1306 if (pthread_stackseg_np(pthread_self(), &stack))
1307 ABORT("pthread_stackseg_np(self) failed");
1308 sb->mem_base = stack.ss_sp;
1311 # define HAVE_GET_STACK_BASE
1312 #endif /* GC_OPENBSD_THREADS */
1314 #if defined(GC_SOLARIS_THREADS) && !defined(_STRICT_STDC)
1316 # include <thread.h>
1317 # include <signal.h>
1318 # include <pthread.h>
1320 /* These variables are used to cache ss_sp value for the primordial */
1321 /* thread (it's better not to call thr_stksegment() twice for this */
1322 /* thread - see JDK bug #4352906). */
1323 static pthread_t stackbase_main_self = 0;
1324 /* 0 means stackbase_main_ss_sp value is unset. */
1325 static void *stackbase_main_ss_sp = NULL;
1327 GC_API int GC_CALL GC_get_stack_base(struct GC_stack_base *b)
1330 pthread_t self = pthread_self();
1332 if (self == stackbase_main_self)
1334 /* If the client calls GC_get_stack_base() from the main thread */
1335 /* then just return the cached value. */
1336 b -> mem_base = stackbase_main_ss_sp;
1337 GC_ASSERT(b -> mem_base != NULL);
1341 if (thr_stksegment(&s)) {
1342 /* According to the manual, the only failure error code returned */
1343 /* is EAGAIN meaning "the information is not available due to the */
1344 /* thread is not yet completely initialized or it is an internal */
1345 /* thread" - this shouldn't happen here. */
1346 ABORT("thr_stksegment failed");
1348 /* s.ss_sp holds the pointer to the stack bottom. */
1349 GC_ASSERT((void *)GC_approx_sp() HOTTER_THAN s.ss_sp);
1351 if (!stackbase_main_self && thr_main() != 0)
1353 /* Cache the stack base value for the primordial thread (this */
1354 /* is done during GC_init, so there is no race). */
1355 stackbase_main_ss_sp = s.ss_sp;
1356 stackbase_main_self = self;
1359 b -> mem_base = s.ss_sp;
1362 # define HAVE_GET_STACK_BASE
1363 #endif /* GC_SOLARIS_THREADS */
1365 #ifdef GC_RTEMS_PTHREADS
1366 GC_API int GC_CALL GC_get_stack_base(struct GC_stack_base *sb)
1368 sb->mem_base = rtems_get_stack_bottom();
1371 # define HAVE_GET_STACK_BASE
1372 #endif /* GC_RTEMS_PTHREADS */
1374 #ifndef HAVE_GET_STACK_BASE
1375 /* Retrieve stack base. */
1376 /* Using the GC_find_limit version is risky. */
1377 /* On IA64, for example, there is no guard page between the */
1378 /* stack of one thread and the register backing store of the */
1379 /* next. Thus this is likely to identify way too large a */
1380 /* "stack" and thus at least result in disastrous performance. */
1381 /* FIXME - Implement better strategies here. */
1382 GC_API int GC_CALL GC_get_stack_base(struct GC_stack_base *b)
1384 # ifdef NEED_FIND_LIMIT
1385 IF_CANCEL(int cancel_state;)
1389 DISABLE_CANCEL(cancel_state); /* May be unnecessary? */
1390 # ifdef STACK_GROWS_DOWN
1391 b -> mem_base = GC_find_limit(GC_approx_sp(), TRUE);
1393 b -> reg_base = GC_find_limit(GC_save_regs_in_stack(), FALSE);
1396 b -> mem_base = GC_find_limit(GC_approx_sp(), FALSE);
1398 RESTORE_CANCEL(cancel_state);
1402 return GC_UNIMPLEMENTED;
1405 #endif /* !HAVE_GET_STACK_BASE */
1407 #ifndef GET_MAIN_STACKBASE_SPECIAL
1408 /* This is always called from the main thread. Default implementation. */
1409 ptr_t GC_get_main_stack_base(void)
1411 struct GC_stack_base sb;
1413 if (GC_get_stack_base(&sb) != GC_SUCCESS)
1414 ABORT("GC_get_stack_base failed");
1415 GC_ASSERT((void *)GC_approx_sp() HOTTER_THAN sb.mem_base);
1416 return (ptr_t)sb.mem_base;
1418 #endif /* !GET_MAIN_STACKBASE_SPECIAL */
1420 /* Register static data segment(s) as roots. If more data segments are */
1421 /* added later then they need to be registered at that point (as we do */
1422 /* with SunOS dynamic loading), or GC_mark_roots needs to check for */
1423 /* them (as we do with PCR). Called with allocator lock held. */
1426 void GC_register_data_segments(void)
1430 HMODULE module_handle;
1431 # define PBUFSIZ 512
1432 UCHAR path[PBUFSIZ];
1434 struct exe_hdr hdrdos; /* MSDOS header. */
1435 struct e32_exe hdr386; /* Real header for my executable */
1436 struct o32_obj seg; /* Currrent segment */
1440 if (DosGetInfoBlocks(&ptib, &ppib) != NO_ERROR) {
1441 ABORT("DosGetInfoBlocks failed");
1443 module_handle = ppib -> pib_hmte;
1444 if (DosQueryModuleName(module_handle, PBUFSIZ, path) != NO_ERROR) {
1445 GC_err_printf("DosQueryModuleName failed\n");
1446 ABORT("DosGetInfoBlocks failed");
1448 myexefile = fopen(path, "rb");
1449 if (myexefile == 0) {
1450 if (GC_print_stats) {
1451 GC_err_puts("Couldn't open executable ");
1455 ABORT("Failed to open executable");
1457 if (fread((char *)(&hdrdos), 1, sizeof(hdrdos), myexefile)
1459 if (GC_print_stats) {
1460 GC_err_puts("Couldn't read MSDOS header from ");
1464 ABORT("Couldn't read MSDOS header");
1466 if (E_MAGIC(hdrdos) != EMAGIC) {
1467 if (GC_print_stats) {
1468 GC_err_puts("Executable has wrong DOS magic number: ");
1472 ABORT("Bad DOS magic number");
1474 if (fseek(myexefile, E_LFANEW(hdrdos), SEEK_SET) != 0) {
1475 if (GC_print_stats) {
1476 GC_err_puts("Seek to new header failed in ");
1480 ABORT("Bad DOS magic number");
1482 if (fread((char *)(&hdr386), 1, sizeof(hdr386), myexefile)
1484 if (GC_print_stats) {
1485 GC_err_puts("Couldn't read MSDOS header from ");
1489 ABORT("Couldn't read OS/2 header");
1491 if (E32_MAGIC1(hdr386) != E32MAGIC1 || E32_MAGIC2(hdr386) != E32MAGIC2) {
1492 if (GC_print_stats) {
1493 GC_err_puts("Executable has wrong OS/2 magic number: ");
1497 ABORT("Bad OS/2 magic number");
1499 if (E32_BORDER(hdr386) != E32LEBO || E32_WORDER(hdr386) != E32LEWO) {
1500 if (GC_print_stats) {
1501 GC_err_puts("Executable has wrong byte order: ");
1505 ABORT("Bad byte order");
1507 if (E32_CPU(hdr386) == E32CPU286) {
1508 if (GC_print_stats) {
1509 GC_err_puts("GC can't handle 80286 executables: ");
1513 ABORT("Intel 80286 executables are unsupported");
1515 if (fseek(myexefile, E_LFANEW(hdrdos) + E32_OBJTAB(hdr386),
1517 if (GC_print_stats) {
1518 GC_err_puts("Seek to object table failed: ");
1522 ABORT("Seek to object table failed");
1524 for (nsegs = E32_OBJCNT(hdr386); nsegs > 0; nsegs--) {
1526 if (fread((char *)(&seg), 1, sizeof(seg), myexefile) < sizeof(seg)) {
1527 if (GC_print_stats) {
1528 GC_err_puts("Couldn't read obj table entry from ");
1532 ABORT("Couldn't read obj table entry");
1534 flags = O32_FLAGS(seg);
1535 if (!(flags & OBJWRITE)) continue;
1536 if (!(flags & OBJREAD)) continue;
1537 if (flags & OBJINVALID) {
1538 GC_err_printf("Object with invalid pages?\n");
1541 GC_add_roots_inner((ptr_t)O32_BASE(seg),
1542 (ptr_t)(O32_BASE(seg)+O32_SIZE(seg)), FALSE);
1548 # if defined(GWW_VDB)
1549 # ifndef MEM_WRITE_WATCH
1550 # define MEM_WRITE_WATCH 0x200000
1552 # ifndef WRITE_WATCH_FLAG_RESET
1553 # define WRITE_WATCH_FLAG_RESET 1
1556 /* Since we can't easily check whether ULONG_PTR and SIZE_T are */
1557 /* defined in Win32 basetsd.h, we define own ULONG_PTR. */
1558 # define GC_ULONG_PTR word
1560 typedef UINT (WINAPI * GetWriteWatch_type)(
1561 DWORD, PVOID, GC_ULONG_PTR /* SIZE_T */,
1562 PVOID *, GC_ULONG_PTR *, PULONG);
1563 static GetWriteWatch_type GetWriteWatch_func;
1564 static DWORD GetWriteWatch_alloc_flag;
1566 # define GC_GWW_AVAILABLE() (GetWriteWatch_func != NULL)
1568 static void detect_GetWriteWatch(void)
1570 static GC_bool done;
1575 # if defined(MPROTECT_VDB)
1577 char * str = GETENV("GC_USE_GETWRITEWATCH");
1578 # if defined(GC_PREFER_MPROTECT_VDB)
1579 if (str == NULL || (*str == '0' && *(str + 1) == '\0')) {
1580 /* GC_USE_GETWRITEWATCH is unset or set to "0". */
1581 done = TRUE; /* falling back to MPROTECT_VDB strategy. */
1582 /* This should work as if GWW_VDB is undefined. */
1586 if (str != NULL && *str == '0' && *(str + 1) == '\0') {
1587 /* GC_USE_GETWRITEWATCH is set "0". */
1588 done = TRUE; /* falling back to MPROTECT_VDB strategy. */
1595 hK32 = GetModuleHandle(TEXT("kernel32.dll"));
1596 if (hK32 != (HMODULE)0 &&
1597 (GetWriteWatch_func = (GetWriteWatch_type)GetProcAddress(hK32,
1598 "GetWriteWatch")) != NULL) {
1599 /* Also check whether VirtualAlloc accepts MEM_WRITE_WATCH, */
1600 /* as some versions of kernel32.dll have one but not the */
1601 /* other, making the feature completely broken. */
1602 void * page = VirtualAlloc(NULL, GC_page_size,
1603 MEM_WRITE_WATCH | MEM_RESERVE,
1607 GC_ULONG_PTR count = 16;
1609 /* Check that it actually works. In spite of some */
1610 /* documentation it actually seems to exist on W2K. */
1611 /* This test may be unnecessary, but ... */
1612 if (GetWriteWatch_func(WRITE_WATCH_FLAG_RESET,
1617 /* GetWriteWatch always fails. */
1618 GetWriteWatch_func = NULL;
1620 GetWriteWatch_alloc_flag = MEM_WRITE_WATCH;
1622 VirtualFree(page, GC_page_size, MEM_RELEASE);
1624 /* GetWriteWatch will be useless. */
1625 GetWriteWatch_func = NULL;
1628 if (GC_print_stats) {
1629 if (GetWriteWatch_func == NULL) {
1630 GC_log_printf("Did not find a usable GetWriteWatch()\n");
1632 GC_log_printf("Using GetWriteWatch()\n");
1639 # define GetWriteWatch_alloc_flag 0
1640 # endif /* !GWW_VDB */
1642 # if defined(MSWIN32) || defined(MSWINCE) || defined(CYGWIN32)
1645 /* Unfortunately, we have to handle win32s very differently from NT, */
1646 /* Since VirtualQuery has very different semantics. In particular, */
1647 /* under win32s a VirtualQuery call on an unmapped page returns an */
1648 /* invalid result. Under NT, GC_register_data_segments is a no-op */
1649 /* and all real work is done by GC_register_dynamic_libraries. Under */
1650 /* win32s, we cannot find the data segments associated with dll's. */
1651 /* We register the main data segment here. */
1652 GC_INNER GC_bool GC_no_win32_dlls = FALSE;
1653 /* This used to be set for gcc, to avoid dealing with */
1654 /* the structured exception handling issues. But we now have */
1655 /* assembly code to do that right. */
1657 GC_INNER GC_bool GC_wnt = FALSE;
1658 /* This is a Windows NT derivative, i.e. NT, W2K, XP or later. */
1660 GC_INNER void GC_init_win32(void)
1662 /* Set GC_wnt. If we're running under win32s, assume that no DLLs */
1663 /* will be loaded. I doubt anyone still runs win32s, but... */
1664 DWORD v = GetVersion();
1665 GC_wnt = !(v & 0x80000000);
1666 GC_no_win32_dlls |= ((!GC_wnt) && (v & 0xff) <= 3);
1668 if (GC_no_win32_dlls) {
1669 /* Turn off unmapping for safety (since may not work well with */
1671 GC_unmap_threshold = 0;
1676 /* Return the smallest address a such that VirtualQuery */
1677 /* returns correct results for all addresses between a and start. */
1678 /* Assumes VirtualQuery returns correct information for start. */
1679 STATIC ptr_t GC_least_described_address(ptr_t start)
1681 MEMORY_BASIC_INFORMATION buf;
1687 limit = GC_sysinfo.lpMinimumApplicationAddress;
1688 p = (ptr_t)((word)start & ~(GC_page_size - 1));
1690 q = (LPVOID)(p - GC_page_size);
1691 if ((ptr_t)q > (ptr_t)p /* underflow */ || q < limit) break;
1692 result = VirtualQuery(q, &buf, sizeof(buf));
1693 if (result != sizeof(buf) || buf.AllocationBase == 0) break;
1694 p = (ptr_t)(buf.AllocationBase);
1698 # endif /* MSWIN32 */
1700 # ifndef REDIRECT_MALLOC
1701 /* We maintain a linked list of AllocationBase values that we know */
1702 /* correspond to malloc heap sections. Currently this is only called */
1703 /* during a GC. But there is some hope that for long running */
1704 /* programs we will eventually see most heap sections. */
1706 /* In the long run, it would be more reliable to occasionally walk */
1707 /* the malloc heap with HeapWalk on the default heap. But that */
1708 /* apparently works only for NT-based Windows. */
1710 STATIC size_t GC_max_root_size = 100000; /* Appr. largest root size. */
1713 /* In the long run, a better data structure would also be nice ... */
1714 STATIC struct GC_malloc_heap_list {
1715 void * allocation_base;
1716 struct GC_malloc_heap_list *next;
1717 } *GC_malloc_heap_l = 0;
1719 /* Is p the base of one of the malloc heap sections we already know */
1721 STATIC GC_bool GC_is_malloc_heap_base(ptr_t p)
1723 struct GC_malloc_heap_list *q = GC_malloc_heap_l;
1726 if (q -> allocation_base == p) return TRUE;
1732 STATIC void *GC_get_allocation_base(void *p)
1734 MEMORY_BASIC_INFORMATION buf;
1735 size_t result = VirtualQuery(p, &buf, sizeof(buf));
1736 if (result != sizeof(buf)) {
1737 ABORT("Weird VirtualQuery result");
1739 return buf.AllocationBase;
1742 GC_INNER void GC_add_current_malloc_heap(void)
1744 struct GC_malloc_heap_list *new_l =
1745 malloc(sizeof(struct GC_malloc_heap_list));
1746 void * candidate = GC_get_allocation_base(new_l);
1748 if (new_l == 0) return;
1749 if (GC_is_malloc_heap_base(candidate)) {
1750 /* Try a little harder to find malloc heap. */
1751 size_t req_size = 10000;
1753 void *p = malloc(req_size);
1758 candidate = GC_get_allocation_base(p);
1761 } while (GC_is_malloc_heap_base(candidate)
1762 && req_size < GC_max_root_size/10 && req_size < 500000);
1763 if (GC_is_malloc_heap_base(candidate)) {
1769 GC_log_printf("Found new system malloc AllocationBase at %p\n",
1771 new_l -> allocation_base = candidate;
1772 new_l -> next = GC_malloc_heap_l;
1773 GC_malloc_heap_l = new_l;
1775 # endif /* !CYGWIN32 */
1777 # endif /* !REDIRECT_MALLOC */
1779 STATIC word GC_n_heap_bases = 0; /* See GC_heap_bases. */
1781 /* Is p the start of either the malloc heap, or of one of our */
1782 /* heap sections? */
1783 GC_INNER GC_bool GC_is_heap_base(ptr_t p)
1786 # ifndef REDIRECT_MALLOC
1787 if (GC_root_size > GC_max_root_size) GC_max_root_size = GC_root_size;
1789 if (GC_is_malloc_heap_base(p)) return TRUE;
1792 for (i = 0; i < GC_n_heap_bases; i++) {
1793 if (GC_heap_bases[i] == p) return TRUE;
1799 STATIC void GC_register_root_section(ptr_t static_root)
1801 MEMORY_BASIC_INFORMATION buf;
1806 char * limit, * new_limit;
1808 if (!GC_no_win32_dlls) return;
1809 p = base = limit = GC_least_described_address(static_root);
1810 while (p < GC_sysinfo.lpMaximumApplicationAddress) {
1811 result = VirtualQuery(p, &buf, sizeof(buf));
1812 if (result != sizeof(buf) || buf.AllocationBase == 0
1813 || GC_is_heap_base(buf.AllocationBase)) break;
1814 new_limit = (char *)p + buf.RegionSize;
1815 protect = buf.Protect;
1816 if (buf.State == MEM_COMMIT
1817 && is_writable(protect)) {
1818 if ((char *)p == limit) {
1821 if (base != limit) GC_add_roots_inner(base, limit, FALSE);
1826 if (p > (LPVOID)new_limit /* overflow */) break;
1827 p = (LPVOID)new_limit;
1829 if (base != limit) GC_add_roots_inner(base, limit, FALSE);
1831 #endif /* MSWIN32 */
1833 void GC_register_data_segments(void)
1836 GC_register_root_section((ptr_t)&GC_pages_executable);
1837 /* any other GC global variable would fit too. */
1841 # else /* !OS2 && !Windows */
1843 # if (defined(SVR4) || defined(AUX) || defined(DGUX) \
1844 || (defined(LINUX) && defined(SPARC))) && !defined(PCR)
1845 ptr_t GC_SysVGetDataStart(size_t max_page_size, ptr_t etext_addr)
1847 word text_end = ((word)(etext_addr) + sizeof(word) - 1)
1848 & ~(sizeof(word) - 1);
1849 /* etext rounded to word boundary */
1850 word next_page = ((text_end + (word)max_page_size - 1)
1851 & ~((word)max_page_size - 1));
1852 word page_offset = (text_end & ((word)max_page_size - 1));
1853 char * volatile result = (char *)(next_page + page_offset);
1854 /* Note that this isn't equivalent to just adding */
1855 /* max_page_size to &etext if &etext is at a page boundary */
1857 GC_setup_temporary_fault_handler();
1858 if (SETJMP(GC_jmp_buf) == 0) {
1859 /* Try writing to the address. */
1861 GC_reset_fault_handler();
1863 GC_reset_fault_handler();
1864 /* We got here via a longjmp. The address is not readable. */
1865 /* This is known to happen under Solaris 2.4 + gcc, which place */
1866 /* string constants in the text segment, but after etext. */
1867 /* Use plan B. Note that we now know there is a gap between */
1868 /* text and data segments, so plan A bought us something. */
1869 result = (char *)GC_find_limit((ptr_t)(DATAEND), FALSE);
1871 return((ptr_t)result);
1875 # if defined(FREEBSD) && !defined(PCR) && (defined(I386) || defined(X86_64) \
1876 || defined(powerpc) || defined(__powerpc__))
1878 /* Its unclear whether this should be identical to the above, or */
1879 /* whether it should apply to non-X86 architectures. */
1880 /* For now we don't assume that there is always an empty page after */
1881 /* etext. But in some cases there actually seems to be slightly more. */
1882 /* This also deals with holes between read-only data and writable data. */
1883 ptr_t GC_FreeBSDGetDataStart(size_t max_page_size, ptr_t etext_addr)
1885 word text_end = ((word)(etext_addr) + sizeof(word) - 1)
1886 & ~(sizeof(word) - 1);
1887 /* etext rounded to word boundary */
1888 volatile word next_page = (text_end + (word)max_page_size - 1)
1889 & ~((word)max_page_size - 1);
1890 volatile ptr_t result = (ptr_t)text_end;
1891 GC_setup_temporary_fault_handler();
1892 if (SETJMP(GC_jmp_buf) == 0) {
1893 /* Try reading at the address. */
1894 /* This should happen before there is another thread. */
1895 for (; next_page < (word)(DATAEND); next_page += (word)max_page_size)
1896 *(volatile char *)next_page;
1897 GC_reset_fault_handler();
1899 GC_reset_fault_handler();
1900 /* As above, we go to plan B */
1901 result = GC_find_limit((ptr_t)(DATAEND), FALSE);
1906 # endif /* FREEBSD */
1911 # define GC_AMIGA_DS
1912 # include "extra/AmigaOS.c"
1915 #elif defined(OPENBSD)
1917 /* Depending on arch alignment, there can be multiple holes */
1918 /* between DATASTART and DATAEND. Scan in DATASTART .. DATAEND */
1919 /* and register each region. */
1920 void GC_register_data_segments(void)
1922 ptr_t region_start = DATASTART;
1926 region_end = GC_find_limit_openbsd(region_start, DATAEND);
1927 GC_add_roots_inner(region_start, region_end, FALSE);
1928 if (region_end >= DATAEND)
1930 region_start = GC_skip_hole_openbsd(region_end, DATAEND);
1934 # else /* !OS2 && !Windows && !AMIGA && !OPENBSD */
1936 void GC_register_data_segments(void)
1938 # if !defined(PCR) && !defined(MACOS)
1939 # if defined(REDIRECT_MALLOC) && defined(GC_SOLARIS_THREADS)
1940 /* As of Solaris 2.3, the Solaris threads implementation */
1941 /* allocates the data structure for the initial thread with */
1942 /* sbrk at process startup. It needs to be scanned, so that */
1943 /* we don't lose some malloc allocated data structures */
1944 /* hanging from it. We're on thin ice here ... */
1945 extern caddr_t sbrk(int);
1947 GC_add_roots_inner(DATASTART, (ptr_t)sbrk(0), FALSE);
1949 GC_add_roots_inner(DATASTART, (ptr_t)(DATAEND), FALSE);
1950 # if defined(DATASTART2)
1951 GC_add_roots_inner(DATASTART2, (ptr_t)(DATAEND2), FALSE);
1957 # if defined(THINK_C)
1958 extern void* GC_MacGetDataStart(void);
1959 /* globals begin above stack and end at a5. */
1960 GC_add_roots_inner((ptr_t)GC_MacGetDataStart(),
1961 (ptr_t)LMGetCurrentA5(), FALSE);
1963 # if defined(__MWERKS__)
1965 extern void* GC_MacGetDataStart(void);
1966 /* MATTHEW: Function to handle Far Globals (CW Pro 3) */
1967 # if __option(far_data)
1968 extern void* GC_MacGetDataEnd(void);
1970 /* globals begin above stack and end at a5. */
1971 GC_add_roots_inner((ptr_t)GC_MacGetDataStart(),
1972 (ptr_t)LMGetCurrentA5(), FALSE);
1973 /* MATTHEW: Handle Far Globals */
1974 # if __option(far_data)
1975 /* Far globals follow he QD globals: */
1976 GC_add_roots_inner((ptr_t)LMGetCurrentA5(),
1977 (ptr_t)GC_MacGetDataEnd(), FALSE);
1980 extern char __data_start__[], __data_end__[];
1981 GC_add_roots_inner((ptr_t)&__data_start__,
1982 (ptr_t)&__data_end__, FALSE);
1983 # endif /* __POWERPC__ */
1984 # endif /* __MWERKS__ */
1985 # endif /* !THINK_C */
1989 /* Dynamic libraries are added at every collection, since they may */
1993 # endif /* ! AMIGA */
1994 # endif /* ! MSWIN32 && ! MSWINCE*/
1998 * Auxiliary routines for obtaining memory from OS.
2001 # if !defined(OS2) && !defined(PCR) && !defined(AMIGA) && !defined(MSWIN32) \
2002 && !defined(MSWINCE) && !defined(MACOS) && !defined(DOS4GW) \
2003 && !defined(NONSTOP) && !defined(SN_TARGET_PS3) && !defined(RTEMS) \
2004 && !defined(__CC_ARM)
2006 # define SBRK_ARG_T ptrdiff_t
2008 #if defined(MMAP_SUPPORTED)
2010 #ifdef USE_MMAP_FIXED
2011 # define GC_MMAP_FLAGS MAP_FIXED | MAP_PRIVATE
2012 /* Seems to yield better performance on Solaris 2, but can */
2013 /* be unreliable if something is already mapped at the address. */
2015 # define GC_MMAP_FLAGS MAP_PRIVATE
2018 #ifdef USE_MMAP_ANON
2020 # if defined(MAP_ANONYMOUS)
2021 # define OPT_MAP_ANON MAP_ANONYMOUS
2023 # define OPT_MAP_ANON MAP_ANON
2027 # define OPT_MAP_ANON 0
2031 # define HEAP_START ((ptr_t)0)
2034 STATIC ptr_t GC_unix_mmap_get_mem(word bytes)
2037 static ptr_t last_addr = HEAP_START;
2039 # ifndef USE_MMAP_ANON
2040 static GC_bool initialized = FALSE;
2043 zero_fd = open("/dev/zero", O_RDONLY);
2044 fcntl(zero_fd, F_SETFD, FD_CLOEXEC);
2049 if (bytes & (GC_page_size - 1)) ABORT("Bad GET_MEM arg");
2050 result = mmap(last_addr, bytes, (PROT_READ | PROT_WRITE)
2051 | (GC_pages_executable ? PROT_EXEC : 0),
2052 GC_MMAP_FLAGS | OPT_MAP_ANON, zero_fd, 0/* offset */);
2053 # undef IGNORE_PAGES_EXECUTABLE
2055 if (result == MAP_FAILED) return(0);
2056 last_addr = (ptr_t)result + bytes + GC_page_size - 1;
2057 last_addr = (ptr_t)((word)last_addr & ~(GC_page_size - 1));
2058 # if !defined(LINUX)
2059 if (last_addr == 0) {
2060 /* Oops. We got the end of the address space. This isn't */
2061 /* usable by arbitrary C code, since one-past-end pointers */
2062 /* don't work, so we discard it and try again. */
2063 munmap(result, (size_t)(-GC_page_size) - (size_t)result);
2064 /* Leave last page mapped, so we can't repeat. */
2065 return GC_unix_mmap_get_mem(bytes);
2068 GC_ASSERT(last_addr != 0);
2070 return((ptr_t)result);
2073 # endif /* MMAP_SUPPORTED */
2075 #if defined(USE_MMAP)
2076 ptr_t GC_unix_get_mem(word bytes)
2078 return GC_unix_mmap_get_mem(bytes);
2080 #else /* !USE_MMAP */
2082 STATIC ptr_t GC_unix_sbrk_get_mem(word bytes)
2086 /* Bare sbrk isn't thread safe. Play by malloc rules. */
2087 /* The equivalent may be needed on other systems as well. */
2091 ptr_t cur_brk = (ptr_t)sbrk(0);
2092 SBRK_ARG_T lsbs = (word)cur_brk & (GC_page_size-1);
2094 if ((SBRK_ARG_T)bytes < 0) {
2095 result = 0; /* too big */
2099 if((ptr_t)sbrk(GC_page_size - lsbs) == (ptr_t)(-1)) {
2104 # ifdef ADD_HEAP_GUARD_PAGES
2105 /* This is useful for catching severe memory overwrite problems that */
2106 /* span heap sections. It shouldn't otherwise be turned on. */
2108 ptr_t guard = (ptr_t)sbrk((SBRK_ARG_T)GC_page_size);
2109 if (mprotect(guard, GC_page_size, PROT_NONE) != 0)
2110 ABORT("ADD_HEAP_GUARD_PAGES: mprotect failed");
2112 # endif /* ADD_HEAP_GUARD_PAGES */
2113 result = (ptr_t)sbrk((SBRK_ARG_T)bytes);
2114 if (result == (ptr_t)(-1)) result = 0;
2123 ptr_t GC_unix_get_mem(word bytes)
2125 # if defined(MMAP_SUPPORTED)
2126 /* By default, we try both sbrk and mmap, in that order. */
2127 static GC_bool sbrk_failed = FALSE;
2130 if (!sbrk_failed) result = GC_unix_sbrk_get_mem(bytes);
2133 result = GC_unix_mmap_get_mem(bytes);
2136 /* Try sbrk again, in case sbrk memory became available. */
2137 result = GC_unix_sbrk_get_mem(bytes);
2140 # else /* !MMAP_SUPPORTED */
2141 return GC_unix_sbrk_get_mem(bytes);
2145 #endif /* !USE_MMAP */
2151 void * os2_alloc(size_t bytes)
2155 if (DosAllocMem(&result, bytes, (PAG_READ | PAG_WRITE | PAG_COMMIT)
2156 | (GC_pages_executable ? PAG_EXECUTE : 0))
2160 /* FIXME: What's the purpose of this recursion? (Probably, if */
2161 /* DosAllocMem returns memory at 0 address then just retry once.) */
2162 if (result == 0) return(os2_alloc(bytes));
2168 # if defined(MSWIN32) || defined(MSWINCE) || defined(CYGWIN32)
2169 GC_INNER SYSTEM_INFO GC_sysinfo;
2174 # ifdef USE_GLOBAL_ALLOC
2175 # define GLOBAL_ALLOC_TEST 1
2177 # define GLOBAL_ALLOC_TEST GC_no_win32_dlls
2180 # ifdef GC_USE_MEM_TOP_DOWN
2181 STATIC DWORD GC_mem_top_down = MEM_TOP_DOWN;
2182 /* Use GC_USE_MEM_TOP_DOWN for better 64-bit */
2183 /* testing. Otherwise all addresses tend to */
2184 /* end up in first 4GB, hiding bugs. */
2186 STATIC DWORD GC_mem_top_down = 0;
2189 #endif /* MSWIN32 */
2191 #if defined(MSWIN32) || defined(CYGWIN32)
2192 ptr_t GC_win32_get_mem(word bytes)
2197 result = GC_unix_get_mem(bytes);
2199 if (GLOBAL_ALLOC_TEST) {
2200 /* VirtualAlloc doesn't like PAGE_EXECUTE_READWRITE. */
2201 /* There are also unconfirmed rumors of other */
2202 /* problems, so we dodge the issue. */
2203 result = (ptr_t) GlobalAlloc(0, bytes + HBLKSIZE);
2204 result = (ptr_t)(((word)result + HBLKSIZE - 1) & ~(HBLKSIZE-1));
2206 /* VirtualProtect only works on regions returned by a */
2207 /* single VirtualAlloc call. Thus we allocate one */
2208 /* extra page, which will prevent merging of blocks */
2209 /* in separate regions, and eliminate any temptation */
2210 /* to call VirtualProtect on a range spanning regions. */
2211 /* This wastes a small amount of memory, and risks */
2212 /* increased fragmentation. But better alternatives */
2213 /* would require effort. */
2214 # ifdef MPROTECT_VDB
2215 /* We can't check for GC_incremental here (because */
2216 /* GC_enable_incremental() might be called some time */
2217 /* later after the GC initialization). */
2219 # define VIRTUAL_ALLOC_PAD (GC_GWW_AVAILABLE() ? 0 : 1)
2221 # define VIRTUAL_ALLOC_PAD 1
2224 # define VIRTUAL_ALLOC_PAD 0
2226 /* Pass the MEM_WRITE_WATCH only if GetWriteWatch-based */
2227 /* VDBs are enabled and the GetWriteWatch function is */
2228 /* available. Otherwise we waste resources or possibly */
2229 /* cause VirtualAlloc to fail (observed in Windows 2000 */
2231 result = (ptr_t) VirtualAlloc(NULL, bytes + VIRTUAL_ALLOC_PAD,
2232 GetWriteWatch_alloc_flag
2233 | (MEM_COMMIT | MEM_RESERVE)
2235 GC_pages_executable ? PAGE_EXECUTE_READWRITE :
2237 # undef IGNORE_PAGES_EXECUTABLE
2239 # endif /* !CYGWIN32 */
2240 if (HBLKDISPL(result) != 0) ABORT("Bad VirtualAlloc result");
2241 /* If I read the documentation correctly, this can */
2242 /* only happen if HBLKSIZE > 64k or not a power of 2. */
2243 if (GC_n_heap_bases >= MAX_HEAP_SECTS) ABORT("Too many heap sections");
2244 if (0 != result) GC_heap_bases[GC_n_heap_bases++] = result;
2248 GC_API void GC_CALL GC_win32_free_heap(void)
2251 if (GC_no_win32_dlls)
2254 while (GC_n_heap_bases-- > 0) {
2256 /* FIXME: Is it ok to use non-GC free() here? */
2258 GlobalFree(GC_heap_bases[GC_n_heap_bases]);
2260 GC_heap_bases[GC_n_heap_bases] = 0;
2264 #endif /* MSWIN32 || CYGWIN32 */
2267 # define GC_AMIGA_AM
2268 # include "extra/AmigaOS.c"
2274 ptr_t GC_wince_get_mem(word bytes)
2276 ptr_t result = 0; /* initialized to prevent warning. */
2279 /* Round up allocation size to multiple of page size */
2280 bytes = (bytes + GC_page_size-1) & ~(GC_page_size-1);
2282 /* Try to find reserved, uncommitted pages */
2283 for (i = 0; i < GC_n_heap_bases; i++) {
2284 if (((word)(-(signed_word)GC_heap_lengths[i])
2285 & (GC_sysinfo.dwAllocationGranularity-1))
2287 result = GC_heap_bases[i] + GC_heap_lengths[i];
2292 if (i == GC_n_heap_bases) {
2293 /* Reserve more pages */
2294 word res_bytes = (bytes + GC_sysinfo.dwAllocationGranularity-1)
2295 & ~(GC_sysinfo.dwAllocationGranularity-1);
2296 /* If we ever support MPROTECT_VDB here, we will probably need to */
2297 /* ensure that res_bytes is strictly > bytes, so that VirtualProtect */
2298 /* never spans regions. It seems to be OK for a VirtualFree */
2299 /* argument to span regions, so we should be OK for now. */
2300 result = (ptr_t) VirtualAlloc(NULL, res_bytes,
2301 MEM_RESERVE | MEM_TOP_DOWN,
2302 GC_pages_executable ? PAGE_EXECUTE_READWRITE :
2304 if (HBLKDISPL(result) != 0) ABORT("Bad VirtualAlloc result");
2305 /* If I read the documentation correctly, this can */
2306 /* only happen if HBLKSIZE > 64k or not a power of 2. */
2307 if (GC_n_heap_bases >= MAX_HEAP_SECTS) ABORT("Too many heap sections");
2308 if (result == NULL) return NULL;
2309 GC_heap_bases[GC_n_heap_bases] = result;
2310 GC_heap_lengths[GC_n_heap_bases] = 0;
2315 result = (ptr_t) VirtualAlloc(result, bytes, MEM_COMMIT,
2316 GC_pages_executable ? PAGE_EXECUTE_READWRITE :
2318 # undef IGNORE_PAGES_EXECUTABLE
2320 if (result != NULL) {
2321 if (HBLKDISPL(result) != 0) ABORT("Bad VirtualAlloc result");
2322 GC_heap_lengths[i] += bytes;
2331 /* For now, this only works on Win32/WinCE and some Unix-like */
2332 /* systems. If you have something else, don't define */
2335 #if !defined(MSWIN32) && !defined(MSWINCE)
2338 #include <sys/mman.h>
2339 #include <sys/stat.h>
2340 #include <sys/types.h>
2344 /* Compute a page aligned starting address for the unmap */
2345 /* operation on a block of size bytes starting at start. */
2346 /* Return 0 if the block is too small to make this feasible. */
2347 STATIC ptr_t GC_unmap_start(ptr_t start, size_t bytes)
2350 /* Round start to next page boundary. */
2351 result = (ptr_t)((word)(start + GC_page_size - 1) & ~(GC_page_size - 1));
2352 if (result + GC_page_size > start + bytes) return 0;
2356 /* Compute end address for an unmap operation on the indicated */
2358 STATIC ptr_t GC_unmap_end(ptr_t start, size_t bytes)
2360 return (ptr_t)((word)(start + bytes) & ~(GC_page_size - 1));
2363 /* Under Win32/WinCE we commit (map) and decommit (unmap) */
2364 /* memory using VirtualAlloc and VirtualFree. These functions */
2365 /* work on individual allocations of virtual memory, made */
2366 /* previously using VirtualAlloc with the MEM_RESERVE flag. */
2367 /* The ranges we need to (de)commit may span several of these */
2368 /* allocations; therefore we use VirtualQuery to check */
2369 /* allocation lengths, and split up the range as necessary. */
2371 /* We assume that GC_remap is called on exactly the same range */
2372 /* as a previous call to GC_unmap. It is safe to consistently */
2373 /* round the endpoints in both places. */
2374 GC_INNER void GC_unmap(ptr_t start, size_t bytes)
2376 ptr_t start_addr = GC_unmap_start(start, bytes);
2377 ptr_t end_addr = GC_unmap_end(start, bytes);
2378 word len = end_addr - start_addr;
2379 if (0 == start_addr) return;
2380 # if defined(MSWIN32) || defined(MSWINCE)
2382 MEMORY_BASIC_INFORMATION mem_info;
2384 if (VirtualQuery(start_addr, &mem_info, sizeof(mem_info))
2385 != sizeof(mem_info))
2386 ABORT("Weird VirtualQuery result");
2387 free_len = (len < mem_info.RegionSize) ? len : mem_info.RegionSize;
2388 if (!VirtualFree(start_addr, free_len, MEM_DECOMMIT))
2389 ABORT("VirtualFree failed");
2390 GC_unmapped_bytes += free_len;
2391 start_addr += free_len;
2395 /* We immediately remap it to prevent an intervening mmap from */
2396 /* accidentally grabbing the same address space. */
2399 result = mmap(start_addr, len, PROT_NONE,
2400 MAP_PRIVATE | MAP_FIXED | OPT_MAP_ANON,
2401 zero_fd, 0/* offset */);
2402 if (result != (void *)start_addr)
2403 ABORT("mmap(PROT_NONE) failed");
2405 GC_unmapped_bytes += len;
2409 GC_INNER void GC_remap(ptr_t start, size_t bytes)
2411 ptr_t start_addr = GC_unmap_start(start, bytes);
2412 ptr_t end_addr = GC_unmap_end(start, bytes);
2413 word len = end_addr - start_addr;
2415 /* FIXME: Handle out-of-memory correctly (at least for Win32) */
2416 # if defined(MSWIN32) || defined(MSWINCE)
2419 if (0 == start_addr) return;
2421 MEMORY_BASIC_INFORMATION mem_info;
2423 if (VirtualQuery(start_addr, &mem_info, sizeof(mem_info))
2424 != sizeof(mem_info))
2425 ABORT("Weird VirtualQuery result");
2426 alloc_len = (len < mem_info.RegionSize) ? len : mem_info.RegionSize;
2427 result = VirtualAlloc(start_addr, alloc_len, MEM_COMMIT,
2428 GC_pages_executable ? PAGE_EXECUTE_READWRITE :
2430 if (result != start_addr) {
2431 if (GetLastError() == ERROR_NOT_ENOUGH_MEMORY ||
2432 GetLastError() == ERROR_OUTOFMEMORY) {
2433 ABORT("Not enough memory to process remapping");
2435 ABORT("VirtualAlloc remapping failed");
2438 GC_unmapped_bytes -= alloc_len;
2439 start_addr += alloc_len;
2443 /* It was already remapped with PROT_NONE. */
2445 if (0 == start_addr) return;
2448 result = mprotect(start_addr, len, (PROT_READ | PROT_WRITE)
2449 | (GC_pages_executable ? PROT_EXEC : 0));
2452 /* NaCl does not expose mprotect, but mmap should work fine. */
2453 void *mmap_result = mmap(start_addr, len, (PROT_READ | PROT_WRITE)
2454 | (GC_pages_executable ? PROT_EXEC : 0),
2455 MAP_PRIVATE | MAP_FIXED | OPT_MAP_ANON,
2456 zero_fd, 0 /* offset */);
2457 if (mmap_result != (void *)start_addr)
2458 ABORT("mmap as mprotect failed");
2459 /* Fake the return value as if mprotect succeeded. */
2463 # undef IGNORE_PAGES_EXECUTABLE
2467 GC_log_printf("Mprotect failed at %p (length %lu) with errno %d\n",
2468 start_addr, (unsigned long)len, errno);
2469 ABORT("mprotect remapping failed");
2471 GC_unmapped_bytes -= len;
2475 /* Two adjacent blocks have already been unmapped and are about to */
2476 /* be merged. Unmap the whole block. This typically requires */
2477 /* that we unmap a small section in the middle that was not previously */
2478 /* unmapped due to alignment constraints. */
2479 GC_INNER void GC_unmap_gap(ptr_t start1, size_t bytes1, ptr_t start2,
2482 ptr_t start1_addr = GC_unmap_start(start1, bytes1);
2483 ptr_t end1_addr = GC_unmap_end(start1, bytes1);
2484 ptr_t start2_addr = GC_unmap_start(start2, bytes2);
2485 ptr_t start_addr = end1_addr;
2486 ptr_t end_addr = start2_addr;
2488 GC_ASSERT(start1 + bytes1 == start2);
2489 if (0 == start1_addr) start_addr = GC_unmap_start(start1, bytes1 + bytes2);
2490 if (0 == start2_addr) end_addr = GC_unmap_end(start1, bytes1 + bytes2);
2491 if (0 == start_addr) return;
2492 len = end_addr - start_addr;
2493 # if defined(MSWIN32) || defined(MSWINCE)
2495 MEMORY_BASIC_INFORMATION mem_info;
2497 if (VirtualQuery(start_addr, &mem_info, sizeof(mem_info))
2498 != sizeof(mem_info))
2499 ABORT("Weird VirtualQuery result");
2500 free_len = (len < mem_info.RegionSize) ? len : mem_info.RegionSize;
2501 if (!VirtualFree(start_addr, free_len, MEM_DECOMMIT))
2502 ABORT("VirtualFree failed");
2503 GC_unmapped_bytes += free_len;
2504 start_addr += free_len;
2509 /* Immediately remap as above. */
2511 result = mmap(start_addr, len, PROT_NONE,
2512 MAP_PRIVATE | MAP_FIXED | OPT_MAP_ANON,
2513 zero_fd, 0/* offset */);
2514 if (result != (void *)start_addr)
2515 ABORT("mmap(PROT_NONE) failed");
2517 GC_unmapped_bytes += len;
2521 #endif /* USE_MUNMAP */
2523 /* Routine for pushing any additional roots. In THREADS */
2524 /* environment, this is also responsible for marking from */
2525 /* thread stacks. */
2527 void (*GC_push_other_roots)(void) = 0;
2531 PCR_ERes GC_push_thread_stack(PCR_Th_T *t, PCR_Any dummy)
2533 struct PCR_ThCtl_TInfoRep info;
2536 info.ti_stkLow = info.ti_stkHi = 0;
2537 result = PCR_ThCtl_GetInfo(t, &info);
2538 GC_push_all_stack((ptr_t)(info.ti_stkLow), (ptr_t)(info.ti_stkHi));
2542 /* Push the contents of an old object. We treat this as stack */
2543 /* data only because that makes it robust against mark stack */
2545 PCR_ERes GC_push_old_obj(void *p, size_t size, PCR_Any data)
2547 GC_push_all_stack((ptr_t)p, (ptr_t)p + size);
2548 return(PCR_ERes_okay);
2551 extern struct PCR_MM_ProcsRep * GC_old_allocator;
2552 /* defined in pcr_interface.c. */
2554 STATIC void GC_default_push_other_roots(void)
2556 /* Traverse data allocated by previous memory managers. */
2557 if ((*(GC_old_allocator->mmp_enumerate))(PCR_Bool_false,
2560 ABORT("Old object enumeration failed");
2562 /* Traverse all thread stacks. */
2564 PCR_ThCtl_ApplyToAllOtherThreads(GC_push_thread_stack,0))
2565 || PCR_ERes_IsErr(GC_push_thread_stack(PCR_Th_CurrThread(), 0))) {
2566 ABORT("Thread stack marking failed");
2572 # if defined(GC_PTHREADS) || defined(GC_WIN32_THREADS)
2573 STATIC void GC_default_push_other_roots(void)
2575 GC_push_all_stacks();
2577 # endif /* GC_WIN32_THREADS || GC_PTHREADS */
2579 # ifdef SN_TARGET_PS3
2580 STATIC void GC_default_push_other_roots(void)
2582 ABORT("GC_default_push_other_roots is not implemented");
2585 void GC_push_thread_structures(void)
2587 ABORT("GC_push_thread_structures is not implemented");
2589 # endif /* SN_TARGET_PS3 */
2591 void (*GC_push_other_roots)(void) = GC_default_push_other_roots;
2592 #endif /* THREADS */
2595 * Routines for accessing dirty bits on virtual pages.
2596 * There are six ways to maintain this information:
2597 * DEFAULT_VDB: A simple dummy implementation that treats every page
2598 * as possibly dirty. This makes incremental collection
2599 * useless, but the implementation is still correct.
2600 * MANUAL_VDB: Stacks and static data are always considered dirty.
2601 * Heap pages are considered dirty if GC_dirty(p) has been
2602 * called on some pointer p pointing to somewhere inside
2603 * an object on that page. A GC_dirty() call on a large
2604 * object directly dirties only a single page, but for
2605 * MANUAL_VDB we are careful to treat an object with a dirty
2606 * page as completely dirty.
2607 * In order to avoid races, an object must be marked dirty
2608 * after it is written, and a reference to the object
2609 * must be kept on a stack or in a register in the interim.
2610 * With threads enabled, an object directly reachable from the
2611 * stack at the time of a collection is treated as dirty.
2612 * In single-threaded mode, it suffices to ensure that no
2613 * collection can take place between the pointer assignment
2614 * and the GC_dirty() call.
2615 * PCR_VDB: Use PPCRs virtual dirty bit facility.
2616 * PROC_VDB: Use the /proc facility for reading dirty bits. Only
2617 * works under some SVR4 variants. Even then, it may be
2618 * too slow to be entirely satisfactory. Requires reading
2619 * dirty bits for entire address space. Implementations tend
2620 * to assume that the client is a (slow) debugger.
2621 * MPROTECT_VDB:Protect pages and then catch the faults to keep track of
2622 * dirtied pages. The implementation (and implementability)
2623 * is highly system dependent. This usually fails when system
2624 * calls write to a protected page. We prevent the read system
2625 * call from doing so. It is the clients responsibility to
2626 * make sure that other system calls are similarly protected
2627 * or write only to the stack.
2628 * GWW_VDB: Use the Win32 GetWriteWatch functions, if available, to
2629 * read dirty bits. In case it is not available (because we
2630 * are running on Windows 95, Windows 2000 or earlier),
2631 * MPROTECT_VDB may be defined as a fallback strategy.
2633 #ifndef GC_DISABLE_INCREMENTAL
2634 GC_INNER GC_bool GC_dirty_maintained = FALSE;
2637 #if defined(PROC_VDB) || defined(GWW_VDB)
2638 /* Add all pages in pht2 to pht1 */
2639 STATIC void GC_or_pages(page_hash_table pht1, page_hash_table pht2)
2641 register unsigned i;
2642 for (i = 0; i < PHT_SIZE; i++) pht1[i] |= pht2[i];
2645 # ifdef MPROTECT_VDB
2646 STATIC GC_bool GC_gww_page_was_dirty(struct hblk * h)
2648 GC_INNER GC_bool GC_page_was_dirty(struct hblk * h)
2651 register word index;
2654 index = PHT_HASH(h);
2655 return get_pht_entry_from_index(GC_grungy_pages, index);
2658 # if defined(CHECKSUMS) || defined(PROC_VDB)
2659 /* Used only if GWW_VDB. */
2660 # ifdef MPROTECT_VDB
2661 STATIC GC_bool GC_gww_page_was_ever_dirty(struct hblk * h)
2663 GC_INNER GC_bool GC_page_was_ever_dirty(struct hblk * h)
2666 register word index;
2669 index = PHT_HASH(h);
2670 return get_pht_entry_from_index(GC_written_pages, index);
2672 # endif /* CHECKSUMS || PROC_VDB */
2674 # ifndef MPROTECT_VDB
2675 /* Ignore write hints. They don't help us here. */
2677 GC_INNER void GC_remove_protection(struct hblk *h, word nblocks,
2678 GC_bool is_ptrfree) {}
2681 #endif /* PROC_VDB || GWW_VDB */
2685 # define GC_GWW_BUF_LEN (MAXHINCR * HBLKSIZE / 4096 /* X86 page size */)
2686 /* Still susceptible to overflow, if there are very large allocations, */
2687 /* and everything is dirty. */
2688 static PVOID gww_buf[GC_GWW_BUF_LEN];
2690 # ifdef MPROTECT_VDB
2691 GC_INNER GC_bool GC_gww_dirty_init(void)
2693 detect_GetWriteWatch();
2694 return GC_GWW_AVAILABLE();
2697 GC_INNER void GC_dirty_init(void)
2699 detect_GetWriteWatch();
2700 GC_dirty_maintained = GC_GWW_AVAILABLE();
2702 # endif /* !MPROTECT_VDB */
2704 # ifdef MPROTECT_VDB
2705 STATIC void GC_gww_read_dirty(void)
2707 GC_INNER void GC_read_dirty(void)
2712 BZERO(GC_grungy_pages, sizeof(GC_grungy_pages));
2714 for (i = 0; i != GC_n_heap_sects; ++i) {
2718 PVOID * pages, * pages_end;
2722 count = GC_GWW_BUF_LEN;
2723 /* GetWriteWatch is documented as returning non-zero when it */
2724 /* fails, but the documentation doesn't explicitly say why it */
2725 /* would fail or what its behaviour will be if it fails. */
2726 /* It does appear to fail, at least on recent W2K instances, if */
2727 /* the underlying memory was not allocated with the appropriate */
2728 /* flag. This is common if GC_enable_incremental is called */
2729 /* shortly after GC initialization. To avoid modifying the */
2730 /* interface, we silently work around such a failure, it only */
2731 /* affects the initial (small) heap allocation. If there are */
2732 /* more dirty pages than will fit in the buffer, this is not */
2733 /* treated as a failure; we must check the page count in the */
2734 /* loop condition. Since each partial call will reset the */
2735 /* status of some pages, this should eventually terminate even */
2736 /* in the overflow case. */
2737 if (GetWriteWatch_func(WRITE_WATCH_FLAG_RESET,
2738 GC_heap_sects[i].hs_start,
2739 GC_heap_sects[i].hs_bytes,
2743 static int warn_count = 0;
2745 struct hblk * start = (struct hblk *)GC_heap_sects[i].hs_start;
2746 static struct hblk *last_warned = 0;
2747 size_t nblocks = divHBLKSZ(GC_heap_sects[i].hs_bytes);
2749 if ( i != 0 && last_warned != start && warn_count++ < 5) {
2750 last_warned = start;
2752 "GC_gww_read_dirty unexpectedly failed at %p: "
2753 "Falling back to marking all pages dirty\n", start);
2755 for (j = 0; j < nblocks; ++j) {
2756 word hash = PHT_HASH(start + j);
2757 set_pht_entry_from_index(GC_grungy_pages, hash);
2759 count = 1; /* Done with this section. */
2760 } else /* succeeded */ {
2761 pages_end = pages + count;
2762 while (pages != pages_end) {
2763 struct hblk * h = (struct hblk *) *pages++;
2764 struct hblk * h_end = (struct hblk *) ((char *) h + page_size);
2766 set_pht_entry_from_index(GC_grungy_pages, PHT_HASH(h));
2767 while (++h < h_end);
2770 } while (count == GC_GWW_BUF_LEN);
2771 /* FIXME: It's unclear from Microsoft's documentation if this loop */
2772 /* is useful. We suspect the call just fails if the buffer fills */
2773 /* up. But that should still be handled correctly. */
2776 GC_or_pages(GC_written_pages, GC_grungy_pages);
2778 #endif /* GWW_VDB */
2781 /* All of the following assume the allocation lock is held. */
2783 /* The client asserts that unallocated pages in the heap are never */
2786 /* Initialize virtual dirty bit implementation. */
2787 GC_INNER void GC_dirty_init(void)
2789 if (GC_print_stats == VERBOSE)
2790 GC_log_printf("Initializing DEFAULT_VDB...\n");
2791 GC_dirty_maintained = TRUE;
2794 /* Retrieve system dirty bits for heap to a local buffer. */
2795 /* Restore the systems notion of which pages are dirty. */
2796 GC_INNER void GC_read_dirty(void) {}
2798 /* Is the HBLKSIZE sized page at h marked dirty in the local buffer? */
2799 /* If the actual page size is different, this returns TRUE if any */
2800 /* of the pages overlapping h are dirty. This routine may err on the */
2801 /* side of labeling pages as dirty (and this implementation does). */
2803 GC_INNER GC_bool GC_page_was_dirty(struct hblk *h)
2808 /* The following two routines are typically less crucial. */
2809 /* They matter most with large dynamic libraries, or if we can't */
2810 /* accurately identify stacks, e.g. under Solaris 2.X. Otherwise the */
2811 /* following default versions are adequate. */
2813 /* Could any valid GC heap pointer ever have been written to this page? */
2815 GC_INNER GC_bool GC_page_was_ever_dirty(struct hblk *h)
2819 # endif /* CHECKSUMS */
2822 /* I) hints that [h, h+nblocks) is about to be written. */
2823 /* II) guarantees that protection is removed. */
2824 /* (I) may speed up some dirty bit implementations. */
2825 /* (II) may be essential if we need to ensure that */
2826 /* pointer-free system call buffers in the heap are */
2827 /* not protected. */
2829 GC_INNER void GC_remove_protection(struct hblk *h, word nblocks,
2830 GC_bool is_ptrfree) {}
2831 #endif /* DEFAULT_VDB */
2834 /* Initialize virtual dirty bit implementation. */
2835 GC_INNER void GC_dirty_init(void)
2837 if (GC_print_stats == VERBOSE)
2838 GC_log_printf("Initializing MANUAL_VDB...\n");
2839 /* GC_dirty_pages and GC_grungy_pages are already cleared. */
2840 GC_dirty_maintained = TRUE;
2843 /* Retrieve system dirty bits for heap to a local buffer. */
2844 /* Restore the systems notion of which pages are dirty. */
2845 GC_INNER void GC_read_dirty(void)
2847 BCOPY((word *)GC_dirty_pages, GC_grungy_pages,
2848 (sizeof GC_dirty_pages));
2849 BZERO((word *)GC_dirty_pages, (sizeof GC_dirty_pages));
2852 /* Is the HBLKSIZE sized page at h marked dirty in the local buffer? */
2853 /* If the actual page size is different, this returns TRUE if any */
2854 /* of the pages overlapping h are dirty. This routine may err on the */
2855 /* side of labeling pages as dirty (and this implementation does). */
2856 GC_INNER GC_bool GC_page_was_dirty(struct hblk *h)
2858 register word index = PHT_HASH(h);
2859 return(HDR(h) == 0 || get_pht_entry_from_index(GC_grungy_pages, index));
2862 # define async_set_pht_entry_from_index(db, index) \
2863 set_pht_entry_from_index(db, index) /* for now */
2865 /* Mark the page containing p as dirty. Logically, this dirties the */
2866 /* entire object. */
2867 void GC_dirty(ptr_t p)
2869 word index = PHT_HASH(p);
2870 async_set_pht_entry_from_index(GC_dirty_pages, index);
2874 GC_INNER void GC_remove_protection(struct hblk *h, word nblocks,
2875 GC_bool is_ptrfree) {}
2878 /* Could any valid GC heap pointer ever have been written to this page? */
2880 GC_INNER GC_bool GC_page_was_ever_dirty(struct hblk *h)
2882 /* FIXME - implement me. */
2885 # endif /* CHECKSUMS */
2887 #endif /* MANUAL_VDB */
2890 /* See DEFAULT_VDB for interface descriptions. */
2893 * This implementation maintains dirty bits itself by catching write
2894 * faults and keeping track of them. We assume nobody else catches
2895 * SIGBUS or SIGSEGV. We assume no write faults occur in system calls.
2896 * This means that clients must ensure that system calls don't write
2897 * to the write-protected heap. Probably the best way to do this is to
2898 * ensure that system calls write at most to POINTERFREE objects in the
2899 * heap, and do even that only if we are on a platform on which those
2900 * are not protected. Another alternative is to wrap system calls
2901 * (see example for read below), but the current implementation holds
2903 * We assume the page size is a multiple of HBLKSIZE.
2904 * We prefer them to be the same. We avoid protecting POINTERFREE
2905 * objects only if they are the same.
2908 /* Using vm_protect (mach syscall) over mprotect (BSD syscall) seems to
2909 decrease the likelihood of some of the problems described below. */
2910 # include <mach/vm_map.h>
2911 STATIC mach_port_t GC_task_self = 0;
2912 # define PROTECT(addr,len) \
2913 if(vm_protect(GC_task_self,(vm_address_t)(addr),(vm_size_t)(len), \
2914 FALSE, VM_PROT_READ \
2915 | (GC_pages_executable ? VM_PROT_EXECUTE : 0)) \
2916 != KERN_SUCCESS) { \
2917 ABORT("vm_protect(PROTECT) failed"); \
2919 # define UNPROTECT(addr,len) \
2920 if(vm_protect(GC_task_self,(vm_address_t)(addr),(vm_size_t)(len), \
2921 FALSE, (VM_PROT_READ | VM_PROT_WRITE) \
2922 | (GC_pages_executable ? VM_PROT_EXECUTE : 0)) \
2923 != KERN_SUCCESS) { \
2924 ABORT("vm_protect(UNPROTECT) failed"); \
2927 # elif !defined(MSWIN32) && !defined(MSWINCE)
2928 # include <sys/mman.h>
2929 # include <signal.h>
2930 # include <sys/syscall.h>
2932 # define PROTECT(addr, len) \
2933 if (mprotect((caddr_t)(addr), (size_t)(len), \
2935 | (GC_pages_executable ? PROT_EXEC : 0)) < 0) { \
2936 ABORT("mprotect failed"); \
2938 # define UNPROTECT(addr, len) \
2939 if (mprotect((caddr_t)(addr), (size_t)(len), \
2940 (PROT_READ | PROT_WRITE) \
2941 | (GC_pages_executable ? PROT_EXEC : 0)) < 0) { \
2942 ABORT(GC_pages_executable ? "un-mprotect executable page" \
2943 " failed (probably disabled by OS)" : \
2944 "un-mprotect failed"); \
2946 # undef IGNORE_PAGES_EXECUTABLE
2948 # else /* MSWIN32 */
2950 # include <signal.h>
2953 static DWORD protect_junk;
2954 # define PROTECT(addr, len) \
2955 if (!VirtualProtect((addr), (len), \
2956 GC_pages_executable ? PAGE_EXECUTE_READ : \
2959 if (GC_print_stats) \
2960 GC_log_printf("Last error code: 0x%lx\n", (long)GetLastError()); \
2961 ABORT("VirtualProtect failed"); \
2963 # define UNPROTECT(addr, len) \
2964 if (!VirtualProtect((addr), (len), \
2965 GC_pages_executable ? PAGE_EXECUTE_READWRITE : \
2968 ABORT("un-VirtualProtect failed"); \
2970 # endif /* MSWIN32 || MSWINCE || DARWIN */
2972 # if defined(MSWIN32)
2973 typedef LPTOP_LEVEL_EXCEPTION_FILTER SIG_HNDLR_PTR;
2975 # define SIG_DFL (LPTOP_LEVEL_EXCEPTION_FILTER)((signed_word)-1)
2976 # elif defined(MSWINCE)
2977 typedef LONG (WINAPI *SIG_HNDLR_PTR)(struct _EXCEPTION_POINTERS *);
2979 # define SIG_DFL (SIG_HNDLR_PTR) (-1)
2980 # elif defined(DARWIN)
2981 typedef void (* SIG_HNDLR_PTR)();
2983 typedef void (* SIG_HNDLR_PTR)(int, siginfo_t *, void *);
2984 typedef void (* PLAIN_HNDLR_PTR)(int);
2987 # if defined(__GLIBC__)
2988 # if __GLIBC__ < 2 || __GLIBC__ == 2 && __GLIBC_MINOR__ < 2
2989 # error glibc too old?
2994 STATIC SIG_HNDLR_PTR GC_old_segv_handler = 0;
2995 /* Also old MSWIN32 ACCESS_VIOLATION filter */
2996 # if !defined(MSWIN32) && !defined(MSWINCE)
2997 STATIC SIG_HNDLR_PTR GC_old_bus_handler = 0;
2998 STATIC GC_bool GC_old_bus_handler_used_si = FALSE;
2999 STATIC GC_bool GC_old_segv_handler_used_si = FALSE;
3001 #endif /* !DARWIN */
3003 #if defined(THREADS)
3004 /* We need to lock around the bitmap update in the write fault handler */
3005 /* in order to avoid the risk of losing a bit. We do this with a */
3006 /* test-and-set spin lock if we know how to do that. Otherwise we */
3007 /* check whether we are already in the handler and use the dumb but */
3008 /* safe fallback algorithm of setting all bits in the word. */
3009 /* Contention should be very rare, so we do the minimum to handle it */
3011 #ifdef AO_HAVE_test_and_set_acquire
3012 GC_INNER volatile AO_TS_t GC_fault_handler_lock = AO_TS_INITIALIZER;
3013 static void async_set_pht_entry_from_index(volatile page_hash_table db,
3016 while (AO_test_and_set_acquire(&GC_fault_handler_lock) == AO_TS_SET) {
3019 /* Could also revert to set_pht_entry_from_index_safe if initial */
3020 /* GC_test_and_set fails. */
3021 set_pht_entry_from_index(db, index);
3022 AO_CLEAR(&GC_fault_handler_lock);
3024 #else /* !AO_HAVE_test_and_set_acquire */
3025 # error No test_and_set operation: Introduces a race.
3026 /* THIS WOULD BE INCORRECT! */
3027 /* The dirty bit vector may be temporarily wrong, */
3028 /* just before we notice the conflict and correct it. We may end up */
3029 /* looking at it while it's wrong. But this requires contention */
3030 /* exactly when a GC is triggered, which seems far less likely to */
3031 /* fail than the old code, which had no reported failures. Thus we */
3032 /* leave it this way while we think of something better, or support */
3033 /* GC_test_and_set on the remaining platforms. */
3034 static volatile word currently_updating = 0;
3035 static void async_set_pht_entry_from_index(volatile page_hash_table db,
3038 unsigned int update_dummy;
3039 currently_updating = (word)(&update_dummy);
3040 set_pht_entry_from_index(db, index);
3041 /* If we get contention in the 10 or so instruction window here, */
3042 /* and we get stopped by a GC between the two updates, we lose! */
3043 if (currently_updating != (word)(&update_dummy)) {
3044 set_pht_entry_from_index_safe(db, index);
3045 /* We claim that if two threads concurrently try to update the */
3046 /* dirty bit vector, the first one to execute UPDATE_START */
3047 /* will see it changed when UPDATE_END is executed. (Note that */
3048 /* &update_dummy must differ in two distinct threads.) It */
3049 /* will then execute set_pht_entry_from_index_safe, thus */
3050 /* returning us to a safe state, though not soon enough. */
3053 #endif /* !AO_HAVE_test_and_set_acquire */
3054 #else /* !THREADS */
3055 # define async_set_pht_entry_from_index(db, index) \
3056 set_pht_entry_from_index(db, index)
3057 #endif /* !THREADS */
3060 void GC_record_fault(struct hblk * h); /* from checksums.c */
3065 # if !defined(MSWIN32) && !defined(MSWINCE)
3067 # if defined(FREEBSD) || defined(HURD) || defined(HPUX)
3068 # define SIG_OK (sig == SIGBUS || sig == SIGSEGV)
3070 # define SIG_OK (sig == SIGSEGV)
3072 # if defined(FREEBSD)
3073 # ifndef SEGV_ACCERR
3074 # define SEGV_ACCERR 2
3076 # define CODE_OK (si -> si_code == BUS_PAGE_FAULT \
3077 || si -> si_code == SEGV_ACCERR)
3078 # elif defined(OSF1)
3079 # define CODE_OK (si -> si_code == 2 /* experimentally determined */)
3080 # elif defined(IRIX5)
3081 # define CODE_OK (si -> si_code == EACCES)
3082 # elif defined(HURD)
3083 # define CODE_OK TRUE
3084 # elif defined(LINUX)
3085 # define CODE_OK TRUE
3086 /* Empirically c.trapno == 14, on IA32, but is that useful? */
3087 /* Should probably consider alignment issues on other */
3088 /* architectures. */
3089 # elif defined(HPUX)
3090 # define CODE_OK (si -> si_code == SEGV_ACCERR \
3091 || si -> si_code == BUS_ADRERR \
3092 || si -> si_code == BUS_UNKNOWN \
3093 || si -> si_code == SEGV_UNKNOWN \
3094 || si -> si_code == BUS_OBJERR)
3095 # elif defined(SUNOS5SIGS)
3096 # define CODE_OK (si -> si_code == SEGV_ACCERR)
3098 # ifndef NO_GETCONTEXT
3099 # include <ucontext.h>
3102 STATIC void GC_write_fault_handler(int sig, siginfo_t *si, void *raw_sc)
3104 # define SIG_OK (exc_info -> ExceptionRecord -> ExceptionCode \
3105 == STATUS_ACCESS_VIOLATION)
3106 # define CODE_OK (exc_info -> ExceptionRecord -> ExceptionInformation[0] \
3107 == 1) /* Write fault */
3108 STATIC LONG WINAPI GC_write_fault_handler(
3109 struct _EXCEPTION_POINTERS *exc_info)
3110 # endif /* MSWIN32 || MSWINCE */
3112 # if !defined(MSWIN32) && !defined(MSWINCE)
3113 char *addr = si -> si_addr;
3115 char * addr = (char *) (exc_info -> ExceptionRecord
3116 -> ExceptionInformation[1]);
3120 if (SIG_OK && CODE_OK) {
3121 register struct hblk * h =
3122 (struct hblk *)((word)addr & ~(GC_page_size-1));
3123 GC_bool in_allocd_block;
3129 /* Address is only within the correct physical page. */
3130 in_allocd_block = FALSE;
3131 for (i = 0; i < divHBLKSZ(GC_page_size); i++) {
3132 if (HDR(h+i) != 0) {
3133 in_allocd_block = TRUE;
3138 in_allocd_block = (HDR(addr) != 0);
3140 if (!in_allocd_block) {
3141 /* FIXME - We should make sure that we invoke the */
3142 /* old handler with the appropriate calling */
3143 /* sequence, which often depends on SA_SIGINFO. */
3145 /* Heap blocks now begin and end on page boundaries */
3146 SIG_HNDLR_PTR old_handler;
3148 # if defined(MSWIN32) || defined(MSWINCE)
3149 old_handler = GC_old_segv_handler;
3153 if (sig == SIGSEGV) {
3154 old_handler = GC_old_segv_handler;
3155 used_si = GC_old_segv_handler_used_si;
3157 old_handler = GC_old_bus_handler;
3158 used_si = GC_old_bus_handler_used_si;
3162 if (old_handler == (SIG_HNDLR_PTR)SIG_DFL) {
3163 # if !defined(MSWIN32) && !defined(MSWINCE)
3165 GC_log_printf("Unexpected segfault at %p\n", addr);
3166 ABORT("Unexpected bus error or segmentation fault");
3168 return(EXCEPTION_CONTINUE_SEARCH);
3172 * FIXME: This code should probably check if the
3173 * old signal handler used the traditional style and
3174 * if so call it using that style.
3176 # if defined(MSWIN32) || defined(MSWINCE)
3177 return((*old_handler)(exc_info));
3180 ((SIG_HNDLR_PTR)old_handler) (sig, si, raw_sc);
3182 /* FIXME: should pass nonstandard args as well. */
3183 ((PLAIN_HNDLR_PTR)old_handler) (sig);
3188 UNPROTECT(h, GC_page_size);
3189 /* We need to make sure that no collection occurs between */
3190 /* the UNPROTECT and the setting of the dirty bit. Otherwise */
3191 /* a write by a third thread might go unnoticed. Reversing */
3192 /* the order is just as bad, since we would end up unprotecting */
3193 /* a page in a GC cycle during which it's not marked. */
3194 /* Currently we do this by disabling the thread stopping */
3195 /* signals while this handler is running. An alternative might */
3196 /* be to record the fact that we're about to unprotect, or */
3197 /* have just unprotected a page in the GC's thread structure, */
3198 /* and then to have the thread stopping code set the dirty */
3199 /* flag, if necessary. */
3200 for (i = 0; i < divHBLKSZ(GC_page_size); i++) {
3201 size_t index = PHT_HASH(h+i);
3203 async_set_pht_entry_from_index(GC_dirty_pages, index);
3205 /* The write may not take place before dirty bits are read. */
3206 /* But then we'll fault again ... */
3207 # if defined(MSWIN32) || defined(MSWINCE)
3208 return(EXCEPTION_CONTINUE_EXECUTION);
3213 # if defined(MSWIN32) || defined(MSWINCE)
3214 return EXCEPTION_CONTINUE_SEARCH;
3217 GC_log_printf("Unexpected segfault at %p\n", addr);
3218 ABORT("Unexpected bus error or segmentation fault");
3222 # ifdef GC_WIN32_THREADS
3223 GC_INNER void GC_set_write_fault_handler(void)
3225 SetUnhandledExceptionFilter(GC_write_fault_handler);
3228 #endif /* !DARWIN */
3230 /* We hold the allocation lock. We expect block h to be written */
3231 /* shortly. Ensure that all pages containing any part of the n hblks */
3232 /* starting at h are no longer protected. If is_ptrfree is false, also */
3233 /* ensure that they will subsequently appear to be dirty. Not allowed */
3234 /* to call GC_printf (and the friends) here, see Win32 GC_stop_world() */
3235 /* for the information. */
3236 GC_INNER void GC_remove_protection(struct hblk *h, word nblocks,
3239 struct hblk * h_trunc; /* Truncated to page boundary */
3240 struct hblk * h_end; /* Page boundary following block end */
3241 struct hblk * current;
3243 # if defined(GWW_VDB)
3244 if (GC_GWW_AVAILABLE()) return;
3246 if (!GC_dirty_maintained) return;
3247 h_trunc = (struct hblk *)((word)h & ~(GC_page_size-1));
3248 h_end = (struct hblk *)(((word)(h + nblocks) + GC_page_size-1)
3249 & ~(GC_page_size-1));
3250 if (h_end == h_trunc + 1 &&
3251 get_pht_entry_from_index(GC_dirty_pages, PHT_HASH(h_trunc))) {
3252 /* already marked dirty, and hence unprotected. */
3255 for (current = h_trunc; current < h_end; ++current) {
3256 size_t index = PHT_HASH(current);
3257 if (!is_ptrfree || current < h || current >= h + nblocks) {
3258 async_set_pht_entry_from_index(GC_dirty_pages, index);
3261 UNPROTECT(h_trunc, (ptr_t)h_end - (ptr_t)h_trunc);
3264 #if !defined(DARWIN)
3265 GC_INNER void GC_dirty_init(void)
3267 # if !defined(MSWIN32) && !defined(MSWINCE)
3268 struct sigaction act, oldact;
3269 act.sa_flags = SA_RESTART | SA_SIGINFO;
3270 act.sa_sigaction = GC_write_fault_handler;
3271 (void)sigemptyset(&act.sa_mask);
3273 /* Arrange to postpone SIG_SUSPEND while we're in a write fault */
3274 /* handler. This effectively makes the handler atomic w.r.t. */
3275 /* stopping the world for GC. */
3276 (void)sigaddset(&act.sa_mask, SIG_SUSPEND);
3277 # endif /* SIG_SUSPEND */
3279 if (GC_print_stats == VERBOSE)
3281 "Initializing mprotect virtual dirty bit implementation\n");
3282 GC_dirty_maintained = TRUE;
3283 if (GC_page_size % HBLKSIZE != 0) {
3284 ABORT("Page size not multiple of HBLKSIZE");
3286 # if !defined(MSWIN32) && !defined(MSWINCE)
3287 # if defined(GC_IRIX_THREADS)
3288 sigaction(SIGSEGV, 0, &oldact);
3289 sigaction(SIGSEGV, &act, 0);
3292 int res = sigaction(SIGSEGV, &act, &oldact);
3293 if (res != 0) ABORT("Sigaction failed");
3296 if (oldact.sa_flags & SA_SIGINFO) {
3297 GC_old_segv_handler = oldact.sa_sigaction;
3298 GC_old_segv_handler_used_si = TRUE;
3300 GC_old_segv_handler = (SIG_HNDLR_PTR)oldact.sa_handler;
3301 GC_old_segv_handler_used_si = FALSE;
3303 if (GC_old_segv_handler == (SIG_HNDLR_PTR)SIG_IGN) {
3305 GC_err_printf("Previously ignored segmentation violation!?\n");
3306 GC_old_segv_handler = (SIG_HNDLR_PTR)SIG_DFL;
3308 if (GC_old_segv_handler != (SIG_HNDLR_PTR)SIG_DFL) {
3309 if (GC_print_stats == VERBOSE)
3310 GC_log_printf("Replaced other SIGSEGV handler\n");
3312 # if defined(HPUX) || defined(LINUX) || defined(HURD) \
3313 || (defined(FREEBSD) && defined(SUNOS5SIGS))
3314 sigaction(SIGBUS, &act, &oldact);
3315 if (oldact.sa_flags & SA_SIGINFO) {
3316 GC_old_bus_handler = oldact.sa_sigaction;
3317 GC_old_bus_handler_used_si = TRUE;
3319 GC_old_bus_handler = (SIG_HNDLR_PTR)oldact.sa_handler;
3320 GC_old_bus_handler_used_si = FALSE;
3322 if (GC_old_bus_handler == (SIG_HNDLR_PTR)SIG_IGN) {
3324 GC_err_printf("Previously ignored bus error!?\n");
3325 GC_old_bus_handler = (SIG_HNDLR_PTR)SIG_DFL;
3327 if (GC_old_bus_handler != (SIG_HNDLR_PTR)SIG_DFL) {
3328 if (GC_print_stats == VERBOSE)
3329 GC_log_printf("Replaced other SIGBUS handler\n");
3331 # endif /* HPUX || LINUX || HURD || (FREEBSD && SUNOS5SIGS) */
3332 # endif /* ! MS windows */
3333 # if defined(GWW_VDB)
3334 if (GC_gww_dirty_init())
3337 # if defined(MSWIN32)
3338 GC_old_segv_handler = SetUnhandledExceptionFilter(GC_write_fault_handler);
3339 if (GC_old_segv_handler != NULL) {
3341 GC_log_printf("Replaced other UnhandledExceptionFilter\n");
3343 GC_old_segv_handler = SIG_DFL;
3345 # elif defined(MSWINCE)
3346 /* MPROTECT_VDB is unsupported for WinCE at present. */
3347 /* FIXME: implement it (if possible). */
3350 #endif /* !DARWIN */
3352 GC_API int GC_CALL GC_incremental_protection_needs(void)
3354 if (GC_page_size == HBLKSIZE) {
3355 return GC_PROTECTS_POINTER_HEAP;
3357 return GC_PROTECTS_POINTER_HEAP | GC_PROTECTS_PTRFREE_HEAP;
3360 #define HAVE_INCREMENTAL_PROTECTION_NEEDS
3362 #define IS_PTRFREE(hhdr) ((hhdr)->hb_descr == 0)
3363 #define PAGE_ALIGNED(x) !((word)(x) & (GC_page_size - 1))
3365 STATIC void GC_protect_heap(void)
3369 struct hblk * current;
3370 struct hblk * current_start; /* Start of block to be protected. */
3371 struct hblk * limit;
3373 GC_bool protect_all =
3374 (0 != (GC_incremental_protection_needs() & GC_PROTECTS_PTRFREE_HEAP));
3375 for (i = 0; i < GC_n_heap_sects; i++) {
3376 start = GC_heap_sects[i].hs_start;
3377 len = GC_heap_sects[i].hs_bytes;
3379 PROTECT(start, len);
3381 GC_ASSERT(PAGE_ALIGNED(len));
3382 GC_ASSERT(PAGE_ALIGNED(start));
3383 current_start = current = (struct hblk *)start;
3384 limit = (struct hblk *)(start + len);
3385 while (current < limit) {
3390 GC_ASSERT(PAGE_ALIGNED(current));
3391 GET_HDR(current, hhdr);
3392 if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {
3393 /* This can happen only if we're at the beginning of a */
3394 /* heap segment, and a block spans heap segments. */
3395 /* We will handle that block as part of the preceding */
3397 GC_ASSERT(current_start == current);
3398 current_start = ++current;
3401 if (HBLK_IS_FREE(hhdr)) {
3402 GC_ASSERT(PAGE_ALIGNED(hhdr -> hb_sz));
3403 nhblks = divHBLKSZ(hhdr -> hb_sz);
3404 is_ptrfree = TRUE; /* dirty on alloc */
3406 nhblks = OBJ_SZ_TO_BLOCKS(hhdr -> hb_sz);
3407 is_ptrfree = IS_PTRFREE(hhdr);
3410 if (current_start < current) {
3411 PROTECT(current_start, (ptr_t)current - (ptr_t)current_start);
3413 current_start = (current += nhblks);
3418 if (current_start < current) {
3419 PROTECT(current_start, (ptr_t)current - (ptr_t)current_start);
3425 /* We assume that either the world is stopped or its OK to lose dirty */
3426 /* bits while this is happenning (as in GC_enable_incremental). */
3427 GC_INNER void GC_read_dirty(void)
3429 # if defined(GWW_VDB)
3430 if (GC_GWW_AVAILABLE()) {
3431 GC_gww_read_dirty();
3435 BCOPY((word *)GC_dirty_pages, GC_grungy_pages,
3436 (sizeof GC_dirty_pages));
3437 BZERO((word *)GC_dirty_pages, (sizeof GC_dirty_pages));
3441 GC_INNER GC_bool GC_page_was_dirty(struct hblk *h)
3443 register word index;
3445 # if defined(GWW_VDB)
3446 if (GC_GWW_AVAILABLE())
3447 return GC_gww_page_was_dirty(h);
3450 index = PHT_HASH(h);
3451 return(HDR(h) == 0 || get_pht_entry_from_index(GC_grungy_pages, index));
3455 * Acquiring the allocation lock here is dangerous, since this
3456 * can be called from within GC_call_with_alloc_lock, and the cord
3457 * package does so. On systems that allow nested lock acquisition, this
3459 * On other systems, SET_LOCK_HOLDER and friends must be suitably defined.
3463 static GC_bool syscall_acquired_lock = FALSE; /* Protected by GC lock. */
3465 void GC_begin_syscall(void)
3467 /* FIXME: Resurrecting this code would require fixing the */
3468 /* test, which can spuriously return TRUE. */
3469 if (!I_HOLD_LOCK()) {
3471 syscall_acquired_lock = TRUE;
3475 void GC_end_syscall(void)
3477 if (syscall_acquired_lock) {
3478 syscall_acquired_lock = FALSE;
3483 void GC_unprotect_range(ptr_t addr, word len)
3485 struct hblk * start_block;
3486 struct hblk * end_block;
3487 register struct hblk *h;
3490 if (!GC_dirty_maintained) return;
3491 obj_start = GC_base(addr);
3492 if (obj_start == 0) return;
3493 if (GC_base(addr + len - 1) != obj_start) {
3494 ABORT("GC_unprotect_range(range bigger than object)");
3496 start_block = (struct hblk *)((word)addr & ~(GC_page_size - 1));
3497 end_block = (struct hblk *)((word)(addr + len - 1) & ~(GC_page_size - 1));
3498 end_block += GC_page_size/HBLKSIZE - 1;
3499 for (h = start_block; h <= end_block; h++) {
3500 register word index = PHT_HASH(h);
3502 async_set_pht_entry_from_index(GC_dirty_pages, index);
3504 UNPROTECT(start_block,
3505 ((ptr_t)end_block - (ptr_t)start_block) + HBLKSIZE);
3509 /* We no longer wrap read by default, since that was causing too many */
3510 /* problems. It is preferred that the client instead avoids writing */
3511 /* to the write-protected heap with a system call. */
3512 /* This still serves as sample code if you do want to wrap system calls.*/
3514 #if !defined(MSWIN32) && !defined(MSWINCE) && !defined(GC_USE_LD_WRAP)
3515 /* Replacement for UNIX system call. */
3516 /* Other calls that write to the heap should be handled similarly. */
3517 /* Note that this doesn't work well for blocking reads: It will hold */
3518 /* the allocation lock for the entire duration of the call. Multithreaded */
3519 /* clients should really ensure that it won't block, either by setting */
3520 /* the descriptor nonblocking, or by calling select or poll first, to */
3521 /* make sure that input is available. */
3522 /* Another, preferred alternative is to ensure that system calls never */
3523 /* write to the protected heap (see above). */
3524 # include <unistd.h>
3525 # include <sys/uio.h>
3526 ssize_t read(int fd, void *buf, size_t nbyte)
3531 GC_unprotect_range(buf, (word)nbyte);
3532 # if defined(IRIX5) || defined(GC_LINUX_THREADS)
3533 /* Indirect system call may not always be easily available. */
3534 /* We could call _read, but that would interfere with the */
3535 /* libpthread interception of read. */
3536 /* On Linux, we have to be careful with the linuxthreads */
3537 /* read interception. */
3542 iov.iov_len = nbyte;
3543 result = readv(fd, &iov, 1);
3547 result = __read(fd, buf, nbyte);
3549 /* The two zero args at the end of this list are because one
3550 IA-64 syscall() implementation actually requires six args
3551 to be passed, even though they aren't always used. */
3552 result = syscall(SYS_read, fd, buf, nbyte, 0, 0);
3558 #endif /* !MSWIN32 && !MSWINCE && !GC_LINUX_THREADS */
3560 #if defined(GC_USE_LD_WRAP) && !defined(THREADS)
3561 /* We use the GNU ld call wrapping facility. */
3562 /* I'm not sure that this actually wraps whatever version of read */
3563 /* is called by stdio. That code also mentions __read. */
3564 # include <unistd.h>
3565 ssize_t __wrap_read(int fd, void *buf, size_t nbyte)
3570 GC_unprotect_range(buf, (word)nbyte);
3571 result = __real_read(fd, buf, nbyte);
3576 /* We should probably also do this for __read, or whatever stdio */
3577 /* actually calls. */
3583 GC_INNER GC_bool GC_page_was_ever_dirty(struct hblk *h)
3585 # if defined(GWW_VDB)
3586 if (GC_GWW_AVAILABLE())
3587 return GC_gww_page_was_ever_dirty(h);
3591 # endif /* CHECKSUMS */
3593 #endif /* MPROTECT_VDB */
3596 /* See DEFAULT_VDB for interface descriptions. */
3598 /* This implementation assumes a Solaris 2.X like /proc */
3599 /* pseudo-file-system from which we can read page modified bits. This */
3600 /* facility is far from optimal (e.g. we would like to get the info for */
3601 /* only some of the address space), but it avoids intercepting system */
3605 # include <sys/types.h>
3606 # include <sys/signal.h>
3607 # include <sys/fault.h>
3608 # include <sys/syscall.h>
3609 # include <sys/procfs.h>
3610 # include <sys/stat.h>
3612 # define INITIAL_BUF_SZ 16384
3613 STATIC word GC_proc_buf_size = INITIAL_BUF_SZ;
3614 STATIC char *GC_proc_buf = NULL;
3615 STATIC int GC_proc_fd = 0;
3617 GC_INNER void GC_dirty_init(void)
3622 if (GC_bytes_allocd != 0 || GC_bytes_allocd_before_gc != 0) {
3623 memset(GC_written_pages, 0xff, sizeof(page_hash_table));
3624 if (GC_print_stats == VERBOSE)
3625 GC_log_printf("Allocated bytes:%lu:all pages may have been written\n",
3626 (unsigned long)(GC_bytes_allocd
3627 + GC_bytes_allocd_before_gc));
3630 sprintf(buf, "/proc/%ld", (long)getpid());
3631 fd = open(buf, O_RDONLY);
3633 ABORT("/proc open failed");
3635 GC_proc_fd = syscall(SYS_ioctl, fd, PIOCOPENPD, 0);
3637 syscall(SYS_fcntl, GC_proc_fd, F_SETFD, FD_CLOEXEC);
3638 if (GC_proc_fd < 0) {
3639 WARN("/proc ioctl(PIOCOPENPD) failed", 0);
3643 GC_dirty_maintained = TRUE;
3644 GC_proc_buf = GC_scratch_alloc(GC_proc_buf_size);
3645 if (GC_proc_buf == NULL)
3646 ABORT("Insufficient space for /proc read");
3651 GC_INNER void GC_read_dirty(void)
3654 unsigned long npages;
3657 struct prasmap * map;
3661 BZERO(GC_grungy_pages, sizeof(GC_grungy_pages));
3663 if (READ(GC_proc_fd, bufp, GC_proc_buf_size) <= 0) {
3664 /* Retry with larger buffer. */
3665 word new_size = 2 * GC_proc_buf_size;
3668 GC_err_printf("/proc read failed: GC_proc_buf_size = %lu\n",
3669 (unsigned long)GC_proc_buf_size);
3671 new_buf = GC_scratch_alloc(new_size);
3673 GC_proc_buf = bufp = new_buf;
3674 GC_proc_buf_size = new_size;
3676 if (READ(GC_proc_fd, bufp, GC_proc_buf_size) <= 0) {
3677 WARN("Insufficient space for /proc read\n", 0);
3679 memset(GC_grungy_pages, 0xff, sizeof (page_hash_table));
3680 memset(GC_written_pages, 0xff, sizeof(page_hash_table));
3685 /* Copy dirty bits into GC_grungy_pages */
3686 nmaps = ((struct prpageheader *)bufp) -> pr_nmap;
3687 # ifdef DEBUG_DIRTY_BITS
3688 GC_log_printf("Proc VDB read: pr_nmap= %u, pr_npage= %lu\n",
3689 nmaps, ((struct prpageheader *)bufp)->pr_npage);
3692 bufp += sizeof(struct prpageheader);
3693 for (i = 0; i < nmaps; i++) {
3694 map = (struct prasmap *)bufp;
3695 vaddr = (ptr_t)(map -> pr_vaddr);
3696 npages = map -> pr_npage;
3697 pagesize = map -> pr_pagesize;
3698 # ifdef DEBUG_DIRTY_BITS
3700 "pr_vaddr= %p, npage= %lu, mflags= 0x%x, pagesize= 0x%x\n",
3701 vaddr, npages, map->pr_mflags, pagesize);
3704 bufp += sizeof(struct prasmap);
3705 limit = vaddr + pagesize * npages;
3706 for (; vaddr < limit; vaddr += pagesize) {
3707 if ((*bufp++) & PG_MODIFIED) {
3708 register struct hblk * h;
3709 ptr_t next_vaddr = vaddr + pagesize;
3710 # ifdef DEBUG_DIRTY_BITS
3711 GC_log_printf("dirty page at: %p\n", vaddr);
3713 for (h = (struct hblk *)vaddr; (ptr_t)h < next_vaddr; h++) {
3714 register word index = PHT_HASH(h);
3715 set_pht_entry_from_index(GC_grungy_pages, index);
3719 bufp = (char *)(((word)bufp + (sizeof(long)-1)) & ~(sizeof(long)-1));
3721 # ifdef DEBUG_DIRTY_BITS
3722 GC_log_printf("Proc VDB read done.\n");
3725 /* Update GC_written_pages. */
3726 GC_or_pages(GC_written_pages, GC_grungy_pages);
3730 #endif /* PROC_VDB */
3734 # include "vd/PCR_VD.h"
3736 # define NPAGES (32*1024) /* 128 MB */
3738 PCR_VD_DB GC_grungy_bits[NPAGES];
3740 STATIC ptr_t GC_vd_base = NULL;
3741 /* Address corresponding to GC_grungy_bits[0] */
3742 /* HBLKSIZE aligned. */
3744 GC_INNER void GC_dirty_init(void)
3746 GC_dirty_maintained = TRUE;
3747 /* For the time being, we assume the heap generally grows up */
3748 GC_vd_base = GC_heap_sects[0].hs_start;
3749 if (GC_vd_base == 0) {
3750 ABORT("Bad initial heap segment");
3752 if (PCR_VD_Start(HBLKSIZE, GC_vd_base, NPAGES*HBLKSIZE)
3754 ABORT("Dirty bit initialization failed");
3758 GC_INNER void GC_read_dirty(void)
3760 /* lazily enable dirty bits on newly added heap sects */
3762 static int onhs = 0;
3763 int nhs = GC_n_heap_sects;
3764 for(; onhs < nhs; onhs++) {
3765 PCR_VD_WriteProtectEnable(
3766 GC_heap_sects[onhs].hs_start,
3767 GC_heap_sects[onhs].hs_bytes );
3771 if (PCR_VD_Clear(GC_vd_base, NPAGES*HBLKSIZE, GC_grungy_bits)
3773 ABORT("Dirty bit read failed");
3777 GC_INNER GC_bool GC_page_was_dirty(struct hblk *h)
3779 if((ptr_t)h < GC_vd_base || (ptr_t)h >= GC_vd_base + NPAGES*HBLKSIZE) {
3782 return(GC_grungy_bits[h - (struct hblk *)GC_vd_base] & PCR_VD_DB_dirtyBit);
3786 GC_INNER void GC_remove_protection(struct hblk *h, word nblocks,
3789 PCR_VD_WriteProtectDisable(h, nblocks*HBLKSIZE);
3790 PCR_VD_WriteProtectEnable(h, nblocks*HBLKSIZE);
3793 #endif /* PCR_VDB */
3795 #if defined(MPROTECT_VDB) && defined(DARWIN)
3796 /* The following sources were used as a "reference" for this exception
3798 1. Apple's mach/xnu documentation
3799 2. Timothy J. Wood's "Mach Exception Handlers 101" post to the
3800 omnigroup's macosx-dev list.
3801 www.omnigroup.com/mailman/archive/macosx-dev/2000-June/014178.html
3802 3. macosx-nat.c from Apple's GDB source code.
3805 /* The bug that caused all this trouble should now be fixed. This should
3806 eventually be removed if all goes well. */
3808 /* #define BROKEN_EXCEPTION_HANDLING */
3810 #include <mach/mach.h>
3811 #include <mach/mach_error.h>
3812 #include <mach/thread_status.h>
3813 #include <mach/exception.h>
3814 #include <mach/task.h>
3815 #include <pthread.h>
3817 /* These are not defined in any header, although they are documented */
3819 exc_server(mach_msg_header_t *, mach_msg_header_t *);
3821 extern kern_return_t
3822 exception_raise(mach_port_t, mach_port_t, mach_port_t, exception_type_t,
3823 exception_data_t, mach_msg_type_number_t);
3825 extern kern_return_t
3826 exception_raise_state(mach_port_t, mach_port_t, mach_port_t, exception_type_t,
3827 exception_data_t, mach_msg_type_number_t,
3828 thread_state_flavor_t*, thread_state_t,
3829 mach_msg_type_number_t, thread_state_t,
3830 mach_msg_type_number_t*);
3832 extern kern_return_t
3833 exception_raise_state_identity(mach_port_t, mach_port_t, mach_port_t,
3834 exception_type_t, exception_data_t,
3835 mach_msg_type_number_t, thread_state_flavor_t*,
3836 thread_state_t, mach_msg_type_number_t,
3837 thread_state_t, mach_msg_type_number_t*);
3839 GC_API_OSCALL kern_return_t
3840 catch_exception_raise(mach_port_t exception_port, mach_port_t thread,
3841 mach_port_t task, exception_type_t exception,
3842 exception_data_t code, mach_msg_type_number_t code_count);
3844 /* These should never be called, but just in case... */
3845 GC_API_OSCALL kern_return_t
3846 catch_exception_raise_state(mach_port_name_t exception_port, int exception,
3847 exception_data_t code,
3848 mach_msg_type_number_t codeCnt, int flavor,
3849 thread_state_t old_state, int old_stateCnt,
3850 thread_state_t new_state, int new_stateCnt)
3852 ABORT("Unexpected catch_exception_raise_state invocation");
3853 return(KERN_INVALID_ARGUMENT);
3856 GC_API_OSCALL kern_return_t
3857 catch_exception_raise_state_identity(mach_port_name_t exception_port,
3858 mach_port_t thread, mach_port_t task,
3859 int exception, exception_data_t code,
3860 mach_msg_type_number_t codeCnt, int flavor,
3861 thread_state_t old_state, int old_stateCnt,
3862 thread_state_t new_state, int new_stateCnt)
3864 ABORT("Unexpected catch_exception_raise_state_identity invocation");
3865 return(KERN_INVALID_ARGUMENT);
3868 #define MAX_EXCEPTION_PORTS 16
3871 mach_msg_type_number_t count;
3872 exception_mask_t masks[MAX_EXCEPTION_PORTS];
3873 exception_handler_t ports[MAX_EXCEPTION_PORTS];
3874 exception_behavior_t behaviors[MAX_EXCEPTION_PORTS];
3875 thread_state_flavor_t flavors[MAX_EXCEPTION_PORTS];
3879 void (*volatile os_callback[3])(void);
3880 mach_port_t exception;
3881 # if defined(THREADS)
3886 /* This is to prevent stripping these routines as dead. */
3887 (void (*)(void))catch_exception_raise,
3888 (void (*)(void))catch_exception_raise_state,
3889 (void (*)(void))catch_exception_raise_state_identity
3895 mach_msg_header_t head;
3902 } GC_mprotect_state_t;
3905 /* FIXME: 1 and 2 seem to be safe to use in the msgh_id field, */
3906 /* but it isn't documented. Use the source and see if they */
3909 # define ID_RESUME 2
3911 /* This value is only used on the reply port. */
3914 STATIC GC_mprotect_state_t GC_mprotect_state = 0;
3916 /* The following should ONLY be called when the world is stopped. */
3917 STATIC void GC_mprotect_thread_notify(mach_msg_id_t id)
3921 mach_msg_trailer_t trailer;
3923 mach_msg_return_t r;
3926 buf.msg.head.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0);
3927 buf.msg.head.msgh_size = sizeof(buf.msg);
3928 buf.msg.head.msgh_remote_port = GC_ports.exception;
3929 buf.msg.head.msgh_local_port = MACH_PORT_NULL;
3930 buf.msg.head.msgh_id = id;
3932 r = mach_msg(&buf.msg.head, MACH_SEND_MSG | MACH_RCV_MSG | MACH_RCV_LARGE,
3933 sizeof(buf.msg), sizeof(buf), GC_ports.reply,
3934 MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
3935 if (r != MACH_MSG_SUCCESS)
3936 ABORT("mach_msg failed in GC_mprotect_thread_notify");
3937 if (buf.msg.head.msgh_id != ID_ACK)
3938 ABORT("Invalid ack in GC_mprotect_thread_notify");
3941 /* Should only be called by the mprotect thread */
3942 STATIC void GC_mprotect_thread_reply(void)
3945 mach_msg_return_t r;
3948 msg.head.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0);
3949 msg.head.msgh_size = sizeof(msg);
3950 msg.head.msgh_remote_port = GC_ports.reply;
3951 msg.head.msgh_local_port = MACH_PORT_NULL;
3952 msg.head.msgh_id = ID_ACK;
3954 r = mach_msg(&msg.head, MACH_SEND_MSG, sizeof(msg), 0, MACH_PORT_NULL,
3955 MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
3956 if (r != MACH_MSG_SUCCESS)
3957 ABORT("mach_msg failed in GC_mprotect_thread_reply");
3960 GC_INNER void GC_mprotect_stop(void)
3962 GC_mprotect_thread_notify(ID_STOP);
3965 GC_INNER void GC_mprotect_resume(void)
3967 GC_mprotect_thread_notify(ID_RESUME);
3970 # ifndef GC_NO_THREADS_DISCOVERY
3971 GC_INNER void GC_darwin_register_mach_handler_thread(mach_port_t thread);
3975 /* The compiler should optimize away any GC_mprotect_state computations */
3976 # define GC_mprotect_state GC_MP_NORMAL
3977 #endif /* !THREADS */
3979 STATIC void *GC_mprotect_thread(void *arg)
3981 mach_msg_return_t r;
3982 /* These two structures contain some private kernel data. We don't */
3983 /* need to access any of it so we don't bother defining a proper */
3984 /* struct. The correct definitions are in the xnu source code. */
3986 mach_msg_header_t head;
3990 mach_msg_header_t head;
3991 mach_msg_body_t msgh_body;
3996 # if defined(THREADS) && !defined(GC_NO_THREADS_DISCOVERY)
3997 GC_darwin_register_mach_handler_thread(mach_thread_self());
4001 r = mach_msg(&msg.head, MACH_RCV_MSG | MACH_RCV_LARGE |
4002 (GC_mprotect_state == GC_MP_DISCARDING ? MACH_RCV_TIMEOUT : 0),
4003 0, sizeof(msg), GC_ports.exception,
4004 GC_mprotect_state == GC_MP_DISCARDING ? 0
4005 : MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
4006 id = r == MACH_MSG_SUCCESS ? msg.head.msgh_id : -1;
4008 # if defined(THREADS)
4009 if(GC_mprotect_state == GC_MP_DISCARDING) {
4010 if(r == MACH_RCV_TIMED_OUT) {
4011 GC_mprotect_state = GC_MP_STOPPED;
4012 GC_mprotect_thread_reply();
4015 if(r == MACH_MSG_SUCCESS && (id == ID_STOP || id == ID_RESUME))
4016 ABORT("Out of order mprotect thread request");
4018 # endif /* THREADS */
4020 if (r != MACH_MSG_SUCCESS) {
4022 GC_log_printf("mach_msg failed with code %d: %s\n", (int)r,
4023 mach_error_string(r));
4024 ABORT("mach_msg failed");
4028 # if defined(THREADS)
4030 if(GC_mprotect_state != GC_MP_NORMAL)
4031 ABORT("Called mprotect_stop when state wasn't normal");
4032 GC_mprotect_state = GC_MP_DISCARDING;
4035 if(GC_mprotect_state != GC_MP_STOPPED)
4036 ABORT("Called mprotect_resume when state wasn't stopped");
4037 GC_mprotect_state = GC_MP_NORMAL;
4038 GC_mprotect_thread_reply();
4040 # endif /* THREADS */
4042 /* Handle the message (calls catch_exception_raise) */
4043 if(!exc_server(&msg.head, &reply.head))
4044 ABORT("exc_server failed");
4045 /* Send the reply */
4046 r = mach_msg(&reply.head, MACH_SEND_MSG, reply.head.msgh_size, 0,
4047 MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE,
4049 if(r != MACH_MSG_SUCCESS) {
4050 /* This will fail if the thread dies, but the thread */
4051 /* shouldn't die... */
4052 # ifdef BROKEN_EXCEPTION_HANDLING
4053 GC_err_printf("mach_msg failed with %d %s while sending "
4054 "exc reply\n", (int)r, mach_error_string(r));
4056 ABORT("mach_msg failed while sending exception reply");
4065 /* All this SIGBUS code shouldn't be necessary. All protection faults should
4066 be going through the mach exception handler. However, it seems a SIGBUS is
4067 occasionally sent for some unknown reason. Even more odd, it seems to be
4068 meaningless and safe to ignore. */
4069 #ifdef BROKEN_EXCEPTION_HANDLING
4071 /* Updates to this aren't atomic, but the SIGBUS'es seem pretty rare. */
4072 /* Even if this doesn't get updated property, it isn't really a problem. */
4073 STATIC int GC_sigbus_count = 0;
4075 STATIC void GC_darwin_sigbus(int num, siginfo_t *sip, void *context)
4078 ABORT("Got a non-sigbus signal in the sigbus handler");
4080 /* Ugh... some seem safe to ignore, but too many in a row probably means
4081 trouble. GC_sigbus_count is reset for each mach exception that is
4083 if (GC_sigbus_count >= 8) {
4084 ABORT("Got more than 8 SIGBUSs in a row!");
4087 WARN("Ignoring SIGBUS.\n", 0);
4090 #endif /* BROKEN_EXCEPTION_HANDLING */
4092 GC_INNER void GC_dirty_init(void)
4097 pthread_attr_t attr;
4098 exception_mask_t mask;
4100 # ifdef CAN_HANDLE_FORK
4101 if (GC_handle_fork) {
4102 /* To both support GC incremental mode and GC functions usage in */
4103 /* the forked child, pthread_atfork should be used to install */
4104 /* handlers that switch off GC_dirty_maintained in the child */
4105 /* gracefully (unprotecting all pages and clearing */
4106 /* GC_mach_handler_thread). For now, we just disable incremental */
4107 /* mode if fork() handling is requested by the client. */
4110 "GC incremental mode disabled since fork() handling requested\n");
4115 if (GC_print_stats == VERBOSE)
4117 "Initializing mach/darwin mprotect virtual dirty bit implementation\n");
4118 # ifdef BROKEN_EXCEPTION_HANDLING
4119 WARN("Enabling workarounds for various darwin "
4120 "exception handling bugs.\n", 0);
4122 GC_dirty_maintained = TRUE;
4123 if (GC_page_size % HBLKSIZE != 0) {
4124 ABORT("Page size not multiple of HBLKSIZE");
4127 GC_task_self = me = mach_task_self();
4129 r = mach_port_allocate(me, MACH_PORT_RIGHT_RECEIVE, &GC_ports.exception);
4130 if (r != KERN_SUCCESS)
4131 ABORT("mach_port_allocate failed (exception port)");
4133 r = mach_port_insert_right(me, GC_ports.exception, GC_ports.exception,
4134 MACH_MSG_TYPE_MAKE_SEND);
4135 if (r != KERN_SUCCESS)
4136 ABORT("mach_port_insert_right failed (exception port)");
4138 # if defined(THREADS)
4139 r = mach_port_allocate(me, MACH_PORT_RIGHT_RECEIVE, &GC_ports.reply);
4140 if(r != KERN_SUCCESS)
4141 ABORT("mach_port_allocate failed (reply port)");
4144 /* The exceptions we want to catch */
4145 mask = EXC_MASK_BAD_ACCESS;
4147 r = task_get_exception_ports(me, mask, GC_old_exc_ports.masks,
4148 &GC_old_exc_ports.count, GC_old_exc_ports.ports,
4149 GC_old_exc_ports.behaviors,
4150 GC_old_exc_ports.flavors);
4151 if (r != KERN_SUCCESS)
4152 ABORT("task_get_exception_ports failed");
4154 r = task_set_exception_ports(me, mask, GC_ports.exception, EXCEPTION_DEFAULT,
4155 GC_MACH_THREAD_STATE);
4156 if (r != KERN_SUCCESS)
4157 ABORT("task_set_exception_ports failed");
4158 if (pthread_attr_init(&attr) != 0)
4159 ABORT("pthread_attr_init failed");
4160 if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0)
4161 ABORT("pthread_attr_setdetachedstate failed");
4163 # undef pthread_create
4164 /* This will call the real pthread function, not our wrapper */
4165 if (pthread_create(&thread, &attr, GC_mprotect_thread, NULL) != 0)
4166 ABORT("pthread_create failed");
4167 pthread_attr_destroy(&attr);
4169 /* Setup the sigbus handler for ignoring the meaningless SIGBUSs */
4170 # ifdef BROKEN_EXCEPTION_HANDLING
4172 struct sigaction sa, oldsa;
4173 sa.sa_handler = (SIG_HNDLR_PTR)GC_darwin_sigbus;
4174 sigemptyset(&sa.sa_mask);
4175 sa.sa_flags = SA_RESTART|SA_SIGINFO;
4176 if (sigaction(SIGBUS, &sa, &oldsa) < 0)
4177 ABORT("sigaction failed");
4178 if ((SIG_HNDLR_PTR)oldsa.sa_handler != SIG_DFL) {
4179 if (GC_print_stats == VERBOSE)
4180 GC_err_printf("Replaced other SIGBUS handler\n");
4183 # endif /* BROKEN_EXCEPTION_HANDLING */
4186 /* The source code for Apple's GDB was used as a reference for the */
4187 /* exception forwarding code. This code is similar to be GDB code only */
4188 /* because there is only one way to do it. */
4189 STATIC kern_return_t GC_forward_exception(mach_port_t thread, mach_port_t task,
4190 exception_type_t exception,
4191 exception_data_t data,
4192 mach_msg_type_number_t data_count)
4197 exception_behavior_t behavior;
4198 thread_state_flavor_t flavor;
4200 thread_state_data_t thread_state;
4201 mach_msg_type_number_t thread_state_count = THREAD_STATE_MAX;
4203 for (i=0; i < GC_old_exc_ports.count; i++)
4204 if (GC_old_exc_ports.masks[i] & (1 << exception))
4206 if (i == GC_old_exc_ports.count)
4207 ABORT("No handler for exception!");
4209 port = GC_old_exc_ports.ports[i];
4210 behavior = GC_old_exc_ports.behaviors[i];
4211 flavor = GC_old_exc_ports.flavors[i];
4213 if (behavior == EXCEPTION_STATE || behavior == EXCEPTION_STATE_IDENTITY) {
4214 r = thread_get_state(thread, flavor, thread_state, &thread_state_count);
4215 if(r != KERN_SUCCESS)
4216 ABORT("thread_get_state failed in forward_exception");
4220 case EXCEPTION_STATE:
4221 r = exception_raise_state(port, thread, task, exception, data, data_count,
4222 &flavor, thread_state, thread_state_count,
4223 thread_state, &thread_state_count);
4225 case EXCEPTION_STATE_IDENTITY:
4226 r = exception_raise_state_identity(port, thread, task, exception, data,
4227 data_count, &flavor, thread_state,
4228 thread_state_count, thread_state,
4229 &thread_state_count);
4231 /* case EXCEPTION_DEFAULT: */ /* default signal handlers */
4232 default: /* user-supplied signal handlers */
4233 r = exception_raise(port, thread, task, exception, data, data_count);
4236 if (behavior == EXCEPTION_STATE || behavior == EXCEPTION_STATE_IDENTITY) {
4237 r = thread_set_state(thread, flavor, thread_state, thread_state_count);
4238 if (r != KERN_SUCCESS)
4239 ABORT("thread_set_state failed in forward_exception");
4244 #define FWD() GC_forward_exception(thread, task, exception, code, code_count)
4247 # define DARWIN_EXC_STATE ARM_EXCEPTION_STATE
4248 # define DARWIN_EXC_STATE_COUNT ARM_EXCEPTION_STATE_COUNT
4249 # define DARWIN_EXC_STATE_T arm_exception_state_t
4250 # define DARWIN_EXC_STATE_DAR THREAD_FLD(far)
4251 #elif defined(POWERPC)
4252 # if CPP_WORDSZ == 32
4253 # define DARWIN_EXC_STATE PPC_EXCEPTION_STATE
4254 # define DARWIN_EXC_STATE_COUNT PPC_EXCEPTION_STATE_COUNT
4255 # define DARWIN_EXC_STATE_T ppc_exception_state_t
4257 # define DARWIN_EXC_STATE PPC_EXCEPTION_STATE64
4258 # define DARWIN_EXC_STATE_COUNT PPC_EXCEPTION_STATE64_COUNT
4259 # define DARWIN_EXC_STATE_T ppc_exception_state64_t
4261 # define DARWIN_EXC_STATE_DAR THREAD_FLD(dar)
4262 #elif defined(I386) || defined(X86_64)
4263 # if CPP_WORDSZ == 32
4264 # define DARWIN_EXC_STATE x86_EXCEPTION_STATE32
4265 # define DARWIN_EXC_STATE_COUNT x86_EXCEPTION_STATE32_COUNT
4266 # define DARWIN_EXC_STATE_T x86_exception_state32_t
4268 # define DARWIN_EXC_STATE x86_EXCEPTION_STATE64
4269 # define DARWIN_EXC_STATE_COUNT x86_EXCEPTION_STATE64_COUNT
4270 # define DARWIN_EXC_STATE_T x86_exception_state64_t
4272 # define DARWIN_EXC_STATE_DAR THREAD_FLD(faultvaddr)
4274 # error FIXME for non-arm/ppc/x86 darwin
4277 /* This violates the namespace rules but there isn't anything that can */
4278 /* be done about it. The exception handling stuff is hard coded to */
4279 /* call this. catch_exception_raise, catch_exception_raise_state and */
4280 /* and catch_exception_raise_state_identity are called from OS. */
4281 GC_API_OSCALL kern_return_t
4282 catch_exception_raise(mach_port_t exception_port, mach_port_t thread,
4283 mach_port_t task, exception_type_t exception,
4284 exception_data_t code, mach_msg_type_number_t code_count)
4290 thread_state_flavor_t flavor = DARWIN_EXC_STATE;
4291 mach_msg_type_number_t exc_state_count = DARWIN_EXC_STATE_COUNT;
4292 DARWIN_EXC_STATE_T exc_state;
4294 if (exception != EXC_BAD_ACCESS || code[0] != KERN_PROTECTION_FAILURE) {
4295 # ifdef DEBUG_EXCEPTION_HANDLING
4296 /* We aren't interested, pass it on to the old handler */
4297 GC_log_printf("Exception: 0x%x Code: 0x%x 0x%x in catch...\n",
4298 exception, code_count > 0 ? code[0] : -1,
4299 code_count > 1 ? code[1] : -1);
4304 r = thread_get_state(thread, flavor, (natural_t*)&exc_state,
4306 if(r != KERN_SUCCESS) {
4307 /* The thread is supposed to be suspended while the exception */
4308 /* handler is called. This shouldn't fail. */
4309 # ifdef BROKEN_EXCEPTION_HANDLING
4310 GC_err_printf("thread_get_state failed in catch_exception_raise\n");
4311 return KERN_SUCCESS;
4313 ABORT("thread_get_state failed in catch_exception_raise");
4317 /* This is the address that caused the fault */
4318 addr = (char*) exc_state.DARWIN_EXC_STATE_DAR;
4319 if (HDR(addr) == 0) {
4320 /* Ugh... just like the SIGBUS problem above, it seems we get */
4321 /* a bogus KERN_PROTECTION_FAILURE every once and a while. We wait */
4322 /* till we get a bunch in a row before doing anything about it. */
4323 /* If a "real" fault ever occurs it'll just keep faulting over and */
4324 /* over and we'll hit the limit pretty quickly. */
4325 # ifdef BROKEN_EXCEPTION_HANDLING
4326 static char *last_fault;
4327 static int last_fault_count;
4329 if(addr != last_fault) {
4331 last_fault_count = 0;
4333 if(++last_fault_count < 32) {
4334 if(last_fault_count == 1)
4335 WARN("Ignoring KERN_PROTECTION_FAILURE at %p\n", addr);
4336 return KERN_SUCCESS;
4340 "Unexpected KERN_PROTECTION_FAILURE at %p; aborting...\n", addr);
4341 /* Can't pass it along to the signal handler because that is */
4342 /* ignoring SIGBUS signals. We also shouldn't call ABORT here as */
4343 /* signals don't always work too well from the exception handler. */
4345 # else /* BROKEN_EXCEPTION_HANDLING */
4346 /* Pass it along to the next exception handler
4347 (which should call SIGBUS/SIGSEGV) */
4349 # endif /* !BROKEN_EXCEPTION_HANDLING */
4352 # ifdef BROKEN_EXCEPTION_HANDLING
4353 /* Reset the number of consecutive SIGBUSs */
4354 GC_sigbus_count = 0;
4357 if (GC_mprotect_state == GC_MP_NORMAL) { /* common case */
4358 h = (struct hblk*)((word)addr & ~(GC_page_size-1));
4359 UNPROTECT(h, GC_page_size);
4360 for (i = 0; i < divHBLKSZ(GC_page_size); i++) {
4361 register int index = PHT_HASH(h+i);
4362 async_set_pht_entry_from_index(GC_dirty_pages, index);
4364 } else if (GC_mprotect_state == GC_MP_DISCARDING) {
4365 /* Lie to the thread for now. No sense UNPROTECT()ing the memory
4366 when we're just going to PROTECT() it again later. The thread
4367 will just fault again once it resumes */
4369 /* Shouldn't happen, i don't think */
4370 GC_err_printf("KERN_PROTECTION_FAILURE while world is stopped\n");
4373 return KERN_SUCCESS;
4377 #ifndef NO_DESC_CATCH_EXCEPTION_RAISE
4378 /* These symbols should have REFERENCED_DYNAMICALLY (0x10) bit set to */
4379 /* let strip know they are not to be stripped. */
4380 __asm__(".desc _catch_exception_raise, 0x10");
4381 __asm__(".desc _catch_exception_raise_state, 0x10");
4382 __asm__(".desc _catch_exception_raise_state_identity, 0x10");
4385 #endif /* DARWIN && MPROTECT_VDB */
4387 #ifndef HAVE_INCREMENTAL_PROTECTION_NEEDS
4388 GC_API int GC_CALL GC_incremental_protection_needs(void)
4390 return GC_PROTECTS_NONE;
4392 #endif /* !HAVE_INCREMENTAL_PROTECTION_NEEDS */
4395 /* Undo sbrk() redirection. */
4399 /* If value is non-zero then allocate executable memory. */
4400 GC_API void GC_CALL GC_set_pages_executable(int value)
4402 GC_ASSERT(!GC_is_initialized);
4403 /* Even if IGNORE_PAGES_EXECUTABLE is defined, GC_pages_executable is */
4404 /* touched here to prevent a compiler warning. */
4405 GC_pages_executable = (GC_bool)(value != 0);
4408 /* Returns non-zero if the GC-allocated memory is executable. */
4409 /* GC_get_pages_executable is defined after all the places */
4410 /* where GC_get_pages_executable is undefined. */
4411 GC_API int GC_CALL GC_get_pages_executable(void)
4413 # ifdef IGNORE_PAGES_EXECUTABLE
4414 return 1; /* Always allocate executable memory. */
4416 return (int)GC_pages_executable;
4420 /* Call stack save code for debugging. Should probably be in */
4421 /* mach_dep.c, but that requires reorganization. */
4423 /* I suspect the following works for most X86 *nix variants, so */
4424 /* long as the frame pointer is explicitly stored. In the case of gcc, */
4425 /* compiler flags (e.g. -fomit-frame-pointer) determine whether it is. */
4426 #if defined(I386) && defined(LINUX) && defined(SAVE_CALL_CHAIN)
4427 # include <features.h>
4430 struct frame *fr_savfp;
4432 long fr_arg[NARGS]; /* All the arguments go here. */
4438 # include <features.h>
4443 struct frame *fr_savfp;
4451 # elif defined (DRSNX)
4452 # include <sys/sparc/frame.h>
4453 # elif defined(OPENBSD)
4455 # elif defined(FREEBSD) || defined(NETBSD)
4456 # include <machine/frame.h>
4458 # include <sys/frame.h>
4461 # error We only know how to get the first 6 arguments
4465 #ifdef NEED_CALLINFO
4466 /* Fill in the pc and argument information for up to NFRAMES of my */
4467 /* callers. Ignore my frame and my callers frame. */
4470 # include <unistd.h>
4473 #endif /* NEED_CALLINFO */
4475 #if defined(GC_HAVE_BUILTIN_BACKTRACE)
4477 # include "private/msvc_dbg.h"
4479 # include <execinfo.h>
4483 #ifdef SAVE_CALL_CHAIN
4485 #if NARGS == 0 && NFRAMES % 2 == 0 /* No padding */ \
4486 && defined(GC_HAVE_BUILTIN_BACKTRACE)
4488 #ifdef REDIRECT_MALLOC
4489 /* Deal with possible malloc calls in backtrace by omitting */
4490 /* the infinitely recursing backtrace. */
4492 __thread /* If your compiler doesn't understand this */
4493 /* you could use something like pthread_getspecific. */
4495 GC_in_save_callers = FALSE;
4498 GC_INNER void GC_save_callers(struct callinfo info[NFRAMES])
4500 void * tmp_info[NFRAMES + 1];
4502 # define IGNORE_FRAMES 1
4504 /* We retrieve NFRAMES+1 pc values, but discard the first, since it */
4505 /* points to our own frame. */
4506 # ifdef REDIRECT_MALLOC
4507 if (GC_in_save_callers) {
4508 info[0].ci_pc = (word)(&GC_save_callers);
4509 for (i = 1; i < NFRAMES; ++i) info[i].ci_pc = 0;
4512 GC_in_save_callers = TRUE;
4514 GC_STATIC_ASSERT(sizeof(struct callinfo) == sizeof(void *));
4515 npcs = backtrace((void **)tmp_info, NFRAMES + IGNORE_FRAMES);
4516 BCOPY(tmp_info+IGNORE_FRAMES, info, (npcs - IGNORE_FRAMES) * sizeof(void *));
4517 for (i = npcs - IGNORE_FRAMES; i < NFRAMES; ++i) info[i].ci_pc = 0;
4518 # ifdef REDIRECT_MALLOC
4519 GC_in_save_callers = FALSE;
4523 #else /* No builtin backtrace; do it ourselves */
4525 #if (defined(OPENBSD) || defined(NETBSD) || defined(FREEBSD)) && defined(SPARC)
4526 # define FR_SAVFP fr_fp
4527 # define FR_SAVPC fr_pc
4529 # define FR_SAVFP fr_savfp
4530 # define FR_SAVPC fr_savpc
4533 #if defined(SPARC) && (defined(__arch64__) || defined(__sparcv9))
4539 GC_INNER void GC_save_callers(struct callinfo info[NFRAMES])
4541 struct frame *frame;
4545 /* We assume this is turned on only with gcc as the compiler. */
4546 asm("movl %%ebp,%0" : "=r"(frame));
4549 frame = (struct frame *)GC_save_regs_in_stack();
4550 fp = (struct frame *)((long) frame -> FR_SAVFP + BIAS);
4553 for (; (!(fp HOTTER_THAN frame) && !(GC_stackbottom HOTTER_THAN (ptr_t)fp)
4554 && (nframes < NFRAMES));
4555 fp = (struct frame *)((long) fp -> FR_SAVFP + BIAS), nframes++) {
4558 info[nframes].ci_pc = fp->FR_SAVPC;
4560 for (i = 0; i < NARGS; i++) {
4561 info[nframes].ci_arg[i] = ~(fp->fr_arg[i]);
4563 # endif /* NARGS > 0 */
4565 if (nframes < NFRAMES) info[nframes].ci_pc = 0;
4568 #endif /* No builtin backtrace */
4570 #endif /* SAVE_CALL_CHAIN */
4572 #ifdef NEED_CALLINFO
4574 /* Print info to stderr. We do NOT hold the allocation lock */
4575 GC_INNER void GC_print_callers(struct callinfo info[NFRAMES])
4578 static int reentry_count = 0;
4579 GC_bool stop = FALSE;
4582 /* FIXME: This should probably use a different lock, so that we */
4583 /* become callable with or without the allocation lock. */
4589 GC_err_printf("\tCaller at allocation:\n");
4591 GC_err_printf("\tCall chain at allocation:\n");
4593 for (i = 0; i < NFRAMES && !stop; i++) {
4594 if (info[i].ci_pc == 0) break;
4599 GC_err_printf("\t\targs: ");
4600 for (j = 0; j < NARGS; j++) {
4601 if (j != 0) GC_err_printf(", ");
4602 GC_err_printf("%d (0x%X)", ~(info[i].ci_arg[j]),
4603 ~(info[i].ci_arg[j]));
4605 GC_err_printf("\n");
4608 if (reentry_count > 1) {
4609 /* We were called during an allocation during */
4610 /* a previous GC_print_callers call; punt. */
4611 GC_err_printf("\t\t##PC##= 0x%lx\n", info[i].ci_pc);
4618 # if defined(GC_HAVE_BUILTIN_BACKTRACE) \
4619 && !defined(GC_BACKTRACE_SYMBOLS_BROKEN)
4621 backtrace_symbols((void **)(&(info[i].ci_pc)), 1);
4622 char *name = sym_name[0];
4626 sprintf(buf, "##PC##= 0x%lx", info[i].ci_pc);
4628 # if defined(LINUX) && !defined(SMALL_CONFIG)
4629 /* Try for a line number. */
4632 static char exe_name[EXE_SZ];
4634 char cmd_buf[CMD_SZ];
4635 # define RESULT_SZ 200
4636 static char result_buf[RESULT_SZ];
4639 # define PRELOAD_SZ 200
4640 char preload_buf[PRELOAD_SZ];
4641 static GC_bool found_exe_name = FALSE;
4642 static GC_bool will_fail = FALSE;
4644 /* Try to get it via a hairy and expensive scheme. */
4645 /* First we get the name of the executable: */
4646 if (will_fail) goto out;
4647 if (!found_exe_name) {
4648 ret_code = readlink("/proc/self/exe", exe_name, EXE_SZ);
4649 if (ret_code < 0 || ret_code >= EXE_SZ
4650 || exe_name[0] != '/') {
4651 will_fail = TRUE; /* Don't try again. */
4654 exe_name[ret_code] = '\0';
4655 found_exe_name = TRUE;
4657 /* Then we use popen to start addr2line -e <exe> <addr> */
4658 /* There are faster ways to do this, but hopefully this */
4659 /* isn't time critical. */
4660 sprintf(cmd_buf, "/usr/bin/addr2line -f -e %s 0x%lx", exe_name,
4661 (unsigned long)info[i].ci_pc);
4662 old_preload = GETENV("LD_PRELOAD");
4663 if (0 != old_preload) {
4664 if (strlen (old_preload) >= PRELOAD_SZ) {
4668 strcpy (preload_buf, old_preload);
4669 unsetenv ("LD_PRELOAD");
4671 pipe = popen(cmd_buf, "r");
4672 if (0 != old_preload
4673 && 0 != setenv ("LD_PRELOAD", preload_buf, 0)) {
4674 WARN("Failed to reset LD_PRELOAD\n", 0);
4677 || (result_len = fread(result_buf, 1, RESULT_SZ - 1, pipe))
4679 if (pipe != NULL) pclose(pipe);
4683 if (result_buf[result_len - 1] == '\n') --result_len;
4684 result_buf[result_len] = 0;
4685 if (result_buf[0] == '?'
4686 || (result_buf[result_len-2] == ':'
4687 && result_buf[result_len-1] == '0')) {
4691 /* Get rid of embedded newline, if any. Test for "main" */
4693 char * nl = strchr(result_buf, '\n');
4694 if (nl != NULL && nl < result_buf + result_len) {
4697 if (strncmp(result_buf, "main", nl - result_buf) == 0) {
4701 if (result_len < RESULT_SZ - 25) {
4702 /* Add in hex address */
4703 sprintf(result_buf + result_len, " [0x%lx]",
4704 (unsigned long)info[i].ci_pc);
4711 GC_err_printf("\t\t%s\n", name);
4712 # if defined(GC_HAVE_BUILTIN_BACKTRACE) \
4713 && !defined(GC_BACKTRACE_SYMBOLS_BROKEN)
4714 free(sym_name); /* May call GC_free; that's OK */
4723 #endif /* NEED_CALLINFO */
4725 #if defined(LINUX) && defined(__ELF__) && !defined(SMALL_CONFIG)
4726 /* Dump /proc/self/maps to GC_stderr, to enable looking up names for */
4727 /* addresses in FIND_LEAK output. */
4728 void GC_print_address_map(void)
4732 GC_err_printf("---------- Begin address map ----------\n");
4733 maps = GC_get_maps();
4734 GC_err_puts(maps != NULL ? maps : "Failed to get map!\n");
4735 GC_err_printf("---------- End address map ----------\n");
4737 #endif /* LINUX && ELF */