⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 os_dep.c

📁 linux下建立JAVA虚拟机的源码KAFFE
💻 C
📖 第 1 页 / 共 5 页
字号:
    static word backing_store_base_from_proc(void)    {        return GC_apply_to_maps(backing_store_base_from_maps);    }#   ifdef USE_LIBC_PRIVATES#     pragma weak __libc_ia64_register_backing_store_base      extern ptr_t __libc_ia64_register_backing_store_base;#   endif    ptr_t GC_get_register_stack_base(void)    {#     ifdef USE_LIBC_PRIVATES        if (0 != &__libc_ia64_register_backing_store_base	    && 0 != __libc_ia64_register_backing_store_base) {	  /* Glibc 2.2.4 has a bug such that for dynamically linked	*/	  /* executables __libc_ia64_register_backing_store_base is 	*/	  /* defined but uninitialized during constructor calls.  	*/	  /* Hence we check for both nonzero address and value.		*/	  return __libc_ia64_register_backing_store_base;        }#     endif      word result = backing_store_base_from_proc();      if (0 == result) {	  /* Use dumb heuristics.  Works only for default configuration. */	  result = (word)GC_stackbottom - BACKING_STORE_DISPLACEMENT;	  result += BACKING_STORE_ALIGNMENT - 1;	  result &= ~(BACKING_STORE_ALIGNMENT - 1);	  /* Verify that it's at least readable.  If not, we goofed. */	  GC_noop1(*(word *)result);       }      return (ptr_t)result;    }# endif  ptr_t GC_linux_stack_base(void)  {    /* We read the stack base value from /proc/self/stat.  We do this	*/    /* using direct I/O system calls in order to avoid calling malloc   */    /* in case REDIRECT_MALLOC is defined.				*/ #   define STAT_BUF_SIZE 4096#   define STAT_READ read	  /* Should probably call the real read, if read is wrapped.	*/    char stat_buf[STAT_BUF_SIZE];    int f;    char c;    word result = 0;    size_t i, buf_offset = 0;    /* First try the easy way.  This should work for glibc 2.2	*/    /* This fails in a prelinked ("prelink" command) executable */    /* since the correct value of __libc_stack_end never	*/    /* becomes visible to us.  The second test works around 	*/    /* this.							*/  #   ifdef USE_LIBC_PRIVATES      if (0 != &__libc_stack_end && 0 != __libc_stack_end ) {#       ifdef IA64	  /* Some versions of glibc set the address 16 bytes too	*/	  /* low while the initialization code is running.		*/	  if (((word)__libc_stack_end & 0xfff) + 0x10 < 0x1000) {	    return __libc_stack_end + 0x10;	  } /* Otherwise it's not safe to add 16 bytes and we fall	*/	    /* back to using /proc.					*/#	else #	ifdef SPARC	  /* Older versions of glibc for 64-bit Sparc do not set	   * this variable correctly, it gets set to either zero	   * or one.	   */	  if (__libc_stack_end != (ptr_t) (unsigned long)0x1)	    return __libc_stack_end;#	else	  return __libc_stack_end;#	endif#	endif      }#   endif    f = open("/proc/self/stat", O_RDONLY);    if (f < 0 || STAT_READ(f, stat_buf, STAT_BUF_SIZE) < 2 * STAT_SKIP) {	ABORT("Couldn't read /proc/self/stat");    }    c = stat_buf[buf_offset++];    /* Skip the required number of fields.  This number is hopefully	*/    /* constant across all Linux implementations.			*/      for (i = 0; i < STAT_SKIP; ++i) {	while (isspace(c)) c = stat_buf[buf_offset++];	while (!isspace(c)) c = stat_buf[buf_offset++];      }    while (isspace(c)) c = stat_buf[buf_offset++];    while (isdigit(c)) {      result *= 10;      result += c - '0';      c = stat_buf[buf_offset++];    }    close(f);    if (result < 0x10000000) ABORT("Absurd stack bottom value");    return (ptr_t)result;  }#endif /* LINUX_STACKBOTTOM */#ifdef FREEBSD_STACKBOTTOM/* This uses an undocumented sysctl call, but at least one expert 	*//* believes it will stay.						*/#include <unistd.h>#include <sys/types.h>#include <sys/sysctl.h>  ptr_t GC_freebsd_stack_base(void)  {    int nm[2] = {CTL_KERN, KERN_USRSTACK};    ptr_t base;    size_t len = sizeof(ptr_t);    int r = sysctl(nm, 2, &base, &len, NULL, 0);        if (r) ABORT("Error getting stack base");    return base;  }#endif /* FREEBSD_STACKBOTTOM */#if !defined(BEOS) && !defined(AMIGA) && !defined(MSWIN32) \    && !defined(MSWINCE) && !defined(OS2) && !defined(NOSYS) && !defined(ECOS)ptr_t GC_get_stack_base(){#   if defined(HEURISTIC1) || defined(HEURISTIC2) || \       defined(LINUX_STACKBOTTOM) || defined(FREEBSD_STACKBOTTOM)    word dummy;    ptr_t result;#   endif#   define STACKBOTTOM_ALIGNMENT_M1 ((word)STACK_GRAN - 1)#   ifdef STACKBOTTOM	return(STACKBOTTOM);#   else#	ifdef HEURISTIC1#	   ifdef STACK_GROWS_DOWN	     result = (ptr_t)((((word)(&dummy))	     		       + STACKBOTTOM_ALIGNMENT_M1)			      & ~STACKBOTTOM_ALIGNMENT_M1);#	   else	     result = (ptr_t)(((word)(&dummy))			      & ~STACKBOTTOM_ALIGNMENT_M1);#	   endif#	endif /* HEURISTIC1 */#	ifdef LINUX_STACKBOTTOM	   result = GC_linux_stack_base();#	endif#	ifdef FREEBSD_STACKBOTTOM	   result = GC_freebsd_stack_base();#	endif#	ifdef HEURISTIC2#	    ifdef STACK_GROWS_DOWN		result = GC_find_limit((ptr_t)(&dummy), TRUE);#           	ifdef HEURISTIC2_LIMIT		    if (result > HEURISTIC2_LIMIT		        && (ptr_t)(&dummy) < HEURISTIC2_LIMIT) {		            result = HEURISTIC2_LIMIT;		    }#	        endif#	    else		result = GC_find_limit((ptr_t)(&dummy), FALSE);#           	ifdef HEURISTIC2_LIMIT		    if (result < HEURISTIC2_LIMIT		        && (ptr_t)(&dummy) > HEURISTIC2_LIMIT) {		            result = HEURISTIC2_LIMIT;		    }#	        endif#	    endif#	endif /* HEURISTIC2 */#	ifdef STACK_GROWS_DOWN	    if (result == 0) result = (ptr_t)(signed_word)(-sizeof(ptr_t));#	endif    	return(result);#   endif /* STACKBOTTOM */}# endif /* ! AMIGA, !OS 2, ! MS Windows, !BEOS, !NOSYS, !ECOS *//* * Register static data segment(s) as roots. * If more data segments are added later then they need to be registered * add that point (as we do with SunOS dynamic loading), * or GC_mark_roots needs to check for them (as we do with PCR). * Called with allocator lock held. */# ifdef OS2void GC_register_data_segments(){    PTIB ptib;    PPIB ppib;    HMODULE module_handle;#   define PBUFSIZ 512    UCHAR path[PBUFSIZ];    FILE * myexefile;    struct exe_hdr hdrdos;	/* MSDOS header.	*/    struct e32_exe hdr386;	/* Real header for my executable */    struct o32_obj seg;	/* Currrent segment */    int nsegs;            if (DosGetInfoBlocks(&ptib, &ppib) != NO_ERROR) {    	GC_err_printf0("DosGetInfoBlocks failed\n");    	ABORT("DosGetInfoBlocks failed\n");    }    module_handle = ppib -> pib_hmte;    if (DosQueryModuleName(module_handle, PBUFSIZ, path) != NO_ERROR) {    	GC_err_printf0("DosQueryModuleName failed\n");    	ABORT("DosGetInfoBlocks failed\n");    }    myexefile = fopen(path, "rb");    if (myexefile == 0) {        GC_err_puts("Couldn't open executable ");        GC_err_puts(path); GC_err_puts("\n");        ABORT("Failed to open executable\n");    }    if (fread((char *)(&hdrdos), 1, sizeof hdrdos, myexefile) < sizeof hdrdos) {        GC_err_puts("Couldn't read MSDOS header from ");        GC_err_puts(path); GC_err_puts("\n");        ABORT("Couldn't read MSDOS header");    }    if (E_MAGIC(hdrdos) != EMAGIC) {        GC_err_puts("Executable has wrong DOS magic number: ");        GC_err_puts(path); GC_err_puts("\n");        ABORT("Bad DOS magic number");    }    if (fseek(myexefile, E_LFANEW(hdrdos), SEEK_SET) != 0) {        GC_err_puts("Seek to new header failed in ");        GC_err_puts(path); GC_err_puts("\n");        ABORT("Bad DOS magic number");    }    if (fread((char *)(&hdr386), 1, sizeof hdr386, myexefile) < sizeof hdr386) {        GC_err_puts("Couldn't read MSDOS header from ");        GC_err_puts(path); GC_err_puts("\n");        ABORT("Couldn't read OS/2 header");    }    if (E32_MAGIC1(hdr386) != E32MAGIC1 || E32_MAGIC2(hdr386) != E32MAGIC2) {        GC_err_puts("Executable has wrong OS/2 magic number:");        GC_err_puts(path); GC_err_puts("\n");        ABORT("Bad OS/2 magic number");    }    if ( E32_BORDER(hdr386) != E32LEBO || E32_WORDER(hdr386) != E32LEWO) {        GC_err_puts("Executable %s has wrong byte order: ");        GC_err_puts(path); GC_err_puts("\n");        ABORT("Bad byte order");    }    if ( E32_CPU(hdr386) == E32CPU286) {        GC_err_puts("GC can't handle 80286 executables: ");        GC_err_puts(path); GC_err_puts("\n");        EXIT();    }    if (fseek(myexefile, E_LFANEW(hdrdos) + E32_OBJTAB(hdr386),    	      SEEK_SET) != 0) {        GC_err_puts("Seek to object table failed: ");        GC_err_puts(path); GC_err_puts("\n");        ABORT("Seek to object table failed");    }    for (nsegs = E32_OBJCNT(hdr386); nsegs > 0; nsegs--) {      int flags;      if (fread((char *)(&seg), 1, sizeof seg, myexefile) < sizeof seg) {        GC_err_puts("Couldn't read obj table entry from ");        GC_err_puts(path); GC_err_puts("\n");        ABORT("Couldn't read obj table entry");      }      flags = O32_FLAGS(seg);      if (!(flags & OBJWRITE)) continue;      if (!(flags & OBJREAD)) continue;      if (flags & OBJINVALID) {          GC_err_printf0("Object with invalid pages?\n");          continue;      }       GC_add_roots_inner(O32_BASE(seg), O32_BASE(seg)+O32_SIZE(seg), FALSE);    }}# else /* !OS2 */# if defined(MSWIN32) || defined(MSWINCE)# ifdef MSWIN32  /* Unfortunately, we have to handle win32s very differently from NT, 	*/  /* Since VirtualQuery has very different semantics.  In particular,	*/  /* under win32s a VirtualQuery call on an unmapped page returns an	*/  /* invalid result.  Under NT, GC_register_data_segments is a noop and	*/  /* all real work is done by GC_register_dynamic_libraries.  Under	*/  /* win32s, we cannot find the data segments associated with dll's.	*/  /* We register the main data segment here.				*/  GC_bool GC_no_win32_dlls = FALSE;	   	/* This used to be set for gcc, to avoid dealing with		*/  	/* the structured exception handling issues.  But we now have	*/  	/* assembly code to do that right.				*/    void GC_init_win32()  {    /* if we're running under win32s, assume that no DLLs will be loaded */    DWORD v = GetVersion();    GC_no_win32_dlls |= ((v & 0x80000000) && (v & 0xff) <= 3);  }  /* Return the smallest address a such that VirtualQuery		*/  /* returns correct results for all addresses between a and start.	*/  /* Assumes VirtualQuery returns correct information for start.	*/  ptr_t GC_least_described_address(ptr_t start)  {      MEMORY_BASIC_INFORMATION buf;    DWORD result;    LPVOID limit;    ptr_t p;    LPVOID q;        limit = GC_sysinfo.lpMinimumApplicationAddress;    p = (ptr_t)((word)start & ~(GC_page_size - 1));    for (;;) {    	q = (LPVOID)(p - GC_page_size);    	if ((ptr_t)q > (ptr_t)p /* underflow */ || q < limit) break;    	result = VirtualQuery(q, &buf, sizeof(buf));    	if (result != sizeof(buf) || buf.AllocationBase == 0) break;    	p = (ptr_t)(buf.AllocationBase);    }    return(p);  }# endif# ifndef REDIRECT_MALLOC  /* We maintain a linked list of AllocationBase values that we know	*/  /* correspond to malloc heap sections.  Currently this is only called */  /* during a GC.  But there is some hope that for long running		*/  /* programs we will eventually see most heap sections.		*/  /* In the long run, it would be more reliable to occasionally walk 	*/  /* the malloc heap with HeapWalk on the default heap.  But that	*/  /* apparently works only for NT-based Windows. 			*/   /* In the long run, a better data structure would also be nice ...	*/  struct GC_malloc_heap_list {    void * allocation_base;    struct GC_malloc_heap_list *next;  } *GC_malloc_heap_l = 0;  /* Is p the base of one of the malloc heap sections we already know	*/  /* about?								*/  GC_bool GC_is_malloc_heap_base(ptr_t p)  {    struct GC_malloc_heap_list *q = GC_malloc_heap_l;    while (0 != q) {      if (q -> allocation_base == p) return TRUE;      q = q -> next;    }    return FALSE;  }  void *GC_get_allocation_base(void *p)  {    MEMORY_BASIC_INFORMATION buf;    DWORD result = VirtualQuery(p, &buf, sizeof(buf));    if (result != sizeof(buf)) {      ABORT("Weird VirtualQuery result");    }    return buf.AllocationBase;  }  size_t GC_max_root_size = 100000;	/* Appr. largest root size.	*/  void GC_add_current_malloc_heap()  {    struct GC_malloc_heap_list *new_l =                 malloc(sizeof(struct GC_malloc_heap_list));    void * candidate = GC_get_allocation_base(new_l);    if (new_l == 0) return;    if (GC_is_malloc_heap_base(candidate)) {      /* Try a little harder to find malloc heap.			*/	size_t req_size = 10000;	do {	  void *p = malloc(req_size);	  if (0 == p) { free(new_l); return; } 	  candidate = GC_get_allocation_base(p);	  free(p);	  req_size *= 2;	} while (GC_is_malloc_heap_base(candidate)	         && req_size < GC_max_root_size/10 && req_size < 500000);	if (GC_is_malloc_heap_base(candidate)) {	  free(new_l); return;	}    }#   ifdef CONDPRINT      if (GC_print_stats)	  GC_printf1("Found new system malloc AllocationBase at 0x%lx\n",                     candidate);#   endif    new_l -> allocation_base = candidate;    new_l -> next = GC_malloc_heap_l;    GC_malloc_heap_l = new_l;  }# endif /* REDIRECT_MALLOC */    /* Is p the start of either the malloc heap, or of one of our */  /* heap sections?						*/  GC_bool GC_is_heap_base (ptr_t p)  {          unsigned i;     #    ifndef REDIRECT_MALLOC       static word last_gc_no = -1;            if (last_gc_no != GC_gc_no) {	 GC_add_current_malloc_heap();	 last_gc_no = GC_gc_no;       }       if (GC_root_size > GC_max_root_size) GC_max_root_size = GC_root_size;       if (GC_is_malloc_heap_base(p)) return TRUE;#    endif     for (i = 0; i < GC_n_heap_bases; i++) {         if (GC_heap_bases[i] == p) return TRUE;     }     return FALSE ;  }# ifdef MSWIN32  void GC_register_root_section(ptr_t static_root)  {      MEMORY_BASIC_INFORMATION buf;      DWORD result;      DWORD protect;      LPVOID p;      char * base;      char * limit, * new_limit;          if (!GC_no_win32_dlls) return;      p = base = limit = GC_least_described_address(static_root);      while (p < GC_sysinfo.lpMaximumApplicationAddress) {        result = VirtualQuery(p, &buf, sizeof(buf));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -