diff options
Diffstat (limited to 'src/alloc.c')
-rw-r--r-- | src/alloc.c | 110 |
1 files changed, 89 insertions, 21 deletions
diff --git a/src/alloc.c b/src/alloc.c index 6eced7bab18..f2b7682b05d 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -438,10 +438,6 @@ struct mem_node enum mem_type type; }; -/* Base address of stack. Set in main. */ - -Lisp_Object *stack_base; - /* Root of the tree describing allocated Lisp memory. */ static struct mem_node *mem_root; @@ -3190,8 +3186,7 @@ vector_nbytes (struct Lisp_Vector *v) } /* Release extra resources still in use by VECTOR, which may be any - vector-like object. For now, this is used just to free data in - font objects. */ + vector-like object. */ static void cleanup_vector (struct Lisp_Vector *vector) @@ -3212,6 +3207,13 @@ cleanup_vector (struct Lisp_Vector *vector) drv->close ((struct font *) vector); } } + + if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_THREAD)) + finalize_one_thread ((struct thread_state *) vector); + else if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_MUTEX)) + finalize_one_mutex ((struct Lisp_Mutex *) vector); + else if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_CONDVAR)) + finalize_one_condvar ((struct Lisp_CondVar *) vector); } /* Reclaim space used by unmarked vectors. */ @@ -5047,14 +5049,13 @@ test_setjmp (void) would be necessary, each one starting with one byte more offset from the stack start. */ -static void -mark_stack (void *end) +void +mark_stack (char *bottom, char *end) { - /* This assumes that the stack is a contiguous region in memory. If that's not the case, something has to be done here to iterate over the stack segments. */ - mark_memory (stack_base, end); + mark_memory (bottom, end); /* Allow for marking a secondary stack, like the register stack on the ia64. */ @@ -5063,6 +5064,81 @@ mark_stack (void *end) #endif } +/* This is a trampoline function that flushes registers to the stack, + and then calls FUNC. ARG is passed through to FUNC verbatim. + + This function must be called whenever Emacs is about to release the + global interpreter lock. This lets the garbage collector easily + find roots in registers on threads that are not actively running + Lisp. + + It is invalid to run any Lisp code or to allocate any GC memory + from FUNC. */ + +void +flush_stack_call_func (void (*func) (void *arg), void *arg) +{ + void *end; + struct thread_state *self = current_thread; + +#ifdef HAVE___BUILTIN_UNWIND_INIT + /* Force callee-saved registers and register windows onto the stack. + This is the preferred method if available, obviating the need for + machine dependent methods. */ + __builtin_unwind_init (); + end = &end; +#else /* not HAVE___BUILTIN_UNWIND_INIT */ +#ifndef GC_SAVE_REGISTERS_ON_STACK + /* jmp_buf may not be aligned enough on darwin-ppc64 */ + union aligned_jmpbuf { + Lisp_Object o; + sys_jmp_buf j; + } j; + volatile bool stack_grows_down_p = (char *) &j > (char *) stack_bottom; +#endif + /* This trick flushes the register windows so that all the state of + the process is contained in the stack. */ + /* Fixme: Code in the Boehm GC suggests flushing (with `flushrs') is + needed on ia64 too. See mach_dep.c, where it also says inline + assembler doesn't work with relevant proprietary compilers. */ +#ifdef __sparc__ +#if defined (__sparc64__) && defined (__FreeBSD__) + /* FreeBSD does not have a ta 3 handler. */ + asm ("flushw"); +#else + asm ("ta 3"); +#endif +#endif + + /* Save registers that we need to see on the stack. We need to see + registers used to hold register variables and registers used to + pass parameters. */ +#ifdef GC_SAVE_REGISTERS_ON_STACK + GC_SAVE_REGISTERS_ON_STACK (end); +#else /* not GC_SAVE_REGISTERS_ON_STACK */ + +#ifndef GC_SETJMP_WORKS /* If it hasn't been checked yet that + setjmp will definitely work, test it + and print a message with the result + of the test. */ + if (!setjmp_tested_p) + { + setjmp_tested_p = 1; + test_setjmp (); + } +#endif /* GC_SETJMP_WORKS */ + + sys_setjmp (j.j); + end = stack_grows_down_p ? (char *) &j + sizeof j : (char *) &j; +#endif /* not GC_SAVE_REGISTERS_ON_STACK */ +#endif /* not HAVE___BUILTIN_UNWIND_INIT */ + + self->stack_top = end; + (*func) (arg); + + eassert (current_thread == self); +} + static bool c_symbol_p (struct Lisp_Symbol *sym) { @@ -5768,24 +5844,14 @@ garbage_collect_1 (void *end) mark_object (*staticvec[i]); mark_pinned_symbols (); - mark_specpdl (); mark_terminals (); mark_kboards (); + mark_threads (); #ifdef USE_GTK xg_mark_data (); #endif - mark_stack (end); - - { - struct handler *handler; - for (handler = handlerlist; handler; handler = handler->next) - { - mark_object (handler->tag_or_ch); - mark_object (handler->val); - } - } #ifdef HAVE_WINDOW_SYSTEM mark_fringe_data (); #endif @@ -5817,6 +5883,8 @@ garbage_collect_1 (void *end) gc_sweep (); + unmark_threads (); + /* Clear the mark bits that we set in certain root slots. */ VECTOR_UNMARK (&buffer_defaults); VECTOR_UNMARK (&buffer_local_symbols); |