Permalink
Browse files

Add alarm mechanism; not yet hooked into anything.

git-svn-id: https://svn.parrot.org/parrot/branches/gsoc_threads@47764 d31e2699-5ff4-0310-a27c-f18f2fbe73fe
  • Loading branch information...
1 parent 6871248 commit eb03064daa8b59eead8ef1f88bc417c84d783632 @NatTuck NatTuck committed Jun 22, 2010
Showing with 1,006 additions and 0 deletions.
  1. +5 −0 config/gen/makefiles/root.in
  2. +40 −0 include/parrot/alarm.h
  3. +24 −0 include/parrot/alarm_private.h
  4. +194 −0 src/alarm.c
  5. +4 −0 src/main.c
  6. +62 −0 src/pmc/alarmtest.pmc
  7. +481 −0 src/pmc/pmclist.pmc
  8. +2 −0 src/pmc/scheduler.pmc
  9. +9 −0 src/scheduler.c
  10. +185 −0 t/pmc/pmclist.t
@@ -445,6 +445,7 @@ INTERP_O_FILES = \
src/exit$(O) \
src/extend$(O) \
src/extend_vtable$(O) \
+ src/alarm$(O) \
src/gc/alloc_memory$(O) \
src/gc/api$(O) \
src/gc/gc_ms$(O) \
@@ -915,6 +916,10 @@ src/scheduler$(O) : $(PARROT_H_HEADERS) src/scheduler.str src/scheduler.c \
$(INC_DIR)/scheduler_private.h \
$(INC_DIR)/runcore_api.h
+src/alarm$(O) : $(PARROT_H_HEADERS) src/alarm.c \
+ $(INC_DIR)/alarm.h \
+ $(INC_DIR)/alarm_private.h
+
src/io/core$(O) : $(PARROT_H_HEADERS) src/io/io_private.h src/io/core.c
src/io/socket_api$(O) : $(PARROT_H_HEADERS) src/io/io_private.h \
View
@@ -0,0 +1,40 @@
+/*
+Copyright (C) 2010, Parrot Foundation.
+$Id$
+*/
+
+#ifndef PARROT_ALARM_H_GUARD
+#define PARROT_ALARM_H_GUARD
+
+typedef unsigned int Parrot_alarm_state;
+
+/* HEADERIZER BEGIN: src/alarm.c */
+/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
+
+PARROT_EXPORT
+void Parrot_alarm_init(void);
+
+PARROT_EXPORT
+void Parrot_alarm_set(FLOATVAL when);
+
+PARROT_EXPORT
+int Parrot_alarm_check(Parrot_alarm_state* last_serial);
+
+void Parrot_alarm_callback(NULLOK(int sig_number));
+void Parrot_alarm_set(FLOATVAL wait);
+#define ASSERT_ARGS_Parrot_alarm_init __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
+#define ASSERT_ARGS_Parrot_alarm_set __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
+#define ASSERT_ARGS_Parrot_alarm_triggered __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
+#define ASSERT_ARGS_Parrot_alarm_callback __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
+#define ASSERT_ARGS_Parrot_alarm_set __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
+/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
+/* HEADERIZER END: src/alarm.c */
+
+#endif /* PARROT_ALARM_H_GUARD */
+
+/*
+ * Local variables:
+ * c-file-style: "parrot"
+ * End:
+ * vim: expandtab shiftwidth=4:
+ */
@@ -0,0 +1,24 @@
+/*
+Copyright (C) 2010, Parrot Foundation.
+$Id$
+*/
+
+#ifndef PARROT_ALARM_PRIVATE_GUARD_H
+#define PARROT_ALARM_PRIVATE_GUARD_H
+
+#include "parrot.h"
+
+typedef struct Parrot_alarm_queue {
+ FLOATVAL when;
+ int alarm_set;
+ struct Parrot_alarm_queue *next;
+} Parrot_alarm_queue;
+
+#endif /* PARROT_ALARM_PRIVATE_GUARD_H */
+
+/*
+ * Local variables:
+ * c-file-style: "parrot"
+ * End:
+ * vim: expandtab shiftwidth=4:
+ */
View
@@ -0,0 +1,194 @@
+/*
+Copyright (C) 2010, Parrot Foundation.
+$Id$
+
+=head1 NAME
+
+src/alarm.c - Implements a mechanism for alarms, setting a flag after a delay.
+
+=cut
+
+*/
+
+#include "parrot/alarm_private.h"
+#include "parrot/alarm.h"
+
+/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
+/* HEADERIZER END: src/alarm.c */
+
+/* Some per-process state */
+static Parrot_alarm_queue* alarm_queue;
+static volatile unsigned int alarm_serial;
+
+/* This file relies on POSIX. Probably need two other versions of it:
+ * one for Windows and one for platforms with no signals or threads. */
+#include <sys/time.h>
+#include <signal.h>
+#include <errno.h>
+
+/* HEADERIZER HFILE: include/parrot/alarm.h */
+
+/*
+=head1 Parrot_alarm_init()
+
+Initialize the alarm queue. This function should only be called from the initial
+pthread. Any other pthreads should make sure to mask out SIGALRM.
+
+=cut
+*/
+
+void Parrot_alarm_callback(SHIM(int sig_number));
+
+PARROT_EXPORT
+void
+Parrot_alarm_init(void)
+{
+ struct sigaction sa;
+ sa.sa_handler = Parrot_alarm_callback;
+ sa.sa_flags = SA_RESTART;
+
+ if(sigaction(SIGALRM, &sa, 0) == -1) {
+ perror("sigaction failed in Parrot_timers_init");
+ exit(EXIT_FAILURE);
+ }
+
+ alarm_serial = 1;
+ alarm_queue = NULL;
+}
+
+/*
+=head1 Parrot_alarm_set(FLOATVAL when)
+
+A helper function to set an alarm.
+
+=cut
+*/
+
+static void
+set_posix_alarm(FLOATVAL wait)
+{
+ const int MIL = 1000000;
+ struct itimerval itmr;
+ int sec, usec;
+
+ sec = (int) wait;
+ usec = (int) ((wait - sec) * MIL);
+
+ itmr.it_value.tv_sec = sec;
+ itmr.it_value.tv_usec = usec;
+ 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);
+ }
+}
+
+
+/*
+=head1 Parrot_alarm_callback()
+
+Callback for SIGALRM. When this is called, a timer should be ready to fire.
+
+=cut
+*/
+
+void
+Parrot_alarm_callback(SHIM(int sig_number))
+{
+ 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;
+
+ // Find the first future item.
+ now = Parrot_floatval_time();
+ while(alarm_queue != NULL && alarm_queue->when < now) {
+ qp = alarm_queue->next;
+ free(alarm_queue);
+ alarm_queue = qp;
+ }
+
+ if(alarm_queue != NULL && alarm_queue->alarm_set == 0) {
+ wait = alarm_queue->when - now;
+ set_posix_alarm(wait);
+ qp->alarm_set = 1;
+ }
+}
+
+/*
+=head1 Parrot_alarm_check(Parrot_alarm_state*)
+
+Has any alarm triggered since we last checked?
+
+Possible design improvement: Alert only the thread that
+set the alarm.
+
+=cut
+*/
+
+PARROT_EXPORT
+int
+Parrot_alarm_check(Parrot_alarm_state* last_serial)
+{
+ if(*last_serial == alarm_serial) {
+ return 0;
+ } else {
+ *last_serial = alarm_serial;
+ return 1;
+ }
+}
+
+/*
+=head1 Parrot_alarm_set(FLOATVAL when)
+
+Sets an alarm to trigger at time 'when'.
+
+=cut
+*/
+
+PARROT_EXPORT
+void
+Parrot_alarm_set(FLOATVAL when) {
+ Parrot_alarm_queue *new_alarm;
+ Parrot_alarm_queue **qpp;
+ FLOATVAL now;
+
+ /* Better late than early */
+ when += 0.0001;
+
+ now = Parrot_floatval_time();
+
+ new_alarm = (Parrot_alarm_queue*) malloc(sizeof(Parrot_alarm_queue));
+ new_alarm->when = when;
+
+ 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;
+ }
+
+ qpp = &alarm_queue;
+ while(*qpp != NULL && (*qpp)->when < when) {
+ qpp = &(alarm_queue->next);
+ }
+
+ new_alarm->next = *qpp;
+ new_alarm->alarm_set = 0;
+ *qpp = new_alarm;
+}
+
+/*
+ * Local variables:
+ * c-file-style: "parrot"
+ * End:
+ * vim: expandtab shiftwidth=4:
+ */
View
@@ -25,6 +25,7 @@ Start Parrot
#include "parrot/imcc.h"
#include "parrot/longopt.h"
#include "parrot/runcore_api.h"
+#include "parrot/alarm.h"
#include "pmc/pmc_callcontext.h"
/* For gc_sys_type_enum */
@@ -136,6 +137,9 @@ main(int argc, const char *argv[])
/* 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);
View
@@ -0,0 +1,62 @@
+
+#include "parrot/alarm.h"
+
+/* HEADERIZER HFILE: none */
+/* HEADERIZER BEGIN: static */
+/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
+
+/* blah */
+
+/* HEADERIZER END: static */
+
+pmclass AlarmTest auto_attrs {
+ ATTR INTVAL id;
+ ATTR INTVAL n;
+ ATTR FLOATVAL set;
+
+ VTABLE void init() {
+ fprintf(stderr, "Made an AlarmTest\n");
+ }
+
+ VTABLE STRING *get_string() {
+ char blah[] = "blah";
+ return Parrot_str_new(interp, blah, strlen(blah));
+ }
+
+ METHOD wonk() {
+ fprintf(stderr, "Wonk\n");
+ }
+
+ METHOD set_alarm(FLOATVAL t) {
+ FLOATVAL now, when;
+ Parrot_AlarmTest_attributes* attrs;
+
+ now = Parrot_floatval_time();
+ when = now + t;
+ Parrot_alarm_set(when);
+
+ attrs = PMC_data_typed(SELF, Parrot_AlarmTest_attributes *);
+ attrs->set = when;
+
+ fprintf(stderr, "At %.06lf set alarm for %.06lf\n", now, when);
+ }
+
+ METHOD check_alarm() {
+ FLOATVAL now;
+ Parrot_AlarmTest_attributes* attrs;
+ INTVAL changed = 0;
+
+ attrs = PMC_data_typed(SELF, Parrot_AlarmTest_attributes *);
+
+ if(Parrot_alarm_check(&(attrs->n))) {
+ now = Parrot_floatval_time();
+
+ fprintf(stderr, "At %.06lf maybe alarm.\n", now);
+
+ if(now > attrs->set)
+ changed = 1;
+ }
+
+ RETURN(INTVAL changed);
+ }
+}
Oops, something went wrong.

0 comments on commit eb03064

Please sign in to comment.