📄 misc.c
字号:
} else { GC_dirty_init(); } if (!GC_dirty_maintained) goto out; if (GC_dont_gc) { /* Can't easily do it. */ UNLOCK(); return; } if (GC_bytes_allocd > 0) { /* There may be unmarked reachable objects */ GC_gcollect_inner(); } /* else we're OK in assuming everything's */ /* clean since nothing can point to an */ /* unmarked object. */ GC_read_dirty();out: UNLOCK(); } else { GC_init(); }# else GC_init();# endif}#if defined(MSWIN32) || defined(MSWINCE)# if defined(_MSC_VER) && defined(_DEBUG)# include <crtdbg.h># endif# ifdef OLD_WIN32_LOG_FILE# define LOG_FILE _T("gc.log")# endif HANDLE GC_stdout = 0; void GC_deinit() { if (GC_is_initialized) { DeleteCriticalSection(&GC_write_cs); } }# ifndef THREADS# define GC_need_to_lock 0 /* Not defined without threads */# endif int GC_write(const char *buf, size_t len) { BOOL tmp; DWORD written; if (len == 0) return 0; if (GC_need_to_lock) EnterCriticalSection(&GC_write_cs); if (GC_stdout == INVALID_HANDLE_VALUE) { if (GC_need_to_lock) LeaveCriticalSection(&GC_write_cs); return -1; } else if (GC_stdout == 0) { char * file_name = GETENV("GC_LOG_FILE"); char logPath[_MAX_PATH + 5]; if (0 == file_name) {# ifdef OLD_WIN32_LOG_FILE strcpy(logPath, LOG_FILE);# else GetModuleFileName(NULL, logPath, _MAX_PATH); strcat(logPath, ".log");# endif file_name = logPath; } GC_stdout = CreateFile(logPath, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH, NULL); if (GC_stdout == INVALID_HANDLE_VALUE) ABORT("Open of log file failed"); } tmp = WriteFile(GC_stdout, buf, (DWORD)len, &written, NULL); if (!tmp) DebugBreak();# if defined(_MSC_VER) && defined(_DEBUG) _CrtDbgReport(_CRT_WARN, NULL, 0, NULL, "%.*s", len, buf);# endif if (GC_need_to_lock) LeaveCriticalSection(&GC_write_cs); return tmp ? (int)written : -1; }# undef GC_need_to_lock#endif#if defined(OS2) || defined(MACOS)FILE * GC_stdout = NULL;FILE * GC_stderr = NULL;FILE * GC_log = NULL;int GC_tmp; /* Should really be local ... */ void GC_set_files() { if (GC_stdout == NULL) { GC_stdout = stdout; } if (GC_stderr == NULL) { GC_stderr = stderr; } if (GC_log == NULL) { GC_log = stderr; } }#endif#if !defined(OS2) && !defined(MACOS) && !defined(MSWIN32) && !defined(MSWINCE) int GC_stdout = 1; int GC_stderr = 2; int GC_log = 2;# if !defined(AMIGA)# include <unistd.h># endif#endif#if !defined(MSWIN32) && !defined(MSWINCE) && !defined(OS2) \ && !defined(MACOS) && !defined(ECOS) && !defined(NOSYS)int GC_write(fd, buf, len)int fd;const char *buf;size_t len;{ register int bytes_written = 0; register int result; while (bytes_written < len) {# ifdef GC_SOLARIS_THREADS result = syscall(SYS_write, fd, buf + bytes_written, len - bytes_written);# else result = write(fd, buf + bytes_written, len - bytes_written);# endif if (-1 == result) return(result); bytes_written += result; } return(bytes_written);}#endif /* UN*X */#ifdef ECOSint GC_write(fd, buf, len){ _Jv_diag_write (buf, len); return len;}#endif#ifdef NOSYSint GC_write(fd, buf, len){ /* No writing. */ return len;}#endif#if defined(MSWIN32) || defined(MSWINCE) /* FIXME: This is pretty ugly ... */# define WRITE(f, buf, len) GC_write(buf, len)#else# if defined(OS2) || defined(MACOS)# define WRITE(f, buf, len) (GC_set_files(), \ GC_tmp = fwrite((buf), 1, (len), (f)), \ fflush(f), GC_tmp)# else# define WRITE(f, buf, len) GC_write((f), (buf), (len))# endif#endif#define BUFSZ 1024#ifdef _MSC_VER# define vsnprintf _vsnprintf#endif/* A version of printf that is unlikely to call malloc, and is thus safer *//* to call from the collector in case malloc has been bound to GC_malloc. *//* Floating point arguments ans formats should be avoided, since fp *//* conversion is more likely to allocate. *//* Assumes that no more than BUFSZ-1 characters are written at once. */void GC_printf(const char *format, ...){ va_list args; char buf[BUFSZ+1]; va_start(args, format); if (GC_quiet) return; buf[BUFSZ] = 0x15; (void) vsnprintf(buf, BUFSZ, format, args); va_end(args); if (buf[BUFSZ] != 0x15) ABORT("GC_printf clobbered stack"); if (WRITE(GC_stdout, buf, strlen(buf)) < 0) ABORT("write to stdout failed");}void GC_err_printf(const char *format, ...){ va_list args; char buf[BUFSZ+1]; va_start(args, format); buf[BUFSZ] = 0x15; (void) vsnprintf(buf, BUFSZ, format, args); va_end(args); if (buf[BUFSZ] != 0x15) ABORT("GC_printf clobbered stack"); if (WRITE(GC_stderr, buf, strlen(buf)) < 0) ABORT("write to stderr failed");}void GC_log_printf(const char *format, ...){ va_list args; char buf[BUFSZ+1]; va_start(args, format); buf[BUFSZ] = 0x15; (void) vsnprintf(buf, BUFSZ, format, args); va_end(args); if (buf[BUFSZ] != 0x15) ABORT("GC_printf clobbered stack"); if (WRITE(GC_log, buf, strlen(buf)) < 0) ABORT("write to log failed");}void GC_err_puts(const char *s){ if (WRITE(GC_stderr, s, strlen(s)) < 0) ABORT("write to stderr failed");}#if defined(LINUX) && !defined(SMALL_CONFIG)void GC_err_write(buf, len)const char *buf;size_t len;{ if (WRITE(GC_stderr, buf, len) < 0) ABORT("write to stderr failed");}#endifvoid GC_default_warn_proc(char *msg, GC_word arg){ GC_err_printf(msg, arg);}GC_warn_proc GC_current_warn_proc = GC_default_warn_proc;GC_warn_proc GC_set_warn_proc(GC_warn_proc p){ GC_warn_proc result;# ifdef GC_WIN32_THREADS GC_ASSERT(GC_is_initialized);# endif LOCK(); result = GC_current_warn_proc; GC_current_warn_proc = p; UNLOCK(); return(result);}GC_word GC_set_free_space_divisor (GC_word value){ GC_word old = GC_free_space_divisor; GC_free_space_divisor = value; return old;}#ifndef PCRvoid GC_abort(const char *msg){# if defined(MSWIN32) (void) MessageBoxA(NULL, msg, "Fatal error in gc", MB_ICONERROR|MB_OK);# else GC_err_printf("%s\n", msg);# endif if (GETENV("GC_LOOP_ON_ABORT") != NULL) { /* In many cases it's easier to debug a running process. */ /* It's arguably nicer to sleep, but that makes it harder */ /* to look at the thread if the debugger doesn't know much */ /* about threads. */ for(;;) {} }# if defined(MSWIN32) || defined(MSWINCE) DebugBreak();# else (void) abort();# endif}#endifvoid GC_enable(){ LOCK(); GC_dont_gc--; UNLOCK();}void GC_disable(){ LOCK(); GC_dont_gc++; UNLOCK();}/* Helper procedures for new kind creation. */void ** GC_new_free_list_inner(){ void *result = GC_INTERNAL_MALLOC((MAXOBJGRANULES+1)*sizeof(ptr_t), PTRFREE); if (result == 0) ABORT("Failed to allocate freelist for new kind"); BZERO(result, (MAXOBJGRANULES+1)*sizeof(ptr_t)); return result;}void ** GC_new_free_list(){ void *result; LOCK(); result = GC_new_free_list_inner(); UNLOCK(); return result;}unsigned GC_new_kind_inner(void **fl, GC_word descr, int adjust, int clear){ unsigned result = GC_n_kinds++; if (GC_n_kinds > MAXOBJKINDS) ABORT("Too many kinds"); GC_obj_kinds[result].ok_freelist = fl; GC_obj_kinds[result].ok_reclaim_list = 0; GC_obj_kinds[result].ok_descriptor = descr; GC_obj_kinds[result].ok_relocate_descr = adjust; GC_obj_kinds[result].ok_init = clear; return result;}unsigned GC_new_kind(void **fl, GC_word descr, int adjust, int clear){ unsigned result; LOCK(); result = GC_new_kind_inner(fl, descr, adjust, clear); UNLOCK(); return result;}unsigned GC_new_proc_inner(GC_mark_proc proc){ unsigned result = GC_n_mark_procs++; if (GC_n_mark_procs > MAX_MARK_PROCS) ABORT("Too many mark procedures"); GC_mark_procs[result] = proc; return result;}unsigned GC_new_proc(GC_mark_proc proc){ unsigned result; LOCK(); result = GC_new_proc_inner(proc); UNLOCK(); return result;}void * GC_call_with_stack_base(GC_stack_base_func fn, void *arg){ int dummy; struct GC_stack_base base; base.mem_base = (void *)&dummy;# ifdef IA64 base.reg_base = (void *)GC_save_regs_in_stack(); /* Unnecessarily flushes register stack, */ /* but that probably doesn't hurt. */# endif return fn(&base, arg);}#if !defined(NO_DEBUGGING)void GC_dump(){ GC_printf("***Static roots:\n"); GC_print_static_roots(); GC_printf("\n***Heap sections:\n"); GC_print_heap_sects(); GC_printf("\n***Free blocks:\n"); GC_print_hblkfreelist(); GC_printf("\n***Blocks in use:\n"); GC_print_block_list(); GC_printf("\n***Finalization statistics:\n"); GC_print_finalization_stats();}#endif /* NO_DEBUGGING */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -