[svn:parrot] r48070 - in branches/gsoc_threads: include/parrot src src/call src/ops t/pmc

Chandon at svn.parrot.org Chandon at svn.parrot.org
Sun Jul 11 03:48:26 UTC 2010


Author: Chandon
Date: Sun Jul 11 03:48:25 2010
New Revision: 48070
URL: https://trac.parrot.org/parrot/changeset/48070

Log:
[gsoc_threads] Can both save *and* restore running tasks.

Modified:
   branches/gsoc_threads/include/parrot/interpreter.h
   branches/gsoc_threads/include/parrot/scheduler.h
   branches/gsoc_threads/src/call/pcc.c
   branches/gsoc_threads/src/ops/core.ops
   branches/gsoc_threads/src/ops/core_ops.c
   branches/gsoc_threads/src/scheduler.c
   branches/gsoc_threads/t/pmc/nci.t

Modified: branches/gsoc_threads/include/parrot/interpreter.h
==============================================================================
--- branches/gsoc_threads/include/parrot/interpreter.h	Sun Jul 11 01:10:24 2010	(r48069)
+++ branches/gsoc_threads/include/parrot/interpreter.h	Sun Jul 11 03:48:25 2010	(r48070)
@@ -269,8 +269,8 @@
     int current_runloop_level;                /* for reentering run loop */
     int current_runloop_id;
 
-    UINTVAL  last_alarm;                      /* has an alarm triggered? */
-    FLOATVAL quantum_done;                    /* expiration of current quantum */
+    UINTVAL          last_alarm;              /* has an alarm triggered? */
+    FLOATVAL         quantum_done;            /* expiration of current quantum */
 
     struct _Thread_data *thread_data;         /* thread specific items */
 

Modified: branches/gsoc_threads/include/parrot/scheduler.h
==============================================================================
--- branches/gsoc_threads/include/parrot/scheduler.h	Sun Jul 11 01:10:24 2010	(r48069)
+++ branches/gsoc_threads/include/parrot/scheduler.h	Sun Jul 11 03:48:25 2010	(r48070)
@@ -94,10 +94,14 @@
         __attribute__nonnull__(1)
         __attribute__nonnull__(2);
 
+PARROT_CANNOT_RETURN_NULL
 PARROT_EXPORT
-void Parrot_cx_handle_tasks(PARROT_INTERP, ARGMOD(PMC *scheduler))
+opcode_t* Parrot_cx_handle_tasks(PARROT_INTERP,
+    ARGMOD(PMC *scheduler),
+    ARGIN(opcode_t *next))
         __attribute__nonnull__(1)
         __attribute__nonnull__(2)
+        __attribute__nonnull__(3)
         FUNC_MODIFIES(*scheduler);
 
 PARROT_EXPORT
@@ -143,17 +147,26 @@
         __attribute__nonnull__(2)
         FUNC_MODIFIES(*scheduler);
 
-void Parrot_cx_check_tasks(PARROT_INTERP, ARGMOD(PMC *scheduler))
+PARROT_CANNOT_RETURN_NULL
+opcode_t* Parrot_cx_check_tasks(PARROT_INTERP, ARGIN(opcode_t* next))
         __attribute__nonnull__(1)
-        __attribute__nonnull__(2)
-        FUNC_MODIFIES(*scheduler);
+        __attribute__nonnull__(2);
 
 void Parrot_cx_init_scheduler(PARROT_INTERP)
         __attribute__nonnull__(1);
 
-void Parrot_cx_reschedule(PARROT_INTERP, ARGMOD(PMC *scheduler))
+void Parrot_cx_next_task(PARROT_INTERP, ARGMOD(PMC *scheduler))
+        __attribute__nonnull__(1)
+        __attribute__nonnull__(2)
+        FUNC_MODIFIES(*scheduler);
+
+PARROT_CANNOT_RETURN_NULL
+opcode_t* Parrot_cx_reschedule(PARROT_INTERP,
+    ARGMOD(PMC *scheduler),
+    ARGIN(opcode_t *next))
         __attribute__nonnull__(1)
         __attribute__nonnull__(2)
+        __attribute__nonnull__(3)
         FUNC_MODIFIES(*scheduler);
 
 void Parrot_cx_runloop_wake(PARROT_INTERP, ARGMOD(PMC *scheduler))
@@ -205,7 +218,8 @@
     , PARROT_ASSERT_ARG(task))
 #define ASSERT_ARGS_Parrot_cx_handle_tasks __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(interp) \
-    , PARROT_ASSERT_ARG(scheduler))
+    , PARROT_ASSERT_ARG(scheduler) \
+    , PARROT_ASSERT_ARG(next))
 #define ASSERT_ARGS_Parrot_cx_request_suspend_for_gc \
      __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(interp))
@@ -230,12 +244,16 @@
     , PARROT_ASSERT_ARG(scheduler))
 #define ASSERT_ARGS_Parrot_cx_check_tasks __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(interp) \
-    , PARROT_ASSERT_ARG(scheduler))
+    , PARROT_ASSERT_ARG(next))
 #define ASSERT_ARGS_Parrot_cx_init_scheduler __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(interp))
-#define ASSERT_ARGS_Parrot_cx_reschedule __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+#define ASSERT_ARGS_Parrot_cx_next_task __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(interp) \
     , PARROT_ASSERT_ARG(scheduler))
+#define ASSERT_ARGS_Parrot_cx_reschedule __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+       PARROT_ASSERT_ARG(interp) \
+    , PARROT_ASSERT_ARG(scheduler) \
+    , PARROT_ASSERT_ARG(next))
 #define ASSERT_ARGS_Parrot_cx_runloop_wake __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(interp) \
     , PARROT_ASSERT_ARG(scheduler))

Modified: branches/gsoc_threads/src/call/pcc.c
==============================================================================
--- branches/gsoc_threads/src/call/pcc.c	Sun Jul 11 01:10:24 2010	(r48069)
+++ branches/gsoc_threads/src/call/pcc.c	Sun Jul 11 03:48:25 2010	(r48070)
@@ -296,6 +296,7 @@
           case enum_class_Sub:
           case enum_class_MultiSub:
           case enum_class_Eval:
+          case enum_class_Continuation:
             return 1;
           case enum_class_Object:
             break;

Modified: branches/gsoc_threads/src/ops/core.ops
==============================================================================
--- branches/gsoc_threads/src/ops/core.ops	Sun Jul 11 01:10:24 2010	(r48069)
+++ branches/gsoc_threads/src/ops/core.ops	Sun Jul 11 03:48:25 2010	(r48070)
@@ -96,8 +96,8 @@
 }
 
 inline op check_events() :base_core :flow {
-    opcode_t * const next = expr NEXT();
-    Parrot_cx_check_tasks(interp, interp->scheduler);
+    opcode_t *next = expr NEXT();
+    next = Parrot_cx_check_tasks(interp, next);
     goto ADDRESS(next);   /* force this being a branch op */
 }
 
@@ -105,7 +105,7 @@
     opcode_t * const _this = CUR_OPCODE;
     /* Restore op_func_table. */
     disable_event_checking(interp);
-    Parrot_cx_handle_tasks(interp, interp->scheduler);
+    /* Parrot_cx_handle_tasks(interp, interp->scheduler); */
     goto ADDRESS(_this);   /* force this being a branch op */
 }
 
@@ -153,7 +153,8 @@
 =cut
 
 inline op branch(in LABEL) :base_loop :flow {
-    Parrot_cx_check_tasks(interp, interp->scheduler);
+    if(Parrot_cx_check_tasks(interp, cur_opcode + $1) == 0)
+        return 0;
     goto OFFSET($1);
 }
 

Modified: branches/gsoc_threads/src/ops/core_ops.c
==============================================================================
--- branches/gsoc_threads/src/ops/core_ops.c	Sun Jul 11 01:10:24 2010	(r48069)
+++ branches/gsoc_threads/src/ops/core_ops.c	Sun Jul 11 03:48:25 2010	(r48070)
@@ -14181,8 +14181,8 @@
 opcode_t *
 Parrot_check_events(opcode_t *cur_opcode, PARROT_INTERP)  {
     const Parrot_Context * const CUR_CTX = Parrot_pcc_get_context_struct(interp, interp->ctx);
-    opcode_t * const next = cur_opcode + 1;
-    Parrot_cx_check_tasks(interp, interp->scheduler);return (opcode_t *)next;   /* force this being a branch op */
+    opcode_t *next = cur_opcode + 1;
+    next = Parrot_cx_check_tasks(interp, next);return (opcode_t *)next;   /* force this being a branch op */
 }
 
 opcode_t *
@@ -14190,8 +14190,7 @@
     const Parrot_Context * const CUR_CTX = Parrot_pcc_get_context_struct(interp, interp->ctx);
     opcode_t * const _this = CUR_OPCODE;
     /* Restore op_func_table. */
-    disable_event_checking(interp);
-    Parrot_cx_handle_tasks(interp, interp->scheduler);return (opcode_t *)_this;   /* force this being a branch op */
+    disable_event_checking(interp);return (opcode_t *)_this;   /* force this being a branch op */
 }
 
 opcode_t *
@@ -14232,13 +14231,15 @@
 opcode_t *
 Parrot_branch_i(opcode_t *cur_opcode, PARROT_INTERP)  {
     const Parrot_Context * const CUR_CTX = Parrot_pcc_get_context_struct(interp, interp->ctx);
-    Parrot_cx_check_tasks(interp, interp->scheduler);return (opcode_t *)cur_opcode + IREG(1);
+    if(Parrot_cx_check_tasks(interp, cur_opcode + IREG(1)) == 0)
+        return 0;return (opcode_t *)cur_opcode + IREG(1);
 }
 
 opcode_t *
 Parrot_branch_ic(opcode_t *cur_opcode, PARROT_INTERP)  {
     const Parrot_Context * const CUR_CTX = Parrot_pcc_get_context_struct(interp, interp->ctx);
-    Parrot_cx_check_tasks(interp, interp->scheduler);return (opcode_t *)cur_opcode + cur_opcode[1];
+    if(Parrot_cx_check_tasks(interp, cur_opcode + cur_opcode[1]) == 0)
+        return 0;return (opcode_t *)cur_opcode + cur_opcode[1];
 }
 
 opcode_t *

Modified: branches/gsoc_threads/src/scheduler.c
==============================================================================
--- branches/gsoc_threads/src/scheduler.c	Sun Jul 11 01:10:24 2010	(r48069)
+++ branches/gsoc_threads/src/scheduler.c	Sun Jul 11 03:48:25 2010	(r48070)
@@ -27,6 +27,7 @@
 #include "pmc/pmc_timer.h"
 #include "pmc/pmc_alarm.h"
 #include "pmc/pmc_pmclist.h"
+#include "pmc/pmc_continuation.h"
 
 #include "scheduler.str"
 
@@ -120,65 +121,90 @@
     Parrot_cx_schedule_task(interp, main_task);
 
     do {
-        Parrot_cx_reschedule(interp, scheduler);
+        Parrot_cx_next_task(interp, scheduler);
         task_count = VTABLE_get_integer(interp, sched->task_queue);
-        return;
+        
+        if(task_count == 0) {
+            INTVAL alarm_count = VTABLE_get_integer(interp, sched->alarms);
+
+            if (alarm_count > 0) {
+                PMC     *alarm      = VTABLE_shift_pmc(interp, sched->alarms);
+                FLOATVAL alarm_time = VTABLE_get_number(interp, alarm);
+                FLOATVAL now_time   = Parrot_floatval_time();
+                FLOATVAL sleep_time = now_time - alarm_time;
+                VTABLE_unshift_pmc(interp, sched->alarms, alarm);
+
+                if(sleep_time > 0.0)
+                    Parrot_floatval_sleep(sleep_time);
+
+                Parrot_cx_check_alarms(interp, interp->scheduler);
+                task_count = 1;
+            }            
+        }
     } while (task_count > 0);
 }
 
 
-/* Parrot_pcc_invoke_sub_from_c_args(interp, main_sub, "P->", userargv); */
-
-
 /*
 
-=item C<void Parrot_cx_check_tasks(PARROT_INTERP, PMC *scheduler)>
+=item C<opcode_t* Parrot_cx_check_tasks(PARROT_INTERP, opcode_t* next)>
 
 If a wake request has been received or an OS timer has expired
-then handle tasks.
+then deal with that.
 
 =cut
 
 */
 
-void
-Parrot_cx_check_tasks(PARROT_INTERP, ARGMOD(PMC *scheduler))
+PARROT_CANNOT_RETURN_NULL
+opcode_t*
+Parrot_cx_check_tasks(PARROT_INTERP, ARGIN(opcode_t* next))
 {
     ASSERT_ARGS(Parrot_cx_check_tasks)
+    PMC *scheduler = interp->scheduler;
+
     if  (Parrot_alarm_check(&(interp->last_alarm))
           || SCHEDULER_wake_requested_TEST(scheduler)) {
-        Parrot_cx_handle_tasks(interp, scheduler);
+        SCHEDULER_wake_requested_CLEAR(scheduler);
+        return Parrot_cx_handle_tasks(interp, scheduler, next);
     }
+
+    return next;
 }
 
 /*
 
-=item C<void Parrot_cx_handle_tasks(PARROT_INTERP, PMC *scheduler)>
+=item C<opcode_t* Parrot_cx_handle_tasks(PARROT_INTERP, PMC *scheduler, opcode_t
+*next)>
 
-Handle the pending tasks in the scheduler's task list. Returns when there are
-no more pending tasks. Returns 0 to terminate the scheduler runloop, or 1 to
-continue the runloop.
+Checks to see if any tasks need to be scheduled or if the current task
+needs to be pre-empted.
 
 =cut
 
 */
 
+PARROT_CANNOT_RETURN_NULL
 PARROT_EXPORT
-void
-Parrot_cx_handle_tasks(PARROT_INTERP, ARGMOD(PMC *scheduler))
+opcode_t*
+Parrot_cx_handle_tasks(PARROT_INTERP, ARGMOD(PMC *scheduler), ARGIN(opcode_t *next))
 {
     ASSERT_ARGS(Parrot_cx_handle_tasks)
 
-    SCHEDULER_wake_requested_CLEAR(scheduler);
-
     Parrot_cx_check_alarms(interp, scheduler);
     Parrot_cx_check_quantum(interp, scheduler);
 
     if (SCHEDULER_resched_requested_TEST(scheduler)) {
         SCHEDULER_resched_requested_CLEAR(scheduler);
-        Parrot_cx_reschedule(interp, scheduler);
+
+        /* Exiting the runloop to swap tasks doesn't play
+           nice with nested runloops */
+        if (interp->current_runloop_level <= 1)
+            return Parrot_cx_reschedule(interp, scheduler, next);
     }
 
+    return next;
+
 #ifdef PARROT_CX_BUILD_OLD_STUFF
     Parrot_cx_refresh_task_list(interp, scheduler);
 
@@ -240,43 +266,61 @@
         SCHEDULER_resched_requested_SET(scheduler);
 }
 
-
 /*
-=item C<void Parrot_cx_reschedule(PARROT_INTERP, PMC *scheduler)>
-
-Put the current task on the foot of the task queue and schedule whatever
-is on the head, then reset the rescheduling quantum.
+=item C<void Parrot_cx_next_task(PARROT_INTERP, PMC *scheduler)>
 
-TODO: Make the above true rather than a dirty lie.
+Run the task at the head of the task queue until it ends or is
+pre-empted.
 
 =cut
-
 */
 
 void
-Parrot_cx_reschedule(PARROT_INTERP, ARGMOD(PMC *scheduler))
+Parrot_cx_next_task(PARROT_INTERP, ARGMOD(PMC *scheduler))
 {
-    ASSERT_ARGS(Parrot_cx_reschedule)
+    ASSERT_ARGS(Parrot_cx_next_task)
     Parrot_Scheduler_attributes *sched = PARROT_SCHEDULER(scheduler);
-    INTVAL task_count = VTABLE_get_integer(interp, sched->task_queue);
+    INTVAL task_count;
 
-    if (task_count > 0) {
-        FLOATVAL time_now = Parrot_floatval_time();
-        /* PMC *task0 = Parrot_pcc_get_continuation(interp, CURRENT_CONTEXT(interp)); */
-        PMC *task1 = VTABLE_shift_pmc(interp, sched->task_queue);
+    task_count = VTABLE_get_integer(interp, sched->task_queue);
 
-        /*if (!PMC_IS_NULL(task0))
-          VTABLE_push_pmc(interp, sched->task_queue, task0); */
+    if (task_count > 0) {
+        FLOATVAL  time_now = Parrot_floatval_time();
+        PMC      *task     = VTABLE_shift_pmc(interp, sched->task_queue);
+        opcode_t *dest;
 
         interp->quantum_done = time_now + PARROT_TASK_SWITCH_QUANTUM;
         Parrot_alarm_set(interp->quantum_done);
 
-        if (!PMC_IS_NULL(task1)) {
-            Parrot_pcc_invoke_sub_from_c_args(interp, task1, "->");
-        }
+        Parrot_pcc_invoke_sub_from_c_args(interp, task, "->");
     }
 }
 
+/*
+=item C<opcode_t* Parrot_cx_reschedule(PARROT_INTERP, PMC *scheduler, opcode_t
+*next)>
+
+Pre-empt the current task. It goes on the foot of the task queue,
+and then we jump all the way back to the task scheduling loop.
+
+=cut
+*/
+
+PARROT_CANNOT_RETURN_NULL
+opcode_t*
+Parrot_cx_reschedule(PARROT_INTERP, ARGMOD(PMC *scheduler), ARGIN(opcode_t *next))
+{
+    ASSERT_ARGS(Parrot_cx_reschedule)
+    Parrot_Scheduler_attributes *sched = PARROT_SCHEDULER(scheduler);
+
+    PMC *cont = Parrot_pmc_new(interp, enum_class_Continuation);
+    VTABLE_set_pointer(interp, cont, next);
+
+    if (!PMC_IS_NULL(cont))
+          VTABLE_push_pmc(interp, sched->task_queue, cont);
+
+    return (opcode_t*) 0;
+}
 
 /*
 
@@ -314,7 +358,8 @@
 {
     ASSERT_ARGS(Parrot_cx_runloop_end)
     SCHEDULER_terminate_requested_SET(interp->scheduler);
-    Parrot_cx_handle_tasks(interp, interp->scheduler);
+    /* Chandon TODO: Why is this here? */
+    /* Parrot_cx_handle_tasks(interp, interp->scheduler); */
 }
 
 /*
@@ -995,39 +1040,22 @@
 {
     ASSERT_ARGS(Parrot_cx_schedule_sleep)
     Parrot_Scheduler_attributes *sched = PARROT_SCHEDULER(interp->scheduler);
-    FLOATVAL now_time   = Parrot_floatval_time();
-    FLOATVAL done_time  = now_time + time;
-    FLOATVAL alarm_time = done_time;
-    FLOATVAL sleep_time;
-    INTVAL   alarm_count;
-    PMC      *alarm;
-
-    Parrot_cx_check_tasks(interp, interp->scheduler);
-    now_time = Parrot_floatval_time();
-
-    while (now_time < done_time) {
-        alarm_count = VTABLE_get_integer(interp, sched->alarms);
-
-        if (alarm_count > 0) {
-            alarm = VTABLE_shift_pmc(interp, sched->alarms);
-            alarm_time = VTABLE_get_number(interp, alarm);
-            VTABLE_unshift_pmc(interp, sched->alarms, alarm);
-        }
+    FLOATVAL now_time  = Parrot_floatval_time();
+    FLOATVAL done_time = now_time + time;
 
-        sleep_time = now_time - fmin(done_time, alarm_time);
+    PMC *alarm = Parrot_pmc_new(interp, enum_class_Alarm);
+    Parrot_Alarm_attributes *adata = PARROT_ALARM(alarm);
 
-        if (sleep_time > 0.0) {
-            Parrot_floatval_sleep(sleep_time);
-        }
+    PMC *cont = Parrot_pmc_new(interp, enum_class_Continuation);
+    VTABLE_set_pointer(interp, cont, next);
 
-        Parrot_cx_check_tasks(interp, interp->scheduler);
-        now_time = Parrot_floatval_time();
-    }
+    adata->alarm_time = done_time;
+    adata->alarm_sub  = cont;
+    VTABLE_invoke(interp, alarm, 0);
 
-    return next;
+    return (opcode_t*) 0;
 }
 
-
 /*
 
 =item C<static void scheduler_process_messages(PARROT_INTERP, PMC *scheduler)>

Modified: branches/gsoc_threads/t/pmc/nci.t
==============================================================================
--- branches/gsoc_threads/t/pmc/nci.t	Sun Jul 11 01:10:24 2010	(r48069)
+++ branches/gsoc_threads/t/pmc/nci.t	Sun Jul 11 03:48:25 2010	(r48070)
@@ -1995,6 +1995,10 @@
     print "loaded a function that takes a callback\n"
     nci_cb_D4( cb_wrapped, user_data )
 
+    # Need to force reschedule to see async callbacks.
+    # Chandon TODO: Is this a bug?
+    sleep 0.001
+
     # reset int_cb_D4 to 1
     int_cb_D4[0] = 1
 


More information about the parrot-commits mailing list