[svn:parrot] r48010 - in branches/gsoc_threads: include/parrot src src/pmc
Chandon at svn.parrot.org
Chandon at svn.parrot.org
Mon Jul 5 15:36:04 UTC 2010
Author: Chandon
Date: Mon Jul 5 15:36:03 2010
New Revision: 48010
URL: https://trac.parrot.org/parrot/changeset/48010
Log:
[gsoc_threads] Everything is a task.
Modified:
branches/gsoc_threads/include/parrot/scheduler.h
branches/gsoc_threads/src/alarm.c
branches/gsoc_threads/src/embed.c
branches/gsoc_threads/src/main.c
branches/gsoc_threads/src/pmc/task.pmc
branches/gsoc_threads/src/scheduler.c
Modified: branches/gsoc_threads/include/parrot/scheduler.h
==============================================================================
--- branches/gsoc_threads/include/parrot/scheduler.h Mon Jul 5 14:33:31 2010 (r48009)
+++ branches/gsoc_threads/include/parrot/scheduler.h Mon Jul 5 15:36:03 2010 (r48010)
@@ -31,6 +31,16 @@
__attribute__nonnull__(2);
PARROT_EXPORT
+void Parrot_cx_begin_execution(PARROT_INTERP,
+ ARGMOD(PMC *main),
+ ARGMOD(PMC *argv))
+ __attribute__nonnull__(1)
+ __attribute__nonnull__(2)
+ __attribute__nonnull__(3)
+ FUNC_MODIFIES(*main)
+ FUNC_MODIFIES(*argv);
+
+PARROT_EXPORT
void Parrot_cx_broadcast_message(PARROT_INTERP,
ARGIN(STRING *messagetype),
ARGIN_NULLOK(PMC *data))
@@ -91,11 +101,6 @@
FUNC_MODIFIES(*scheduler);
PARROT_EXPORT
-PARROT_CAN_RETURN_NULL
-PMC * Parrot_cx_peek_task(PARROT_INTERP)
- __attribute__nonnull__(1);
-
-PARROT_EXPORT
void Parrot_cx_request_suspend_for_gc(PARROT_INTERP)
__attribute__nonnull__(1);
@@ -109,14 +114,6 @@
__attribute__nonnull__(2);
PARROT_EXPORT
-void Parrot_cx_schedule_callback(PARROT_INTERP,
- ARGIN(PMC *user_data),
- ARGIN(char *ext_data))
- __attribute__nonnull__(1)
- __attribute__nonnull__(2)
- __attribute__nonnull__(3);
-
-PARROT_EXPORT
void Parrot_cx_schedule_immediate(PARROT_INTERP, ARGIN(PMC *task))
__attribute__nonnull__(1)
__attribute__nonnull__(2);
@@ -154,16 +151,12 @@
void Parrot_cx_init_scheduler(PARROT_INTERP)
__attribute__nonnull__(1);
-void Parrot_cx_invoke_callback(PARROT_INTERP, ARGIN(PMC *callback))
- __attribute__nonnull__(1)
- __attribute__nonnull__(2);
-
-void Parrot_cx_runloop_wake(PARROT_INTERP, ARGMOD(PMC *scheduler))
+void Parrot_cx_reschedule(PARROT_INTERP, ARGMOD(PMC *scheduler))
__attribute__nonnull__(1)
__attribute__nonnull__(2)
FUNC_MODIFIES(*scheduler);
-void Parrot_cx_schedule_next_task(PARROT_INTERP, ARGMOD(PMC *scheduler))
+void Parrot_cx_runloop_wake(PARROT_INTERP, ARGMOD(PMC *scheduler))
__attribute__nonnull__(1)
__attribute__nonnull__(2)
FUNC_MODIFIES(*scheduler);
@@ -174,6 +167,10 @@
#define ASSERT_ARGS_Parrot_cx_add_handler_local __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(handler))
+#define ASSERT_ARGS_Parrot_cx_begin_execution __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+ PARROT_ASSERT_ARG(interp) \
+ , PARROT_ASSERT_ARG(main) \
+ , PARROT_ASSERT_ARG(argv))
#define ASSERT_ARGS_Parrot_cx_broadcast_message __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(messagetype))
@@ -209,8 +206,6 @@
#define ASSERT_ARGS_Parrot_cx_handle_tasks __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(scheduler))
-#define ASSERT_ARGS_Parrot_cx_peek_task __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))
@@ -219,10 +214,6 @@
#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_callback __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
- PARROT_ASSERT_ARG(interp) \
- , PARROT_ASSERT_ARG(user_data) \
- , PARROT_ASSERT_ARG(ext_data))
#define ASSERT_ARGS_Parrot_cx_schedule_immediate __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(task))
@@ -242,13 +233,10 @@
, PARROT_ASSERT_ARG(scheduler))
#define ASSERT_ARGS_Parrot_cx_init_scheduler __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp))
-#define ASSERT_ARGS_Parrot_cx_invoke_callback __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
- PARROT_ASSERT_ARG(interp) \
- , PARROT_ASSERT_ARG(callback))
-#define ASSERT_ARGS_Parrot_cx_runloop_wake __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+#define ASSERT_ARGS_Parrot_cx_reschedule __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(scheduler))
-#define ASSERT_ARGS_Parrot_cx_schedule_next_task __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+#define ASSERT_ARGS_Parrot_cx_runloop_wake __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(scheduler))
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
Modified: branches/gsoc_threads/src/alarm.c
==============================================================================
--- branches/gsoc_threads/src/alarm.c Mon Jul 5 14:33:31 2010 (r48009)
+++ branches/gsoc_threads/src/alarm.c Mon Jul 5 15:36:03 2010 (r48010)
@@ -14,8 +14,9 @@
#include "parrot/alarm.h"
/* Some per-process state */
-static Parrot_alarm_queue* alarm_queue;
-static volatile UINTVAL alarm_serial;
+static Parrot_alarm_queue* alarm_queue = NULL;
+static volatile UINTVAL alarm_serial = 0;
+static volatile UINTVAL alarm_init = 0;
/* This file relies on POSIX. Probably need two other versions of it:
* one for Windows and one for platforms with no signals or threads. */
@@ -65,8 +66,7 @@
exit(EXIT_FAILURE);
}
- alarm_serial = 1;
- alarm_queue = NULL;
+ alarm_init = 1;
}
/*
@@ -88,6 +88,9 @@
struct itimerval itmr;
int sec, usec;
+ if (!alarm_init)
+ Parrot_alarm_init();
+
sec = (int) wait;
usec = (int) ((wait - sec) * MIL);
@@ -97,8 +100,13 @@
itmr.it_interval.tv_usec = 0;
if (setitimer(ITIMER_REAL, &itmr, 0) == -1) {
- perror("setitimer failed in set_posix_alarm");
- exit(EXIT_FAILURE);
+ if (errno == EINVAL) {
+ raise(SIGALRM);
+ }
+ else {
+ perror("setitimer failed in set_posix_alarm");
+ exit(EXIT_FAILURE);
+ }
}
}
@@ -193,6 +201,7 @@
new_alarm = (Parrot_alarm_queue*) malloc(sizeof (Parrot_alarm_queue));
new_alarm->when = when;
+ new_alarm->next = NULL;
if (alarm_queue == NULL || when < alarm_queue->when) {
new_alarm->next = alarm_queue;
Modified: branches/gsoc_threads/src/embed.c
==============================================================================
--- branches/gsoc_threads/src/embed.c Mon Jul 5 14:33:31 2010 (r48009)
+++ branches/gsoc_threads/src/embed.c Mon Jul 5 15:36:03 2010 (r48010)
@@ -808,7 +808,7 @@
Parrot_pcc_set_sub(interp, CURRENT_CONTEXT(interp), NULL);
Parrot_pcc_set_constants(interp, interp->ctx, interp->code->const_table->constants);
- Parrot_pcc_invoke_sub_from_c_args(interp, main_sub, "P->", userargv);
+ Parrot_cx_begin_execution(interp, main_sub, userargv);
}
Modified: branches/gsoc_threads/src/main.c
==============================================================================
--- branches/gsoc_threads/src/main.c Mon Jul 5 14:33:31 2010 (r48009)
+++ branches/gsoc_threads/src/main.c Mon Jul 5 15:36:03 2010 (r48010)
@@ -137,9 +137,6 @@
/* Now initialize interpreter */
initialize_interpreter(interp, (void*)&stacktop);
- /* Register signal handler for timers */
- Parrot_alarm_init();
-
/* Parse flags */
sourcefile = parseflags(interp, argc, argv, &pir_argc, &pir_argv, &core, &trace);
Modified: branches/gsoc_threads/src/pmc/task.pmc
==============================================================================
--- branches/gsoc_threads/src/pmc/task.pmc Mon Jul 5 14:33:31 2010 (r48009)
+++ branches/gsoc_threads/src/pmc/task.pmc Mon Jul 5 15:36:03 2010 (r48010)
@@ -24,7 +24,7 @@
/* HEADERIZER BEGIN: static */
/* HEADERIZER END: static */
-pmclass Task auto_attrs {
+pmclass Task provides invokable auto_attrs {
ATTR INTVAL id; /* The task ID. */
ATTR INTVAL priority; /* The priority of the task. */
ATTR FLOATVAL birthtime; /* The creation time stamp of the task. */
@@ -173,6 +173,36 @@
/*
+=item C<opcode_t *invoke(void *next)>
+
+Invokes whatever is in the Task's associated codeblock.
+
+If the Task's data attribute is not null, pass it to the
+codeblock as the first argument.
+
+=cut
+
+*/
+
+ VTABLE opcode_t *invoke(void *next) {
+ Parrot_Task_attributes *const task = PARROT_TASK(SELF);
+
+ if (PMC_IS_NULL(task->codeblock))
+ return (opcode_t*) next;
+
+ if (PMC_IS_NULL(task->data)) {
+ Parrot_pcc_invoke_sub_from_c_args(interp, task->codeblock, "->");
+ }
+ else {
+ Parrot_pcc_invoke_sub_from_c_args(interp, task->codeblock, "P->", task->data);
+ }
+
+ return (opcode_t*) next;
+ }
+
+
+/*
+
=item C<PMC *clone()>
Create a copy of the task, resetting status, ID, and birthtime.
Modified: branches/gsoc_threads/src/scheduler.c
==============================================================================
--- branches/gsoc_threads/src/scheduler.c Mon Jul 5 14:33:31 2010 (r48009)
+++ branches/gsoc_threads/src/scheduler.c Mon Jul 5 15:36:03 2010 (r48010)
@@ -43,18 +43,9 @@
__attribute__nonnull__(2)
FUNC_MODIFIES(*scheduler);
-static void scheduler_process_wait_list(PARROT_INTERP,
- ARGMOD(PMC *scheduler))
- __attribute__nonnull__(1)
- __attribute__nonnull__(2)
- FUNC_MODIFIES(*scheduler);
-
#define ASSERT_ARGS_scheduler_process_messages __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(scheduler))
-#define ASSERT_ARGS_scheduler_process_wait_list __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
- PARROT_ASSERT_ARG(interp) \
- , PARROT_ASSERT_ARG(scheduler))
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
/* HEADERIZER END: static */
@@ -103,6 +94,43 @@
/*
+=item C<void Parrot_cx_begin_execution(PARROT_INTERP, PMC *main, PMC *argv)>
+
+Construct the main task, add it to the task queue, and then execute tasks
+until the task queue becomes empty.
+
+=cut
+
+*/
+
+PARROT_EXPORT
+void
+Parrot_cx_begin_execution(PARROT_INTERP, ARGMOD(PMC *main), ARGMOD(PMC *argv))
+{
+ ASSERT_ARGS(Parrot_cx_begin_execution)
+ PMC *scheduler = interp->scheduler;
+ Parrot_Scheduler_attributes *sched = PARROT_SCHEDULER(scheduler);
+ INTVAL task_count = 1;
+
+ PMC* main_task = Parrot_pmc_new(interp, enum_class_Task);
+ Parrot_Task_attributes *tdata = PARROT_TASK(main_task);
+ tdata->codeblock = main;
+ tdata->data = argv;
+
+ Parrot_cx_schedule_task(interp, main_task);
+
+ do {
+ Parrot_cx_reschedule(interp, scheduler);
+ task_count = VTABLE_get_integer(interp, sched->task_queue);
+ } 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)>
If a wake request has been received or an OS timer has expired
@@ -147,7 +175,7 @@
if (SCHEDULER_resched_requested_TEST(scheduler)) {
SCHEDULER_resched_requested_CLEAR(scheduler);
- Parrot_cx_schedule_next_task(interp, scheduler);
+ Parrot_cx_reschedule(interp, scheduler);
}
#ifdef PARROT_CX_BUILD_OLD_STUFF
@@ -213,7 +241,7 @@
/*
-=item C<void Parrot_cx_schedule_next_task(PARROT_INTERP, PMC *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.
@@ -225,20 +253,25 @@
*/
void
-Parrot_cx_schedule_next_task(PARROT_INTERP, ARGMOD(PMC *scheduler))
+Parrot_cx_reschedule(PARROT_INTERP, ARGMOD(PMC *scheduler))
{
- ASSERT_ARGS(Parrot_cx_schedule_next_task)
+ ASSERT_ARGS(Parrot_cx_reschedule)
Parrot_Scheduler_attributes *sched = PARROT_SCHEDULER(scheduler);
INTVAL task_count = VTABLE_get_integer(interp, sched->task_queue);
if (task_count > 0) {
- PMC *sub = VTABLE_shift_pmc(interp, sched->task_queue);
-
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);
+
+ if (!PMC_IS_NULL(task0))
+ VTABLE_push_pmc(interp, sched->task_queue, task0);
+
interp->quantum_done = time_now + PARROT_TASK_SWITCH_QUANTUM;
Parrot_alarm_set(interp->quantum_done);
- Parrot_pcc_invoke_sub_from_c_args(interp, sub, "->");
+ if (!PMC_IS_NULL(task1))
+ Parrot_pcc_invoke_sub_from_c_args(interp, task1, "->");
}
}
@@ -332,60 +365,6 @@
/*
-=item C<PMC * Parrot_cx_peek_task(PARROT_INTERP)>
-
-Retrieve the the top task on the scheduler's task list, but don't remove it
-from the list.
-
-=cut
-
-*/
-
-#ifdef COMPILE_OLD_STUFF
-PARROT_EXPORT
-PARROT_CAN_RETURN_NULL
-PMC *
-Parrot_cx_peek_task(PARROT_INTERP)
-{
- ASSERT_ARGS(Parrot_cx_peek_task)
- if (!interp->scheduler)
- Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
- "Scheduler was not initialized for this interpreter.\n");
-
-
-
- return VTABLE_pop_pmc(interp, interp->scheduler);
-}
-
-/*
-
-=item C<void Parrot_cx_schedule_callback(PARROT_INTERP, PMC *user_data, char
-*ext_data)>
-
-Create a new callback event, with an argument for the call.
-
-=cut
-
-*/
-
-PARROT_EXPORT
-void
-Parrot_cx_schedule_callback(PARROT_INTERP, ARGIN(PMC *user_data), ARGIN(char *ext_data))
-{
- ASSERT_ARGS(Parrot_cx_schedule_callback)
- PMC * const callback = Parrot_pmc_new(interp, enum_class_Task);
- Parrot_Task_attributes * const task_struct = PARROT_TASK(callback);
-
- task_struct->type = CONST_STRING(interp, "callback");
- task_struct->data = user_data;
- task_struct->cb_data = ext_data;
-
- Parrot_cx_schedule_task(interp, callback);
-}
-#endif
-
-/*
-
=item C<void Parrot_cx_request_suspend_for_gc(PARROT_INTERP)>
Tell the scheduler to suspend for GC at the next safe pause.
@@ -985,27 +964,6 @@
/*
-=item C<void Parrot_cx_invoke_callback(PARROT_INTERP, PMC *callback)>
-
-Run the associated code block for a callback event.
-
-=cut
-
-*/
-
-void
-Parrot_cx_invoke_callback(PARROT_INTERP, ARGIN(PMC *callback))
-{
- ASSERT_ARGS(Parrot_cx_invoke_callback)
- Parrot_Task_attributes * const task_struct = PARROT_TASK(callback);
- if (!PMC_IS_NULL(task_struct->data)) {
- Parrot_run_callback(interp, task_struct->data,
- task_struct->cb_data);
- }
-}
-
-/*
-
=back
=head2 Opcode Functions
@@ -1066,60 +1024,6 @@
return next;
}
-/*
-
-=back
-
-=head2 Internal Functions
-
-Functions that are only used within the scheduler.
-
-=over 4
-
-=item C<static void scheduler_process_wait_list(PARROT_INTERP, PMC *scheduler)>
-
-Scheduler maintenance, scan the list of waiting tasks to see if any are ready
-to become active tasks.
-
-=cut
-
-*/
-
-static void
-scheduler_process_wait_list(PARROT_INTERP, ARGMOD(PMC *scheduler))
-{
- ASSERT_ARGS(scheduler_process_wait_list)
-
-#ifdef BUILD_OLD_CODE
- Parrot_Scheduler_attributes * sched_struct = PARROT_SCHEDULER(scheduler);
- INTVAL num_tasks, index;
-
- /* Sweep the wait list for completed timers */
- num_tasks = VTABLE_elements(interp, sched_struct->wait_index);
- for (index = 0; index < num_tasks; ++index) {
- INTVAL tid = VTABLE_get_integer_keyed_int(interp, sched_struct->wait_index, index);
- if (tid > 0) {
- PMC *task = VTABLE_get_pmc_keyed_int(interp, sched_struct->task_list, tid);
- if (PMC_IS_NULL(task)) {
- /* Cleanup expired tasks. */
- VTABLE_set_integer_keyed_int(interp, sched_struct->wait_index, index, 0);
- }
- else {
- /* Move the timer to the active task list if the timer has
- * completed. */
- FLOATVAL timer_end_time = VTABLE_get_number_keyed_int(interp,
- task, PARROT_TIMER_NSEC);
- if (timer_end_time <= Parrot_floatval_time()) {
- VTABLE_push_integer(interp, sched_struct->task_index, tid);
- VTABLE_set_integer_keyed_int(interp, sched_struct->wait_index, index, 0);
- Parrot_cx_schedule_repeat(interp, task);
- SCHEDULER_cache_valid_CLEAR(scheduler);
- }
- }
- }
- }
-#endif
-}
/*
More information about the parrot-commits
mailing list