X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fruntime%2Fgc-common.c;h=11b3addeb48bab77441993fe34fd5e9e1506e608;hb=4f86979ad00797600929481bc01c08e00de266a1;hp=a439957d23bad509c3793c6fb1a4620f503e88f6;hpb=1479483c5f40fc470053da0fc5cd8e42fc77676e;p=sbcl.git diff --git a/src/runtime/gc-common.c b/src/runtime/gc-common.c index a439957..11b3add 100644 --- a/src/runtime/gc-common.c +++ b/src/runtime/gc-common.c @@ -53,6 +53,8 @@ #endif #endif +size_t dynamic_space_size = DEFAULT_DYNAMIC_SPACE_SIZE; + inline static boolean forwarding_pointer_p(lispobj *pointer) { lispobj first_word=*pointer; @@ -365,6 +367,7 @@ scav_code_header(lispobj *where, lispobj object) scavenge(&function_ptr->name, 1); scavenge(&function_ptr->arglist, 1); scavenge(&function_ptr->type, 1); + scavenge(&function_ptr->xrefs, 1); } return n_words; @@ -2081,12 +2084,11 @@ gc_init_tables(void) scavtab[SIMPLE_FUN_HEADER_WIDETAG] = scav_fun_header; scavtab[RETURN_PC_HEADER_WIDETAG] = scav_return_pc_header; #endif + scavtab[FUNCALLABLE_INSTANCE_HEADER_WIDETAG] = scav_boxed; #if defined(LISP_FEATURE_X86) || defined(LISP_FEATURE_X86_64) scavtab[CLOSURE_HEADER_WIDETAG] = scav_closure_header; - scavtab[FUNCALLABLE_INSTANCE_HEADER_WIDETAG] = scav_closure_header; #else scavtab[CLOSURE_HEADER_WIDETAG] = scav_boxed; - scavtab[FUNCALLABLE_INSTANCE_HEADER_WIDETAG] = scav_boxed; #endif scavtab[VALUE_CELL_HEADER_WIDETAG] = scav_boxed; scavtab[SYMBOL_HEADER_WIDETAG] = scav_boxed; @@ -2433,3 +2435,60 @@ gc_search_space(lispobj *start, size_t words, lispobj *pointer) } return (NULL); } + +boolean +maybe_gc(os_context_t *context) +{ +#ifndef LISP_FEATURE_WIN32 + struct thread *thread = arch_os_get_current_thread(); +#endif + + fake_foreign_function_call(context); + /* SUB-GC may return without GCing if *GC-INHIBIT* is set, in + * which case we will be running with no gc trigger barrier + * thing for a while. But it shouldn't be long until the end + * of WITHOUT-GCING. + * + * FIXME: It would be good to protect the end of dynamic space for + * CheneyGC and signal a storage condition from there. + */ + + /* Restore the signal mask from the interrupted context before + * calling into Lisp if interrupts are enabled. Why not always? + * + * Suppose there is a WITHOUT-INTERRUPTS block far, far out. If an + * interrupt hits while in SUB-GC, it is deferred and the + * os_context_sigmask of that interrupt is set to block further + * deferrable interrupts (until the first one is + * handled). Unfortunately, that context refers to this place and + * when we return from here the signals will not be blocked. + * + * A kludgy alternative is to propagate the sigmask change to the + * outer context. + */ +#ifndef LISP_FEATURE_WIN32 + if(SymbolValue(INTERRUPTS_ENABLED,thread)!=NIL) { + sigset_t *context_sigmask = os_context_sigmask_addr(context); +#ifdef LISP_FEATURE_SB_THREAD + /* What if the context we'd like to restore has GC signals + * blocked? Just skip the GC: we can't set GC_PENDING, because + * that would block the next attempt, and we don't know when + * we'd next check for it -- and it's hard to be sure that + * unblocking would be safe. */ + if (sigismember(context_sigmask,SIG_STOP_FOR_GC)) { + undo_fake_foreign_function_call(context); + return 1; + } +#endif + thread_sigmask(SIG_SETMASK, context_sigmask, 0); + } + else + unblock_gc_signals(); +#endif + /* SIG_STOP_FOR_GC needs to be enabled before we can call lisp: + * otherwise two threads racing here may deadlock: the other will + * wait on the GC lock, and the other cannot stop the first one... */ + funcall0(SymbolFunction(SUB_GC)); + undo_fake_foreign_function_call(context); + return 1; +}