📄 misc.c
字号:
return GC_bytes_allocd;}size_t GC_get_total_bytes(void){ return GC_bytes_allocd+GC_bytes_allocd_before_gc;}GC_bool GC_is_initialized = FALSE;# if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC) extern void GC_init_parallel(void);# endif /* PARALLEL_MARK || THREAD_LOCAL_ALLOC */void GC_init(void){ DCL_LOCK_STATE; #if defined(GC_WIN32_THREADS) && !defined(GC_PTHREADS) if (!GC_is_initialized) { BOOL (WINAPI *pfn) (LPCRITICAL_SECTION, DWORD) = NULL; HMODULE hK32 = GetModuleHandleA("kernel32.dll"); if (hK32) pfn = (BOOL (WINAPI *) (LPCRITICAL_SECTION, DWORD)) GetProcAddress (hK32, "InitializeCriticalSectionAndSpinCount"); if (pfn) pfn(&GC_allocate_ml, 4000); else InitializeCriticalSection (&GC_allocate_ml); }#endif /* MSWIN32 */ LOCK(); GC_init_inner(); UNLOCK();# if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC) /* Make sure marker threads and started and thread local */ /* allocation is initialized, in case we didn't get */ /* called from GC_init_parallel(); */ { GC_init_parallel(); }# endif /* PARALLEL_MARK || THREAD_LOCAL_ALLOC */# if defined(DYNAMIC_LOADING) && defined(DARWIN) { /* This must be called WITHOUT the allocation lock held and before any threads are created */ extern void GC_init_dyld(); GC_init_dyld(); }# endif}#if defined(MSWIN32) || defined(MSWINCE) CRITICAL_SECTION GC_write_cs;#endif#ifdef MSWIN32 extern void GC_init_win32(void);#endifextern void GC_setpagesize();#ifdef MSWIN32extern GC_bool GC_no_win32_dlls;#else# define GC_no_win32_dlls FALSE#endifvoid GC_exit_check(void){ GC_gcollect();}#ifdef SEARCH_FOR_DATA_START extern void GC_init_linux_data_start(void);#endif#ifdef UNIX_LIKEextern void GC_set_and_save_fault_handler(void (*handler)(int));static void looping_handler(sig)int sig;{ GC_err_printf("Caught signal %d: looping in handler\n", sig); for(;;);}static GC_bool installed_looping_handler = FALSE;static void maybe_install_looping_handler(){ /* Install looping handler before the write fault handler, so we */ /* handle write faults correctly. */ if (!installed_looping_handler && 0 != GETENV("GC_LOOP_ON_ABORT")) { GC_set_and_save_fault_handler(looping_handler); installed_looping_handler = TRUE; }}#else /* !UNIX_LIKE */# define maybe_install_looping_handler()#endifvoid GC_init_inner(){# if !defined(THREADS) && defined(GC_ASSERTIONS) word dummy;# endif word initial_heap_sz = (word)MINHINCR; if (GC_is_initialized) return;# if defined(MSWIN32) || defined(MSWINCE) InitializeCriticalSection(&GC_write_cs);# endif# if (!defined(SMALL_CONFIG)) if (0 != GETENV("GC_PRINT_STATS")) { GC_print_stats = 1; } if (0 != GETENV("GC_PRINT_VERBOSE_STATS")) { GC_print_stats = VERBOSE; } # if defined(UNIX_LIKE) { char * file_name = GETENV("GC_LOG_FILE"); if (0 != file_name) { int log_d = open(file_name, O_CREAT|O_WRONLY|O_APPEND, 0666); if (log_d < 0) { GC_log_printf("Failed to open %s as log file\n", file_name); } else { GC_log = log_d; } } }# endif# endif# ifndef NO_DEBUGGING if (0 != GETENV("GC_DUMP_REGULARLY")) { GC_dump_regularly = 1; }# endif# ifdef KEEP_BACK_PTRS { char * backtraces_string = GETENV("GC_BACKTRACES"); if (0 != backtraces_string) { GC_backtraces = atol(backtraces_string); if (backtraces_string[0] == '\0') GC_backtraces = 1; } }# endif if (0 != GETENV("GC_FIND_LEAK")) { GC_find_leak = 1; atexit(GC_exit_check); } if (0 != GETENV("GC_ALL_INTERIOR_POINTERS")) { GC_all_interior_pointers = 1; } if (0 != GETENV("GC_DONT_GC")) { GC_dont_gc = 1; } if (0 != GETENV("GC_PRINT_BACK_HEIGHT")) { GC_print_back_height = 1; } if (0 != GETENV("GC_NO_BLACKLIST_WARNING")) { GC_large_alloc_warn_interval = LONG_MAX; } { char * addr_string = GETENV("GC_TRACE"); if (0 != addr_string) {# ifndef ENABLE_TRACE WARN("Tracing not enabled: Ignoring GC_TRACE value\n", 0);# else# ifdef STRTOULL long long addr = strtoull(addr_string, NULL, 16);# else long addr = strtoul(addr_string, NULL, 16);# endif if (addr < 0x1000) WARN("Unlikely trace address: 0x%lx\n", (GC_word)addr); GC_trace_addr = (ptr_t)addr;# endif } } { char * time_limit_string = GETENV("GC_PAUSE_TIME_TARGET"); if (0 != time_limit_string) { long time_limit = atol(time_limit_string); if (time_limit < 5) { WARN("GC_PAUSE_TIME_TARGET environment variable value too small " "or bad syntax: Ignoring\n", 0); } else { GC_time_limit = time_limit; } } } { char * interval_string = GETENV("GC_LARGE_ALLOC_WARN_INTERVAL"); if (0 != interval_string) { long interval = atol(interval_string); if (interval <= 0) { WARN("GC_LARGE_ALLOC_WARN_INTERVAL environment variable has " "bad value: Ignoring\n", 0); } else { GC_large_alloc_warn_interval = interval; } } } maybe_install_looping_handler(); /* Adjust normal object descriptor for extra allocation. */ if (ALIGNMENT > GC_DS_TAGS && EXTRA_BYTES != 0) { GC_obj_kinds[NORMAL].ok_descriptor = ((word)(-ALIGNMENT) | GC_DS_LENGTH); } GC_setpagesize(); GC_exclude_static_roots(beginGC_arrays, endGC_arrays); GC_exclude_static_roots(beginGC_obj_kinds, endGC_obj_kinds);# ifdef SEPARATE_GLOBALS GC_exclude_static_roots(beginGC_objfreelist, endGC_objfreelist); GC_exclude_static_roots(beginGC_aobjfreelist, endGC_aobjfreelist);# endif# ifdef MSWIN32 GC_init_win32();# endif# if defined(USE_PROC_FOR_LIBRARIES) && defined(GC_LINUX_THREADS) WARN("USE_PROC_FOR_LIBRARIES + GC_LINUX_THREADS performs poorly.\n", 0); /* If thread stacks are cached, they tend to be scanned in */ /* entirety as part of the root set. This wil grow them to */ /* maximum size, and is generally not desirable. */# endif# if defined(SEARCH_FOR_DATA_START) GC_init_linux_data_start();# endif# if (defined(NETBSD) || defined(OPENBSD)) && defined(__ELF__) GC_init_netbsd_elf();# endif# if !defined(THREADS) || defined(GC_PTHREADS) || defined(GC_WIN32_THREADS) \ || defined(GC_SOLARIS_THREADS) if (GC_stackbottom == 0) { GC_stackbottom = GC_get_main_stack_base();# if (defined(LINUX) || defined(HPUX)) && defined(IA64) GC_register_stackbottom = GC_get_register_stack_base();# endif } else {# if (defined(LINUX) || defined(HPUX)) && defined(IA64) if (GC_register_stackbottom == 0) { WARN("GC_register_stackbottom should be set with GC_stackbottom\n", 0); /* The following may fail, since we may rely on */ /* alignment properties that may not hold with a user set */ /* GC_stackbottom. */ GC_register_stackbottom = GC_get_register_stack_base(); }# endif }# endif /* Ignore gcc -Wall warnings on the following. */ GC_STATIC_ASSERT(sizeof (ptr_t) == sizeof(word)); GC_STATIC_ASSERT(sizeof (signed_word) == sizeof(word)); GC_STATIC_ASSERT(sizeof (struct hblk) == HBLKSIZE);# ifndef THREADS# ifdef STACK_GROWS_DOWN GC_ASSERT((word)(&dummy) <= (word)GC_stackbottom);# else GC_ASSERT((word)(&dummy) >= (word)GC_stackbottom);# endif# endif# if !defined(_AUX_SOURCE) || defined(__GNUC__) GC_ASSERT((word)(-1) > (word)0); /* word should be unsigned */# endif GC_ASSERT((ptr_t)(word)(-1) > (ptr_t)0); /* Ptr_t comparisons should behave as unsigned comparisons. */ GC_ASSERT((signed_word)(-1) < (signed_word)0);# if !defined(SMALL_CONFIG) if (GC_incremental || 0 != GETENV("GC_ENABLE_INCREMENTAL")) { /* This used to test for !GC_no_win32_dlls. Why? */ GC_setpagesize(); /* For GWW_MPROTECT on Win32, this needs to happen before any */ /* heap memory is allocated. */ GC_dirty_init(); GC_ASSERT(GC_bytes_allocd == 0) GC_incremental = TRUE; }# endif /* !SMALL_CONFIG */ /* Add initial guess of root sets. Do this first, since sbrk(0) */ /* might be used. */ if (GC_REGISTER_MAIN_STATIC_DATA()) GC_register_data_segments(); GC_init_headers(); GC_bl_init(); GC_mark_init(); { char * sz_str = GETENV("GC_INITIAL_HEAP_SIZE"); if (sz_str != NULL) { initial_heap_sz = atoi(sz_str); if (initial_heap_sz <= MINHINCR * HBLKSIZE) { WARN("Bad initial heap size %s - ignoring it.\n", sz_str); } initial_heap_sz = divHBLKSZ(initial_heap_sz); } } { char * sz_str = GETENV("GC_MAXIMUM_HEAP_SIZE"); if (sz_str != NULL) { word max_heap_sz = (word)atol(sz_str); if (max_heap_sz < initial_heap_sz * HBLKSIZE) { WARN("Bad maximum heap size %s - ignoring it.\n", sz_str); } if (0 == GC_max_retries) GC_max_retries = 2; GC_set_max_heap_size(max_heap_sz); } } if (!GC_expand_hp_inner(initial_heap_sz)) { GC_err_printf("Can't start up: not enough memory\n"); EXIT(); } GC_initialize_offsets(); GC_register_displacement_inner(0L);# if defined(GC_LINUX_THREADS) && defined(REDIRECT_MALLOC) if (!GC_all_interior_pointers) { /* TLS ABI uses pointer-sized offsets for dtv. */ GC_register_displacement_inner(sizeof(void *)); }# endif GC_init_size_map();# ifdef PCR if (PCR_IL_Lock(PCR_Bool_false, PCR_allSigsBlocked, PCR_waitForever) != PCR_ERes_okay) { ABORT("Can't lock load state\n"); } else if (PCR_IL_Unlock() != PCR_ERes_okay) { ABORT("Can't unlock load state\n"); } PCR_IL_Unlock(); GC_pcr_install();# endif GC_is_initialized = TRUE;# if defined(GC_PTHREADS) || defined(GC_WIN32_THREADS) GC_thr_init();# endif COND_DUMP; /* Get black list set up and/or incremental GC started */ if (!GC_dont_precollect || GC_incremental) GC_gcollect_inner();# ifdef STUBBORN_ALLOC GC_stubborn_init();# endif# if defined(GC_LINUX_THREADS) && defined(REDIRECT_MALLOC) { extern void GC_init_lib_bounds(void); GC_init_lib_bounds(); }# endif /* Convince lint that some things are used */# ifdef LINT { extern char * GC_copyright[]; extern int GC_read(); extern void GC_register_finalizer_no_order(); GC_noop(GC_copyright, GC_find_header, GC_push_one, GC_call_with_alloc_lock, GC_read, GC_dont_expand,# ifndef NO_DEBUGGING GC_dump,# endif GC_register_finalizer_no_order); }# endif}void GC_enable_incremental(void){# if !defined(SMALL_CONFIG) && !defined(KEEP_BACK_PTRS) /* If we are keeping back pointers, the GC itself dirties all */ /* pages on which objects have been marked, making */ /* incremental GC pointless. */ if (!GC_find_leak) { DCL_LOCK_STATE; LOCK(); if (GC_incremental) goto out; GC_setpagesize(); /* if (GC_no_win32_dlls) goto out; Should be win32S test? */ maybe_install_looping_handler(); /* Before write fault handler! */ GC_incremental = TRUE; if (!GC_is_initialized) { GC_init_inner();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -