cleanup: partial long cleanup in sniff_code_object and gencgc_apply_code_fixups
[sbcl.git] / src / runtime / thread.c
index ca265b8..7a18c5a 100644 (file)
@@ -119,6 +119,80 @@ unlink_thread(struct thread *th)
     if (th->next)
         th->next->prev = th->prev;
 }
+
+/* Only access thread state with blockables blocked. */
+lispobj
+thread_state(struct thread *thread)
+{
+    lispobj state;
+    sigset_t old;
+    block_blockable_signals(NULL, &old);
+    os_sem_wait(thread->state_sem, "thread_state");
+    state = thread->state;
+    os_sem_post(thread->state_sem, "thread_state");
+    thread_sigmask(SIG_SETMASK, &old, NULL);
+    return state;
+}
+
+void
+set_thread_state(struct thread *thread, lispobj state)
+{
+    int i, waitcount = 0;
+    sigset_t old;
+    block_blockable_signals(NULL, &old);
+    os_sem_wait(thread->state_sem, "set_thread_state");
+    if (thread->state != state) {
+        if ((STATE_STOPPED==state) ||
+            (STATE_DEAD==state)) {
+            waitcount = thread->state_not_running_waitcount;
+            thread->state_not_running_waitcount = 0;
+            for (i=0; i<waitcount; i++)
+                os_sem_post(thread->state_not_running_sem, "set_thread_state (not running)");
+        }
+        if ((STATE_RUNNING==state) ||
+            (STATE_DEAD==state)) {
+            waitcount = thread->state_not_stopped_waitcount;
+            thread->state_not_stopped_waitcount = 0;
+            for (i=0; i<waitcount; i++)
+                os_sem_post(thread->state_not_stopped_sem, "set_thread_state (not stopped)");
+        }
+        thread->state = state;
+    }
+    os_sem_post(thread->state_sem, "set_thread_state");
+    thread_sigmask(SIG_SETMASK, &old, NULL);
+}
+
+void
+wait_for_thread_state_change(struct thread *thread, lispobj state)
+{
+    sigset_t old;
+    os_sem_t *wait_sem;
+    block_blockable_signals(NULL, &old);
+  start:
+    os_sem_wait(thread->state_sem, "wait_for_thread_state_change");
+    if (thread->state == state) {
+        switch (state) {
+        case STATE_RUNNING:
+            wait_sem = thread->state_not_running_sem;
+            thread->state_not_running_waitcount++;
+            break;
+        case STATE_STOPPED:
+            wait_sem = thread->state_not_stopped_sem;
+            thread->state_not_stopped_waitcount++;
+            break;
+        default:
+            lose("Invalid state in wait_for_thread_state_change: "OBJ_FMTX"\n", state);
+        }
+    } else {
+        wait_sem = NULL;
+    }
+    os_sem_post(thread->state_sem, "wait_for_thread_state_change");
+    if (wait_sem) {
+        os_sem_wait(wait_sem, "wait_for_thread_state_change");
+        goto start;
+    }
+    thread_sigmask(SIG_SETMASK, &old, NULL);
+}
 #endif
 
 static int
@@ -158,7 +232,7 @@ initial_thread_trampoline(struct thread *th)
 
 #ifdef LISP_FEATURE_SB_THREAD
 #define THREAD_STATE_LOCK_SIZE \
-    (sizeof(pthread_mutex_t))+(sizeof(pthread_cond_t))
+    ((sizeof(os_sem_t))+(sizeof(os_sem_t))+(sizeof(os_sem_t)))
 #else
 #define THREAD_STATE_LOCK_SIZE 0
 #endif
@@ -310,8 +384,9 @@ new_thread_trampoline(struct thread *th)
     gc_assert(lock_ret == 0);
 
     if(th->tls_cookie>=0) arch_os_thread_cleanup(th);
-    pthread_mutex_destroy(th->state_lock);
-    pthread_cond_destroy(th->state_cond);
+    os_sem_destroy(th->state_sem);
+    os_sem_destroy(th->state_not_running_sem);
+    os_sem_destroy(th->state_not_stopped_sem);
 
     os_invalidate((os_vm_address_t)th->interrupt_data,
                   (sizeof (struct interrupt_data)));
@@ -393,12 +468,12 @@ create_thread_struct(lispobj initial_function) {
         per_thread->dynamic_values[i] = NO_TLS_VALUE_MARKER_WIDETAG;
     if (all_threads == 0) {
         if(SymbolValue(FREE_TLS_INDEX,0)==UNBOUND_MARKER_WIDETAG) {
-            SetSymbolValue(FREE_TLS_INDEX,make_fixnum(tls_index_start),0);
+            SetSymbolValue(FREE_TLS_INDEX,tls_index_start << WORD_SHIFT,0);
             SetSymbolValue(TLS_INDEX_LOCK,make_fixnum(0),0);
         }
 #define STATIC_TLS_INIT(sym,field) \
   ((struct symbol *)(sym-OTHER_POINTER_LOWTAG))->tls_index= \
-  make_fixnum(THREAD_SLOT_OFFSET_WORDS(field))
+  (THREAD_SLOT_OFFSET_WORDS(field) << WORD_SHIFT)
 
         STATIC_TLS_INIT(BINDING_STACK_START,binding_stack_start);
 #ifdef BINDING_STACK_POINTER
@@ -430,12 +505,16 @@ create_thread_struct(lispobj initial_function) {
     th->os_thread=0;
 #ifdef LISP_FEATURE_SB_THREAD
     th->os_attr=malloc(sizeof(pthread_attr_t));
-    th->state_lock=(pthread_mutex_t *)((void *)th->alien_stack_start +
-                                       ALIEN_STACK_SIZE);
-    pthread_mutex_init(th->state_lock, NULL);
-    th->state_cond=(pthread_cond_t *)((void *)th->state_lock +
-                                      (sizeof(pthread_mutex_t)));
-    pthread_cond_init(th->state_cond, NULL);
+    th->state_sem=(os_sem_t *)((void *)th->alien_stack_start + ALIEN_STACK_SIZE);
+    th->state_not_running_sem=(os_sem_t *)
+        ((void *)th->state_sem + (sizeof(os_sem_t)));
+    th->state_not_stopped_sem=(os_sem_t *)
+        ((void *)th->state_not_running_sem + (sizeof(os_sem_t)));
+    th->state_not_running_waitcount = 0;
+    th->state_not_stopped_waitcount = 0;
+    os_sem_init(th->state_sem, 1);
+    os_sem_init(th->state_not_running_sem, 0);
+    os_sem_init(th->state_not_stopped_sem, 0);
 #endif
     th->state=STATE_RUNNING;
 #ifdef LISP_FEATURE_STACK_GROWS_DOWNWARD_NOT_UPWARD
@@ -523,9 +602,6 @@ void create_initial_thread(lispobj initial_function) {
     pthread_key_create(&lisp_thread, 0);
 #endif
     if(th) {
-#ifdef LISP_FEATURE_MACH_EXCEPTION_HANDLER
-        setup_mach_exception_handling_thread();
-#endif
         initial_thread_trampoline(th); /* no return */
     } else lose("can't create initial thread\n");
 }
@@ -679,7 +755,7 @@ void gc_start_the_world()
         if (p!=th) {
             lispobj state = thread_state(p);
             if (state != STATE_DEAD) {
-                if(state != STATE_SUSPENDED) {
+                if(state != STATE_STOPPED) {
                     lose("gc_start_the_world: wrong thread state is %d\n",
                          fixnum_value(state));
                 }