[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