Update of /cvsroot/sbcl/sbcl/src/runtime
In directory sc8-pr-cvs1:/tmp/cvs-serv6761/src/runtime
Modified Files:
Tag: stop_the_world_branch
runtime.c thread.c x86-arch.c x86-arch.h
Log Message:
0.8.2.38.stop_the_world.1
(assert 'want-to-get-off)
Beginnings of a new scheme for stopping threads during GC,
that avoids the use of ptrace and lets any of the threads
stop any of the others
This commit contains the necessary parent changes (untested,
may not compile, almost certainly won't run). Also forthcoming:
1) New SIG_STOP_FOR_GC signal to define, with handler that
gets deferred a la maybe_now_maybe_later in critical sections,
and decrements countdown_to_gc then SIGSTOPs when ready
2) make GC actually call collect_garbage instead of sending
signals around
Index: runtime.c
===================================================================
RCS file: /cvsroot/sbcl/sbcl/src/runtime/runtime.c,v
retrieving revision 1.30
retrieving revision 1.30.2.1
diff -u -d -r1.30 -r1.30.2.1
--- runtime.c 6 Aug 2003 12:38:12 -0000 1.30
+++ runtime.c 17 Aug 2003 23:20:17 -0000 1.30.2.1
@@ -379,67 +379,6 @@
}
#ifdef LISP_FEATURE_SB_THREAD
-static void parent_do_garbage_collect(void)
-{
- int waiting_threads=0;
- struct thread *th;
- int status,p;
-
- for_each_thread(th) {
- if(ptrace(PTRACE_ATTACH,th->pid,0,0)) {
- perror("PTRACE_ATTACH");
- }
- else waiting_threads++;
- }
- stop_the_world=1;
-
- do {
- /* not sure if we have to wait for PTRACE_ATTACH to finish
- * before we can send PTRACE_CONT, so let's play it safe
- */
- while(waiting_threads>0) {
- if((p=waitpid(-1,&status, WUNTRACED|__WALL))>0) {
- if(WIFEXITED(status) || WIFSIGNALED(status))
- destroy_thread(find_thread_by_pid(p));
- else {
-#if 0
- fprintf(stderr, "wait returned pid %d signal %x\n",
- p,WSTOPSIG(status));
-#endif
- if(WSTOPSIG(status)==SIGTRAP) {
- if(ptrace(PTRACE_CONT,p,0,SIGTRAP))
- perror("PTRACE_CONT");
- }
- else waiting_threads--;
- }
- }
- }
- for_each_thread(th) {
- if(SymbolTlValue(PSEUDO_ATOMIC_ATOMIC,th)) {
- /* restart the child, setting *p-a-i* which will cause it
- * to go into interrupt_handle_pending as soon as it's
- * finished being pseudo_atomic. once there it will
- * signal itself SIGSTOP, which will give us another
- * event to wait for */
-#if 0
- fprintf(stderr, "%d was pseudo-atomic, letting it resume \n",
- th->pid);
-#endif
- SetTlSymbolValue(PSEUDO_ATOMIC_INTERRUPTED,make_fixnum(1),th);
- if(ptrace(PTRACE_CONT,th->pid,0,0))
- perror("PTRACE_CONT");
- waiting_threads++;
- }
- }
- } while (waiting_threads>0);
-
- collect_garbage(maybe_gc_pending-1);
- maybe_gc_pending=0;
- stop_the_world=0;
- for_each_thread(th)
- if(ptrace(PTRACE_DETACH,th->pid,0,0))
- perror("PTRACE_DETACH");
-}
static void /* noreturn */ parent_loop(void)
{
@@ -468,11 +407,9 @@
while(!all_threads) {
sched_yield();
}
- maybe_gc_pending=0;
while(all_threads && (pid=waitpid(-1,&status,__WALL|WUNTRACED))) {
struct thread *th;
int real_errno=errno;
- while(maybe_gc_pending) parent_do_garbage_collect();
if(pid==-1) {
if(real_errno == EINTR) {
continue;
@@ -485,9 +422,7 @@
if(!th) continue;
if(WIFEXITED(status) || WIFSIGNALED(status)) {
fprintf(stderr,"waitpid : child %d %x exited \n", pid,th);
- destroy_thread(th);
- /* FIXME arrange to call or fake (free-mutex *session-lock*)
- * if necessary */
+ destroy_thread(th);
if(!all_threads) break;
}
}
Index: thread.c
===================================================================
RCS file: /cvsroot/sbcl/sbcl/src/runtime/thread.c,v
retrieving revision 1.11
retrieving revision 1.11.2.1
diff -u -d -r1.11 -r1.11.2.1
--- thread.c 16 Aug 2003 20:38:40 -0000 1.11
+++ thread.c 17 Aug 2003 23:20:18 -0000 1.11.2.1
@@ -235,6 +235,7 @@
gc_alloc_update_page_tables(0, &th->alloc_region);
#endif
get_spinlock(&all_threads_lock,th->pid);
+ if(countdown_to_gc>0) countdown_to_gc--;
if(th==all_threads)
all_threads=th->next;
else {
@@ -242,7 +243,7 @@
while(th1->next!=th) th1=th1->next;
th1->next=th->next; /* unlink */
}
- all_threads_lock=0;
+ release_spinlock(&all_threads_lock);
if(th && th->tls_cookie>=0) arch_os_thread_cleanup(th);
os_invalidate((os_vm_address_t) th->control_stack_start,
((sizeof (lispobj))
@@ -291,4 +292,44 @@
sigqueue(pid, SIG_INTERRUPT_THREAD, sigval);
}
+
+int gc_stop_the_world()
+{
+ /* stop all other threads by sending them SIG_STOP_FOR_GC */
+ struct thread *th=arch_os_get_current_thread();
+ int countdown_to_gc=0;
+ struct thread *tail=0;
+ int finished=0;
+ do {
+ get_spinlock(&all_threads_lock,th);
+ if(tail!=all_threads) {
+ /* new threads always get consed onto the front of all_threads,
+ * and may be created by any thread that we haven't signalled
+ * yet or hasn't received our signal and stopped yet. So, check
+ * for them on each time around */
+ for(p=all_threads;p!=tail;p=p->next) {
+ if(p==th) continue;
+ countdown_to_gc++;
+ kill(p->pid,SIG_STOP_FOR_GC);
+ }
+ tail=all_threads;
+ } else {
+ finished=(countdown_to_gc==0);
+ }
+ release_spinlock(&all_threads_lock);
+ sched_yield();
+ } while(!finished);
+ return 0;
+}
+
+int gc_start_the_world()
+{
+ struct thread *p,*th=arch_os_get_current_thread();
+ get_spinlock(&all_threads_lock);
+ for(p=all_threads;p;p=p->next) {
+ if(p==th) continue;
+ kill(p->pid,SIGCONT);
+ }
+}
+
#endif
Index: x86-arch.c
===================================================================
RCS file: /cvsroot/sbcl/sbcl/src/runtime/x86-arch.c,v
retrieving revision 1.21
retrieving revision 1.21.2.1
diff -u -d -r1.21 -r1.21.2.1
--- x86-arch.c 27 Jul 2003 17:13:52 -0000 1.21
+++ x86-arch.c 17 Aug 2003 23:20:18 -0000 1.21.2.1
@@ -141,19 +141,6 @@
return result;
}
-void
-get_spinlock(lispobj *word,int value)
-{
- u32 eax=0;
- do {
- asm ("xor %0,%0\n\
- lock cmpxchg %1,%2"
- : "=a" (eax)
- : "r" (value), "m" (*word)
- : "memory", "cc");
- } while(eax!=0);
-}
-
void
arch_remove_breakpoint(void *pc, unsigned long orig_inst)
{
Index: x86-arch.h
===================================================================
RCS file: /cvsroot/sbcl/sbcl/src/runtime/x86-arch.h,v
retrieving revision 1.1
retrieving revision 1.1.28.1
diff -u -d -r1.1 -r1.1.28.1
--- x86-arch.h 15 Feb 2002 17:10:02 -0000 1.1
+++ x86-arch.h 17 Aug 2003 23:20:18 -0000 1.1.28.1
@@ -12,4 +12,23 @@
* here? (The answer wasn't obvious to me when merging the
* architecture-abstracting patches for CSR's SPARC port. -- WHN 2002-02-15) */
+inline void
+get_spinlock(lispobj *word,int value)
+{
+ u32 eax=0;
+ do {
+ asm ("xor %0,%0\n\
+ lock cmpxchg %1,%2"
+ : "=a" (eax)
+ : "r" (value), "m" (*word)
+ : "memory", "cc");
+ } while(eax!=0);
+}
+
+inline void
+release_spinlock(lispobj *word)
+{
+ *word=0;
+}
+
#endif /* _X86_ARCH_H */
|