[svn:parrot] r48680 - in branches/gsoc_threads: include/parrot src src/gc src/interp src/io src/ops src/pmc

Chandon at svn.parrot.org Chandon at svn.parrot.org
Thu Aug 26 23:06:39 UTC 2010


Author: Chandon
Date: Thu Aug 26 23:06:38 2010
New Revision: 48680
URL: https://trac.parrot.org/parrot/changeset/48680

Log:
[gsoc_threads] Can now kill blocked threads.
Also, now with less completely wrong code.

Modified:
   branches/gsoc_threads/include/parrot/interpreter.h
   branches/gsoc_threads/include/parrot/scheduler.h
   branches/gsoc_threads/include/parrot/threads.h
   branches/gsoc_threads/src/gc/mark_sweep.c
   branches/gsoc_threads/src/interp/inter_create.c
   branches/gsoc_threads/src/interp/inter_misc.c
   branches/gsoc_threads/src/io/unix.c
   branches/gsoc_threads/src/ops/core_ops.c
   branches/gsoc_threads/src/ops/experimental.ops
   branches/gsoc_threads/src/pmc/pmclist.pmc
   branches/gsoc_threads/src/pmc/task.pmc
   branches/gsoc_threads/src/scheduler.c
   branches/gsoc_threads/src/threads.c

Modified: branches/gsoc_threads/include/parrot/interpreter.h
==============================================================================
--- branches/gsoc_threads/include/parrot/interpreter.h	Thu Aug 26 23:00:30 2010	(r48679)
+++ branches/gsoc_threads/include/parrot/interpreter.h	Thu Aug 26 23:06:38 2010	(r48680)
@@ -270,7 +270,6 @@
 
     UINTVAL          last_alarm;              /* has an alarm triggered? */
     FLOATVAL         quantum_done;            /* expiration of current quantum */
-    PMC             *current_task;            /* there's always one running task */
 
     Parrot_mutex     interp_lock;             /* Enforce one running thread per interp */
 

Modified: branches/gsoc_threads/include/parrot/scheduler.h
==============================================================================
--- branches/gsoc_threads/include/parrot/scheduler.h	Thu Aug 26 23:00:30 2010	(r48679)
+++ branches/gsoc_threads/include/parrot/scheduler.h	Thu Aug 26 23:06:38 2010	(r48680)
@@ -132,6 +132,10 @@
         __attribute__nonnull__(1)
         __attribute__nonnull__(2);
 
+PARROT_CANNOT_RETURN_NULL
+PMC* Parrot_task_current(PARROT_INTERP)
+        __attribute__nonnull__(1);
+
 #define ASSERT_ARGS_Parrot_cx_begin_execution __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(interp) \
     , PARROT_ASSERT_ARG(main) \
@@ -189,6 +193,8 @@
 #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_task_current __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+       PARROT_ASSERT_ARG(interp))
 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
 /* HEADERIZER END: src/scheduler.c */
 

Modified: branches/gsoc_threads/include/parrot/threads.h
==============================================================================
--- branches/gsoc_threads/include/parrot/threads.h	Thu Aug 26 23:00:30 2010	(r48679)
+++ branches/gsoc_threads/include/parrot/threads.h	Thu Aug 26 23:06:38 2010	(r48680)
@@ -28,6 +28,7 @@
     Parrot_cond   cvar;
     void         *lo_var_ptr; /* Full range of stack for GC scan */
     void         *hi_var_ptr;
+    PMC          *cur_task;
 } Thread_info;
 
 typedef struct Thread_table {
@@ -65,6 +66,9 @@
 /* HEADERIZER BEGIN: src/threads.c */
 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
 
+void Parrot_check_if_task_killed(PARROT_INTERP)
+        __attribute__nonnull__(1);
+
 void Parrot_threads_block(PARROT_INTERP, ARGOUT(INTVAL *tidx))
         __attribute__nonnull__(1)
         __attribute__nonnull__(2)
@@ -82,6 +86,9 @@
 INTVAL Parrot_threads_current(PARROT_INTERP)
         __attribute__nonnull__(1);
 
+void Parrot_threads_gc_mark(PARROT_INTERP)
+        __attribute__nonnull__(1);
+
 void Parrot_threads_idle(PARROT_INTERP, INTVAL tidx)
         __attribute__nonnull__(1);
 
@@ -108,13 +115,22 @@
 void Parrot_threads_set_signal(PARROT_INTERP)
         __attribute__nonnull__(1);
 
+void Parrot_threads_setup_signal_handler(PARROT_INTERP)
+        __attribute__nonnull__(1);
+
 void Parrot_threads_spawn(PARROT_INTERP)
         __attribute__nonnull__(1);
 
+void Parrot_threads_task_killed(PARROT_INTERP, INTVAL tidx)
+        __attribute__nonnull__(1);
+
+void Parrot_threads_task_killed_handler(NULLOK(int sig_number));
 void Parrot_threads_unblock(PARROT_INTERP, ARGIN(INTVAL *tidx_ptr))
         __attribute__nonnull__(1)
         __attribute__nonnull__(2);
 
+#define ASSERT_ARGS_Parrot_check_if_task_killed __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+       PARROT_ASSERT_ARG(interp))
 #define ASSERT_ARGS_Parrot_threads_block __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(interp) \
     , PARROT_ASSERT_ARG(tidx))
@@ -127,6 +143,8 @@
        PARROT_ASSERT_ARG(interp))
 #define ASSERT_ARGS_Parrot_threads_current __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(interp))
+#define ASSERT_ARGS_Parrot_threads_gc_mark __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))
 #define ASSERT_ARGS_Parrot_threads_init __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
@@ -143,8 +161,15 @@
        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_setup_signal_handler \
+     __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_task_killed __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+       PARROT_ASSERT_ARG(interp))
+#define ASSERT_ARGS_Parrot_threads_task_killed_handler \
+     __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
 #define ASSERT_ARGS_Parrot_threads_unblock __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(interp) \
     , PARROT_ASSERT_ARG(tidx_ptr))

Modified: branches/gsoc_threads/src/gc/mark_sweep.c
==============================================================================
--- branches/gsoc_threads/src/gc/mark_sweep.c	Thu Aug 26 23:00:30 2010	(r48679)
+++ branches/gsoc_threads/src/gc/mark_sweep.c	Thu Aug 26 23:06:38 2010	(r48680)
@@ -159,6 +159,7 @@
 {
     ASSERT_ARGS(Parrot_gc_trace_root)
     PObj    *obj;
+    PMC     *tmp;
 
     /* note: adding locals here did cause increased GC runs */
     mark_context_start();
@@ -195,9 +196,9 @@
     /* mark the root_namespace */
     Parrot_gc_mark_PMC_alive(interp, interp->root_namespace);
 
-    /* mark the concurrency scheduler and current task */
+    /* mark the concurrency scheduler and tasks */
     Parrot_gc_mark_PMC_alive(interp, interp->scheduler);
-    Parrot_gc_mark_PMC_alive(interp, interp->current_task);
+    Parrot_threads_gc_mark(interp);
 
     /* s. packfile.c */
     mark_const_subs(interp);

Modified: branches/gsoc_threads/src/interp/inter_create.c
==============================================================================
--- branches/gsoc_threads/src/interp/inter_create.c	Thu Aug 26 23:00:30 2010	(r48679)
+++ branches/gsoc_threads/src/interp/inter_create.c	Thu Aug 26 23:06:38 2010	(r48680)
@@ -165,8 +165,6 @@
                                     ? parent->gc_sys->sys_type
                                     : PARROT_GC_DEFAULT_TYPE;
 
-    interp->current_task = PMCNULL;
-
     /* Done. Return and be done with it */
     return interp;
 }

Modified: branches/gsoc_threads/src/interp/inter_misc.c
==============================================================================
--- branches/gsoc_threads/src/interp/inter_misc.c	Thu Aug 26 23:00:30 2010	(r48679)
+++ branches/gsoc_threads/src/interp/inter_misc.c	Thu Aug 26 23:06:38 2010	(r48680)
@@ -268,7 +268,7 @@
         result = Parrot_pcc_get_lex_pad(interp, CURRENT_CONTEXT(interp));
         break;
       case CURRENT_TASK:
-        result = interp->current_task;
+        result = Parrot_task_current(interp);
         break;
       default:        /* or a warning only? */
         Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_UNIMPLEMENTED,

Modified: branches/gsoc_threads/src/io/unix.c
==============================================================================
--- branches/gsoc_threads/src/io/unix.c	Thu Aug 26 23:00:30 2010	(r48679)
+++ branches/gsoc_threads/src/io/unix.c	Thu Aug 26 23:06:38 2010	(r48680)
@@ -529,6 +529,7 @@
         else if (bytes < 0) {
             switch (errno) {
               case EINTR:
+                Parrot_check_if_task_killed(interp);
                 continue;
               default:
                 s->bufused = s->strlen = 0;

Modified: branches/gsoc_threads/src/ops/core_ops.c
==============================================================================
--- branches/gsoc_threads/src/ops/core_ops.c	Thu Aug 26 23:00:30 2010	(r48679)
+++ branches/gsoc_threads/src/ops/core_ops.c	Thu Aug 26 23:06:38 2010	(r48680)
@@ -26164,7 +26164,7 @@
 Parrot_receive_p(opcode_t *cur_opcode, PARROT_INTERP)  {
     const Parrot_Context * const CUR_CTX = Parrot_pcc_get_context_struct(interp, interp->ctx);
     opcode_t *const dest = cur_opcode + 2;
-    PMC *cur_task = interp->current_task;
+    PMC *cur_task = Parrot_task_current(interp);
     Parrot_Task_attributes *tdata = PARROT_TASK(cur_task);
     int msg_count = VTABLE_get_integer(interp, tdata->mailbox);
 
@@ -26172,7 +26172,7 @@
         PREG(1) = VTABLE_shift_pmc(interp, tdata->mailbox);return (opcode_t *)dest;
     }
     else {
-        TASK_recv_block_SET(interp->current_task);
+        TASK_recv_block_SET(cur_task);
         (void) Parrot_cx_stop_task(interp, cur_opcode);return (opcode_t *)0;
     }
 

Modified: branches/gsoc_threads/src/ops/experimental.ops
==============================================================================
--- branches/gsoc_threads/src/ops/experimental.ops	Thu Aug 26 23:00:30 2010	(r48679)
+++ branches/gsoc_threads/src/ops/experimental.ops	Thu Aug 26 23:06:38 2010	(r48680)
@@ -428,7 +428,7 @@
 
 op receive(out PMC) {
     opcode_t *const dest = expr NEXT();
-    PMC *cur_task = interp->current_task;
+    PMC *cur_task = Parrot_task_current(interp);
     Parrot_Task_attributes *tdata = PARROT_TASK(cur_task);
     int msg_count = VTABLE_get_integer(interp, tdata->mailbox);
 
@@ -437,7 +437,7 @@
         goto ADDRESS(dest);
     }
     else {
-        TASK_recv_block_SET(interp->current_task);
+        TASK_recv_block_SET(cur_task);
         (void) Parrot_cx_stop_task(interp, cur_opcode);
         goto ADDRESS(0);
     }

Modified: branches/gsoc_threads/src/pmc/pmclist.pmc
==============================================================================
--- branches/gsoc_threads/src/pmc/pmclist.pmc	Thu Aug 26 23:00:30 2010	(r48679)
+++ branches/gsoc_threads/src/pmc/pmclist.pmc	Thu Aug 26 23:06:38 2010	(r48680)
@@ -484,11 +484,11 @@
 
 =back
 
-=head2 Auxiliar functions
+=head2 Auxiliary functions
 
 =over 4
 
-=item C(void Parrot_pmc_list_insert_by_num(PARROT_INTERP, PMC* list, PMC* value)
+=item C<void Parrot_pmc_list_insert_by_number(PARROT_INTERP, PMC *list, PMC *value) >
 
 Insert an item into a sorted list by its num value.
 
@@ -497,7 +497,8 @@
 
 PARROT_EXPORT
 void
-Parrot_pmc_list_insert_by_number(PARROT_INTERP, PMC *list, PMC *value) {
+Parrot_pmc_list_insert_by_number(PARROT_INTERP, PMC *list, PMC *value) 
+{
     void *tmp;
     PMC_List_Item *item;
     PMC_List_Item *head;

Modified: branches/gsoc_threads/src/pmc/task.pmc
==============================================================================
--- branches/gsoc_threads/src/pmc/task.pmc	Thu Aug 26 23:00:30 2010	(r48679)
+++ branches/gsoc_threads/src/pmc/task.pmc	Thu Aug 26 23:06:38 2010	(r48680)
@@ -32,8 +32,10 @@
     ATTR PMC          *code;      /* An (optional) code for the task */
     ATTR PMC          *data;      /* Additional data for the task */
     ATTR INTVAL        killed;    /* Dead tasks don't get run */
+    ATTR INTVAL        tidx;      /* Which thread to signal if killed */
     ATTR PMC          *mailbox;   /* List of incoming messages */
     ATTR PMC          *waiters;   /* Tasks waiting on this one */
+    ATTR Parrot_jump_buff abort_jump; /* Jump buffer to abort task */
 
 /*
 
@@ -58,6 +60,7 @@
         core_struct->data      = PMCNULL;
         core_struct->interp    = INTERP;
         core_struct->killed    = 0;
+        core_struct->tidx      = -1;
         core_struct->mailbox   = Parrot_pmc_new(interp, enum_class_PMCList);
         core_struct->waiters   = Parrot_pmc_new(interp, enum_class_ResizablePMCArray);
 
@@ -147,6 +150,10 @@
         /* If a task is pre-empted, this will be set again. */
         TASK_in_preempt_CLEAR(SELF);
 
+        if (setjmp(task->abort_jump)) {
+            /* do nothing, we're back where we want to be */
+        }
+
         if (!(task->killed || PMC_IS_NULL(task->code))) {
             /* Add the task to the set of active Tasks */
             PMC *task_id = Parrot_pmc_new(interp, enum_class_Integer);
@@ -155,15 +162,17 @@
             TASK_active_SET(SELF);
 
             /* Actually run the task */
+            task->tidx = Parrot_threads_current(interp);
             if (PMC_IS_NULL(task->data)) {
                 Parrot_ext_call(interp, task->code, "->");
             }
             else {
                 Parrot_ext_call(interp, task->code, "P->", task->data);
             }
+            task->tidx = -1;
         }
 
-        if (!TASK_in_preempt_TEST(SELF)) {
+        if (task->killed || !TASK_in_preempt_TEST(SELF)) {
             /* The task is done. */
             /* Remove it from the set of active Tasks */
 
@@ -424,6 +433,10 @@
     METHOD kill() {
         Parrot_Task_attributes *tdata = PARROT_TASK(SELF);
         tdata->killed = 1;
+
+        if (tdata->tidx >= 0) {
+            Parrot_threads_task_killed(interp, tdata->tidx);
+        }
     }
 }
 

Modified: branches/gsoc_threads/src/scheduler.c
==============================================================================
--- branches/gsoc_threads/src/scheduler.c	Thu Aug 26 23:00:30 2010	(r48679)
+++ branches/gsoc_threads/src/scheduler.c	Thu Aug 26 23:06:38 2010	(r48680)
@@ -52,6 +52,9 @@
 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
 /* HEADERIZER END: static */
 
+
+static int enable_scheduling = 0;
+
 /*
 
 =head2 Scheduler Interface Functions
@@ -115,6 +118,8 @@
     PMC* main_task = Parrot_pmc_new(interp, enum_class_Task);
     Parrot_Task_attributes *tdata = PARROT_TASK(main_task);
 
+    enable_scheduling  = 1;
+
     tdata->code = main;
     tdata->data = argv;
 
@@ -167,16 +172,19 @@
         FLOATVAL  time_now = Parrot_floatval_time();
         opcode_t *dest;
 
-        interp->current_task = VTABLE_shift_pmc(interp, sched->task_queue);
+        PMC *task = VTABLE_shift_pmc(interp, sched->task_queue);
+        INTVAL tidx = Parrot_threads_current(interp);
 
-        if (!VTABLE_isa(interp, interp->current_task, CONST_STRING(interp, "Task")))
+        if (!VTABLE_isa(interp, task, CONST_STRING(interp, "Task")))
             Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
                 "Found a non-Task in the task queue.\n");
 
+        interp->thread_table->threads[tidx].cur_task = task;
+
         interp->quantum_done = time_now + PARROT_TASK_SWITCH_QUANTUM;
         Parrot_alarm_set(interp->quantum_done);
 
-        Parrot_ext_call(interp, interp->current_task, "->");
+        Parrot_ext_call(interp, task, "->");
     }
     else {
         Parrot_alarm_now();
@@ -243,13 +251,8 @@
         /* 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)
+        if (enable_scheduling && 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;
@@ -291,13 +294,13 @@
 {
     ASSERT_ARGS(Parrot_cx_stop_task)
 
-    PMC *task = interp->current_task;
+    PMC *task = Parrot_task_current(interp);
     Parrot_Task_attributes *tdata = PARROT_TASK(task);
 
     PMC *cont = Parrot_pmc_new(interp, enum_class_Continuation);
     VTABLE_set_pointer(interp, cont, next);
 
-    if (PMC_IS_NULL(task) || !VTABLE_isa(interp, interp->current_task, CONST_STRING(interp, "Task")))
+    if (PMC_IS_NULL(task) || !VTABLE_isa(interp, task, CONST_STRING(interp, "Task")))
         Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
             "Attempt to stop invalid interp->current_task.\n");
 
@@ -327,7 +330,6 @@
     PMC* task = Parrot_cx_stop_task(interp, next);
     VTABLE_push_pmc(interp, sched->task_queue, task);
 
-    interp->current_task = PMCNULL;
     return (opcode_t*) 0;
 }
 
@@ -451,6 +453,26 @@
 
 /*
 
+=item C<PMC* Parrot_task_current(PARROT_INTERP)>
+
+Returns the task that is currently running.
+
+=cut
+
+*/
+
+PARROT_CANNOT_RETURN_NULL
+PMC*
+Parrot_task_current(PARROT_INTERP)
+{
+    ASSERT_ARGS(Parrot_task_current)
+    INTVAL tidx = Parrot_threads_current(interp);
+    return interp->thread_table->threads[tidx].cur_task;
+}
+
+
+/*
+
 =item C<void Parrot_cx_request_suspend_for_gc(PARROT_INTERP)>
 
 Tell the scheduler to suspend for GC at the next safe pause.
@@ -700,7 +722,7 @@
     PMC *alarm = Parrot_pmc_new(interp, enum_class_Alarm);
     Parrot_Alarm_attributes *adata = PARROT_ALARM(alarm);
 
-    PMC *task = interp->current_task;
+    PMC *task = Parrot_task_current(interp);
     Parrot_Task_attributes *tdata = PARROT_TASK(task);
 
     PMC *cont = Parrot_pmc_new(interp, enum_class_Continuation);

Modified: branches/gsoc_threads/src/threads.c
==============================================================================
--- branches/gsoc_threads/src/threads.c	Thu Aug 26 23:00:30 2010	(r48679)
+++ branches/gsoc_threads/src/threads.c	Thu Aug 26 23:06:38 2010	(r48680)
@@ -21,6 +21,7 @@
 #include "parrot/threads.h"
 #include "parrot/alarm.h"
 #include "pmc/pmc_scheduler.h"
+#include "pmc/pmc_task.h"
 
 /* HEADERIZER HFILE: include/parrot/threads.h */
 
@@ -63,6 +64,8 @@
     THREAD_STATE_SET(interp, 0, INITIALIZED);
     COND_INIT(tbl->threads[0].cvar);
 
+    Parrot_threads_setup_signal_handler(interp);
+
     LOCK_INTERP(interp);
 }
 
@@ -115,6 +118,8 @@
     Parrot_alarm_mask(interp);
     *tidx = args->idx;
 
+    Parrot_threads_setup_signal_handler(interp);
+
     /* Yay stack scanning */
     LOCK(interp->thread_lock);
     tbl->threads[*tidx].lo_var_ptr = &tidx;
@@ -567,6 +572,115 @@
 
 /*
 
+=item C<void Parrot_threads_task_killed(PARROT_INTERP, INTVAL tidx)>
+
+Send a signal to a thread notifying it that its active task has been killed.
+
+=cut
+
+*/
+
+void
+Parrot_threads_task_killed(PARROT_INTERP, INTVAL tidx)
+{
+    ASSERT_ARGS(Parrot_threads_task_killed)
+
+    Thread_table *tbl = interp->thread_table;
+    pthread_kill(tbl->threads[tidx].id, SIGUSR2);
+}
+
+/*
+
+=item C<void Parrot_threads_task_killed_handler(int sig_number)>
+
+Signal handler that does the stuff when the thing happens.
+
+=cut
+
+*/
+
+void
+Parrot_threads_task_killed_handler(SHIM(int sig_number))
+{
+    ASSERT_ARGS(Parrot_threads_task_killed_handler)
+       
+    /* interrupt_blocking_system_calls_from_a_comment(); */
+}
+
+/*
+
+=item C<void Parrot_threads_setup_signal_handler(PARROT_INTERP)>
+
+Prepare the current thread to handle a signal notifying it that its active
+task has been killed.
+
+=cut
+
+*/
+
+void
+Parrot_threads_setup_signal_handler(PARROT_INTERP)
+{
+    ASSERT_ARGS(Parrot_threads_setup_signal_handler)
+
+    struct sigaction sa;
+    memset(&sa, 0, sizeof (struct sigaction));
+    sa.sa_handler = Parrot_threads_task_killed_handler;
+    sa.sa_flags   = ~SA_RESTART;
+
+    if (sigaction(SIGUSR2, &sa, 0) == -1) {
+        perror("sigaction failed in Parrot_threads_setup-signal_handler");
+        exit(EXIT_FAILURE);
+    }
+}
+
+/*
+
+=item C<void Parrot_check_if_task_killed(PARROT_INTERP)>
+
+If the current task has been killed, longjmp back to the task
+entry point.
+
+=cut
+
+*/
+
+void
+Parrot_check_if_task_killed(PARROT_INTERP)
+{
+    ASSERT_ARGS(Parrot_check_if_task_killed)
+    
+    PMC *current_task = Parrot_task_current(interp);
+    Parrot_Task_attributes *const tdata = PARROT_TASK(current_task);
+
+    if (tdata->killed) {
+        longjmp(tdata->abort_jump, 1);
+    }
+}
+
+/*
+
+=item C<void Parrot_threads_gc_mark(PARROT_INTERP)>
+
+Marks any PMCs in the thread table alive.
+
+=cut
+
+*/
+
+void
+Parrot_threads_gc_mark(PARROT_INTERP)
+{
+    ASSERT_ARGS(Parrot_threads_gc_mark)
+    Thread_table *tbl = interp->thread_table;
+    INTVAL i;
+    for (i = 0; i < tbl->count; ++i) {
+        Parrot_gc_mark_PMC_alive(interp, tbl->threads[i].cur_task);
+    }
+}
+
+/*
+
 =back
 
 =head1 SEE ALSO


More information about the parrot-commits mailing list