[svn:parrot] r47951 - in branches/gsoc_threads: config/gen/platform/generic include/parrot src src/gc src/pmc t/pmc
Chandon at svn.parrot.org
Chandon at svn.parrot.org
Thu Jul 1 22:20:45 UTC 2010
Author: Chandon
Date: Thu Jul 1 22:20:44 2010
New Revision: 47951
URL: https://trac.parrot.org/parrot/changeset/47951
Log:
[gsoc_threads] Alarms work, at least the easy way.
Added:
branches/gsoc_threads/t/pmc/alarm.t (contents, props changed)
Modified:
branches/gsoc_threads/config/gen/platform/generic/time.c
branches/gsoc_threads/include/parrot/alarm_private.h
branches/gsoc_threads/include/parrot/scheduler.h
branches/gsoc_threads/include/parrot/scheduler_private.h
branches/gsoc_threads/src/alarm.c
branches/gsoc_threads/src/gc/gc_ms.c
branches/gsoc_threads/src/pmc/alarm.pmc
branches/gsoc_threads/src/pmc/pmclist.pmc
branches/gsoc_threads/src/pmc/scheduler.pmc
branches/gsoc_threads/src/scheduler.c
Modified: branches/gsoc_threads/config/gen/platform/generic/time.c
==============================================================================
--- branches/gsoc_threads/config/gen/platform/generic/time.c Thu Jul 1 21:51:08 2010 (r47950)
+++ branches/gsoc_threads/config/gen/platform/generic/time.c Thu Jul 1 22:20:44 2010 (r47951)
@@ -94,6 +94,28 @@
/*
+=item C<FLOATVAL Parrot_floatval_sleep(void)>
+
+Parrot wrapper around standard library C<time()> function, returning a FLOATVAL.
+
+=cut
+
+*/
+
+void
+Parrot_floatval_sleep(FLOATVAL time)
+{
+ if (time > 1000) {
+ /* prevent integer overflow when converting to microseconds */
+ const int seconds = floor(time);
+ Parrot_sleep(seconds);
+ time -= seconds;
+ }
+ Parrot_usleep((UINTVAL) time*1000000);
+}
+
+/*
+
=item C<struct tm * Parrot_gmtime_r(const time_t *t, struct tm *tm)>
Parrot wrapper around standard library C<gmtime_r()> function.
Modified: branches/gsoc_threads/include/parrot/alarm_private.h
==============================================================================
--- branches/gsoc_threads/include/parrot/alarm_private.h Thu Jul 1 21:51:08 2010 (r47950)
+++ branches/gsoc_threads/include/parrot/alarm_private.h Thu Jul 1 22:20:44 2010 (r47951)
@@ -10,7 +10,6 @@
typedef struct Parrot_alarm_queue {
FLOATVAL when;
- int alarm_set;
struct Parrot_alarm_queue *next;
} Parrot_alarm_queue;
Modified: branches/gsoc_threads/include/parrot/scheduler.h
==============================================================================
--- branches/gsoc_threads/include/parrot/scheduler.h Thu Jul 1 21:51:08 2010 (r47950)
+++ branches/gsoc_threads/include/parrot/scheduler.h Thu Jul 1 22:20:44 2010 (r47951)
@@ -15,6 +15,8 @@
#include "parrot/parrot.h"
+#define PARROT_TASK_SWITCH_QUANTUM 0.02
+
/* HEADERIZER BEGIN: src/scheduler.c */
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
@@ -82,6 +84,12 @@
__attribute__nonnull__(2);
PARROT_EXPORT
+void Parrot_cx_handle_alarms(PARROT_INTERP, ARGMOD(PMC *scheduler))
+ __attribute__nonnull__(1)
+ __attribute__nonnull__(2)
+ FUNC_MODIFIES(*scheduler);
+
+PARROT_EXPORT
void Parrot_cx_handle_tasks(PARROT_INTERP, ARGMOD(PMC *scheduler))
__attribute__nonnull__(1)
__attribute__nonnull__(2)
@@ -114,6 +122,17 @@
__attribute__nonnull__(3);
PARROT_EXPORT
+void Parrot_cx_schedule_immediate(PARROT_INTERP, ARGIN(PMC *sub))
+ __attribute__nonnull__(1)
+ __attribute__nonnull__(2);
+
+PARROT_EXPORT
+void Parrot_cx_schedule_next_task(PARROT_INTERP, ARGMOD(PMC *scheduler))
+ __attribute__nonnull__(1)
+ __attribute__nonnull__(2)
+ FUNC_MODIFIES(*scheduler);
+
+PARROT_EXPORT
void Parrot_cx_schedule_repeat(PARROT_INTERP, ARGIN(PMC *task))
__attribute__nonnull__(1)
__attribute__nonnull__(2);
@@ -211,6 +230,9 @@
#define ASSERT_ARGS_Parrot_cx_find_handler_local __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(task))
+#define ASSERT_ARGS_Parrot_cx_handle_alarms __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+ PARROT_ASSERT_ARG(interp) \
+ , PARROT_ASSERT_ARG(scheduler))
#define ASSERT_ARGS_Parrot_cx_handle_tasks __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(scheduler))
@@ -228,6 +250,12 @@
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(sub))
+#define ASSERT_ARGS_Parrot_cx_schedule_next_task __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+ PARROT_ASSERT_ARG(interp) \
+ , PARROT_ASSERT_ARG(scheduler))
#define ASSERT_ARGS_Parrot_cx_schedule_repeat __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(task))
Modified: branches/gsoc_threads/include/parrot/scheduler_private.h
==============================================================================
--- branches/gsoc_threads/include/parrot/scheduler_private.h Thu Jul 1 21:51:08 2010 (r47950)
+++ branches/gsoc_threads/include/parrot/scheduler_private.h Thu Jul 1 22:20:44 2010 (r47951)
@@ -22,6 +22,8 @@
SCHEDULER_terminate_requested_FLAG = PObj_private2_FLAG
} scheduler_flags_enum;
+void Parrot_pmc_list_insert_by_number(PARROT_INTERP, PMC *list, PMC *value);
+
#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)
Modified: branches/gsoc_threads/src/alarm.c
==============================================================================
--- branches/gsoc_threads/src/alarm.c Thu Jul 1 21:51:08 2010 (r47950)
+++ branches/gsoc_threads/src/alarm.c Thu Jul 1 22:20:44 2010 (r47951)
@@ -85,8 +85,6 @@
itmr.it_interval.tv_sec = 0;
itmr.it_interval.tv_usec = 0;
- fprintf(stderr, "setitimer(%.02lf): sec = %d; usec = %d\n", wait, sec, usec);
-
if(setitimer(ITIMER_REAL, &itmr, 0) == -1) {
perror("setitimer failed in set_posix_alarm");
exit(EXIT_FAILURE);
@@ -108,8 +106,6 @@
FLOATVAL now, wait;
Parrot_alarm_queue* qp;
- fprintf(stderr, "Got Parrot_timers_alarm_callback()\n");
-
/* Not atomic; only one thread ever writes this value */
alarm_serial += 1;
@@ -121,10 +117,9 @@
alarm_queue = qp;
}
- if(alarm_queue != NULL && alarm_queue->alarm_set == 0) {
+ if(alarm_queue != NULL) {
wait = alarm_queue->when - now;
set_posix_alarm(wait);
- qp->alarm_set = 1;
}
}
@@ -176,7 +171,6 @@
if(alarm_queue == NULL || when < alarm_queue->when) {
new_alarm->next = alarm_queue;
- new_alarm->alarm_set = 1;
alarm_queue = new_alarm;
set_posix_alarm(when - now);
return;
@@ -188,7 +182,6 @@
}
new_alarm->next = *qpp;
- new_alarm->alarm_set = 0;
*qpp = new_alarm;
}
Modified: branches/gsoc_threads/src/gc/gc_ms.c
==============================================================================
--- branches/gsoc_threads/src/gc/gc_ms.c Thu Jul 1 21:51:08 2010 (r47950)
+++ branches/gsoc_threads/src/gc/gc_ms.c Thu Jul 1 22:20:44 2010 (r47951)
@@ -636,11 +636,14 @@
/* keep the scheduler and its kids alive for Task-like PMCs to destroy
* themselves; run a sweep to collect them */
+ /* TODO: Figure out if this stuff was important */
+#ifdef PARROT_CX_BUILD_OLD_STUFF
if (interp->scheduler) {
Parrot_gc_mark_PMC_alive(interp, interp->scheduler);
VTABLE_mark(interp, interp->scheduler);
Parrot_gc_sweep_pool(interp, mem_pools, mem_pools->pmc_pool);
}
+#endif
/* now sweep everything that's left */
Parrot_gc_sweep_pool(interp, mem_pools, mem_pools->pmc_pool);
Modified: branches/gsoc_threads/src/pmc/alarm.pmc
==============================================================================
--- branches/gsoc_threads/src/pmc/alarm.pmc Thu Jul 1 21:51:08 2010 (r47950)
+++ branches/gsoc_threads/src/pmc/alarm.pmc Thu Jul 1 22:20:44 2010 (r47951)
@@ -48,6 +48,10 @@
*/
VTABLE void init() {
+ Parrot_Alarm_attributes *data = PARROT_ALARM(SELF);
+ data->alarm_time = 0.0;
+ data->alarm_sub = PMCNULL;
+
PObj_custom_mark_SET(SELF);
}
Modified: branches/gsoc_threads/src/pmc/pmclist.pmc
==============================================================================
--- branches/gsoc_threads/src/pmc/pmclist.pmc Thu Jul 1 21:51:08 2010 (r47950)
+++ branches/gsoc_threads/src/pmc/pmclist.pmc Thu Jul 1 22:20:44 2010 (r47951)
@@ -480,10 +480,6 @@
=cut
*/
-void debug_my_face() {
- fprintf(stderr, "");
-};
-
PARROT_EXPORT
void
Parrot_pmc_list_insert_by_number(PARROT_INTERP, PMC *list, PMC *value) {
Modified: branches/gsoc_threads/src/pmc/scheduler.pmc
==============================================================================
--- branches/gsoc_threads/src/pmc/scheduler.pmc Thu Jul 1 21:51:08 2010 (r47950)
+++ branches/gsoc_threads/src/pmc/scheduler.pmc Thu Jul 1 22:20:44 2010 (r47951)
@@ -38,7 +38,8 @@
ATTR PMC *messages; /* A message queue used for communication
between schedulers. */
- ATTR PMC *alarms; /* Array of future alarms ordered by time */
+ ATTR PMC *task_queue; /* List of tasks/green threads waiting to run */
+ ATTR PMC *alarms; /* List of future alarms ordered by time */
ATTR Parrot_mutex msg_lock; /* Lock to synchronize the message queue. */
ATTR Parrot_Interp interp; /* A link to the scheduler's interpreter. */
@@ -69,6 +70,7 @@
core_struct->wait_index = Parrot_pmc_new(INTERP, enum_class_ResizablePMCArray);
core_struct->handlers = Parrot_pmc_new(INTERP, enum_class_ResizablePMCArray);
core_struct->messages = Parrot_pmc_new(INTERP, enum_class_ResizablePMCArray);
+ core_struct->task_queue = Parrot_pmc_new(INTERP, enum_class_PMCList);
core_struct->alarms = Parrot_pmc_new(INTERP, enum_class_PMCList);
core_struct->interp = INTERP;
MUTEX_INIT(core_struct->msg_lock);
@@ -281,12 +283,8 @@
Parrot_gc_mark_PMC_alive(INTERP, core_struct->wait_index);
Parrot_gc_mark_PMC_alive(INTERP, core_struct->handlers);
Parrot_gc_mark_PMC_alive(INTERP, core_struct->messages);
-
- if(PObj_is_PMC_TEST(core_struct->alarms)) {
- Parrot_gc_mark_PMC_alive(INTERP, core_struct->alarms);
- } else {
- fprintf(stderr, "Why is this thing not a PMC?\n");
- }
+ Parrot_gc_mark_PMC_alive(INTERP, core_struct->task_queue);
+ Parrot_gc_mark_PMC_alive(INTERP, core_struct->alarms);
}
}
Modified: branches/gsoc_threads/src/scheduler.c
==============================================================================
--- branches/gsoc_threads/src/scheduler.c Thu Jul 1 21:51:08 2010 (r47950)
+++ branches/gsoc_threads/src/scheduler.c Thu Jul 1 22:20:44 2010 (r47951)
@@ -20,11 +20,13 @@
#include "parrot/scheduler_private.h"
#include "parrot/runcore_api.h"
#include "parrot/alarm.h"
+#include "parrot/scheduler.h"
#include "pmc/pmc_scheduler.h"
#include "pmc/pmc_task.h"
#include "pmc/pmc_timer.h"
#include "pmc/pmc_alarm.h"
+#include "pmc/pmc_pmclist.h"
#include "scheduler.str"
@@ -136,9 +138,15 @@
{
ASSERT_ARGS(Parrot_cx_handle_tasks)
-
-
SCHEDULER_wake_requested_CLEAR(scheduler);
+
+ Parrot_cx_handle_alarms(interp, scheduler);
+ // Parrot_cx_check_quantum(interp)
+
+ if(SCHEDULER_wake_requested_TEST(scheduler))
+ Parrot_cx_schedule_next_task(interp, scheduler);
+
+#ifdef PARROT_CX_BUILD_OLD_STUFF
Parrot_cx_refresh_task_list(interp, scheduler);
while (VTABLE_get_integer(interp, scheduler) > 0) {
@@ -175,6 +183,27 @@
Parrot_cx_refresh_task_list(interp, scheduler);
} /* end of pending tasks */
+#endif
+}
+
+/*
+=item C<void Parrot_cx_schedule_next_task(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.
+
+TODO: Make the above true rather than a dirty lie.
+
+=end
+*/
+
+PARROT_EXPORT
+void
+Parrot_cx_schedule_next_task(PARROT_INTERP, ARGMOD(PMC *scheduler))
+{
+ Parrot_Scheduler_attributes *sched = PARROT_SCHEDULER(interp->scheduler);
+ PMC *sub = VTABLE_shift_pmc(interp, sched->task_queue);
+ Parrot_pcc_invoke_sub_from_c_args(interp, sub, "->");
}
/*
@@ -238,7 +267,9 @@
{
ASSERT_ARGS(Parrot_cx_runloop_end)
SCHEDULER_terminate_requested_SET(interp->scheduler);
- Parrot_cx_handle_tasks(interp, interp->scheduler);
+
+ /* TODO: Figure out why this was here, fix it if useful. */
+ /* Parrot_cx_handle_tasks(interp, interp->scheduler); */
}
/*
@@ -976,6 +1007,26 @@
/*
+=item C<void Parrot_cx_schedule_immediate(PARROT_INTERP, PMC *sub) >
+
+Add a task to the task queue for immediate execution.
+
+=cut
+
+*/
+
+PARROT_EXPORT
+void
+Parrot_cx_schedule_immediate(PARROT_INTERP, ARGIN(PMC *sub))
+{
+ ASSERT_ARGS(Parrot_cx_schedule_immediate)
+ Parrot_Scheduler_attributes *sched = PARROT_SCHEDULER(interp->scheduler);
+ VTABLE_unshift_pmc(interp, sched->task_queue, sub);
+ SCHEDULER_wake_requested_SET(interp->scheduler);
+}
+
+/*
+
=item C<void Parrot_cx_schedule_alarm(PARROT_INTERP, PMC *alarm)>
Schedule an alarm.
@@ -989,22 +1040,49 @@
Parrot_cx_schedule_alarm(PARROT_INTERP, ARGIN(PMC *alarm))
{
ASSERT_ARGS(Parrot_cx_schedule_alarm)
- FLOATVAL alarm_time;
- int i;
- PMC *tmp1;
- PMC *tmp2;
Parrot_Scheduler_attributes *sched = PARROT_SCHEDULER(interp->scheduler);
-
- alarm_time = VTABLE_get_number(interp, alarm);
-
- fprintf(stderr, "Schedule alarm for %.02f\n", alarm_time);
+ FLOATVAL alarm_time = VTABLE_get_number(interp, alarm);
Parrot_alarm_set(alarm_time);
/* Insert new alarm at correct (ordered by time) position in array. */
Parrot_pmc_list_insert_by_number(interp, sched->alarms, alarm);
}
+/*
+
+=item C<void Parrot_cx_handle_alarms(PARROT_INTERP, PMC *scheduler) >
+
+Add the subs attached to any expired alarms to the task queue.
+
+=cut
+
+*/
+
+PARROT_EXPORT
+void
+Parrot_cx_handle_alarms(PARROT_INTERP, ARGMOD(PMC *scheduler))
+{
+ ASSERT_ARGS(Parrot_cx_handle_alarms)
+ Parrot_Scheduler_attributes *sched = PARROT_SCHEDULER(interp->scheduler);
+ INTVAL alarm_count = VTABLE_get_integer(interp, sched->alarms);
+ FLOATVAL now_time = Parrot_floatval_time();
+
+ while(alarm_count) {
+ PMC *alarm = VTABLE_shift_pmc(interp, sched->alarms);
+ FLOATVAL alarm_time = VTABLE_get_number(interp, alarm);
+
+ if(alarm_time < now_time) {
+ Parrot_Alarm_attributes *data = PARROT_ALARM(alarm);
+ Parrot_cx_schedule_immediate(interp, data->alarm_sub);
+ } else {
+ VTABLE_unshift_pmc(interp, sched->alarms, alarm);
+ break;
+ }
+
+ alarm_count--;
+ }
+}
/*
@@ -1056,6 +1134,27 @@
Parrot_cx_schedule_sleep(PARROT_INTERP, FLOATVAL time, ARGIN_NULLOK(opcode_t *next))
{
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;
+ INTVAL alarm_count;
+ PMC *alarm;
+
+ 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);
+ }
+
+ Parrot_floatval_sleep(done_time - fmin(done_time, alarm_time));
+ Parrot_cx_check_tasks(interp, interp->scheduler);
+ }
+
+#ifdef PARROT_CX_BUILD_OLD_STUFF
#ifdef PARROT_HAS_THREADS
Parrot_cond condition;
Parrot_mutex lock;
@@ -1086,6 +1185,10 @@
}
Parrot_usleep((UINTVAL) time*1000000);
#endif
+#endif
+
+
+
return next;
}
Added: branches/gsoc_threads/t/pmc/alarm.t
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/gsoc_threads/t/pmc/alarm.t Thu Jul 1 22:20:44 2010 (r47951)
@@ -0,0 +1,149 @@
+#!./parrot
+# Copyright (C) 2010, Parrot Foundation.
+# $Id$
+
+.include 'timer.pasm'
+
+.sub main
+ .include 'test_more.pir'
+
+ plan(7)
+
+ $P0 = new 'Integer'
+ $P0 = 0
+ set_global 'A', $P0
+
+ $N0 = time
+ $N0 = $N0 + 0.25
+
+ $P0 = get_global 'alarm2'
+ $N1 = $N0 + 0.04
+ make_alarm($N1, $P0)
+
+ $P0 = get_global 'alarm1'
+ $N1 = $N0 + 0.02
+ make_alarm($N1, $P0)
+
+ $P0 = get_global 'alarm4'
+ $N1 = $N0 + 0.10
+ make_alarm($N1, $P0)
+
+ $P0 = get_global 'alarm3'
+ $N1 = $N0 + 0.09
+ make_alarm($N1, $P0)
+
+loop:
+ $P0 = get_global 'A'
+ $I0 = $P0
+ if $I0 == 4 goto done
+ goto loop
+
+done:
+ ok(1, "All alarms executed")
+
+ $N1 = $N0 + 0.10
+ $N0 = time
+
+ if $N0 >= $N1 goto good
+ ok(0, "Alarms actually waited")
+ .return()
+
+good:
+ ok(1, "Alarms actually waited")
+
+ $P1 = get_global 'alarm_finish'
+ $N0 = time
+ $N0 = $N0 + 0.1
+
+ $P0 = new 'Float'
+ $P0 = $N0
+ set_global 'FT', $P0
+
+ make_alarm($N0, $P1)
+
+ sleep 5.0
+ ok(0, "Alarm/sleep interaction")
+.end
+
+.sub make_alarm
+ .param num when
+ .param pmc proc
+
+ $P1 = new 'Alarm'
+ $P1[.PARROT_ALARM_TIME] = when
+ $P1[.PARROT_ALARM_SUB] = proc
+
+ $P1()
+.end
+
+.sub inc_A
+ $P0 = get_global 'A'
+ $P0 = $P0 + 1
+ set_global 'A', $P0
+ .return($P0)
+.end
+
+.sub alarm1
+ $P0 = inc_A()
+
+ if $P0 == 1 goto a1_good
+ ok(0, "alarm 1")
+ .return()
+
+a1_good:
+ ok(1, "alarm 1")
+ .return()
+.end
+
+.sub alarm2
+ $P0 = inc_A()
+
+ if $P0 == 2 goto a1_good
+ ok(0, "alarm 2")
+ .return()
+
+a1_good:
+ ok(1, "alarm 2")
+ .return()
+.end
+
+.sub alarm3
+ $P0 = inc_A()
+
+ if $P0 == 3 goto a1_good
+ ok(0, "alarm 3")
+ .return()
+
+a1_good:
+ ok(1, "alarm 3")
+ .return()
+.end
+
+.sub alarm4
+ $P0 = inc_A()
+
+ if $P0 == 4 goto a1_good
+ ok(0, "alarm 4")
+ .return()
+
+a1_good:
+ ok(1, "alarm 4")
+ .return()
+.end
+
+.sub alarm_finish
+ $N0 = time
+
+ $P0 = get_global 'FT'
+ $N1 = $P0
+
+ if $N0 < $N1 goto fail
+ $N1 = $N1 + 0.5
+ if $N0 > $N1 goto fail
+
+ ok(1, "Alarm/sleep interaction")
+ exit 0
+
+fail:
+ ok(0, "Alarm/sleep interaction")
+.end
More information about the parrot-commits
mailing list