Skip to content
Browse files

[concurrency] Initial implementations of the Scheduler and Task PMCs.

git-svn-id: https://svn.parrot.org/parrot/trunk@23034 d31e2699-5ff4-0310-a27c-f18f2fbe73fe
  • Loading branch information...
1 parent 9227653 commit 1d259c67612d4bdd1e7becf04707b3248cafd75d @allisonrandal allisonrandal committed Nov 25, 2007
Showing with 731 additions and 1 deletion.
  1. +6 −1 MANIFEST
  2. +1 −0 include/parrot/parrot.h
  3. +72 −0 include/parrot/scheduler.h
  4. +248 −0 src/pmc/scheduler.pmc
  5. +294 −0 src/pmc/task.pmc
  6. +59 −0 t/pmc/scheduler.t
  7. +51 −0 t/pmc/task.t
View
7 MANIFEST
@@ -1,7 +1,7 @@
# ex: set ro:
# $Id$
#
-# generated by tools/dev/mk_manifest_and_skip.pl Sat Nov 24 02:33:22 2007 UT
+# generated by tools/dev/mk_manifest_and_skip.pl Sun Nov 25 12:12:12 2007 UT
#
# See tools/dev/install_files.pl for documentation on the
# format of this file.
@@ -854,6 +854,7 @@ include/parrot/pmc_freeze.h [main]include
include/parrot/pobj.h [main]include
include/parrot/register.h [main]include
include/parrot/resources.h [main]include
+include/parrot/scheduler.h [main]include
include/parrot/settings.h [main]include
include/parrot/slice.h [main]include
include/parrot/smallobject.h [main]include
@@ -2811,6 +2812,7 @@ src/pmc/retcontinuation.pmc []
src/pmc/role.pmc []
src/pmc/sarray.pmc []
src/pmc/scalar.pmc []
+src/pmc/scheduler.pmc []
src/pmc/sharedref.pmc []
src/pmc/slice.pmc []
src/pmc/stmlog.pmc []
@@ -2819,6 +2821,7 @@ src/pmc/stmvar.pmc []
src/pmc/string.pmc []
src/pmc/sub.pmc []
src/pmc/super.pmc []
+src/pmc/task.pmc []
src/pmc/timer.pmc []
src/pmc/tqueue.pmc []
src/pmc/undef.pmc []
@@ -3360,6 +3363,7 @@ t/pmc/ro.t []
t/pmc/role.t []
t/pmc/sarray.t []
t/pmc/scalar.t []
+t/pmc/scheduler.t []
t/pmc/sharedref.t []
t/pmc/signal.t []
t/pmc/slice.t []
@@ -3370,6 +3374,7 @@ t/pmc/string.t []
t/pmc/sub.t []
t/pmc/super.t []
t/pmc/sys.t []
+t/pmc/task.t []
t/pmc/threads.t []
t/pmc/timer.t []
t/pmc/tqueue.t []
View
1 include/parrot/parrot.h
@@ -285,6 +285,7 @@ typedef void (*funcptr_t)(void);
#include "parrot/exit.h"
#include "parrot/nci.h"
#include "parrot/thread.h"
+#include "parrot/scheduler.h"
#include "parrot/tsq.h"
#include "parrot/longopt.h"
#include "parrot/oo.h"
View
72 include/parrot/scheduler.h
@@ -0,0 +1,72 @@
+/* scheduler.h
+ * Copyright (C) 2007, The Perl Foundation.
+ * SVN Info
+ * $Id$
+ * Overview:
+ * Parrot concurrency scheduler header stuff
+ * Data Structure and Algorithms:
+ * History:
+ * Notes:
+ * References:
+ */
+
+#ifndef PARROT_SCHEDULER_H_GUARD
+#define PARROT_SCHEDULER_H_GUARD
+
+#include "parrot/parrot.h"
+
+/* HEADERIZER BEGIN: src/scheduler.c */
+
+/* HEADERIZER END: src/scheduler.c */
+
+/* Scheduler PMC's underlying struct. */
+typedef struct Parrot_Scheduler {
+ int id; /* The scheduler's ID. */
+ int max_tid; /* The highest assigned task ID. */
+ PMC *task_list; /* The current list of tasks. */
+ PMC *task_index; /* An index into the current list of tasks, ordered by priority. */
+ PMC *handlers; /* The list of currently active handlers. */
+} Parrot_Scheduler;
+
+/* Macro to access underlying structure of a Scheduler PMC. */
+#define PARROT_SCHEDULER(s) ((Parrot_Scheduler *) PMC_data(s))
+
+/* Task PMC's underlying struct. */
+typedef struct Parrot_Task {
+ int id; /* The task ID. */
+ STRING *type; /* The type of the task. */
+ STRING *priority; /* The priority of the task. */
+ STRING *status; /* The status of the task. */
+ int birthtime; /* A time stamp marking the creation of the task. */
+ PMC *codeblock; /* An (optional) codeblock for the task. */
+ PMC *interp; /* An (optional) interpreter structure for the task. */
+} Parrot_Task;
+
+/* Macro to access underlying structure of a Task PMC. */
+#define PARROT_TASK(t) ((Parrot_Task *) PMC_data(t))
+
+/*
+ * Scheduler private flags
+ */
+typedef enum {
+ SCHEDULER_cache_valid_FLAG = PObj_private0_FLAG,
+} scheduler_flags_enum;
+
+#define SCHEDULER_get_FLAGS(o) (PObj_get_FLAGS(o))
+#define SCHEDULER_flag_TEST(flag, o) (SCHEDULER_get_FLAGS(o) & SCHEDULER_ ## flag ## _FLAG)
+#define SCHEDULER_flag_SET(flag, o) (SCHEDULER_get_FLAGS(o) |= SCHEDULER_ ## flag ## _FLAG)
+#define SCHEDULER_flag_CLEAR(flag, o) (SCHEDULER_get_FLAGS(o) &= ~(UINTVAL)(SCHEDULER_ ## flag ## _FLAG))
+
+/* Mark if the scheduler's cache is valid */
+#define SCHEDULER_cache_valid_TEST(o) SCHEDULER_flag_TEST(cache_valid, o)
+#define SCHEDULER_cache_valid_SET(o) SCHEDULER_flag_SET(cache_valid, o)
+#define SCHEDULER_cache_valid_CLEAR(o) SCHEDULER_flag_CLEAR(cache_valid, o)
+
+#endif /* PARROT_SCHEDULER_H_GUARD */
+
+/*
+ * Local variables:
+ * c-file-style: "parrot"
+ * End:
+ * vim: expandtab shiftwidth=4:
+ */
View
248 src/pmc/scheduler.pmc
@@ -0,0 +1,248 @@
+/*
+Copyright (C) 2001-2007, The Perl Foundation.
+$Id$
+
+=head1 NAME
+
+src/pmc/scheduler.pmc - The concurrency scheduler
+
+=head1 DESCRIPTION
+
+Implements the core concurrency scheduler.
+
+=head2 Functions
+
+=over 4
+
+=cut
+
+*/
+
+#include "parrot/parrot.h"
+
+pmclass Scheduler need_ext {
+
+/*
+
+=item C<void init()>
+
+Initialize a concurrency scheduler object.
+
+=cut
+
+*/
+
+ void init() {
+ Parrot_Scheduler *core_struct = mem_allocate_zeroed_typed(Parrot_Scheduler);
+
+ /* Set flags for custom DOD mark and destroy. */
+ PObj_custom_mark_SET(SELF);
+ PObj_active_destroy_SET(SELF);
+
+ /* Set up the core struct. */
+ PMC_data(SELF) = core_struct;
+ core_struct->id = 0;
+ core_struct->max_tid = 0;
+ core_struct->task_list = pmc_new(interp, enum_class_Hash);
+ core_struct->task_index = pmc_new(interp, enum_class_ResizablePMCArray);
+ core_struct->handlers = pmc_new(interp, enum_class_ResizablePMCArray);
+
+ }
+
+/*
+
+=item C<void push_pmc(PMC *value)>
+
+Insert a task into the task list, giving it a task ID one higher than the
+current maximum.
+
+=cut
+
+*/
+
+ void push_pmc(PMC *value) {
+ Parrot_Scheduler * core_struct = PARROT_SCHEDULER(SELF);
+ PMC * key = pmc_new(INTERP, enum_class_Integer);
+
+ core_struct->max_tid++;
+ VTABLE_set_integer_native(INTERP, key, core_struct->max_tid);
+
+ VTABLE_set_pmc_keyed(INTERP, core_struct->task_list, key, value);
+ VTABLE_push_pmc(INTERP, core_struct->task_index, key);
+ }
+
+/*
+
+=item C<PMC *pop_pmc()>
+
+Retrieve the next task from the task list. If the task index is invalid,
+recalculate it before retrieving the next task.
+
+=cut
+
+*/
+
+ PMC *pop_pmc() {
+ Parrot_Scheduler * core_struct = PARROT_SCHEDULER(SELF);
+
+/* if (!SCHEDULER_cache_valid_TEST(SELF))
+ Parrot_task_recalculate_index(INTERP, SELF); */
+
+ if (VTABLE_elements(INTERP, core_struct->task_index) > 0) {
+ PMC *key = VTABLE_pop_pmc(INTERP, core_struct->task_index);
+ return VTABLE_get_pmc_keyed(INTERP, core_struct->task_list, key);
+ }
+ else
+ return PMCNULL;
+
+ }
+
+/*
+
+=item C<void destroy()>
+
+Free the scheduler's underlying struct.
+
+=cut
+
+*/
+ void destroy() {
+ mem_sys_free(PMC_data(SELF));
+ }
+
+/*
+
+=item C<void mark()>
+
+Mark any referenced strings and PMCs.
+
+=cut
+
+*/
+ void mark() {
+ if (PARROT_SCHEDULER(SELF)) {
+ Parrot_Scheduler * const core_struct = PARROT_SCHEDULER(SELF);
+
+ if (core_struct->task_list)
+ pobject_lives(interp, (PObj*)core_struct->task_list);
+ if (core_struct->task_index)
+ pobject_lives(interp, (PObj*)core_struct->task_index);
+ if (core_struct->handlers)
+ pobject_lives(interp, (PObj*)core_struct->handlers);
+ }
+ }
+
+/*
+
+=item C<void visit(visit_info *info)>
+
+This is used by freeze/thaw to visit the contents of the scheduler.
+
+C<*info> is the visit info, (see F<include/parrot/pmc_freeze.h>).
+
+=cut
+
+*/
+
+ void visit(visit_info *info) {
+ INTVAL i, n;
+ Parrot_Scheduler * core_struct = PARROT_SCHEDULER(SELF);
+ PMC **pos;
+
+ /* 1) visit task list */
+ pos = &core_struct->task_list;
+ info->thaw_ptr = pos;
+ (info->visit_pmc_now)(INTERP, *pos, info);
+
+ /* 2) visit the handlers */
+ pos = &core_struct->handlers;
+ info->thaw_ptr = pos;
+ (info->visit_pmc_now)(INTERP, *pos, info);
+ }
+
+/*
+
+=item C<void freeze(visit_info *info)>
+
+Used to archive the scheduler.
+
+=cut
+
+*/
+
+ void freeze(visit_info *info) {
+ IMAGE_IO *io = info->image_io;
+ Parrot_Scheduler * const core_struct = PARROT_SCHEDULER(SELF);
+
+ /* 1) freeze scheduler id */
+ VTABLE_push_integer(INTERP, io, core_struct->id);
+
+ /* 2) freeze maximum task id */
+ VTABLE_push_integer(INTERP, io, core_struct->max_tid);
+ }
+
+/*
+
+=item C<void thaw(visit_info *info)>
+
+Used to unarchive the scheduler.
+
+=cut
+
+*/
+
+ void thaw(visit_info *info) {
+ IMAGE_IO *io = info->image_io;
+
+ /* 1. thaw scheduler id */
+ INTVAL id = VTABLE_shift_integer(INTERP, io);
+
+ /* 2. thaw maximum task id */
+ INTVAL max_tid = VTABLE_shift_integer(INTERP, io);
+
+ /* Allocate the scheduler's core data struct and set custom flags. */
+ SELF.init();
+
+ /* Set the scheduler's id to the frozen id */
+ PARROT_SCHEDULER(SELF)->id = id;
+
+ /* Set the scheduler's maximum task id to the frozen tid */
+ PARROT_SCHEDULER(SELF)->max_tid = max_tid;
+ }
+
+/*
+
+=item C<void thawfinish(visit_info *info)>
+
+Called after the scheduler has been thawed.
+
+=cut
+
+*/
+
+ void thawfinish(visit_info *info) {
+ Parrot_Scheduler * core_struct = PARROT_SCHEDULER(SELF);
+
+ /* TODO: Rebuild the task index. */
+ }
+
+}
+
+/*
+
+=back
+
+=head1 SEE ALSO
+
+F<docs/pdds/pdd15_objects.pod>.
+
+=cut
+
+*/
+
+/*
+ * Local variables:
+ * c-file-style: "parrot"
+ * End:
+ * vim: expandtab shiftwidth=4:
+ */
View
294 src/pmc/task.pmc
@@ -0,0 +1,294 @@
+/*
+Copyright (C) 2001-2007, The Perl Foundation.
+$Id$
+
+=head1 NAME
+
+src/pmc/task.pmc - A concurrent task
+
+=head1 DESCRIPTION
+
+Implements the basic task behavior for the concurrency scheduler.
+
+=head2 Functions
+
+=over 4
+
+=cut
+
+*/
+
+#include "parrot/parrot.h"
+
+pmclass Task need_ext {
+
+/*
+
+=item C<void init()>
+
+Initialize a concurrency task object.
+
+=cut
+
+*/
+
+ void init() {
+ Parrot_Task *core_struct = mem_allocate_zeroed_typed(Parrot_Task);
+
+ /* Set flags for custom DOD mark and destroy. */
+ PObj_custom_mark_SET(SELF);
+ PObj_active_destroy_SET(SELF);
+
+ /* Set up the core struct. */
+ PMC_data(SELF) = core_struct;
+ core_struct->id = 0;
+ core_struct->type = CONST_STRING(interp, "");
+ core_struct->priority = CONST_STRING(interp, "");
+ core_struct->status = CONST_STRING(interp, "created");
+ core_struct->birthtime = 0;
+ core_struct->codeblock = PMCNULL;
+ core_struct->interp = PMCNULL;
+
+ }
+
+/*
+
+=item C<PMC *get_attr_str(STRING *name)>
+
+Gets the value of an attribute for this task.
+
+=cut
+
+*/
+ PMC *get_attr_str(STRING *name) {
+ Parrot_Task * core_struct = PARROT_TASK(SELF);
+ PMC *value = PMCNULL;
+
+ if (string_equal(interp, name, CONST_STRING(interp, "id")) == 0) {
+ value = pmc_new(interp, enum_class_Integer);
+ VTABLE_set_integer_native(interp, value, core_struct->id);
+ }
+ else if (string_equal(interp, name, CONST_STRING(interp, "type")) == 0) {
+ value = pmc_new(interp, enum_class_String);
+ VTABLE_set_string_native(interp, value, core_struct->type);
+ }
+ else if (string_equal(interp, name, CONST_STRING(interp, "priority")) == 0) {
+ value = pmc_new(interp, enum_class_String);
+ VTABLE_set_string_native(interp, value, core_struct->priority);
+ }
+ else if (string_equal(interp, name, CONST_STRING(interp, "status")) == 0) {
+ value = pmc_new(interp, enum_class_String);
+ VTABLE_set_string_native(interp, value, core_struct->status);
+ }
+ else if (string_equal(interp, name, CONST_STRING(interp, "birthtime")) == 0) {
+ value = pmc_new(interp, enum_class_Integer);
+ VTABLE_set_integer_native(interp, value, core_struct->birthtime);
+ }
+
+ return value;
+ }
+
+/*
+
+=item C<void set_attr_str(STRING *name, PMC *value)>
+
+Sets the value of an attribute for this task.
+
+=cut
+
+*/
+ void set_attr_str(STRING *name, PMC *value) {
+ Parrot_Task * core_struct = PARROT_TASK(SELF);
+
+ if (string_equal(interp, name, CONST_STRING(interp, "id")) == 0) {
+ core_struct->id = VTABLE_get_integer(interp, value);
+ }
+ else if (string_equal(interp, name, CONST_STRING(interp, "type")) == 0) {
+ core_struct->type = VTABLE_get_string(interp, value);
+ }
+ else if (string_equal(interp, name, CONST_STRING(interp, "priority")) == 0) {
+ core_struct->priority = VTABLE_get_string(interp, value);
+ }
+ else if (string_equal(interp, name, CONST_STRING(interp, "status")) == 0) {
+ core_struct->status = VTABLE_get_string(interp, value);
+ }
+ else if (string_equal(interp, name, CONST_STRING(interp, "birthtime")) == 0) {
+ core_struct->birthtime = VTABLE_get_integer(interp, value);
+ }
+ }
+
+/*
+
+=item C<void destroy()>
+
+Free the task's underlying struct.
+
+=cut
+
+*/
+ void destroy() {
+ mem_sys_free(PMC_data(SELF));
+ }
+
+/*
+
+=item C<void mark()>
+
+Mark any referenced strings and PMCs.
+
+=cut
+
+*/
+ void mark() {
+ if (PARROT_TASK(SELF)) {
+ Parrot_Task * const core_struct = PARROT_TASK(SELF);
+
+ if (core_struct->codeblock)
+ pobject_lives(interp, (PObj*)core_struct->codeblock);
+ if (core_struct->interp)
+ pobject_lives(interp, (PObj*)core_struct->interp);
+ }
+ }
+
+/*
+
+=item C<void visit(visit_info *info)>
+
+This is used by freeze/thaw to visit the contents of the task.
+
+C<*info> is the visit info, (see F<include/parrot/pmc_freeze.h>).
+
+=cut
+
+*/
+
+ void visit(visit_info *info) {
+ INTVAL i, n;
+ Parrot_Task * core_struct = PARROT_TASK(SELF);
+ PMC **pos;
+
+ /* 1) visit code block */
+ pos = &core_struct->codeblock;
+ info->thaw_ptr = pos;
+ (info->visit_pmc_now)(INTERP, *pos, info);
+
+ /* 2) visit the interpreter structure */
+ pos = &core_struct->interp;
+ info->thaw_ptr = pos;
+ (info->visit_pmc_now)(INTERP, *pos, info);
+ }
+
+/*
+
+=item C<void freeze(visit_info *info)>
+
+Used to archive the task.
+
+=cut
+
+*/
+
+ void freeze(visit_info *info) {
+ IMAGE_IO *io = info->image_io;
+ Parrot_Task * const core_struct = PARROT_TASK(SELF);
+
+ /* 1) freeze task id */
+ VTABLE_push_integer(INTERP, io, core_struct->id);
+
+ /* 2) freeze task birthtime */
+ VTABLE_push_integer(INTERP, io, core_struct->birthtime);
+
+ /* 3) freeze task type */
+ VTABLE_push_string(INTERP, io, core_struct->type);
+
+ /* 4) freeze task priority */
+ VTABLE_push_string(INTERP, io, core_struct->priority);
+
+ /* 5) freeze task status */
+ VTABLE_push_string(INTERP, io, core_struct->status);
+ }
+
+/*
+
+=item C<void thaw(visit_info *info)>
+
+Used to unarchive the task.
+
+=cut
+
+*/
+
+ void thaw(visit_info *info) {
+ IMAGE_IO *io = info->image_io;
+
+ /* 1. thaw task id */
+ INTVAL id = VTABLE_shift_integer(INTERP, io);
+
+ /* 2. thaw task birthtime */
+ INTVAL birthtime = VTABLE_shift_integer(INTERP, io);
+
+ /* 3. thaw task type */
+ STRING *type = VTABLE_shift_string(INTERP, io);
+
+ /* 4. thaw task priority */
+ STRING *priority = VTABLE_shift_string(INTERP, io);
+
+ /* 5. thaw task status */
+ STRING *status = VTABLE_shift_string(INTERP, io);
+
+ /* Allocate the task's core data struct and set custom flags. */
+ SELF.init();
+
+ /* Set the task's id to the frozen id */
+ PARROT_TASK(SELF)->id = id;
+
+ /* Set the task's birthtime to the frozen birthtime */
+ PARROT_TASK(SELF)->birthtime = birthtime;
+
+ /* Set the task's type to the frozen type */
+ PARROT_TASK(SELF)->type = type;
+
+ /* Set the task's priority to the frozen priority */
+ PARROT_TASK(SELF)->priority = priority;
+
+ /* Set the task's status to the frozen status */
+ PARROT_TASK(SELF)->status = status;
+
+ }
+
+/*
+
+=item C<void thawfinish(visit_info *info)>
+
+Called after the task has been thawed.
+
+=cut
+
+*/
+
+ void thawfinish(visit_info *info) {
+ Parrot_Task * core_struct = PARROT_TASK(SELF);
+
+ /* TODO: Rebuild the task index. */
+ }
+
+}
+
+/*
+
+=back
+
+=head1 SEE ALSO
+
+F<docs/pdds/pdd15_objects.pod>.
+
+=cut
+
+*/
+
+/*
+ * Local variables:
+ * c-file-style: "parrot"
+ * End:
+ * vim: expandtab shiftwidth=4:
+ */
View
59 t/pmc/scheduler.t
@@ -0,0 +1,59 @@
+#! perl
+# Copyright (C) 2007, The Perl Foundation.
+# $Id$
+
+use strict;
+use warnings;
+use lib qw( . lib ../lib ../../lib );
+use Test::More;
+use Parrot::Test tests => 1;
+
+=head1 NAME
+
+t/pmc/scheduler.t - Concurrency Scheduler
+
+=head1 SYNOPSIS
+
+ % prove t/pmc/scheduler.t
+
+=head1 DESCRIPTION
+
+Tests the concurrency scheduler PMC.
+
+=cut
+
+pir_output_is( <<'CODE', <<'OUT', "create a concurrency scheduler and set attributes" );
+ .sub main :main
+ $P0 = new "Scheduler"
+ $P1 = new "Task"
+
+ push $P0, $P1
+
+ $P2 = pop $P0
+
+ if null $P2 goto no_task
+ $P3 = getattribute $P2, 'status'
+ print $P3
+ print "\n"
+ goto got_task
+
+ no_task:
+ print "no task to retrieve\n"
+
+ got_task:
+
+ print 1
+ print "\n"
+ end
+ .end
+CODE
+created
+1
+OUT
+
+# Local Variables:
+# mode: cperl
+# cperl-indent-level: 4
+# fill-column: 100
+# End:
+# vim: expandtab shiftwidth=4:
View
51 t/pmc/task.t
@@ -0,0 +1,51 @@
+#! perl
+# Copyright (C) 2007, The Perl Foundation.
+# $Id$
+
+use strict;
+use warnings;
+use lib qw( . lib ../lib ../../lib );
+use Test::More;
+use Parrot::Test tests => 1;
+
+=head1 NAME
+
+t/pmc/task.t - Concurrent Task
+
+=head1 SYNOPSIS
+
+ % prove t/pmc/task.t
+
+=head1 DESCRIPTION
+
+Tests the task PMC used by the concurrency scheduler.
+
+=cut
+
+pir_output_is( <<'CODE', <<'OUT', "create a task and set attributes" );
+ .sub main :main
+ $P0 = new "Task"
+ $P1 = getattribute $P0, 'status'
+ print $P1
+ print "\n"
+
+ $P2 = new "String"
+ $P2 = "inprocess"
+ setattribute $P0, 'status', $P2
+
+ $P3 = getattribute $P0, 'status'
+ print $P3
+ print "\n"
+ end
+ .end
+CODE
+created
+inprocess
+OUT
+
+# Local Variables:
+# mode: cperl
+# cperl-indent-level: 4
+# fill-column: 100
+# End:
+# vim: expandtab shiftwidth=4:

0 comments on commit 1d259c6

Please sign in to comment.
Something went wrong with that request. Please try again.