[svn:parrot] r48374 - in branches/gsoc_threads: include/parrot src src/gc src/interp src/io src/pmc src/runcore t/src

Chandon at svn.parrot.org Chandon at svn.parrot.org
Tue Aug 10 01:10:49 UTC 2010


Author: Chandon
Date: Tue Aug 10 01:10:47 2010
New Revision: 48374
URL: https://trac.parrot.org/parrot/changeset/48374

Log:
[gsoc_threads] Just need a couple less explosions...

Added:
   branches/gsoc_threads/t/src/threads_io.t
Modified:
   branches/gsoc_threads/include/parrot/alarm.h
   branches/gsoc_threads/include/parrot/atomic.h
   branches/gsoc_threads/include/parrot/interpreter.h
   branches/gsoc_threads/include/parrot/scheduler.h
   branches/gsoc_threads/include/parrot/thread.h
   branches/gsoc_threads/include/parrot/threads.h
   branches/gsoc_threads/src/alarm.c
   branches/gsoc_threads/src/exceptions.c
   branches/gsoc_threads/src/gc/gc_ms.c
   branches/gsoc_threads/src/gc/system.c
   branches/gsoc_threads/src/interp/inter_create.c
   branches/gsoc_threads/src/io/unix.c
   branches/gsoc_threads/src/main.c
   branches/gsoc_threads/src/pmc/pmclist.pmc
   branches/gsoc_threads/src/runcore/trace.c
   branches/gsoc_threads/src/scheduler.c
   branches/gsoc_threads/src/threads.c

Modified: branches/gsoc_threads/include/parrot/alarm.h
==============================================================================
--- branches/gsoc_threads/include/parrot/alarm.h	Tue Aug 10 00:18:55 2010	(r48373)
+++ branches/gsoc_threads/include/parrot/alarm.h	Tue Aug 10 01:10:47 2010	(r48374)
@@ -18,13 +18,17 @@
 void Parrot_alarm_set(FLOATVAL when);
 
 void Parrot_alarm_callback(NULLOK(int sig_number));
+void Parrot_alarm_init(void);
 void Parrot_alarm_mask(SHIM_INTERP);
+void Parrot_alarm_now(void);
 void Parrot_alarm_unmask(SHIM_INTERP);
 #define ASSERT_ARGS_Parrot_alarm_check __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(last_serial))
 #define ASSERT_ARGS_Parrot_alarm_set __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
 #define ASSERT_ARGS_Parrot_alarm_callback __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
+#define ASSERT_ARGS_Parrot_alarm_init __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
 #define ASSERT_ARGS_Parrot_alarm_mask __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
+#define ASSERT_ARGS_Parrot_alarm_now __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
 #define ASSERT_ARGS_Parrot_alarm_unmask __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
 /* HEADERIZER END: src/alarm.c */

Modified: branches/gsoc_threads/include/parrot/atomic.h
==============================================================================
--- branches/gsoc_threads/include/parrot/atomic.h	Tue Aug 10 00:18:55 2010	(r48373)
+++ branches/gsoc_threads/include/parrot/atomic.h	Tue Aug 10 01:10:47 2010	(r48374)
@@ -15,7 +15,7 @@
 #define PARROT_ATOMIC_H_GUARD
 
 #  include "parrot/has_header.h"
-#  include "parrot/thread.h"
+//#  include "parrot/thread.h"
 
 #ifdef PARROT_HAS_THREADS
 #  if defined(PARROT_HAS_I386_GCC_CMPXCHG)

Modified: branches/gsoc_threads/include/parrot/interpreter.h
==============================================================================
--- branches/gsoc_threads/include/parrot/interpreter.h	Tue Aug 10 00:18:55 2010	(r48373)
+++ branches/gsoc_threads/include/parrot/interpreter.h	Tue Aug 10 01:10:47 2010	(r48374)
@@ -132,6 +132,8 @@
 #include "parrot/multidispatch.h"
 #include "parrot/call.h"
 
+#include "parrot/atomic.h"
+
 typedef struct warnings_t {
     Warnings_classes classes;
 } *Warnings;
@@ -272,7 +274,10 @@
 
     Parrot_mutex     interp_lock;             /* Enforce one running thread per interp */
     INTVAL           active_thread;           /* Index of the active thread in thread_table */
-    struct Thread_table *thread_table;         /* Array of this interpreter's threads */
+
+    struct Thread_table  *thread_table;       /* Array of this interpreter's threads */
+    Parrot_atomic_integer thread_signal;      /* Flag. Set if threads need rescheduling */
+    Parrot_mutex          thread_lock;        /* Lock for the thread_table */
 
     struct _Thread_data *thread_data;         /* thread specific items */
 

Modified: branches/gsoc_threads/include/parrot/scheduler.h
==============================================================================
--- branches/gsoc_threads/include/parrot/scheduler.h	Tue Aug 10 00:18:55 2010	(r48373)
+++ branches/gsoc_threads/include/parrot/scheduler.h	Tue Aug 10 01:10:47 2010	(r48374)
@@ -49,10 +49,6 @@
         __attribute__nonnull__(1);
 
 PARROT_EXPORT
-void Parrot_cx_outer_runloop(PARROT_INTERP, INTVAL tidx)
-        __attribute__nonnull__(1);
-
-PARROT_EXPORT
 void Parrot_cx_request_suspend_for_gc(PARROT_INTERP)
         __attribute__nonnull__(1);
 
@@ -67,15 +63,6 @@
         FUNC_MODIFIES(*scheduler);
 
 PARROT_EXPORT
-void Parrot_cx_runloop_end(PARROT_INTERP)
-        __attribute__nonnull__(1);
-
-PARROT_EXPORT
-void Parrot_cx_schedule_alarm(PARROT_INTERP, ARGIN(PMC *alarm))
-        __attribute__nonnull__(1)
-        __attribute__nonnull__(2);
-
-PARROT_EXPORT
 void Parrot_cx_schedule_immediate(PARROT_INTERP, ARGIN(PMC *task_or_sub))
         __attribute__nonnull__(1)
         __attribute__nonnull__(2);
@@ -100,6 +87,12 @@
         __attribute__nonnull__(1)
         __attribute__nonnull__(2);
 
+PARROT_EXPORT
+PARROT_CANNOT_RETURN_NULL
+PMC* Parrot_cx_stop_task(PARROT_INTERP, ARGIN(opcode_t *next))
+        __attribute__nonnull__(1)
+        __attribute__nonnull__(2);
+
 void Parrot_cx_check_quantum(PARROT_INTERP, ARGMOD(PMC *scheduler))
         __attribute__nonnull__(1)
         __attribute__nonnull__(2)
@@ -127,13 +120,15 @@
         __attribute__nonnull__(3)
         FUNC_MODIFIES(*scheduler);
 
+void Parrot_cx_runloop_end(PARROT_INTERP)
+        __attribute__nonnull__(1);
+
 void Parrot_cx_runloop_wake(PARROT_INTERP, ARGMOD(PMC *scheduler))
         __attribute__nonnull__(1)
         __attribute__nonnull__(2)
         FUNC_MODIFIES(*scheduler);
 
-PARROT_CANNOT_RETURN_NULL
-PMC* Parrot_cx_stop_task(PARROT_INTERP, ARGIN(opcode_t *next))
+void Parrot_cx_schedule_alarm(PARROT_INTERP, ARGIN(PMC *alarm))
         __attribute__nonnull__(1)
         __attribute__nonnull__(2);
 
@@ -150,8 +145,6 @@
 #define ASSERT_ARGS_Parrot_cx_delete_suspend_for_gc \
      __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(interp))
-#define ASSERT_ARGS_Parrot_cx_outer_runloop __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
-       PARROT_ASSERT_ARG(interp))
 #define ASSERT_ARGS_Parrot_cx_request_suspend_for_gc \
      __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(interp))
@@ -159,11 +152,6 @@
        PARROT_ASSERT_ARG(interp) \
     , PARROT_ASSERT_ARG(scheduler) \
     , PARROT_ASSERT_ARG(next))
-#define ASSERT_ARGS_Parrot_cx_runloop_end __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
-       PARROT_ASSERT_ARG(interp))
-#define ASSERT_ARGS_Parrot_cx_schedule_alarm __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
-       PARROT_ASSERT_ARG(interp) \
-    , PARROT_ASSERT_ARG(alarm))
 #define ASSERT_ARGS_Parrot_cx_schedule_immediate __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(interp) \
     , PARROT_ASSERT_ARG(task_or_sub))
@@ -175,6 +163,9 @@
 #define ASSERT_ARGS_Parrot_cx_send_message __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(interp) \
     , PARROT_ASSERT_ARG(messagetype))
+#define ASSERT_ARGS_Parrot_cx_stop_task __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+       PARROT_ASSERT_ARG(interp) \
+    , PARROT_ASSERT_ARG(next))
 #define ASSERT_ARGS_Parrot_cx_check_quantum __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(interp) \
     , PARROT_ASSERT_ARG(scheduler))
@@ -190,12 +181,14 @@
        PARROT_ASSERT_ARG(interp) \
     , PARROT_ASSERT_ARG(scheduler) \
     , PARROT_ASSERT_ARG(next))
+#define ASSERT_ARGS_Parrot_cx_runloop_end __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+       PARROT_ASSERT_ARG(interp))
 #define ASSERT_ARGS_Parrot_cx_runloop_wake __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(interp) \
     , PARROT_ASSERT_ARG(scheduler))
-#define ASSERT_ARGS_Parrot_cx_stop_task __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+#define ASSERT_ARGS_Parrot_cx_schedule_alarm __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(interp) \
-    , PARROT_ASSERT_ARG(next))
+    , PARROT_ASSERT_ARG(alarm))
 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
 /* HEADERIZER END: src/scheduler.c */
 

Modified: branches/gsoc_threads/include/parrot/thread.h
==============================================================================
--- branches/gsoc_threads/include/parrot/thread.h	Tue Aug 10 00:18:55 2010	(r48373)
+++ branches/gsoc_threads/include/parrot/thread.h	Tue Aug 10 01:10:47 2010	(r48374)
@@ -56,18 +56,6 @@
 
 #endif /* PARROT_HAS_THREADS */
 
-#define LOCK_INTERP(interp) \
-    LOCK((interp)->interp_lock)
-
-#define UNLOCK_INTERP(interp) \
-    UNLOCK((interp)->interp_lock)
-
-#define BLOCK_THREAD(interp) \
-    Parrot_cx_block_thread(interp)
-
-#define UNBLOCK_THREAD(interp) \
-    Parrot_cx_unblock_thread(interp)
-
 #ifndef YIELD
 #  define YIELD
 #endif /* YIELD */

Modified: branches/gsoc_threads/include/parrot/threads.h
==============================================================================
--- branches/gsoc_threads/include/parrot/threads.h	Tue Aug 10 00:18:55 2010	(r48373)
+++ branches/gsoc_threads/include/parrot/threads.h	Tue Aug 10 01:10:47 2010	(r48374)
@@ -7,11 +7,26 @@
 
 #include "parrot/thread.h"
 
+enum Thread_states {
+    THREAD_STATE_INITIALIZED = 0x01, /* Thread has been created */
+    THREAD_STATE_RUNNABLE    = 0x02, /* We could signal this thread and it would run */
+    THREAD_STATE_SCAN_STACK  = 0x04, /* This thread may have PMCs on its stack */
+    THREAD_STATE_RESTLESS    = 0x08, /* This thread wants to run ASAP */
+    THREAD_STATE_DEATH_MARK  = 0x10  /* This thread is marked for death */
+};
+
+#define THREAD_STATE_TEST(interp, tidx, flag) \
+    ((interp)->thread_table->threads[(tidx)].state & (THREAD_STATE_ ## flag))
+#define THREAD_STATE_SET(interp, tidx, flag) \
+    ((interp)->thread_table->threads[(tidx)].state |= (THREAD_STATE_ ## flag))
+#define THREAD_STATE_CLEAR(interp, tidx, flag) \
+    ((interp)->thread_table->threads[(tidx)].state &= ~(THREAD_STATE_ ## flag))
+
 typedef struct Thread_info {
     Parrot_thread id;
-    INTVAL        blocked;
+    INTVAL        state;
     Parrot_cond   cvar;
-    void         *lo_var_ptr;
+    void         *lo_var_ptr; /* Full range of stack for GC scan */
     void         *hi_var_ptr;
 } Thread_info;
 
@@ -26,6 +41,26 @@
     INTVAL  idx;
 } Thread_args;
 
+#define LOCK_INTERP(interp) \
+    LOCK((interp)->interp_lock)
+
+#define UNLOCK_INTERP(interp) \
+    UNLOCK((interp)->interp_lock)
+
+#define BLOCK_THREAD_ON(interp, blocking_call) \
+    do { \
+      INTVAL tid, runloop_id, runloop_level; \
+      PMC *context = Parrot_pmc_new((interp), enum_class_Continuation); \
+      runloop_id    = interp->current_runloop_id; \
+      runloop_level = interp->current_runloop_level; \
+      Parrot_threads_block((interp), &tid); \
+      blocking_call; \
+      Parrot_threads_unblock((interp), &tid); \
+      (void) VTABLE_invoke((interp), context, 0); \
+      interp->current_runloop_id    = runloop_id; \
+      interp->current_runloop_level = runloop_level; \
+    } while (0)
+
 /* HEADERIZER BEGIN: src/threads.c */
 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
 
@@ -34,10 +69,13 @@
         __attribute__nonnull__(2)
         FUNC_MODIFIES(*tidx);
 
-INTVAL Parrot_threads_count_blocked(PARROT_INTERP)
+INTVAL Parrot_threads_check_and_reset(PARROT_INTERP)
+        __attribute__nonnull__(1);
+
+INTVAL Parrot_threads_count_active(PARROT_INTERP)
         __attribute__nonnull__(1);
 
-INTVAL Parrot_threads_current_idx(PARROT_INTERP)
+INTVAL Parrot_threads_current(PARROT_INTERP)
         __attribute__nonnull__(1);
 
 void Parrot_threads_idle(PARROT_INTERP, INTVAL tidx)
@@ -51,22 +89,37 @@
         __attribute__nonnull__(1)
         FUNC_MODIFIES(*args_ptr);
 
+INTVAL Parrot_threads_next_to_run(PARROT_INTERP, INTVAL cur_idx)
+        __attribute__nonnull__(1);
+
+void Parrot_threads_outer_runloop(PARROT_INTERP, INTVAL tidx)
+        __attribute__nonnull__(1);
+
+void Parrot_threads_print_table(PARROT_INTERP)
+        __attribute__nonnull__(1);
+
 void Parrot_threads_reap(PARROT_INTERP)
         __attribute__nonnull__(1);
 
+void Parrot_threads_set_signal(PARROT_INTERP)
+        __attribute__nonnull__(1);
+
 void Parrot_threads_spawn(PARROT_INTERP)
         __attribute__nonnull__(1);
 
-void Parrot_threads_unblock(PARROT_INTERP, ARGIN(INTVAL *tidx))
+void Parrot_threads_unblock(PARROT_INTERP, ARGIN(INTVAL *tidx_ptr))
         __attribute__nonnull__(1)
         __attribute__nonnull__(2);
 
 #define ASSERT_ARGS_Parrot_threads_block __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(interp) \
     , PARROT_ASSERT_ARG(tidx))
-#define ASSERT_ARGS_Parrot_threads_count_blocked __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+#define ASSERT_ARGS_Parrot_threads_check_and_reset \
+     __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+       PARROT_ASSERT_ARG(interp))
+#define ASSERT_ARGS_Parrot_threads_count_active __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(interp))
-#define ASSERT_ARGS_Parrot_threads_current_idx __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+#define ASSERT_ARGS_Parrot_threads_current __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(interp))
 #define ASSERT_ARGS_Parrot_threads_idle __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(interp))
@@ -74,13 +127,21 @@
        PARROT_ASSERT_ARG(interp))
 #define ASSERT_ARGS_Parrot_threads_main __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(args_ptr))
+#define ASSERT_ARGS_Parrot_threads_next_to_run __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+       PARROT_ASSERT_ARG(interp))
+#define ASSERT_ARGS_Parrot_threads_outer_runloop __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+       PARROT_ASSERT_ARG(interp))
+#define ASSERT_ARGS_Parrot_threads_print_table __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+       PARROT_ASSERT_ARG(interp))
 #define ASSERT_ARGS_Parrot_threads_reap __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(interp))
+#define ASSERT_ARGS_Parrot_threads_set_signal __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+       PARROT_ASSERT_ARG(interp))
 #define ASSERT_ARGS_Parrot_threads_spawn __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(interp))
 #define ASSERT_ARGS_Parrot_threads_unblock __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(interp) \
-    , PARROT_ASSERT_ARG(tidx))
+    , PARROT_ASSERT_ARG(tidx_ptr))
 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
 /* HEADERIZER END: src/threads.c */
 

Modified: branches/gsoc_threads/src/alarm.c
==============================================================================
--- branches/gsoc_threads/src/alarm.c	Tue Aug 10 00:18:55 2010	(r48373)
+++ branches/gsoc_threads/src/alarm.c	Tue Aug 10 01:10:47 2010	(r48374)
@@ -15,7 +15,6 @@
 
 /* Some per-process state */
 static volatile UINTVAL  alarm_serial = 0;
-static volatile UINTVAL  alarm_init   = 0;
 static volatile FLOATVAL alarm_set_to = 0.0;
 
 /* This file relies on POSIX. Probably need two other versions of it:
@@ -30,9 +29,7 @@
 /* HEADERIZER BEGIN: static */
 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
 
-static void posix_alarm_init(void);
 static void posix_alarm_set(FLOATVAL wait);
-#define ASSERT_ARGS_posix_alarm_init __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
 #define ASSERT_ARGS_posix_alarm_set __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
 /* HEADERIZER END: static */
@@ -42,7 +39,7 @@
 
 =over 4
 
-=item C<static void posix_alarm_init(void)>
+=item C<void Parrot_alarm_init(void)>
 
 Initialize the alarm queue. This function should only be called from the initial
 pthread. Any other pthreads should make sure to mask out SIGALRM.
@@ -53,10 +50,10 @@
 
 void Parrot_alarm_callback(SHIM(int sig_number));
 
-static void
-posix_alarm_init(void)
+void
+Parrot_alarm_init(void)
 {
-    ASSERT_ARGS(posix_alarm_init)
+    ASSERT_ARGS(Parrot_alarm_init)
 
     struct sigaction sa;
     sa.sa_handler = Parrot_alarm_callback;
@@ -68,8 +65,6 @@
     }
 
     Parrot_alarm_unmask(NULL);
-
-    alarm_init = 1;
 }
 
 /*
@@ -91,9 +86,6 @@
     struct itimerval itmr;
     int sec, usec;
 
-    if (!alarm_init)
-        posix_alarm_init();
-
     sec  = (int) wait;
     usec = (int) ((wait - sec) * MIL);
 
@@ -221,6 +213,23 @@
 }
 
 /*
+
+=item C<void Parrot_alarm_now(void)>
+
+Trigger an alarm wakeup.
+
+=cut
+
+*/
+
+void
+Parrot_alarm_now(void)
+{
+    ASSERT_ARGS(Parrot_alarm_now)
+    kill(getpid(), SIGALRM);
+}
+
+/*
  * Local variables:
  *   c-file-style: "parrot"
  * End:

Modified: branches/gsoc_threads/src/exceptions.c
==============================================================================
--- branches/gsoc_threads/src/exceptions.c	Tue Aug 10 00:18:55 2010	(r48373)
+++ branches/gsoc_threads/src/exceptions.c	Tue Aug 10 01:10:47 2010	(r48374)
@@ -21,6 +21,8 @@
 #include "parrot/parrot.h"
 #include "exceptions.str"
 #include "pmc/pmc_continuation.h"
+#include "parrot/exceptions.h"
+#include "parrot/events.h"
 
 /* HEADERIZER HFILE: include/parrot/exceptions.h */
 

Modified: branches/gsoc_threads/src/gc/gc_ms.c
==============================================================================
--- branches/gsoc_threads/src/gc/gc_ms.c	Tue Aug 10 00:18:55 2010	(r48373)
+++ branches/gsoc_threads/src/gc/gc_ms.c	Tue Aug 10 01:10:47 2010	(r48374)
@@ -636,6 +636,7 @@
 
     /* keep the scheduler and its kids alive for Task-like PMCs to destroy
      * themselves; run a sweep to collect them */
+
     if (interp->scheduler) {
         Parrot_gc_mark_PMC_alive(interp, interp->scheduler);
         VTABLE_mark(interp, interp->scheduler);

Modified: branches/gsoc_threads/src/gc/system.c
==============================================================================
--- branches/gsoc_threads/src/gc/system.c	Tue Aug 10 00:18:55 2010	(r48373)
+++ branches/gsoc_threads/src/gc/system.c	Tue Aug 10 01:10:47 2010	(r48374)
@@ -253,11 +253,7 @@
     int i, cur_idx;
 
     /* We need to trace the stack in one running thread (this thread) as
-       well as the stack in each blocked thread. 
-
-       If a thread isn't running or in the "blocked" state, then it's waiting 
-       on something outside of any runloop, so it doesn't have any PMCs on its
-       stack.
+       well as the stack in each other active thread.
     */
     cur_idx = Parrot_threads_current(interp);
 
@@ -268,7 +264,7 @@
             void *hi = &i;
             trace_mem_block(interp, mem_pools, (size_t)lo, (size_t)hi);
         }
-        else if (tbl->threads[i].blocked) {
+        else if (THREAD_STATE_TEST(interp, i, SCAN_STACK)) {
             void *hi = tbl->threads[i].hi_var_ptr;
             trace_mem_block(interp, mem_pools, (size_t)lo, (size_t)hi);
         }

Modified: branches/gsoc_threads/src/interp/inter_create.c
==============================================================================
--- branches/gsoc_threads/src/interp/inter_create.c	Tue Aug 10 00:18:55 2010	(r48373)
+++ branches/gsoc_threads/src/interp/inter_create.c	Tue Aug 10 01:10:47 2010	(r48374)
@@ -296,7 +296,6 @@
      */
     interp->thread_data = NULL;
 
-    MUTEX_INIT(interp->interp_lock);
     Parrot_cx_init_scheduler(interp);
 
 #ifdef ATEXIT_DESTROY
@@ -355,6 +354,10 @@
 Parrot_really_destroy(PARROT_INTERP, SHIM(int exit_code), SHIM(void *arg))
 {
     ASSERT_ARGS(Parrot_really_destroy)
+
+    /* Chandon TODO: Restore this functionality */
+    return;
+
     /* wait for threads to complete if needed; terminate the event loop */
     if (!interp->parent_interpreter) {
         Parrot_cx_runloop_end(interp);

Modified: branches/gsoc_threads/src/io/unix.c
==============================================================================
--- branches/gsoc_threads/src/io/unix.c	Tue Aug 10 00:18:55 2010	(r48373)
+++ branches/gsoc_threads/src/io/unix.c	Tue Aug 10 01:10:47 2010	(r48374)
@@ -31,6 +31,7 @@
 #include "parrot/parrot.h"
 #include "io_private.h"
 #include "pmc/pmc_filehandle.h"
+#include "parrot/threads.h"
 
 #ifdef PIO_OS_UNIX
 
@@ -515,7 +516,12 @@
     void * const buffer = Buffer_bufstart(s);
 
     for (;;) {
-        const int bytes = read(file_descriptor, buffer, len);
+        int bytes;
+        INTVAL tid;
+
+        BLOCK_THREAD_ON(interp,
+            bytes = read(file_descriptor, buffer, len));
+
         if (bytes > 0) {
             s->bufused = s->strlen = bytes;
             return bytes;

Modified: branches/gsoc_threads/src/main.c
==============================================================================
--- branches/gsoc_threads/src/main.c	Tue Aug 10 00:18:55 2010	(r48373)
+++ branches/gsoc_threads/src/main.c	Tue Aug 10 01:10:47 2010	(r48374)
@@ -25,7 +25,6 @@
 #include "parrot/imcc.h"
 #include "parrot/longopt.h"
 #include "parrot/runcore_api.h"
-#include "parrot/alarm.h"
 #include "pmc/pmc_callcontext.h"
 
 /* For gc_sys_type_enum */

Modified: branches/gsoc_threads/src/pmc/pmclist.pmc
==============================================================================
--- branches/gsoc_threads/src/pmc/pmclist.pmc	Tue Aug 10 00:18:55 2010	(r48373)
+++ branches/gsoc_threads/src/pmc/pmclist.pmc	Tue Aug 10 01:10:47 2010	(r48374)
@@ -38,6 +38,9 @@
 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
 /* HEADERIZER END: static */
 
+void Parrot_pmc_list_insert_by_number(PARROT_INTERP, PMC *list, PMC *value);
+
+
 /* It's a doubly linked list */
 typedef struct PMC_List_Item {
     PMC *data;

Modified: branches/gsoc_threads/src/runcore/trace.c
==============================================================================
--- branches/gsoc_threads/src/runcore/trace.c	Tue Aug 10 00:18:55 2010	(r48373)
+++ branches/gsoc_threads/src/runcore/trace.c	Tue Aug 10 01:10:47 2010	(r48374)
@@ -239,7 +239,7 @@
             break;
           case KEY_string_FLAG|KEY_register_FLAG:
             {
-            const INTVAL keynum = VTABLE_get_integer(interp, key);
+            const UINTVAL keynum = VTABLE_get_integer(interp, key);
             if (keynum < Parrot_pcc_get_regs_used(interp, CURRENT_CONTEXT(interp), REGNO_STR)) {
                 const STRING * const s = REG_STR(interp, keynum);
                 STRING * const escaped = Parrot_str_escape_truncate(interp, s, 20);

Modified: branches/gsoc_threads/src/scheduler.c
==============================================================================
--- branches/gsoc_threads/src/scheduler.c	Tue Aug 10 00:18:55 2010	(r48373)
+++ branches/gsoc_threads/src/scheduler.c	Tue Aug 10 01:10:47 2010	(r48374)
@@ -85,6 +85,9 @@
         scheduler = VTABLE_share_ro(interp, scheduler);
 
         interp->scheduler = scheduler;
+
+        /* Make sure the program can handle alarm signals */
+        Parrot_alarm_init();
     }
 }
 
@@ -121,7 +124,7 @@
 
     do {
         Parrot_cx_check_alarms(interp, interp->scheduler);
-        Parrot_threads_wakeup(interp);
+        (void) Parrot_threads_next_to_run(interp, 0);
 
         UNLOCK_INTERP(interp);
         pause();
@@ -129,7 +132,7 @@
 
         task_count    = VTABLE_get_integer(interp, sched->task_queue);
         alarm_count   = VTABLE_get_integer(interp, sched->alarms);
-        blocked_count = Parrot_threads_count_blocked(interp);
+        blocked_count = Parrot_threads_count_active(interp);
     } while (task_count + alarm_count + blocked_count > 0);
 
     Parrot_threads_reap(interp);
@@ -142,42 +145,6 @@
 
 /*
 
-=item C<void Parrot_cx_outer_runloop(PARROT_INTERP, INTVAL tidx)>
-
-This is the core loop performed by each active OS thread, looking for Tasks
-to run and running them.
-
-=cut
-
-*/
-
-void
-Parrot_cx_outer_runloop(PARROT_INTERP, INTVAL tidx)
-{
-    ASSERT_ARGS(Parrot_cx_outer_runloop)
-    PMC* scheduler = interp->scheduler;
-    Parrot_Scheduler_attributes *sched = PARROT_SCHEDULER(scheduler);
-    INTVAL task_count;
-
-    for (;;) {
-        LOCK_INTERP(interp);
-        interp->active_thread = tidx;
-
-        task_count = VTABLE_get_integer(interp, sched->task_queue);
-
-        if (task_count > 0) {
-            Parrot_cx_next_task(interp, scheduler);
-        }
-        else {
-            Parrot_threads_idle(interp, tidx);
-        }
-
-        UNLOCK(interp->interp_lock);
-    }
-}
-
-/*
-
 =item C<void Parrot_cx_next_task(PARROT_INTERP, PMC *scheduler)>
 
 Run the task at the head of the task queue until it ends or is
@@ -210,6 +177,9 @@
         Parrot_alarm_set(interp->quantum_done);
 
         Parrot_ext_call(interp, interp->current_task, "->");
+    } 
+    else {
+        Parrot_alarm_now();
     }
 }
 
@@ -230,8 +200,13 @@
     ASSERT_ARGS(Parrot_cx_check_scheduler)
     PMC *scheduler = interp->scheduler;
 
-    if  (Parrot_alarm_check(&(interp->last_alarm))
-          || SCHEDULER_wake_requested_TEST(scheduler)) {
+    if (Parrot_threads_check_and_reset(interp)) {
+        SCHEDULER_wake_requested_SET(scheduler);
+        SCHEDULER_resched_requested_SET(scheduler);
+    }
+
+    if (Parrot_alarm_check(&(interp->last_alarm))
+        || SCHEDULER_wake_requested_TEST(scheduler)) {
         SCHEDULER_wake_requested_CLEAR(scheduler);
         return Parrot_cx_run_scheduler(interp, scheduler, next);
     }
@@ -257,6 +232,7 @@
 Parrot_cx_run_scheduler(PARROT_INTERP, ARGMOD(PMC *scheduler), ARGIN(opcode_t *next))
 {
     ASSERT_ARGS(Parrot_cx_run_scheduler)
+    INTVAL tid = interp->active_thread;
 
     Parrot_cx_check_alarms(interp, scheduler);
     Parrot_cx_check_quantum(interp, scheduler);
@@ -264,10 +240,16 @@
     if (SCHEDULER_resched_requested_TEST(scheduler)) {
         SCHEDULER_resched_requested_CLEAR(scheduler);
 
-        /* Exiting the runloop to swap tasks doesn't play
-           nice with nested runloops */
-        if (interp->current_runloop_level <= 1)
+        /* A task switch will only work in the outer runloop of a fully
+           booted Parrot. In a Parrot that hasn't called begin_execution,
+           or in a nested runloop, we silently ignore task switches. */
+        if (interp->current_task && interp->current_runloop_level <= 1)
             return Parrot_cx_preempt_task(interp, scheduler, next);
+
+#ifdef ARBITRARY_DEBUG_STATEMENT
+        fprintf(stderr, "Should have exited runloop. Didn't (%lx, %ld)\n",
+                interp->current_task, interp->current_runloop_level);
+#endif
     }
 
     return next;

Modified: branches/gsoc_threads/src/threads.c
==============================================================================
--- branches/gsoc_threads/src/threads.c	Tue Aug 10 00:18:55 2010	(r48373)
+++ branches/gsoc_threads/src/threads.c	Tue Aug 10 01:10:47 2010	(r48374)
@@ -20,6 +20,7 @@
 
 #include "parrot/threads.h"
 #include "parrot/alarm.h"
+#include "pmc/pmc_scheduler.h"
 
 /* HEADERIZER HFILE: include/parrot/threads.h */
 
@@ -41,6 +42,12 @@
     ASSERT_ARGS(Parrot_threads_init)
     Thread_table *tbl;
 
+    MUTEX_INIT(interp->interp_lock);
+    PARROT_ATOMIC_INT_INIT(interp->thread_signal);
+    PARROT_ATOMIC_INT_SET(interp->thread_signal, 0);
+
+    MUTEX_INIT(interp->thread_lock);
+
     interp->thread_table = (Thread_table*) malloc(sizeof(Thread_table));
     interp->active_thread = 0;
 
@@ -50,8 +57,9 @@
     tbl->count   = 1;
     tbl->threads = (Thread_info*) malloc(sizeof(Thread_info) * tbl->size);
 
-    tbl->threads[0].id      = THREAD_SELF();
-    tbl->threads[0].blocked = 0;
+    tbl->threads[0].id    = THREAD_SELF();
+    tbl->threads[0].state = 0;
+    THREAD_STATE_SET(interp, 0, INITIALIZED);
     COND_INIT(tbl->threads[0].cvar);
 
     LOCK_INTERP(interp);
@@ -82,23 +90,70 @@
     Parrot_alarm_mask(interp);
 
     /* Yay stack scanning */
+    LOCK(interp->thread_lock);
     tbl->threads[tidx].lo_var_ptr = &tidx;
+    UNLOCK(interp->thread_lock);
 
-    //fprintf(stderr, "Thread id# %d started.\n", (int) tidx);
+    Parrot_threads_outer_runloop(interp, tidx);
+    return 0;
+}
 
-    Parrot_cx_outer_runloop(interp, tidx);
+/*
 
-    //fprintf(stderr, "Thread id# %d ending.\n", (int) tidx);
-    return 0;
+=item C<void Parrot_threads_outer_runloop(PARROT_INTERP, INTVAL tidx)>
+
+This is the core loop performed by each active OS thread. If it's the
+thread that needs to be running, it invokes the Scheduler to pick a
+task.
+
+=cut
+
+*/
+
+void
+Parrot_threads_outer_runloop(PARROT_INTERP, INTVAL tidx)
+{
+    ASSERT_ARGS(Parrot_threads_outer_runloop)
+    PMC* scheduler = interp->scheduler;
+    Parrot_Scheduler_attributes *sched = PARROT_SCHEDULER(scheduler);
+    INTVAL next_thread, task_count;
+
+    for (;;) {
+        LOCK_INTERP(interp);
+        interp->active_thread = tidx;
+        interp->current_runloop_level = 0;
+
+        LOCK(interp->thread_lock);
+        if (THREAD_STATE_TEST(interp, tidx, DEATH_MARK)) {
+            UNLOCK(interp->thread_lock);
+            UNLOCK_INTERP(interp);
+            return;
+        }
+        UNLOCK(interp->thread_lock);
+
+        /* Are we the best thread to be running right now? */
+        next_thread = Parrot_threads_next_to_run(interp, tidx);
+        task_count  = VTABLE_get_integer(interp, sched->task_queue);
+
+        if (next_thread == tidx && task_count > 0) {
+            Parrot_cx_next_task(interp, scheduler);
+        } else {
+            /* Wake up the main thread to check if we're done before 
+               going idle. */
+            Parrot_alarm_now();
+            Parrot_threads_idle(interp, tidx);
+        }
+
+        UNLOCK(interp->interp_lock);
+    }
 }
 
 /*
 
 =item C<void Parrot_threads_block(PARROT_INTERP, INTVAL *tidx)>
 
-The current thread is about to block. Make sure there's
-another thread ready to do work once we release the
-interpreter lock.
+The current thread is about to block. Make sure there's another thread ready 
+to do work once we release the interpreter lock.
 
 Use macros BLOCK_THREAD and UNBLOCK_THREAD rather than
 calling this directly.
@@ -112,34 +167,41 @@
 {
     ASSERT_ARGS(Parrot_threads_block)
     Thread_table *tbl = interp->thread_table;
-    int next;
+    int next, i, have_runnable;
 
-    /* scan to find who's next */
-    for (next = 1; next < tbl->count; ++next) {
-        if(tbl->threads[next].blocked == 0)
-            break;
-    }
+    *tidx = interp->active_thread;
 
-    /* Maybe spawn more threads */
-    if (next > tbl->count) {
-        Parrot_threads_spawn(interp);
-    }
+    next = Parrot_threads_next_to_run(interp, *tidx);
 
-    *tidx = interp->active_thread;
+    LOCK(interp->thread_lock);
 
     /* While we're blocked, we might have PMCs on stack */
     tbl->threads[*tidx].hi_var_ptr = &next;
+    THREAD_STATE_CLEAR(interp, *tidx, RUNNABLE);
+    THREAD_STATE_SET(interp, *tidx, SCAN_STACK);
+    
+    /* Maybe spawn more threads */
+    have_runnable = 0;
+    for (i = 1; i < tbl->count; ++i) {
+        if (THREAD_STATE_TEST(interp, i, RUNNABLE)) {
+            have_runnable = 1;
+            break;
+        }
+    }
 
-    tbl->threads[*tidx].blocked = 1;
+    if (!have_runnable) {
+        Parrot_threads_spawn(interp);
+    }
 
     COND_SIGNAL(tbl->threads[*tidx].cvar);
+    UNLOCK(interp->thread_lock);
 
     UNLOCK_INTERP(interp);
 }
 
 /*
 
-=item C<void Parrot_threads_unblock(PARROT_INTERP, INTVAL *tidx)>
+=item C<void Parrot_threads_unblock(PARROT_INTERP, INTVAL *tidx_ptr)>
 
 The current thread has completed a blocking operation.
 It's going to have to wait for someone else to finish.
@@ -152,41 +214,58 @@
 */
 
 void
-Parrot_threads_unblock(PARROT_INTERP, ARGIN(INTVAL *tidx))
+Parrot_threads_unblock(PARROT_INTERP, ARGIN(INTVAL *tidx_ptr))
 {
     ASSERT_ARGS(Parrot_threads_unblock)
     Thread_table *tbl;
+    const INTVAL tidx = *tidx_ptr;
 
-    LOCK_INTERP(interp);
+    /* We need to signal that we want the interpreter back. */
+    Parrot_alarm_now();
+
+    LOCK(interp->thread_lock);
 
     tbl = interp->thread_table;
-    interp->active_thread = *tidx;
-    tbl->threads[*tidx].blocked = 0;
+    interp->active_thread = tidx;
+    THREAD_STATE_SET(interp, tidx, RESTLESS);
+
+    UNLOCK(interp->thread_lock);
+
+    Parrot_threads_set_signal(interp);
+
+    LOCK_INTERP(interp);
+    THREAD_STATE_CLEAR(interp, tidx, SCAN_STACK);
+    THREAD_STATE_CLEAR(interp, tidx, RESTLESS);
 }
 
 /*
 
-=item C<INTVAL Parrot_threads_count_blocked(PARROT_INTERP)>
+=item C<INTVAL Parrot_threads_count_active(PARROT_INTERP)>
 
-Scan the interpreter's thread table to find how many are blocked.
+Scan the interpreter's thread table to find how many threads currently
+have an active task.
 
 =cut
 
 */
 
 INTVAL
-Parrot_threads_count_blocked(PARROT_INTERP)
+Parrot_threads_count_active(PARROT_INTERP)
 {
-    ASSERT_ARGS(Parrot_threads_count_blocked)
+    ASSERT_ARGS(Parrot_threads_count_active)
 
     Thread_table *tbl = interp->thread_table;
     int i;
     INTVAL count = 0;
 
+    /* An active thread will have its SCAN_STACK flag set */
+
+    LOCK(interp->thread_lock);
     for (i = 1; i < tbl->count; ++i) {
-        if(tbl->threads[i].blocked)
+        if (THREAD_STATE_TEST(interp, i, SCAN_STACK))
             ++count;
     }
+    UNLOCK(interp->thread_lock);
 
     return count;
 }
@@ -197,6 +276,9 @@
 
 Someone needs another thread. Add one at the end of table.
 
+Important: You must have interp->thread_lock before calling
+    this function.
+
 =cut
 
 */
@@ -209,18 +291,21 @@
     INTVAL    new_idx = tbl->count;
     Thread_args *args = (Thread_args*) malloc(sizeof(Thread_args));
 
+
     tbl->count += 1;
 
     /* Maybe grow table */
     if (tbl->count > tbl->size) {
         tbl->size *= 2;
-        tbl = (Thread_table*) realloc(tbl, sizeof(Thread_info) * tbl->size);
+        tbl->threads = (Thread_info*) realloc(tbl, sizeof(Thread_info) * tbl->size);
     }
 
     args->interp = interp;
     args->idx    = new_idx;
 
-    tbl->threads[new_idx].blocked = 0;
+    tbl->threads[new_idx].state = 0;
+    THREAD_STATE_SET(interp, new_idx, INITIALIZED);
+    THREAD_STATE_SET(interp, new_idx, RUNNABLE);
     COND_INIT(tbl->threads[new_idx].cvar);
 
     THREAD_CREATE_JOINABLE(tbl->threads[new_idx].id, Parrot_threads_main, args);
@@ -232,6 +317,8 @@
 
 Clean up any excess threads at the end of table.
 
+Important: You must have the interpreter lock to call this function.
+
 =cut
 
 */
@@ -240,7 +327,45 @@
 Parrot_threads_reap(PARROT_INTERP)
 {
     ASSERT_ARGS(Parrot_threads_reap)
-    /* fprintf(stderr, "Parrot_reap_threads not implemented.\n"); */
+    Thread_table *tbl = interp->thread_table;
+    int i;
+
+    LOCK(interp->thread_lock);
+    for (i = tbl->count - 1; i > interp->active_thread; --i) {
+        void *rv;
+
+        if (THREAD_STATE_TEST(interp, i, SCAN_STACK))
+            break;
+
+        if (THREAD_STATE_TEST(interp, i, RUNNABLE)) {
+            THREAD_STATE_SET(interp, i, DEATH_MARK);
+            THREAD_STATE_SET(interp, i, RESTLESS);
+
+            COND_SIGNAL(tbl->threads[i].cvar);
+
+            UNLOCK_INTERP(interp);
+            UNLOCK(interp->thread_lock);
+
+            JOIN(tbl->threads[i].id, rv);
+
+            LOCK_INTERP(interp);
+            LOCK(interp->thread_lock);
+
+            tbl->threads[i].state = 0;
+            COND_DESTROY(tbl->threads[i].cvar);
+            
+            tbl->count -= 1;
+        }
+
+    }
+
+    if (i < (long)tbl->size / 3) {
+        /* Shrink that table */
+        tbl->size /= 2;
+        tbl->threads = (Thread_info*) realloc(tbl, sizeof(Thread_info) * tbl->size);        
+    }
+
+    UNLOCK(interp->thread_lock);
 }
 
 /*
@@ -258,35 +383,56 @@
 {
     ASSERT_ARGS(Parrot_threads_idle)
     Thread_table *tbl = interp->thread_table;
+    THREAD_STATE_SET(interp, tidx, RUNNABLE);
     COND_WAIT(tbl->threads[tidx].cvar, interp->interp_lock);
     interp->active_thread = tidx;
 }
 
 /*
 
-=item C<void Parrot_threads_wakeup(PARROT_INTERP)>
+=item C<INTVAL Parrot_threads_check_and_reset(PARROT_INTERP)>
 
-There might be work to do, wake up a thread.
+Sees if a thread signal has occured and, if so, resets the
+signal flag.
 
 =cut
 
 */
 
-void
-Parrot_threads_wakeup(PARROT_INTERP)
+INTVAL
+Parrot_threads_check_and_reset(PARROT_INTERP)
 {
-    ASSERT_ARGS(Parrot_threads_idle)
-    Thread_table *tbl = interp->thread_table;
-    int i;
+    ASSERT_ARGS(Parrot_threads_check_and_reset)
 
-    for(i = 1; i < tbl->count; ++i) {
-        if (tbl->threads[i].blocked == 0) {
-            COND_SIGNAL(tbl->threads[i].cvar);
-            return;
-        }
+    INTVAL flag;
+    PARROT_ATOMIC_INT_GET(flag, interp->thread_signal);
+
+    /* If we reset thread_signal unconditionally here
+       then there would be a race and we could miss
+       the flag being set. */
+    if (flag) {
+        PARROT_ATOMIC_INT_SET(interp->thread_signal, 0);
     }
 
-    Parrot_threads_spawn(interp);
+    return flag;
+}
+
+/*
+
+=item C<void Parrot_threads_set_signal(PARROT_INTERP)>
+
+Set the thread signal, indicating that a thread reschedule
+wants to occur.
+
+=cut
+
+*/
+
+void
+Parrot_threads_set_signal(PARROT_INTERP)
+{
+    ASSERT_ARGS(Parrot_threads_set_signal)
+    PARROT_ATOMIC_INT_SET(interp->thread_signal, 1);
 }
 
 /*
@@ -302,19 +448,107 @@
 INTVAL
 Parrot_threads_current(PARROT_INTERP)
 {
+    ASSERT_ARGS(Parrot_threads_current)
+
     INTVAL idx;
     Thread_table *tbl = interp->thread_table;
     Parrot_thread tid = THREAD_SELF();
 
-
+    LOCK(interp->thread_lock);
     for(idx = 0; idx < tbl->count; ++idx) {
-        if (THREAD_EQUAL(tbl->threads[idx].id, tid))
+        if (THREAD_EQUAL(tbl->threads[idx].id, tid)) {
+            UNLOCK(interp->thread_lock);
             return idx;
+        }
     }
+    UNLOCK(interp->thread_lock);
 
     exit_fatal(1, "threads.c: Current thread is not in the threads table.");
 }
 
+/*
+
+=item C<INTVAL Parrot_threads_next_to_run(PARROT_INTERP, INTVAL cur_idx)>
+
+Scan the thread table for the best thread to run now.
+
+=cut
+
+*/
+
+INTVAL
+Parrot_threads_next_to_run(PARROT_INTERP, INTVAL cur_idx)
+{
+    ASSERT_ARGS(Parrot_threads_next_to_run)
+
+    Thread_table *tbl = interp->thread_table;
+    int i;
+
+    LOCK(interp->thread_lock);
+
+    /* Pick threads to run to try to fill the thread table
+       at the beginning, so we can shrink it at the end. */
+
+
+    /* If there's a restless thread, run the last one. */
+    for (i = tbl->count - 1; i > 0; --i) {
+        if (THREAD_STATE_TEST(interp, i, RESTLESS)) {
+            COND_SIGNAL(tbl->threads[i].cvar);
+            UNLOCK(interp->thread_lock);
+            return i;
+        }
+    }
+
+    /* Otherwise there's a runnable thread, run the first one. */
+    for (i = 1; i < tbl->count; ++i) {
+        if (THREAD_STATE_TEST(interp, i, RUNNABLE)) {
+            COND_SIGNAL(tbl->threads[i].cvar);            
+            UNLOCK(interp->thread_lock);
+            return i;
+        }
+    }
+
+    UNLOCK(interp->thread_lock);
+
+    /* Otherwise, the current thread is fine. */
+    return cur_idx;
+}
+
+/*
+
+=item C<void Parrot_threads_print_table(PARROT_INTERP)>
+
+Print the current thread table, which hopefully shows what's horribly
+broken this time.
+
+=cut
+
+*/
+
+void
+Parrot_threads_print_table(PARROT_INTERP)
+{
+    ASSERT_ARGS(Parrot_threads_print_table)
+    Thread_table *tbl = interp->thread_table;
+    INTVAL i;
+
+    fprintf(stderr, " === Thread Info ===\n");
+    fprintf(stderr, "Table count/size: %ld / %ld.\n", tbl->count, tbl->size);
+    fprintf(stderr, "Current thread: %ld\n", Parrot_threads_current(interp));
+
+    for (i = 0; i < tbl->count; ++i) {
+        fprintf(stderr, " %ld\t", i);
+        if (THREAD_STATE_TEST(interp, i, INITIALIZED))
+            fprintf(stderr, "init ");
+        if (THREAD_STATE_TEST(interp, i, RUNNABLE))
+            fprintf(stderr, "runnable ");
+        if (THREAD_STATE_TEST(interp, i, SCAN_STACK))
+            fprintf(stderr, "scan_stack ");
+        if (THREAD_STATE_TEST(interp, i, RESTLESS))
+            fprintf(stderr, "restless ");
+        fprintf(stderr, "\n");
+    }
+}
 
 /*
 

Added: branches/gsoc_threads/t/src/threads_io.t
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ branches/gsoc_threads/t/src/threads_io.t	Tue Aug 10 01:10:47 2010	(r48374)
@@ -0,0 +1,73 @@
+#! perl
+# Copyright (C) 2010, Parrot Foundation.
+# $Id$
+
+use strict;
+use warnings;
+use File::Temp;
+use Time::HiRes qw(sleep);
+
+# TAP Plan
+print "1..4\n";
+
+my $pir = File::Temp->new(TEMPLATE => 'thread_io_XXXX', SUFFIX => '.pir');
+my $tmp = File::Temp->new(TEMPLATE => 'thread_io_XXXX', SUFFIX => '.tmp');
+
+$pir->print(<<'EOF');
+#! ./parrot
+
+.sub main :main
+    .local pmc insub, spinsub, spintask
+
+    insub = get_global 'insub'
+    $P0 = new 'Task', insub
+    schedule $P0
+
+    spinsub  = get_global 'spin'
+    spintask = new 'Task', spinsub
+    schedule spintask
+    
+    pass
+
+    say "ok 2 - main task sleeping"
+    sleep 0.2
+    say "ok 4 - main task back"
+
+    spintask.'kill'()
+.end
+
+.sub insub
+    .local pmc stdin
+    stdin = getstdin
+
+    $P0 = stdin.'readline'()
+    
+    $S0 = $P0
+    if $S0 == "grumblecake\n" goto good
+    say "not ok 3"
+    .return()
+
+good:
+    say "ok 3 - got input"
+    .return()
+.end
+
+.sub spin
+    say "ok 1 - spinning"
+    $I0 = 0
+spin_more:
+    $I0 = $I0 + 1
+    goto spin_more
+.end
+
+EOF
+
+my $pir_file = $pir->filename;
+
+open my $run, "|perl ${\$pir->filename} ${\$tmp->filename}";
+
+sleep(0.1);
+$run->print("grumblecake\n");
+sleep(0.3);
+
+close($run);


More information about the parrot-commits mailing list