📄 os_dep.c
字号:
unsigned long mapsize; unsigned long reserved;};#define O32_FLAGS(x) (x).flags#define OBJREAD 0x0001L#define OBJWRITE 0x0002L#define OBJINVALID 0x0080L#define O32_SIZE(x) (x).size#define O32_BASE(x) (x).base# else /* IBM's compiler *//* A kludge to get around what appears to be a header file bug */# ifndef WORD# define WORD unsigned short# endif# ifndef DWORD# define DWORD unsigned long# endif# define EXE386 1# include <newexe.h># include <exe386.h># endif /* __IBMC__ */# define INCL_DOSEXCEPTIONS# define INCL_DOSPROCESS# define INCL_DOSERRORS# define INCL_DOSMODULEMGR# define INCL_DOSMEMMGR# include <os2.h>/* Disable and enable signals during nontrivial allocations */void GC_disable_signals(void){ ULONG nest; DosEnterMustComplete(&nest); if (nest != 1) ABORT("nested GC_disable_signals");}void GC_enable_signals(void){ ULONG nest; DosExitMustComplete(&nest); if (nest != 0) ABORT("GC_enable_signals");}# else# if !defined(PCR) && !defined(AMIGA) && !defined(MSWIN32) \ && !defined(MSWINCE) \ && !defined(MACOS) && !defined(DJGPP) && !defined(DOS4GW) \ && !defined(NOSYS) && !defined(ECOS)# if defined(sigmask) && !defined(UTS4) && !defined(HURD) /* Use the traditional BSD interface */# define SIGSET_T int# define SIG_DEL(set, signal) (set) &= ~(sigmask(signal))# define SIG_FILL(set) (set) = 0x7fffffff /* Setting the leading bit appears to provoke a bug in some */ /* longjmp implementations. Most systems appear not to have */ /* a signal 32. */# define SIGSETMASK(old, new) (old) = sigsetmask(new)# else /* Use POSIX/SYSV interface */# define SIGSET_T sigset_t# define SIG_DEL(set, signal) sigdelset(&(set), (signal))# define SIG_FILL(set) sigfillset(&set)# define SIGSETMASK(old, new) sigprocmask(SIG_SETMASK, &(new), &(old))# endifstatic GC_bool mask_initialized = FALSE;static SIGSET_T new_mask;static SIGSET_T old_mask;static SIGSET_T dummy;#if defined(PRINTSTATS) && !defined(THREADS)# define CHECK_SIGNALS int GC_sig_disabled = 0;#endifvoid GC_disable_signals(){ if (!mask_initialized) { SIG_FILL(new_mask); SIG_DEL(new_mask, SIGSEGV); SIG_DEL(new_mask, SIGILL); SIG_DEL(new_mask, SIGQUIT);# ifdef SIGBUS SIG_DEL(new_mask, SIGBUS);# endif# ifdef SIGIOT SIG_DEL(new_mask, SIGIOT);# endif# ifdef SIGEMT SIG_DEL(new_mask, SIGEMT);# endif# ifdef SIGTRAP SIG_DEL(new_mask, SIGTRAP);# endif mask_initialized = TRUE; }# ifdef CHECK_SIGNALS if (GC_sig_disabled != 0) ABORT("Nested disables"); GC_sig_disabled++;# endif SIGSETMASK(old_mask,new_mask);}void GC_enable_signals(){# ifdef CHECK_SIGNALS if (GC_sig_disabled != 1) ABORT("Unmatched enable"); GC_sig_disabled--;# endif SIGSETMASK(dummy,old_mask);}# endif /* !PCR */# endif /*!OS/2 *//* Ivan Demakov: simplest way (to me) */#if defined (DOS4GW) void GC_disable_signals() { } void GC_enable_signals() { }#endif/* Find the page size */word GC_page_size;# if defined(MSWIN32) || defined(MSWINCE) void GC_setpagesize() { GetSystemInfo(&GC_sysinfo); GC_page_size = GC_sysinfo.dwPageSize; }# else# if defined(MPROTECT_VDB) || defined(PROC_VDB) || defined(USE_MMAP) \ || defined(USE_MUNMAP) void GC_setpagesize() { GC_page_size = GETPAGESIZE(); }# else /* It's acceptable to fake it. */ void GC_setpagesize() { GC_page_size = HBLKSIZE; }# endif# endif/* * Find the base of the stack. * Used only in single-threaded environment. * With threads, GC_mark_roots needs to know how to do this. * Called with allocator lock held. */# if defined(MSWIN32) || defined(MSWINCE)# define is_writable(prot) ((prot) == PAGE_READWRITE \ || (prot) == PAGE_WRITECOPY \ || (prot) == PAGE_EXECUTE_READWRITE \ || (prot) == PAGE_EXECUTE_WRITECOPY)/* Return the number of bytes that are writable starting at p. *//* The pointer p is assumed to be page aligned. *//* If base is not 0, *base becomes the beginning of the *//* allocation region containing p. */word GC_get_writable_length(ptr_t p, ptr_t *base){ MEMORY_BASIC_INFORMATION buf; word result; word protect; result = VirtualQuery(p, &buf, sizeof(buf)); if (result != sizeof(buf)) ABORT("Weird VirtualQuery result"); if (base != 0) *base = (ptr_t)(buf.AllocationBase); protect = (buf.Protect & ~(PAGE_GUARD | PAGE_NOCACHE)); if (!is_writable(protect)) { return(0); } if (buf.State != MEM_COMMIT) return(0); return(buf.RegionSize);}ptr_t GC_get_stack_base(){ int dummy; ptr_t sp = (ptr_t)(&dummy); ptr_t trunc_sp = (ptr_t)((word)sp & ~(GC_page_size - 1)); word size = GC_get_writable_length(trunc_sp, 0); return(trunc_sp + size);}# endif /* MS Windows */# ifdef BEOS# include <kernel/OS.h>ptr_t GC_get_stack_base(){ thread_info th; get_thread_info(find_thread(NULL),&th); return th.stack_end;}# endif /* BEOS */# ifdef OS2ptr_t GC_get_stack_base(){ PTIB ptib; PPIB ppib; if (DosGetInfoBlocks(&ptib, &ppib) != NO_ERROR) { GC_err_printf0("DosGetInfoBlocks failed\n"); ABORT("DosGetInfoBlocks failed\n"); } return((ptr_t)(ptib -> tib_pstacklimit));}# endif /* OS2 */# ifdef AMIGA# define GC_AMIGA_SB# include "AmigaOS.c"# undef GC_AMIGA_SB# endif /* AMIGA */# if defined(NEED_FIND_LIMIT) || defined(UNIX_LIKE)# ifdef __STDC__ typedef void (*handler)(int);# else typedef void (*handler)();# endif# if defined(SUNOS5SIGS) || defined(IRIX5) || defined(OSF1) \ || defined(HURD) || defined(NETBSD) static struct sigaction old_segv_act;# if defined(IRIX5) || defined(HPUX) \ || defined(HURD) || defined(NETBSD) static struct sigaction old_bus_act;# endif# else static handler old_segv_handler, old_bus_handler;# endif # ifdef __STDC__ void GC_set_and_save_fault_handler(handler h)# else void GC_set_and_save_fault_handler(h) handler h;# endif {# if defined(SUNOS5SIGS) || defined(IRIX5) \ || defined(OSF1) || defined(HURD) || defined(NETBSD) struct sigaction act; act.sa_handler = h;# if 0 /* Was necessary for Solaris 2.3 and very temporary */ /* NetBSD bugs. */ act.sa_flags = SA_RESTART | SA_NODEFER;# else act.sa_flags = SA_RESTART;# endif (void) sigemptyset(&act.sa_mask);# ifdef GC_IRIX_THREADS /* Older versions have a bug related to retrieving and */ /* and setting a handler at the same time. */ (void) sigaction(SIGSEGV, 0, &old_segv_act); (void) sigaction(SIGSEGV, &act, 0); (void) sigaction(SIGBUS, 0, &old_bus_act); (void) sigaction(SIGBUS, &act, 0);# else (void) sigaction(SIGSEGV, &act, &old_segv_act);# if defined(IRIX5) \ || defined(HPUX) || defined(HURD) || defined(NETBSD) /* Under Irix 5.x or HP/UX, we may get SIGBUS. */ /* Pthreads doesn't exist under Irix 5.x, so we */ /* don't have to worry in the threads case. */ (void) sigaction(SIGBUS, &act, &old_bus_act);# endif# endif /* GC_IRIX_THREADS */# else old_segv_handler = signal(SIGSEGV, h);# ifdef SIGBUS old_bus_handler = signal(SIGBUS, h);# endif# endif }# endif /* NEED_FIND_LIMIT || UNIX_LIKE */# ifdef NEED_FIND_LIMIT /* Some tools to implement HEURISTIC2 */# define MIN_PAGE_SIZE 256 /* Smallest conceivable page size, bytes */ /* static */ JMP_BUF GC_jmp_buf; /*ARGSUSED*/ void GC_fault_handler(sig) int sig; { LONGJMP(GC_jmp_buf, 1); } void GC_setup_temporary_fault_handler() { GC_set_and_save_fault_handler(GC_fault_handler); } void GC_reset_fault_handler() {# if defined(SUNOS5SIGS) || defined(IRIX5) \ || defined(OSF1) || defined(HURD) || defined(NETBSD) (void) sigaction(SIGSEGV, &old_segv_act, 0);# if defined(IRIX5) \ || defined(HPUX) || defined(HURD) || defined(NETBSD) (void) sigaction(SIGBUS, &old_bus_act, 0);# endif# else (void) signal(SIGSEGV, old_segv_handler);# ifdef SIGBUS (void) signal(SIGBUS, old_bus_handler);# endif# endif } /* Return the first nonaddressible location > p (up) or */ /* the smallest location q s.t. [q,p) is addressable (!up). */ /* We assume that p (up) or p-1 (!up) is addressable. */ ptr_t GC_find_limit(p, up) ptr_t p; GC_bool up; { static VOLATILE ptr_t result; /* Needs to be static, since otherwise it may not be */ /* preserved across the longjmp. Can safely be */ /* static since it's only called once, with the */ /* allocation lock held. */ GC_setup_temporary_fault_handler(); if (SETJMP(GC_jmp_buf) == 0) { result = (ptr_t)(((word)(p)) & ~(MIN_PAGE_SIZE-1)); for (;;) { if (up) { result += MIN_PAGE_SIZE; } else { result -= MIN_PAGE_SIZE; } GC_noop1((word)(*result)); } } GC_reset_fault_handler(); if (!up) { result += MIN_PAGE_SIZE; } return(result); }# endif#if defined(ECOS) || defined(NOSYS) ptr_t GC_get_stack_base() { return STACKBOTTOM; }#endif#ifdef HPUX_STACKBOTTOM#include <sys/param.h>#include <sys/pstat.h> ptr_t GC_get_register_stack_base(void) { struct pst_vm_status vm_status; int i = 0; while (pstat_getprocvm(&vm_status, sizeof(vm_status), 0, i++) == 1) { if (vm_status.pst_type == PS_RSESTACK) { return (ptr_t) vm_status.pst_vaddr; } } /* old way to get the register stackbottom */ return (ptr_t)(((word)GC_stackbottom - BACKING_STORE_DISPLACEMENT - 1) & ~(BACKING_STORE_ALIGNMENT - 1)); }#endif /* HPUX_STACK_BOTTOM */#ifdef LINUX_STACKBOTTOM#include <sys/types.h>#include <sys/stat.h># define STAT_SKIP 27 /* Number of fields preceding startstack */ /* field in /proc/self/stat */#ifdef USE_LIBC_PRIVATES# pragma weak __libc_stack_end extern ptr_t __libc_stack_end;#endif# ifdef IA64 /* Try to read the backing store base from /proc/self/maps. */ /* We look for the writable mapping with a 0 major device, */ /* which is as close to our frame as possible, but below it.*/ static word backing_store_base_from_maps(char *maps) { char prot_buf[5]; char *buf_ptr = maps; word start, end; unsigned int maj_dev; word current_best = 0; word dummy; for (;;) { buf_ptr = GC_parse_map_entry(buf_ptr, &start, &end, prot_buf, &maj_dev); if (buf_ptr == NULL) return current_best; if (prot_buf[1] == 'w' && maj_dev == 0) { if (end < (word)(&dummy) && start > current_best) current_best = start; } } return current_best; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -