Update of /cvsroot/sbcl/sbcl/src/runtime
In directory sc8-pr-cvs1:/tmp/cvs-serv12069/src/runtime
Modified Files:
Tag: dan_native_threads_branch
interrupt.c thread.c thread.h validate.c validate.h
x86-linux-os.c
Log Message:
0.7.54.thread.13
#+quis-custodiet-control-stack
Reintroduce the control stack exhaustion checking that had
been disabled when doing the original cope-with-multi-threads
work.
New static symbol *current-thread* (actually an aligned
machine word that looks like a fixnum, *current-thread-address*
would be a better name)
protect_control_stack_guard_page gets another arg for the
thread whose control stack needs guarding. Lisp glue hides
this, though
Nopify uninstall_low_level_interrupt_handlers_atexit for the
time being: we don't want the first exiting thread to remove
our handlers for all the others
Index: interrupt.c
===================================================================
RCS file: /cvsroot/sbcl/sbcl/src/runtime/interrupt.c,v
retrieving revision 1.32.4.3
retrieving revision 1.32.4.4
diff -u -d -r1.32.4.3 -r1.32.4.4
--- interrupt.c 2 Dec 2002 15:57:53 -0000 1.32.4.3
+++ interrupt.c 18 Dec 2002 17:23:44 -0000 1.32.4.4
@@ -107,7 +107,7 @@
*/
void
-build_fake_control_stack_frames(os_context_t *context)
+build_fake_control_stack_frames(struct thread *th,os_context_t *context)
{
#ifndef LISP_FEATURE_X86
@@ -177,7 +177,7 @@
(lispobj *)(*os_context_register_addr(context, reg_BSP));
#endif
- build_fake_control_stack_frames(context);
+ build_fake_control_stack_frames(thread,context);
/* Do dynamic binding of the active interrupt context index
* and save the context in the context array. */
@@ -524,9 +524,57 @@
boolean handle_control_stack_guard_triggered(os_context_t *context,void *addr)
{
- /* not thinking too hard about this just now */
- /* FIXME so think! */
- return 0;
+ struct thread *th=arch_os_get_current_thread();
+ /* note the os_context hackery here. When the signal handler returns,
+ * it won't go back to what it was doing ... */
+ if(addr>=(void *)CONTROL_STACK_GUARD_PAGE(th) &&
+ addr<(void *)(CONTROL_STACK_GUARD_PAGE(th)+os_vm_page_size)) {
+ void *fun;
+ void *code;
+ /* fprintf(stderr, "hit end of control stack\n"); */
+ /* we hit the end of the control stack. disable protection
+ * temporarily so the error handler has some headroom */
+ protect_control_stack_guard_page(th,0L);
+
+ fun = (void *)
+ native_pointer((lispobj) SymbolFunction(CONTROL_STACK_EXHAUSTED_ERROR));
+ code = &(((struct simple_fun *) fun)->code);
+
+ /* Build a stack frame showing `interrupted' so that the
+ * user's backtrace makes (as much) sense (as usual) */
+ build_fake_control_stack_frames(th,context);
+ /* signal handler will "return" to this error-causing function */
+ *os_context_pc_addr(context) = code;
+#ifdef LISP_FEATURE_X86
+ *os_context_register_addr(context,reg_ECX) = 0;
+#else
+ /* this much of the calling convention is common to all
+ non-x86 ports */
+ *os_context_register_addr(context,reg_NARGS) = 0;
+ *os_context_register_addr(context,reg_LIP) = code;
+ *os_context_register_addr(context,reg_CFP) =
+ current_control_frame_pointer;
+#endif
+#ifdef ARCH_HAS_NPC_REGISTER
+ *os_context_npc_addr(context) =
+ 4 + *os_context_pc_addr(context);
+#endif
+#ifdef LISP_FEATURE_SPARC
+ /* Bletch. This is a feature of the SPARC calling convention,
+ which sadly I'm not going to go into in large detail here,
+ as I don't know it well enough. Suffice to say that if the
+ line
+
+ (INST MOVE CODE-TN FUNCTION)
+
+ in compiler/sparc/call.lisp is changed, then this bit can
+ probably go away. -- CSR, 2002-07-24 */
+ *os_context_register_addr(context,reg_CODE) =
+ fun + FUN_POINTER_LOWTAG;
+#endif
+ return 1;
+ }
+ else return 0;
}
#ifndef LISP_FEATURE_X86
@@ -605,6 +653,7 @@
uninstall_low_level_interrupt_handlers_atexit(void)
{
int signal;
+#if 0
for (signal = 0; signal < NSIG; ++signal) {
struct low_level_signal_handler_state
*old_low_level_signal_handler_state =
@@ -617,8 +666,14 @@
sigaction(signal, &sa, NULL);
}
}
+#endif
}
+/* FIXME the "undoable" below is currently a lie. We don't want to
+ * remove any signal handlers while there are still >0 threads left,
+ * so that atexit thing has been disabled for the moment
+ */
+
/* Undoably install a special low-level handler for signal; or if
* handler is SIG_DFL, remove any special handling for signal.
*
@@ -651,12 +706,9 @@
sigaddset_blockable(&sa.sa_mask);
sa.sa_flags = SA_SIGINFO | SA_RESTART;
#ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK
- /* Signal handlers are run on the control stack, so if it is exhausted
- * we had better use an alternate stack for whatever signal tells us
- * we've exhausted it */
- /* XXX this bit got untimely ripped out in pursuit of threads */
+ if(signal==SIG_MEMORY_FAULT) sa.sa_flags|= SA_ONSTACK;
#endif
-
+
/* In the case of interrupt handlers which are modified more than
* once, we only save the original unmodified copy. */
if (!old_low_level_signal_handler_state->was_modified) {
@@ -704,7 +756,6 @@
sigemptyset(&sa.sa_mask);
sigaddset_blockable(&sa.sa_mask);
sa.sa_flags = SA_SIGINFO | SA_RESTART;
-
sigaction(signal, &sa, NULL);
}
Index: thread.c
===================================================================
RCS file: /cvsroot/sbcl/sbcl/src/runtime/Attic/thread.c,v
retrieving revision 1.1.2.8
retrieving revision 1.1.2.9
diff -u -d -r1.1.2.8 -r1.1.2.9
--- thread.c 13 Dec 2002 02:03:27 -0000 1.1.2.8
+++ thread.c 18 Dec 2002 17:23:45 -0000 1.1.2.9
@@ -1,6 +1,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <sched.h>
+#include <stddef.h>
#ifndef CLONE_PARENT /* lameass glibc 2.2 doesn't define this */
#define CLONE_PARENT 0x00008000 /* even though the manpage documents it */
#endif
@@ -63,11 +64,18 @@
* having to decide what to do if only some of the allocations
* succeed */
spaces=os_validate(0,
- THREAD_CONTROL_STACK_SIZE+BINDING_STACK_SIZE+
- ALIEN_STACK_SIZE+dynamic_values_bytes);
+ THREAD_CONTROL_STACK_SIZE+
+ BINDING_STACK_SIZE+
+ ALIEN_STACK_SIZE+
+ dynamic_values_bytes+
+ 32*SIGSTKSZ
+ );
if(!spaces) goto cleanup;
per_thread=(union per_thread_data *)
- (spaces+THREAD_CONTROL_STACK_SIZE+BINDING_STACK_SIZE+ALIEN_STACK_SIZE);
+ (spaces+
+ THREAD_CONTROL_STACK_SIZE+
+ BINDING_STACK_SIZE+
+ ALIEN_STACK_SIZE);
th=&per_thread->thread;
if(all_threads) {
@@ -87,8 +95,10 @@
->tls_index=make_fixnum(2);
((struct symbol *)(CONTROL_STACK_START-OTHER_POINTER_LOWTAG))
->tls_index=make_fixnum(3);
- ((struct symbol *)(ALIEN_STACK-OTHER_POINTER_LOWTAG))
- ->tls_index=make_fixnum(5);
+ ((struct symbol *)(ALIEN_STACK-OTHER_POINTER_LOWTAG))->tls_index=
+ make_fixnum(THREAD_SLOT_OFFSET_WORDS(alien_stack_pointer));
+ ((struct symbol *)(CURRENT_THREAD-OTHER_POINTER_LOWTAG))
+ ->tls_index=make_fixnum(THREAD_SLOT_OFFSET_WORDS(this));
}
th->control_stack_start = spaces;
@@ -97,8 +107,13 @@
th->alien_stack_start=
(lispobj*)((void*)th->binding_stack_start+BINDING_STACK_SIZE);
th->binding_stack_pointer=th->binding_stack_start;
+ th->this=th;
+#ifdef LISP_FEATURE_STACK_GROWS_DOWNWARD_NOT_UPWARD
th->alien_stack_pointer=((void *)th->alien_stack_start
+ ALIEN_STACK_SIZE-4); /* naked 4. FIXME */
+#else
+ th->alien_stack_pointer=((void *)th->alien_stack_start);
+#endif
gc_set_region_empty(&th->alloc_region);
bind_variable(CURRENT_CATCH_BLOCK,make_fixnum(0),th);
@@ -108,17 +123,19 @@
bind_variable(FREE_INTERRUPT_CONTEXT_INDEX,make_fixnum(0),th);
bind_variable(INTERRUPT_PENDING, NIL,th);
bind_variable(INTERRUPTS_ENABLED,T,th);
-
th->next=all_threads;
+ protect_control_stack_guard_page(th,1);
#if defined(LISP_FEATURE_X86) && defined (LISP_FEATURE_LINUX)
th->unbound_marker=initial_function;
th->pid=
- clone(new_thread_trampoline,th->binding_stack_start-2,
+ clone(new_thread_trampoline,
+ (((void*)th->control_stack_start)+THREAD_CONTROL_STACK_SIZE-4),
(((getpid()!=parent_pid)?CLONE_PARENT:0)
|CLONE_SIGHAND|CLONE_VM),th);
fprintf(stderr,"child pid is %d\n",th->pid);
if(th->pid<=0) goto cleanup;
+
#else
#error this stuff presently only works on x86 Linux
#endif
Index: thread.h
===================================================================
RCS file: /cvsroot/sbcl/sbcl/src/runtime/Attic/thread.h,v
retrieving revision 1.1.2.7
retrieving revision 1.1.2.8
diff -u -d -r1.1.2.7 -r1.1.2.8
--- thread.h 13 Dec 2002 02:03:27 -0000 1.1.2.7
+++ thread.h 18 Dec 2002 17:23:45 -0000 1.1.2.8
@@ -1,3 +1,7 @@
+
+#if !defined(_INCLUDE_THREAD_H_)
+#define _INCLUDE_THREAD_H_
+
#include <sys/types.h>
#include <unistd.h>
#include "runtime.h"
@@ -10,6 +14,9 @@
#error "threading doesn't work with cheney gc yet"
#endif
+#define THREAD_SLOT_OFFSET_WORDS(c) \
+ (offsetof(struct thread,c)/(sizeof (struct thread *)))
+
struct thread {
lispobj unbound_marker; /* tls[0] = UNBOUND_MARKER_WIDETAG */
/* unbound_marker is borrowed very briefly at thread startup to
@@ -76,3 +83,6 @@
=val;
}
+
+
+#endif /* _INCLUDE_THREAD_H_ */
Index: validate.c
===================================================================
RCS file: /cvsroot/sbcl/sbcl/src/runtime/validate.c,v
retrieving revision 1.13.4.1
retrieving revision 1.13.4.2
diff -u -d -r1.13.4.1 -r1.13.4.2
--- validate.c 24 Nov 2002 13:14:17 -0000 1.13.4.1
+++ validate.c 18 Dec 2002 17:23:45 -0000 1.13.4.2
@@ -83,14 +83,17 @@
#ifdef PRINTNOISE
printf(" done.\n");
#endif
- protect_control_stack_guard_page(1);
}
-void protect_control_stack_guard_page(int protect_p) {
- /*
- os_protect(CONTROL_STACK_GUARD_PAGE,
+void protect_control_stack_guard_page(struct thread *th,int protect_p) {
+ fprintf(stderr, "%sprotecting control stack guard page, th=%x, args %x,%x,%x\n",
+ protect_p ? "" : "un", th,
+ CONTROL_STACK_GUARD_PAGE(th),
+ os_vm_page_size,protect_p ?
+ (OS_VM_PROT_READ|OS_VM_PROT_EXECUTE) : OS_VM_PROT_ALL);
+
+ os_protect(CONTROL_STACK_GUARD_PAGE(th),
os_vm_page_size,protect_p ?
(OS_VM_PROT_READ|OS_VM_PROT_EXECUTE) : OS_VM_PROT_ALL);
- */
}
Index: validate.h
===================================================================
RCS file: /cvsroot/sbcl/sbcl/src/runtime/validate.h,v
retrieving revision 1.7.4.1
retrieving revision 1.7.4.2
diff -u -d -r1.7.4.1 -r1.7.4.2
--- validate.h 24 Nov 2002 13:14:17 -0000 1.7.4.1
+++ validate.h 18 Dec 2002 17:23:45 -0000 1.7.4.2
@@ -19,15 +19,16 @@
#define STATIC_SPACE_SIZE ( STATIC_SPACE_END - STATIC_SPACE_START)
#define THREAD_CONTROL_STACK_SIZE (2*1024*1024) /* wired elsewhere-watch out */
+#if !defined(LANGUAGE_ASSEMBLY)
+#include <thread.h>
#ifdef LISP_FEATURE_STACK_GROWS_DOWNWARD_NOT_UPWARD
-#define CONTROL_STACK_GUARD_PAGE (CONTROL_STACK_START)
+#define CONTROL_STACK_GUARD_PAGE(th) ((void *)(th->control_stack_start))
#else
-#define CONTROL_STACK_GUARD_PAGE (CONTROL_STACK_END - os_vm_page_size)
+#define CONTROL_STACK_GUARD_PAGE(th) (((void *)(th->control_stack_start))+THREAD_CONTROL_STACK_SIZE - os_vm_page_size)
#endif
-#if !defined(LANGUAGE_ASSEMBLY)
extern void validate(void);
-extern void protect_control_stack_guard_page(int protect_p);
+extern void protect_control_stack_guard_page(struct thread *th,int protect_p);
#endif
/* note for anyone trying to port an architecture's support files
Index: x86-linux-os.c
===================================================================
RCS file: /cvsroot/sbcl/sbcl/src/runtime/x86-linux-os.c,v
retrieving revision 1.7.4.4
retrieving revision 1.7.4.5
diff -u -d -r1.7.4.4 -r1.7.4.5
--- x86-linux-os.c 13 Dec 2002 02:03:27 -0000 1.7.4.4
+++ x86-linux-os.c 18 Dec 2002 17:23:45 -0000 1.7.4.5
@@ -60,6 +60,7 @@
/* this must be called from a function that has an exclusive lock
* on all_threads
*/
+ stack_t sigstack;
struct modify_ldt_ldt_s ldt_entry = {
1, 0, 0, /* index, address, length filled in later */
1, MODIFY_LDT_CONTENTS_DATA, 0, 0, 0, 1
@@ -85,6 +86,16 @@
+ (1 << 2) /* TI set = LDT */
+ 3)); /* privilege level */
thread->tls_cookie=n;
+ if(n<0) return 0;
+#ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK
+ /* Signal handlers are run on the control stack, so if it is exhausted
+ * we had better use an alternate stack for whatever signal tells us
+ * we've exhausted it */
+ sigstack.ss_sp=((void *) thread)+dynamic_values_bytes;
+ sigstack.ss_flags=0;
+ sigstack.ss_size = 32*SIGSTKSZ;
+ sigaltstack(&sigstack,0);
+#endif
return (n>=0);
}
|