# New Ticket Created by  Leopold Toetsch 
# Please include the string:  [perl #23039]
# in the subject line of all future correspondence about this issue. 
# <URL: http://rt.perl.org/rt2/Ticket/Display.html?id=23039 >


OK here it is.
Again the description for the record:

1) Initialization:
    - normal core: build op_func_table with all opcode #4 [1]
    - CG core: build ops_addr[] filled with this opcode
    - prederef cores: build a list of (backward) branch instructions
      and the opcode at that offset

2) When an events gets scheduled (signal handler) it calls the running
    core with:

     interpreter->op_func_table =
        init_func(interpreter, OPLIB_SET_CHK_EV_FT)->op_func_table;

    This replaces for normal and CG core the op_func_table or the
    ops_addr with that from 1)
    Prederefed cores get on all branch instruction from the list built
    in 1) an opcode #4 patched.

3) So when the next instruction (normal, CG core) or the branch
    instruction (prederefed cores) gets executed, first the op_func_table
    or the patched instructions are restored and then the event handler
    can be called.

This now works for all cores (except JIT[2]). It doesn't have any 
runtime penalty for an extra check if events are due.
[1] This opcode (check_event__) calls the actual event handling code
     and returns the same address, i.e. doesn't advance the PC.

[2] We could do the same here, but this needs cache sync for ARM and 
PPC, which may or may not be allowed in signal code.

Still needs some cleanup ...

leo


-- attachment  1 ------------------------------------------------------
url: http://rt.perl.org/rt2/attach/61323/45267/aa640c/event handling-2.patch

--- parrot/classes/timer.pmc    Thu Jul 17 15:46:23 2003
+++ parrot-leo/classes/timer.pmc        Thu Jul 17 17:55:17 2003
@@ -54,6 +54,7 @@
  * for now we keep all stuff inside the pmc
  */
 
+void do_alarm_handler(void);   /* XXX s. events.c */
 /* interface constants */
 /* &gen_from_enum(timer.pasm) */
 typedef enum {
@@ -203,7 +204,7 @@
        stop_sys_timer_ms(handle);
 }
 
-static void
+void
 do_alarm_handler(void)
 {
     parrot_timer_t *t;
@@ -211,6 +212,8 @@
     int recalc = 0;
 
     ms = get_sys_timer_ms(handle);
+    if (!ms)   /* no timer running */
+       return;
     for (t = rtimer; t; t = t->next) {
        if (!--t->ticks) {
            t->state = TIMER_STATE_FIRE;
--- parrot/config/gen/config_h/config_h.in      Sun Mar 16 12:12:04 2003
+++ parrot-leo/config/gen/config_h/config_h.in  Fri Jul 18 13:33:42 2003
@@ -106,7 +106,11 @@
 
 #define PARROT_CORE_OPLIB_NAME "core"
 #define PARROT_CORE_OPLIB_INIT Parrot_DynOp_core_${MAJOR}_${MINOR}_${PATCH}
+
 #define PARROT_CORE_PREDEREF_OPLIB_INIT 
Parrot_DynOp_core_prederef_${MAJOR}_${MINOR}_${PATCH}
+#define PARROT_CORE_SWITCH_OPLIB_INIT 
Parrot_DynOp_core_switch_${MAJOR}_${MINOR}_${PATCH}
+#define PARROT_CORE_CG_OPLIB_INIT Parrot_DynOp_core_cg_${MAJOR}_${MINOR}_${PATCH}
+#define PARROT_CORE_CG_OPLIB_INIT Parrot_DynOp_core_cg_${MAJOR}_${MINOR}_${PATCH}
 #define PARROT_CORE_CGP_OPLIB_INIT Parrot_DynOp_core_cgp_${MAJOR}_${MINOR}_${PATCH}
 
 #define INTVAL_FMT "${intvalfmt}"
--- parrot/core.ops     Fri Jul 18 07:34:06 2003
+++ parrot-leo/core.ops Fri Jul 18 16:41:24 2003
@@ -97,7 +97,7 @@
 }
 
 inline op check_events__() {
-  opcode_t *this = CUR_OPCODE;
+  opcode_t *this = CUR_OPCODE; /* repeat the same opcode */
   HANDLE_EVENTS(interpreter);
   goto ADDRESS(this);  /* force this being a branch op */
 }
--- parrot/events.c     Sun Jul 13 17:54:46 2003
+++ parrot-leo/events.c Fri Jul 18 16:41:19 2003
@@ -15,30 +15,76 @@
 #ifdef HAS_HEADER_SETJMP
 /* XXX s. exceptions.c */
 void do_exception(exception_severity severity, long error);
-void Parrot_init_signals(void);
 #endif
 
+void do_alarm_handler(void);   /* XXX s. timer.c */
+
+void Parrot_init_signals(Parrot_Interp);
+static Parrot_Interp the_interpreter;
+
+void
+Parrot_do_handle_events(Parrot_Interp interpreter)
+{
+    oplib_init_f init_func = interpreter->op_init_func;
+    interpreter->op_func_table =
+        init_func(interpreter, OPLIB_INIT)->op_func_table;
+    if (interpreter->has_events) {
+        fprintf(stderr, "got event\n");
+        --interpreter->has_events;
+        /* TODO pop event off the event queue */
+        /* case SIGALRM: */
+            do_alarm_handler();
+    }
+}
+
+/* synchronous event checker from check_event opcode */
+void
+Parrot_do_check_events(Parrot_Interp interpreter)
+{
+}
+
+/*
+ * next 2 are interrupt code
+ */
+
+static void
+enable_event_checker(Parrot_Interp interpreter) {
+    oplib_init_f init_func = interpreter->op_init_func;
+    interpreter->op_func_table =
+        init_func(interpreter, OPLIB_SET_CHK_EV_FT)->op_func_table;
+}
+
+#if defined(HAS_HEADER_SIGNAL) && defined(SIGFPE) && defined(SIGALRM)
 static void
 sig_handler(int signum)
 {
     switch (signum) {
-        default:
-#ifdef HAS_HEADER_SETJMP
-            /* quick hack to test signals and exceptions
-             */
+        /* can't return from that */
+        case SIGFPE:
             do_exception(0, -signum);
-#endif
+            break;
+        /* convert signal to an event */
+        default:
+            ++the_interpreter->has_events;
+            /* TODO place event in event queue */
+            enable_event_checker(the_interpreter);
+            fprintf(stderr, "got signal\n");
             break;
     }
 }
 
+#endif
+
 void
-Parrot_init_signals(void)
+Parrot_init_signals(Parrot_Interp interpreter)
 {
-    /* quick hack to test signals and exceptions
-     * s. t/op/hacks_4.pasm
-     */
-    /*    Parrot_set_sighandler(SIGFPE, sig_handler);*/
+    /* XXX actually the interpreter, that receives signals */
+    the_interpreter = interpreter;
+#if defined(HAS_HEADER_SIGNAL) && defined(SIGFPE) && defined(SIGALRM)
+    Parrot_set_sighandler(SIGFPE, sig_handler);
+    Parrot_set_sighandler(SIGALRM, sig_handler);
+    /* Parrot_set_sighandler(SIGINT, sig_handler); */
+#endif
 }
 
 /*
--- parrot/exceptions.c Wed Jul 16 22:00:36 2003
+++ parrot-leo/exceptions.c     Thu Jul 17 11:28:22 2003
@@ -194,7 +194,7 @@
     /* translate an absolute location in byte_code to an offset
      * used for resuming after an exception had occured
      */
-    switch (interpreter->flags) {
+    switch (interpreter->flags & PARROT_PREDEREF_FLAG) {
         case PARROT_PREDEREF_FLAG:
             offset = (void **)dest - interpreter->prederef_code;
         default:
--- parrot/include/parrot/events.h      Tue Jul 15 11:40:06 2003
+++ parrot-leo/include/parrot/events.h  Thu Jul 17 11:47:04 2003
@@ -13,10 +13,14 @@
 #if !defined(PARROT_EVENT_H_GUARD)
 #define PARROT_EVENT_H_GUARD
 
-#define CHECK_EVENTS(x)
-#define HANDLE_EVENTS(x)
+#define CHECK_EVENTS(x) \
+  if (x->has_events) \
+      Parrot_do_check_events(x)
+#define HANDLE_EVENTS(x) Parrot_do_handle_events(x)
 
-void Parrot_init_signals(void);
+void Parrot_init_signals(struct Parrot_Interp *);
+void Parrot_do_check_events(struct Parrot_Interp *);
+void Parrot_do_handle_events(struct Parrot_Interp *);
 
 #endif
 
--- parrot/include/parrot/interpreter.h Wed Jul 16 22:00:37 2003
+++ parrot-leo/include/parrot/interpreter.h     Fri Jul 18 12:57:43 2003
@@ -29,7 +29,9 @@
     PARROT_GC_DEBUG_FLAG = 0x80,  /* We're debugging memory management */
     PARROT_EXTERN_CODE_FLAG = 0x100,    /* reusing anothers interps code */
     PARROT_SWITCH_FLAG   = 0x200, /* We're using the switched runops */
-    PARROT_DESTROY_FLAG  = 0x400  /* the last interpreter shall cleanup */
+    PARROT_DESTROY_FLAG  = 0x400,  /* the last interpreter shall cleanup */
+    PARROT_RUN_CORE_FLAGS= 0x270  /* flags denoting run core */
+
 } Parrot_Interp_flag;
 
 /* &end_gen */
@@ -115,6 +117,7 @@
     op_info_t *op_info_table; /* Opcode info table (name, nargs, arg types) */
 
     op_func_t *op_func_table;
+    oplib_init_f op_init_func;
 
 #if 0
     str_func_t *string_funcs;
@@ -134,6 +137,7 @@
     /* the next items point to the real thngs, which are
      * in the byte_code_segment, that is currently executed */
     void **prederef_code;       /* The predereferenced code */
+    size_t *prederef_branches;  /* list of branch ops offsets in above */
     void *jit_info;             /* JITs data */
     size_t current_line;        /* Which line we're executing in the
                                  * source */
@@ -181,6 +185,8 @@
 /* 3:   PMC *Env;                    hash_like Env PMC */
 /* 4:   PMC *ParrotInterpreter       that's me */
     int has_early_DOD_PMCs;   /* Flag that some want immediate destruction */
+    volatile int has_events;    /* something arrived in the event queue */
+    struct QUEUE *event_queue;  /* the event queues */
 } Interp;
 
 /* &gen_from_enum(iglobals.pasm) */
@@ -233,6 +239,7 @@
 void Parrot_compreg(Parrot_Interp interpreter, STRING *type, PMC *func);
 INTVAL sysinfo_i(Parrot_Interp interpreter, INTVAL info_wanted);
 STRING *sysinfo_s(Parrot_Interp interpreter, INTVAL info_wanted);
+void turn_ev_check(Parrot_Interp interpreter, int on, int flag);
 
 #endif   /* Parrot core */
 
--- parrot/include/parrot/oplib.h       Fri Jan 17 21:41:38 2003
+++ parrot-leo/include/parrot/oplib.h   Fri Jul 18 09:31:47 2003
@@ -29,11 +29,18 @@
     size_t      op_count;
     op_info_t * op_info_table;
     void *      op_func_table;
+    void *      orig_func_table;
+    void *      check_func_table;
     int (*op_code)(const char * name, int full);
 } op_lib_t;
 
-/* when init = true initialize, else de_initialize */
-typedef op_lib_t *(*oplib_init_f)(int init);
+typedef op_lib_t *(*oplib_init_f)(struct Parrot_Interp*, int init);
+/* init may have these values: */
+typedef enum {
+    OPLIB_DEINIT,       /* cleanup */
+    OPLIB_INIT,         /* initialize, set std. func_table */
+    OPLIB_SET_CHK_EV_FT /* set all op functions to the event checker */
+} oplib_init_enum_t;
 
 #endif
 
--- parrot/interpreter.c        Wed Jul 16 22:00:36 2003
+++ parrot-leo/interpreter.c    Fri Jul 18 15:53:13 2003
@@ -58,7 +58,7 @@
     if (!init_func)
         internal_exception(1, "Invalid oplib, '%s' not exported\n",
                 init_func_name);
-    oplib = init_func(1);
+    oplib = init_func(interpreter, OPLIB_INIT);
     /* XXX now what
      * if oplib is a prederefed oplib, and matches the current
      * oplib, we would run it */
@@ -109,6 +109,7 @@
     for (i = 0; i < opinfo->arg_count; i++) {
         switch (opinfo->types[i]) {
         case PARROT_ARG_OP:
+            if (prederef_op_func)
             pc_prederef[i] = (void *)(ptrcast_t)prederef_op_func[pc[i]];
             break;
 
@@ -162,12 +163,6 @@
                                "Unhandled argtype %d\n",opinfo->types[i]);
             break;
         }
-
-        if (pc_prederef[i] == 0) {
-            internal_exception(INTERP_ERROR,
-                    "Prederef generated a NULL pointer for arg of type %d!\n",
-                    opinfo->types[i]);
-        }
     }
 
     return pc_prederef;
@@ -185,15 +180,18 @@
 init_prederef(struct Parrot_Interp *interpreter, int cgp)
 {
 #ifdef HAVE_COMPUTED_GOTO
-    oplib_init_f init_func = cgp ?
-        PARROT_CORE_CGP_OPLIB_INIT :
-        PARROT_CORE_PREDEREF_OPLIB_INIT;
+    oplib_init_f init_func =
+        cgp == PREDEREF_FOR_SWITCH ? PARROT_CORE_SWITCH_OPLIB_INIT :
+        cgp ? PARROT_CORE_CGP_OPLIB_INIT : PARROT_CORE_PREDEREF_OPLIB_INIT;
 #else
-    oplib_init_f init_func = PARROT_CORE_PREDEREF_OPLIB_INIT;
-    UNUSED(cgp);
+    oplib_init_f init_func =
+        cgp == PREDEREF_FOR_SWITCH ? PARROT_CORE_SWITCH_OPLIB_INIT :
+        PARROT_CORE_PREDEREF_OPLIB_INIT;
 #endif
-    interpreter->op_lib = init_func(1);
-    interpreter->op_lib->op_code = PARROT_CORE_OPLIB_INIT(1)->op_code;
+    interpreter->op_lib = init_func(interpreter, OPLIB_INIT);
+    interpreter->op_init_func = init_func;
+    interpreter->op_lib->op_code =
+        PARROT_CORE_OPLIB_INIT(interpreter, OPLIB_INIT)->op_code;
     if (interpreter->op_lib->op_count != interpreter->op_count)
         internal_exception(PREDEREF_LOAD_ERROR,
                 "Illegal op count (%d) in prederef oplib\n",
@@ -203,39 +201,91 @@
         size_t i;
         void **temp = (void **)Parrot_memalign_if_possible(256,
                 N * sizeof(void *));
+        size_t branch_list_size = N / 16;      /* estimated size */
+        /* TODO branches per code segment like prederef code */
+        size_t *branches = mem_sys_allocate(branch_list_size * sizeof(size_t));
+        size_t n_branches = 0;
 
-        for (i = 0; i < N; i++) {
-            temp[i] = (void *)(ptrcast_t)prederef;
-        }
+        opcode_t *pc = interpreter->code->cur_cs->base.data;
+        op_info_t *op_info;
 
         interpreter->prederef_code = temp;
+        interpreter->prederef_branches = branches;
         interpreter->code->cur_cs->prederef_code = temp;
-        if (cgp == PREDEREF_FOR_SWITCH) {
-            opcode_t *pc = interpreter->code->cur_cs->base.data;
-            size_t n;
             for (i = 0; i < N; ) {
+            size_t n;
+            /* prederef immediately all code */
                 prederef(temp, interpreter);
+            if (cgp == PREDEREF_FOR_SWITCH) {
                 *temp = (void**) *pc;
-                n = interpreter->op_info_table[*pc].arg_count;
-                pc += n;
-                i += n;
-                temp += n;
-            }
         }
 #ifdef HAVE_COMPUTED_GOTO
-        if (cgp == PREDEREF_FOR_CGP) {
-            opcode_t *pc = interpreter->code->cur_cs->base.data;
-            size_t n;
-            for (i = 0; i < N; ) {
-                prederef(temp, interpreter);
+            else if (cgp == PREDEREF_FOR_CGP) {
                 *temp = ((void**)(interpreter->op_lib->op_func_table)) [*pc];
-                n = interpreter->op_info_table[*pc].arg_count;
+            }
+            op_info = &interpreter->op_info_table[*pc];
+            n = op_info->arg_count;
+            /* if this is a backward branch, remember its position in
+             * the prederef code for event checking
+             */
+            if ((op_info->jump & PARROT_JUMP_RELATIVE)  &&
+                    op_info->types[n - 1] == PARROT_ARG_IC &&
+                    pc[n - 1] < 0) {
+                if (n_branches >= branch_list_size - 2) {
+                    branch_list_size *= 1.5;
+                    branches = mem_sys_realloc(branches,
+                            branch_list_size * sizeof(size_t));
+                }
+                /* location and opcode pairs */
+                branches[n_branches++] = i;
+                branches[n_branches++] = (size_t)(*temp);
+            }
                 pc += n;
                 i += n;
                 temp += n;
+#endif
             }
+        /* mark end of list */
+        branches[n_branches] = 0;
+    }
+}
+
+void
+turn_ev_check(Parrot_Interp interpreter, int on, int flag)
+{
+    size_t i, offs, code;
+    void *chk_op;
+
+    if (!interpreter->prederef_branches) {
+        /* called from first init before init_prederef */
+        return;
+    }
+    switch (flag) {
+        case PARROT_PREDEREF_FLAG:
+        case PARROT_PREDEREF_FLAG | PARROT_CGOTO_FLAG:
+            chk_op = ((void**)(interpreter->op_lib->op_func_table)) [4];
+            break;
+        case PARROT_SWITCH_FLAG:
+            chk_op = (void *) 4;
+            break;
+    }
+    for (i = 0; interpreter->prederef_branches[i]; i += 2) {
+        offs = interpreter->prederef_branches[i];
+        code = interpreter->prederef_branches[i+1];
+        switch (on) {
+            case 0:
+                /* disable (or initialize) event checker:
+                 * patch the original code at offset
+                 */
+                interpreter->prederef_code[offs] = (void *)code;
+                break;
+            default:
+                /* enable event checker
+                 * THIS CODE GETS CALLED FROM INETERRUPT (signal handler)
+                 */
+                interpreter->prederef_code[offs] = chk_op;
+                break;
         }
-#endif
     }
 }
 
@@ -247,7 +297,7 @@
 static void
 stop_prederef(struct Parrot_Interp *interpreter)
 {
-    (void) PARROT_CORE_PREDEREF_OPLIB_INIT(0);
+    (void) PARROT_CORE_PREDEREF_OPLIB_INIT(interpreter, OPLIB_DEINIT);
 }
 
 static opcode_t *
@@ -405,6 +455,8 @@
             /* clear stacktop, it gets set in runops_cgoto_core beyond the
              * opfunc table again, if the compiler supports nested funcs
              */
+            interpreter->op_init_func = PARROT_CORE_CG_OPLIB_INIT;
+            interpreter->op_init_func(interpreter, OPLIB_INIT);
 /* #ifdef HAVE_NESTED_FUNC */
 #ifdef __GNUC__
             interpreter->lo_var_ptr = 0;
@@ -577,7 +629,8 @@
     interpreter->ctx.intstack = intstack_new(interpreter);
 
     /* Load the core op func and info tables */
-    interpreter->op_lib = PARROT_CORE_OPLIB_INIT(1);
+    interpreter->op_lib = PARROT_CORE_OPLIB_INIT(interpreter, OPLIB_INIT);
+    interpreter->op_init_func = PARROT_CORE_OPLIB_INIT;
     interpreter->op_count = interpreter->op_lib->op_count;
     interpreter->op_func_table = interpreter->op_lib->op_func_table;
     interpreter->op_info_table = interpreter->op_lib->op_info_table;
@@ -614,7 +667,7 @@
     Parrot_unblock_GC(interpreter);
 
     /* all sys running, init the signal stuff */
-    Parrot_init_signals();
+    Parrot_init_signals(interpreter);
 
 #ifdef ATEXIT_DESTROY
     Parrot_on_exit(Parrot_really_destroy, (void*)interpreter);
@@ -682,7 +735,7 @@
         mem_sys_free(interpreter->profile);
 
     /* deinit op_lib */
-    (void) PARROT_CORE_OPLIB_INIT(0);
+    (void) PARROT_CORE_OPLIB_INIT(interpreter, OPLIB_DEINIT);
 
     /* XXX move this to register.c */
     {
--- parrot/ops2c.pl     Sun May 18 18:03:32 2003
+++ parrot-leo/ops2c.pl Fri Jul 18 12:21:39 2003
@@ -110,6 +110,17 @@
 # Print the preamble for the HEADER and SOURCE files:
 #
 
+my $core_enum_flag;
+if ($suffix eq '_cgp') {
+    $core_enum_flag = 'PARROT_PREDEREF_FLAG | PARROT_CGOTO_FLAG';
+}
+elsif ($suffix eq '_prederef') {
+    $core_enum_flag = 'PARROT_PREDEREF_FLAG';
+}
+elsif ($suffix eq '_switch') {
+    $core_enum_flag = 'PARROT_SWITCH_FLAG';
+}
+
 my $preamble = <<END_C;
 /*
  * !!!!!!!   DO NOT EDIT THIS FILE   !!!!!!!
@@ -123,12 +134,13 @@
 
 END_C
 
+
 print HEADER $preamble;
 print HEADER <<END_C;
 #include "parrot/parrot.h"
 #include "parrot/oplib.h"
 
-extern op_lib_t 
*Parrot_DynOp_${base}${suffix}_${major_version}_${minor_version}_${patch_version}(int 
init);
+extern op_lib_t 
*Parrot_DynOp_${base}${suffix}_${major_version}_${minor_version}_${patch_version}(struct
 Parrot_Interp *, int init);
 
 END_C
 my $cg_func = $suffix =~ /cgp/ ? 'cgp_' :
@@ -142,6 +154,13 @@
 }
 
 print SOURCE $preamble;
+if ($core_enum_flag) {
+    print SOURCE <<END_C;
+#define ENABLE_EV_CHECK(interp)  turn_ev_check(interp, 1, $core_enum_flag)
+#define DISABLE_EV_CHECK(interp) turn_ev_check(interp, 0, $core_enum_flag)
+END_C
+}
+
 print SOURCE <<END_C;
 #include "$include"
 
@@ -164,7 +183,7 @@
     opcode_t *cur_opcode = cur_op;
 #endif
 
-    static void *ops_addr[] = {
+    static void *rops_addr[] = {
 END_C
 
 } elsif ($suffix =~ /switch/) {
@@ -267,8 +286,15 @@
   NULL
 };
 
+    static void **ops_addr = rops_addr;
+
 /* #ifdef HAVE_NESTED_FUNC */
 #ifdef __GNUC__
+    /*
+     * this nested function is here to reduce the size of
+     * trace_system_stack - gcc has somewhere the jumptable
+     * in a stack frame
+     */
     static void _check(void);
     static void _check(void) {
        int lo_var_ptr;
@@ -277,13 +303,20 @@
     }
 #endif
 /* #endif */
+
+    if (cur_opcode == 0) {
+      /* set and report the default branch table */
+      return (opcode_t *)ops_addr = rops_addr;
+    }
+    else if (interpreter == (struct Parrot_Interp *) 1) {
+      /* set branch table to the passed address */
+      ops_addr = (void **)cur_opcode;
+      return cur_opcode;
+    }
 END_C
 }
-
 if ($suffix =~ /cgp/) {
     print SOURCE <<END_C;
-    if (cur_opcode == 0)
-      return (opcode_t *)ops_addr;
 #ifdef __GNUC__
 # ifdef I386
     else if (cur_opcode == (opcode_t *) 1)
@@ -553,28 +586,91 @@
   $num_ops,
   $op_info,
   $op_func,
+  $op_func,
+  NULL,
   $getop
 };
 
 op_lib_t *
-Parrot_DynOp_${base}${suffix}_${major_version}_${minor_version}_${patch_version}(int 
init) {
-    if (init) {
-
+Parrot_DynOp_${base}${suffix}_${major_version}_${minor_version}_${patch_version}(Parrot_Interp
 interpreter, int init) {
+    switch (init) {
 END_C
 
-if ($suffix =~ /cgp/) {
-print SOURCE <<END_C;
-       op_lib.op_func_table = (op_func_t *) cgp_$base(0, 0);
+if ($suffix eq '_cg') {
+    print SOURCE <<END_C;
+       case OPLIB_INIT:
+           op_lib.op_func_table = op_lib.orig_func_table =
+               (op_func_t *) $cg_func$base(0, 0);
+           /* set all op addresses to the event checker */
+           if (!op_lib.check_func_table) {
+               size_t i;
+               op_lib.check_func_table = mem_sys_allocate(
+                    sizeof(void *) * (1 + op_lib.op_count));
+               for (i = 0; i <= op_lib.op_count; i++)
+                   ((void **)op_lib.check_func_table)[i] =
+                   ((void **)op_lib.orig_func_table)[4];
+           }
+            break;
+       case OPLIB_SET_CHK_EV_FT:
+           /* tell the core, to switch addr table */
+           $cg_func$base(op_lib.check_func_table, (Parrot_Interp)1);
+           op_lib.op_func_table = op_lib.check_func_table;
+           break;
+END_C
+}
+elsif ($suffix eq '_cgp') {
+    print SOURCE <<END_C;
+       case OPLIB_INIT:
+           op_lib.op_func_table = op_lib.orig_func_table =
+               (op_func_t *) $cg_func$base(0, 0);
+           DISABLE_EV_CHECK(interpreter);
+            break;
+       case OPLIB_SET_CHK_EV_FT:
+           ENABLE_EV_CHECK(interpreter);
+            break;
+END_C
+}
+elsif ($suffix =~ /switch/ || $suffix eq '_prederef') {
+    print SOURCE <<END_C;
+       case OPLIB_INIT:
+           DISABLE_EV_CHECK(interpreter);
+            break;
+       case OPLIB_SET_CHK_EV_FT:
+           ENABLE_EV_CHECK(interpreter);
+            break;
+END_C
+}
+else {
+    print SOURCE <<END_C;
+       case OPLIB_INIT:
+           op_lib.op_func_table = op_lib.orig_func_table =
+               op_func_table;
+           /* set all op functions to the event checker */
+           if (!op_lib.check_func_table) {
+               size_t i;
+               op_lib.check_func_table = mem_sys_allocate(
+                    sizeof(op_func_t) * (1 + op_lib.op_count));
+               for (i = 0; i <= op_lib.op_count; i++)
+                   ((op_func_t **)op_lib.check_func_table)[i] =
+                   ((op_func_t **)op_lib.orig_func_table)[4];
+           }
+            break;
+       case OPLIB_SET_CHK_EV_FT:
+           op_lib.op_func_table = op_lib.check_func_table;
+           break;
 END_C
 }
 
 print SOURCE <<END_C;
-       return &op_lib;
-    }
-    else {
+       case OPLIB_DEINIT:
        hop_deinit();
+           if (op_lib.check_func_table) {
+               mem_sys_free(op_lib.check_func_table);
+               op_lib.check_func_table = NULL;
+           }
        return NULL;
     }
+    return &op_lib;
 }
 
 END_C
--- parrot/t/op/hacks.t Sun Jul 13 20:52:59 2003
+++ parrot-leo/t/op/hacks.t     Fri Jul 18 17:45:56 2003
@@ -1,6 +1,6 @@
 #! perl -w
 
-use Parrot::Test tests => 5;
+use Parrot::Test tests => 6;
 use Test::More;
 use Parrot::Config;
 
@@ -56,7 +56,7 @@
 }
 
 SKIP: {
-skip("no events yet", 2);
+skip("no events yet", 3) unless $^O eq 'linux';
 
 output_is(<<'CODE', <<OUT, "catch a SIGFPE");
     newsub P0, .Exception_Handler, _handler
@@ -100,6 +100,38 @@
 CODE
 catched it
 ok
+OUT
+
+output_is(<<'CODE', <<OUT, "SIGALRM - no event handler yet");
+.include "timer.pasm"
+.include "interpflags.pasm"
+        getinterp P0
+       set I0, P0[-1]  # get flags
+       band I0, .INTERPFLAG_PARROT_JIT_FLAG
+       unless I0, core_ok
+       print "Yep. It fails with JIT.\n"
+       end
+core_ok:
+       new P0, .Timer
+       set P0[.TIMER_NSEC], 0.2
+       set P0[.TIMER_REPEAT], 1
+       set P0[.TIMER_RUNNING], 1       # fires 2 times, 0.4 sec
+       time N1
+       null I10
+loop:  dec I10
+       time N2
+       sub N0, N2, N1
+       gt N0, 0.5, ex
+       if I10, loop
+ex:
+       printerr "fin\n"
+       end
+CODE
+got signal
+got event
+got signal
+got event
+fin
 OUT
 }
 

Reply via email to