Permalink
Newer
Older
100644 346 lines (216 sloc) 7.77 KB
2
Copyright (C) 2001-2011, Parrot Foundation.
3
4
=head1 NAME
5
6
src/pmc/scheduler.pmc - The concurrency scheduler
7
8
=head1 DESCRIPTION
9
10
Implements the core concurrency scheduler.
11
13
14
=over 4
15
16
=cut
17
18
*/
19
20
#include "parrot/scheduler_private.h"
22
/* HEADERIZER HFILE: none */
23
/* HEADERIZER BEGIN: static */
24
/* HEADERIZER END: static */
25
26
pmclass Scheduler auto_attrs {
27
ATTR INTVAL id; /* The scheduler's ID. */
28
ATTR PMC *handlers; /* The list of currently active handlers. */
29
ATTR PMC *messages; /* A message queue used for communication
30
between schedulers. */
32
ATTR PMC *task_queue; /* List of tasks/green threads waiting to run */
33
ATTR PMC *alarms; /* List of future alarms ordered by time */
35
ATTR PMC *all_tasks; /* Hash of all active tasks by ID */
36
ATTR UINTVAL next_task_id; /* ID to assign to the next created task */
37
ATTR INTVAL enable_preemption;
38
/* Can perform uncooperative task preemption */
39
ATTR INTVAL enable_scheduling;
40
/* Can perform task scheduling behaviors */
42
ATTR Parrot_Interp interp; /* A link to the scheduler's interpreter. */
43
44
/*
45
46
=item C<void init()>
47
48
Initializes a concurrency scheduler object.
55
Parrot_Scheduler_attributes * const core_struct =
56
(Parrot_Scheduler_attributes *) PMC_data(SELF);
58
/* Set flags for custom GC mark and destroy. */
61
62
/* Set up the core struct. */
63
core_struct->id = 0;
64
core_struct->handlers = Parrot_pmc_new(INTERP, enum_class_ResizablePMCArray);
65
core_struct->messages = Parrot_pmc_new(INTERP, enum_class_ResizablePMCArray);
66
core_struct->task_queue = Parrot_pmc_new(INTERP, enum_class_PMCList);
67
core_struct->alarms = Parrot_pmc_new(INTERP, enum_class_PMCList);
68
core_struct->all_tasks = Parrot_pmc_new(INTERP, enum_class_Hash);
69
core_struct->enable_scheduling = 0;
70
core_struct->enable_preemption = 0;
71
core_struct->next_task_id = 0;
72
core_struct->interp = INTERP;
73
74
/* Chandon TODO: Delete from int-keyed hash doesn't like me. */
75
/* VTABLE_set_integer_native(interp, core_struct->all_tasks, Hash_key_type_int); */
76
82
=item C<void init_pmc(PMC *data)>
83
84
Initializes a new Scheduler with a C<Hash> PMC with any or all of the keys:
85
86
=over 4
87
88
=item C<id>
89
90
An C<Integer> representing the unique identifier for this scheduler.
91
92
=back
93
98
VTABLE void init_pmc(PMC *data) {
100
Parrot_Scheduler_attributes *core_struct;
102
if (!VTABLE_isa(INTERP, data, CONST_STRING(INTERP, "Hash")))
103
Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION,
104
"Scheduler initializer must be a Hash");
108
core_struct = PARROT_SCHEDULER(SELF);
109
elem = VTABLE_get_pmc_keyed_str(INTERP, data, CONST_STRING(INTERP, "id"));
111
if (!PMC_IS_NULL(elem))
112
core_struct->id = VTABLE_get_integer(INTERP, elem);
117
=item C<void push_pmc(PMC *value)>
118
119
Inserts a task into the task list, giving it a task ID one higher than the
120
current maximum, and a birthtime of the current time.
127
/* TODO: This doesn't appear to do anything */
128
Parrot_Scheduler_attributes * const core_struct = PARROT_SCHEDULER(SELF);
129
PMC * const type_pmc = VTABLE_get_attr_str(interp, task, CONST_STRING(interp, "type"));
130
STRING * const type = VTABLE_get_string(interp, type_pmc);
134
/*
135
136
=item C<PMC *pop_pmc()>
137
138
Retrieves the next task from the task list. If the task index is invalid,
139
recalculates it before retrieving the next task.
146
Parrot_Scheduler_attributes * const core_struct = PARROT_SCHEDULER(SELF);
147
PMC * const task = VTABLE_shift_pmc(INTERP, core_struct->task_queue);
154
=item C<INTVAL get_integer()>
155
156
Retrieves the number of pending tasks in the scheduler's task list.
163
Parrot_Scheduler_attributes * const core_struct = PARROT_SCHEDULER(SELF);
164
return VTABLE_elements(INTERP, core_struct->task_queue);
172
Frees the scheduler's underlying struct.
178
Parrot_Scheduler_attributes * const core_struct = PARROT_SCHEDULER(SELF);
181
core_struct->interp->scheduler = NULL;
185
/*
186
187
=item C<void mark()>
188
189
Marks any referenced strings and PMCs as live.
195
if (PARROT_SCHEDULER(SELF)) {
196
Parrot_Scheduler_attributes * const core_struct = PARROT_SCHEDULER(SELF);
198
Parrot_gc_mark_PMC_alive(INTERP, core_struct->handlers);
199
Parrot_gc_mark_PMC_alive(INTERP, core_struct->messages);
200
Parrot_gc_mark_PMC_alive(INTERP, core_struct->task_queue);
201
Parrot_gc_mark_PMC_alive(INTERP, core_struct->alarms);
202
Parrot_gc_mark_PMC_alive(INTERP, core_struct->all_tasks);
209
=item C<void visit(PMC *info)>
211
Visits the contents of the scheduler (used by freeze/thaw).
213
C<*info> is the visit info (see F<include/parrot/pmc_freeze.h>).
219
VTABLE void visit(PMC *info) {
221
VISIT_PMC_ATTR(INTERP, info, SELF, Scheduler, task_queue);
222
223
/* 2) visit the handlers */
224
VISIT_PMC_ATTR(INTERP, info, SELF, Scheduler, handlers);
225
226
/* 3) visit the alarms */
227
VISIT_PMC_ATTR(INTERP, info, SELF, Scheduler, alarms);
228
229
/* 3) visit all tasks */
230
VISIT_PMC_ATTR(INTERP, info, SELF, Scheduler, all_tasks);
236
=item C<void freeze(PMC *info)>
244
VTABLE void freeze(PMC *info) {
245
Parrot_Scheduler_attributes * const core_struct = PARROT_SCHEDULER(SELF);
246
247
/* 1) freeze scheduler id */
248
VTABLE_push_integer(INTERP, info, core_struct->id);
253
=item C<void thaw(PMC *info)>
261
VTABLE void thaw(PMC *info) {
263
const INTVAL id = VTABLE_shift_integer(INTERP, info);
264
265
/* Allocate the scheduler's core data struct and set custom flags. */
266
SELF.init();
267
268
/* Set the scheduler's id to the frozen id */
269
PARROT_SCHEDULER(SELF)->id = id;
270
}
271
275
=item C<void thawfinish(PMC *info)>
283
VTABLE void thawfinish(PMC *info) {
284
/* Parrot_cx_refresh_task_list(INTERP, SELF); */
288
/*
289
290
=back
291
292
=head2 Methods
293
294
=over 4
295
296
=cut
297
298
*/
299
300
/*
301
302
=item C<METHOD active_tasks()>
304
Returns a ResizablePMCArray containing pointers to all active tasks.
310
METHOD active_tasks() {
311
Parrot_Scheduler_attributes *sdata = PARROT_SCHEDULER(SELF);
312
PMC * const tasks = Parrot_pmc_new(interp, enum_class_ResizablePMCArray);
313
PMC * const iter = Parrot_pmc_new_init(interp, enum_class_HashIterator, sdata->all_tasks);
314
315
while (!VTABLE_get_bool(interp, iter)) {
316
PMC * const pair = VTABLE_shift_pmc(interp, iter);
317
PMC * task = PMCNULL;
318
STRING * const value = CONST_STRING(interp, "value");
319
Parrot_pcc_invoke_method_from_c_args(interp, pair,
321
VTABLE_push_pmc(interp, tasks, task);
324
RETURN(PMC* tasks);
326
}
327
328
/*
329
330
=back
331
332
=head1 SEE ALSO
333
334
F<docs/pdds/pdd25_concurrency.pod>.
335
336
=cut
337
338
*/
339
340
/*
341
* Local variables:
342
* c-file-style: "parrot"
343
* End:
344
* vim: expandtab shiftwidth=4 cinoptions='\:2=2' :