Hey all,

I redid all of the resource allocation stuff in
plugin.c.  A patch is attached.

IO ports are now handled as mentioned in my previous
email.  It looks complicated but it appears to work,
and should be pretty fast (try following the code
path in "neat", aligned cases.  It is minimal.)
I also redid the interrupt allocation.  I've given
up on unified allocation and moved everything into
separate functions.

This patch is on top of plex86-2000_0722b.tar.gz.

-- Ramon
diff -Nur plex86-old/kernel/nexus.S plex86/kernel/nexus.S
--- plex86-old/kernel/nexus.S   Mon Jul 31 19:30:49 2000
+++ plex86/kernel/nexus.S       Mon Jul 31 19:32:06 2000
@@ -185,7 +185,7 @@
   // Switch to monitor stack and CS
   // and jump to the monitor-side nexus page
   lss   (MON_STACK_INFO)(%ebx), %esp
-  ljmp  *(MON_JMP_INFO)(%ebx)
+  ljmp  (MON_JMP_INFO)(%ebx)
 .globl __mon_cs
 __mon_cs:
 
@@ -280,7 +280,7 @@
 
   // Restore host stack and CS
   lss    (HOST_STACK_INFO)(%ebx), %esp
-  ljmp   *(HOST_JMP_INFO)(%ebx)
+  ljmp   (HOST_JMP_INFO)(%ebx)
 __host_cs:
 
   // Clear busy bit of the host TSS and switch to it
diff -Nur plex86-old/user/plugin.c plex86/user/plugin.c
--- plex86-old/user/plugin.c    Mon Jul 31 19:30:49 2000
+++ plex86/user/plugin.c        Tue Aug  1 00:13:54 2000
@@ -26,45 +26,14 @@
 #include "plugin.h"
 
 
-#define  BOVERLP(base1,range1,base2,range2) \
-               ((base2 >= base1) && (base2 < (base1+range1)))
-
-#define  TOVERLP(base1,range1,base2,range2) \
-               (((base2+range2) > base1) && ((base2+range2) <= (base1+range1)))
-
-#define  OVERLP(base1,range1,base2,range2) \
-               (BOVERLP(base1,range1,base2,range2) || 
TOVERLP(base1,range1,base2,range2))
-
-
-
-/************************************************************************/
-/* Declarations                                                         */
-/************************************************************************/
-
-static int plugin_emulate_int (int data, int op_size, int count, void *loc);
-
-static int plugin_alloc_int (event_t event, handler_t handler, int base, int range);
-static void plugin_free_int (callback_t *callback);
-
-
 
 /************************************************************************/
-/* Structures / Variables                                               */
+/* Plugin initialization / deinitialization                             */
 /************************************************************************/
 
-plugin_t *plugins     = NULL;  /* Head of the linked list of plugins  */
-
-callback_t *ioreads   = NULL;   /* Head of I/O read callback list      */
-callback_t *iowrites  = NULL;   /* Head of I/O write callback list     */
-callback_t *ints      = NULL;   /* Head of interrupt callback list     */
-
-static void (*save_funct)(Bit64u) = NULL;
+plugin_t *plugins = NULL;      /* Head of the linked list of plugins  */
 
 
-/************************************************************************/
-/* Plugin initialization / deinitialization                             */
-/************************************************************************/
-
 void
 plugin_load (char *name, char *args)
 {
@@ -80,7 +49,6 @@
 
     plugin->name = name;
     plugin->args = args;
-    plugin->callbacks = NULL;
     plugin->initialized = 0;
 
     plugin->handle = dlopen (name, RTLD_LAZY);
@@ -104,19 +72,25 @@
        exit (1);
     }
 
-    // Insert plugin at the _end_ of the plugin linked list.
+
+    /* Insert plugin at the _end_ of the plugin linked list. */
     plugin->next = NULL;
-    if (!plugins) {
-      // Empty list, this become the first entry.
-      plugins = plugin;
-      }
-    else {
-      plugin_t *temp = plugins;
-      // Non-empty list.  Add to end.
-      while (temp->next)
-        temp = temp->next;
-      temp->next = plugin;
-      }
+
+    if (!plugins)
+    {
+        /* Empty list, this become the first entry. */
+        plugins = plugin;
+    }
+    else
+    {
+        /* Non-empty list.  Add to end. */
+        plugin_t *temp = plugins;
+
+        while (temp->next)
+            temp = temp->next;
+
+        temp->next = plugin;
+    }
 
     return;
 }
@@ -167,14 +141,17 @@
 plugin_t *
 plugin_unload (plugin_t *plugin)
 {
+    int i;
     plugin_t *dead_plug;
-    callback_t *dead_call;
 
     if (plugin->initialized)
         plugin->fini ();
 
-    for (dead_call = plugin->callbacks; dead_call; dead_call = dead_call->next_plug)
-        plugin_free (dead_call);
+    /* XXX -- this is SLOW; any alternatives ?? */
+    plugin_free_inp  (plugin, 0, 65536);
+    plugin_free_outp (plugin, 0, 65536);
+    for (i=0; i<256; i++)
+        plugin_free_intr (plugin, i);
 
     dlclose (plugin->handle);
     free (plugin->name);
@@ -201,319 +178,497 @@
 
 
 /************************************************************************/
-/* Resource allocation                                                  */
+/* I/O port handling                                                    */
 /************************************************************************/
 
-callback_t *
-plugin_alloc (plugin_t *plugin, event_t event, handler_t handler, int base, int range)
-{
-    callback_t **list, *callback, *call2;
-    int (*plugin_evt_alloc) (event_t event, handler_t handler, int base, int range) = 
NULL;
+/*
+ *  I/O ports are allocated in a three-layered structure.  There is one
+ *  layer for 4-byte allocations, one layer for 2-byte allocations, and
+ *  one layer with 1-byte allocations.  When an I/O port is allocated,
+ *  the bottom (1-byte) layer is always updated.  It is then checked
+ *  whether the plugin has allocated two consecutive I/O ports (and they
+ *  do not cross an alignment boundary), in which case the plugin is
+ *  also entered into the layer above it.  The top layer is updated in
+ *  the case of the allocation of four consecutive ports (with correct
+ *  alignment).
+ *
+ *  When an I/O event comes in, we start at the layer which corresponds
+ *  to the opsize of the event (bottom layer for inb/outb, middle layer
+ *  for inw/outw, etc.)  If this layer contains an entry, the event is
+ *  send to the appropiate handler and we're finished.  If not, we break
+ *  up the request into two pieces and go down to the next layer.
+ *  Of course, the event is broken up immediately if it is not properly
+ *  aligned.
+ *
+ *  Note: unlike interrupts, only one device can allocate an I/O port
+ *  at any time (otherwise we have a conflict!).
+ */
 
+#define PORTS 65536
 
-    if (range == 0)
-    {
-        return NULL;
-    }
-
+static struct ioport_t
+{
+    plugin_t  *plugin;
+    handler_t  handler;
+}
+ilayer0[PORTS >> 0] = {{ NULL, NULL }},        /* input  Single-byte aligns */
+olayer0[PORTS >> 0] = {{ NULL, NULL }};        /* output Single-byte aligns */
 
-    switch (event)
-    {
-    case EVT_INPORT:
-        list = &ioreads;
-        break;
+static handler_t
+    ilayer1[PORTS >> 1] = { NULL },    /* input  Word alignment     */
+    olayer1[PORTS >> 1] = { NULL },    /* output Word alignment     */
+    ilayer2[PORTS >> 2] = { NULL },    /* input  Dword alignment    */
+    olayer2[PORTS >> 2] = { NULL };    /* output Dword alignment    */
 
-    case EVT_OUTPORT:
-        list = &iowrites;
-        break;
+static int
+io_sift_alloc_inp (plugin_t *plugin, handler_t handler, int port)
+{
+    if (ilayer0[port].plugin != NULL)
+        return -1;
 
-    case EVT_INT:
-        list = &ints;
-        plugin_evt_alloc = plugin_alloc_int;
-        break;
+    ilayer0[port].plugin  = plugin;
+    ilayer0[port].handler = handler;
 
-    default:
-        fprintf (stderr, "Error: plugin %s attempted to allocate non-implemented 
resource. Ignoring\n", plugin->name);
-        return NULL;
+    if (ilayer0[port | 0x1].handler == ilayer0[port & ~0x1].handler)
+    {
+        ilayer1[port >> 1] = handler;
     }
 
+    if (ilayer1[(port >> 1) | 0x1] == ilayer1[(port >> 1) & ~0x1])
+    {
+        ilayer2[port >> 2] = handler;
+    }
 
-    /* look for conflicting allocation */
+    return 0;
+}
 
-    if (conflict[event])
-        for (call2 = *list; call2; call2 = call2->next_type)
-            if (OVERLP(call2->base, call2->range, base, range))
-            {
-                fprintf (stderr, "Conflict: plugin %s attempted to allocate busy 
resource. Ignoring\n", plugin->name);
-                return NULL;
-            }
+static int
+io_sift_alloc_outp (plugin_t *plugin, handler_t handler, int port)
+{
+    if (olayer0[port].plugin != NULL)
+        return -1;
 
+    olayer0[port].plugin  = plugin;
+    olayer0[port].handler = handler;
 
-    /* do event-specific allocation */
+    if (olayer0[port | 0x1].handler == olayer0[port & ~0x1].handler)
+    {
+        olayer1[port >> 1] = handler;
+    }
 
-    if (plugin_evt_alloc && plugin_evt_alloc (event, handler, base, range))
-        return NULL;
+    if (olayer1[(port >> 1) | 0x1] == olayer1[(port >> 1) & ~0x1])
+    {
+        olayer2[port >> 2] = handler;
+    }
 
+    return 0;
+}
 
-    /* allocate plugin */
+static int
+io_sift_free_inp (plugin_t *plugin, int port)
+{
+    if (ilayer0[port].plugin != plugin)
+        return -1;
 
-    callback = malloc (sizeof (callback_t));
-    callback->type    = event;
-    callback->handler = handler;
-    callback->base    = base;
-    callback->range   = range;
-    callback->plugin  = plugin;
+    ilayer0[port].plugin  = NULL;
+    ilayer0[port].handler = NULL;
 
+    ilayer1[port >> 1] = NULL;
+    ilayer2[port >> 2] = NULL;
 
-    /* put callback in linked list IN ORDER (this is important !!) */
+    return 0;
+}
 
-    call2 = *list;
-    if (call2 == NULL || base <= call2->base)
-    {
-        callback->next_type = *list;
-        *list = callback;
-    }
-    else
-        for (; ; call2 = call2->next_type)
-            if (call2->next_type == NULL || base <= call2->next_type->base)
-            {
-                callback->next_type = call2->next_type;
-                call2->next_type = callback;
-                break;
-            }
+static int
+io_sift_free_outp (plugin_t *plugin, int port)
+{
+    if (olayer0[port].plugin != plugin)
+        return -1;
 
+    olayer0[port].plugin  = NULL;
+    olayer0[port].handler = NULL;
 
-    /* we're done!! */
+    olayer1[port >> 1] = NULL;
+    olayer2[port >> 2] = NULL;
 
-    return callback;
+    return 0;
 }
 
-
-void
-plugin_free (callback_t *callback)
+static void
+io_rearrange_data (int op_size, int count, void *data)
+/*
+ *  We need io_rearrange_data() in order to split the data stream into
+ *  muliple data streams, which we use when we drop down a layer (see
+ *  plugin_emulate_inport() for more details).  This is the idea:
+ *  initially the data consist of low byte/word (o), high byte/word (x),
+ *  in this order:
+ *      oxoxoxoxox...
+ *  We want to rearrange it to look like
+ *      ooooo...xxxxx...
+ *  The algorithm used is simple but it work (check this for
+ *  yourself by drawing strings like the ones above on a piece of
+ *  paper and exchanging the o's and x's).
+ */
 {
-    callback_t **list, *next;
+#define EXCHG(dt,a,b) \
+    { dt tmp; tmp = *(dt *)a; *(dt *)a = *(dt *)b; *(dt *)b = tmp; }
 
+    int i, j;
 
-    switch (callback->type)
-    {
-    case EVT_INPORT:
-        list = &ioreads;
-        break;
+    if (count == 1)
+        return;
 
-    case EVT_OUTPORT:
-        list = &iowrites;
+    switch (op_size)
+    {
+    case 4:
+        for (i = 1; i < count; i++)
+            for (j = 0; j < i; j++)
+                EXCHG (short,
+                       & ((short *) data)[2 * i - j],
+                       & ((short *) data)[2 * i - 1 - j]);
         break;
 
-    case EVT_INT:
-        list = &ints;
-        plugin_free_int (callback);
+    case 2:
+        for (i = 1; i < count; i++)
+            for (j = 0; j < i; j++)
+                EXCHG (char,
+                       & ((char *) data)[2 * i - j],
+                       & ((char *) data)[2 * i - 1 - j]);
         break;
 
     default:
-        fprintf (stderr, "Error: attempted to free non-implemented resource. 
Ignoring\n");
-        return;
     }
 
+    return;
 
-    /* look for callback in callback list */
-
-    if (*list == callback)
-        *list = callback->next_type;
-    else
-        for (next = *list; next; next = next->next_type)
-            if (next->next_type == callback)
-                next->next_type = callback->next_type;
-
-
-    /* look for callback in plugin list */
-
-    if (callback->plugin->callbacks == callback)
-        callback->plugin->callbacks = callback->next_plug;
-    else
-        for (next = callback->plugin->callbacks; next; next = next->next_plug)
-            if (next->next_plug == callback)
-                next->next_plug = callback->next_type;
+#undef EXCHG
+}
 
 
-    /* clean up callback */
+int
+plugin_alloc_inp (plugin_t *plugin, handler_t handler, int base, int range)
+{
+    int port;
 
-    free (callback);
+    if (base+range > PORTS)
+    {
+        return -1;
+    }
 
+    for (port = base; port < base+range; port++)
+    {
+        if (ilayer0[port].plugin != NULL)
+            return -1;
+    }
 
-    /* we're done!! */
+    for (port = base; port < base+range; port++)
+    {
+        io_sift_alloc_inp (plugin, handler, port);
+    }
 
-    return;
+    return 0;
 }
 
 
 int
-plugin_alloc_int (event_t event, handler_t handler, int base, int range)
+plugin_alloc_outp (plugin_t *plugin, handler_t handler, int base, int range)
 {
-    int i;
+    int port;
 
-    for (i = base; i < base+range; i++)
-        if (vm_alloc_intr (i))
-        {
-            int j;
+    if (base+range > PORTS)
+    {
+        return -1;
+    }
 
-            for (j = base; j < i; j++)
-                vm_release_intr (j);
+    for (port = base; port < base+range; port++)
+    {
+        if (olayer0[port].plugin != NULL)
+            return -1;
+    }
 
-            return 1;
-        }
+    for (port = base; port < base+range; port++)
+    {
+        io_sift_alloc_outp (plugin, handler, port);
+    }
 
     return 0;
 }
 
+
 void
-plugin_free_int (callback_t *callback)
+plugin_free_inp (plugin_t *plugin, int base, int range)
 {
-    int j;
+    int port;
 
-    for (j = callback->base; j < callback->base+callback->range; j++)
-        vm_release_intr (j);
+    if (base+range > PORTS)
+    {
+        return;
+    }
+
+    for (port = base; port < base+range; port++)
+    {
+        io_sift_free_inp (plugin, port);
+    }
 
     return;
 }
 
 
-
-/************************************************************************/
-/* Event handling (plugin needs to handle evt / plugin generates evt)   */
-/************************************************************************/
-
-  int
-plugin_emulate (event_t event, int data, int op_size, int count, void *loc)
+void
+plugin_free_outp (plugin_t *plugin, int base, int range)
 {
-    switch (event)
-    {
-    case EVT_INPORT:
-        return plugin_emulate_inport (data, op_size, count, loc);
+    int port;
 
-    case EVT_OUTPORT:
-        return plugin_emulate_outport (data, op_size, count, loc);
-
-    case EVT_INT:
-        return plugin_emulate_int (data, op_size, count, loc);
+    if (base+range > PORTS)
+    {
+        return;
+    }
 
-    default:
-        fprintf (stderr, "Error: emulation of event %d not supported. Ignoring\n", 
(int) event);
-        return 0;
+    for (port = base; port < base+range; port++)
+    {
+        io_sift_free_outp (plugin, port);
     }
+
+    return;
 }
 
 
-  int
-plugin_emulate_inport (int data, int op_size, int count, void *loc)
+int
+plugin_emulate_inport (int port, int op_size, int count, void *loc)
 {
-    callback_t *next = ioreads;
+    int i;
+    int split = 1, split2 = 0;
 
-    unsigned handled = 0;
-    for (; next; next = next->next_type)
+    switch (op_size)
     {
-        int range;
+    case 4:
+        if (ilayer2[port >> 2] != NULL)
+        {
+            ilayer2[port >> 2] (EVT_INPORT, port, 4, count, loc);
+            break;
+        }
+
+        /* Rearrange data from 1 * op_size=4 to 2 * op_size=2 */
+
+        io_rearrange_data (4, count, loc);
+
+        /* Fallthrough to next layer */
 
-        if (BOVERLP(next->base, next->range, data, op_size))
+        split = 2;
+
+    case 2:
+        for (i = 0; i < split; i++)
         {
-            /* Find top limit */
-            if ((data + op_size) > (next->base + next->range))
-                range = next->base + next->range - data;
+            if (ilayer1[(port >> 1) + i] != NULL)
+            {
+                ilayer1[(port >> 1) + i] (EVT_INPORT,
+                                          port + i * 2,
+                                          2,
+                                          count / split,
+                                          loc  + i * (count / split));
+            }
             else
-                range = op_size;
+            {
+                split2 |= (i + 1);
+                io_rearrange_data (2, count / split,
+                                   loc + i * (count / split));
+            }
+        }
 
-            next->handler (EVT_INPORT, data, range, count, loc);
-            handled = 1;
+        if (split2 == 0)
+            break;
+
+        /* Fallthrough to next layer */
+
+        if (split2 == 3)
+            split = 4;
+        else if (split2 == 2)
+        {
+            port += 2;
+            loc  += (count / split);
         }
         else
-        if (TOVERLP(next->base, next->range, data, op_size))
-        {
-            /* We know base doesn't overlap, so use next->base as bottom limit.
-               We do need to recalculate the offset, though, and adjust loc */
-
-            int ofs = next->base - data;
-            range = op_size - ofs;
+            split = 2;
 
-            next->handler (EVT_INPORT, next->base, range, count, loc + ofs);
-            handled = 1;
+    case 1:
+        for (i = 0; i < split; i++)
+        {
+            if (ilayer0[port].handler != NULL)
+            {
+                ilayer0[port].handler (EVT_INPORT,
+                                       port + i,
+                                       1,
+                                       count / op_size,
+                                       loc  + i * (count / op_size));
+            }
         }
     }
-if (!handled) {
-  unsigned i;
-  fprintf(stderr, "inport 0x%x\n", data);
-  for (i=0; i<op_size; i++)
-    ((unsigned char *) loc)[i] = 0xff;
-  }
 
     return 0;
 }
 
 
-  int
-plugin_emulate_outport (int data, int op_size, int count, void *loc)
+int
+plugin_emulate_outport (int port, int op_size, int count, void *loc)
 {
-    callback_t *next = iowrites;
+    int i;
+    int split = 1, split2 = 0;
 
-    unsigned handled = 0;
-    for (; next; next = next->next_type)
+    switch (op_size)
     {
-        int range;
+    case 4:
+        if (olayer2[port >> 2] != NULL)
+        {
+            olayer2[port >> 2] (EVT_OUTPORT, port, 4, count, loc);
+            break;
+        }
+
+        /* Rearrange data from 1 * op_size=4 to 2 * op_size=2 */
+
+        io_rearrange_data (4, count, loc);
+
+        /* Fallthrough to next layer */
+
+        split = 2;
 
-        if (BOVERLP(next->base, next->range, data, op_size))
+    case 2:
+        for (i = 0; i < split; i++)
         {
-            /* Find top limit */
-            if ((data + op_size) > (next->base + next->range))
-                range = next->base + next->range - data;
+            if (olayer1[(port >> 1) + i] != NULL)
+            {
+                olayer1[(port >> 1) + i] (EVT_OUTPORT,
+                                          port + i * 2,
+                                          2,
+                                          count / split,
+                                          loc  + i * (count / split));
+            }
             else
-                range = op_size;
+            {
+                split2 |= (i + 1);
+                io_rearrange_data (2, count / split,
+                                   loc + i * (count / split));
+            }
+        }
+
+        if (split2 == 0)
+            break;
 
-            next->handler (EVT_OUTPORT, data, range, count, loc);
-            handled = 1;
+        /* Fallthrough to next layer */
+
+        if (split2 == 3)
+            split = 4;
+        else if (split2 == 2)
+        {
+            port += 2;
+            loc  += (count / split);
         }
         else
-        if (TOVERLP(next->base, next->range, data, op_size))
+            split = 2;
+
+    case 1:
+        for (i = 0; i < split; i++)
         {
-            /* We know base doesn't overlap, so use next->base as bottom limit.
-               We do need to recalculate the offset, though, and adjust loc */
+            if (olayer0[port].handler != NULL)
+            {
+                olayer0[port].handler (EVT_OUTPORT,
+                                       port + i,
+                                       1,
+                                       count / op_size,
+                                       loc  + i * (count / op_size));
+            }
+        }
+    }
 
-            int ofs = next->base - data;
-            range = op_size - ofs;
+    return 0;
+}
 
-            next->handler (EVT_OUTPORT, next->base, range, count, loc + ofs);
-            handled = 1;
-        }
+
+
+/************************************************************************/
+/* Software interrupt handling                                          */
+/************************************************************************/
+
+static struct intr_t
+{
+    plugin_t  *plugin;
+    handler_t  handler;
+    struct intr_t *next;
+}
+*ints[256] = { NULL };         /* Heads of linked lists for each int */
+
+
+int
+plugin_alloc_intr (plugin_t *plugin, handler_t handler, int vec)
+{
+    struct intr_t *intr;
+
+    for (intr = ints[vec]; intr != NULL; intr = intr->next)
+    {
+        if (intr->plugin == plugin)
+            return -1;
     }
-if (!handled)
-  fprintf(stderr, "outport 0x%x\n", data);
+
+    if (ints[vec] == NULL && vm_alloc_intr (vec))
+        return -1;
+
+    intr = malloc (sizeof (struct intr_t));
+    intr->plugin  = plugin;
+    intr->handler = handler;
+    intr->next    = ints[vec];
+    ints[vec]     = intr;
 
     return 0;
 }
 
 
-  int
-plugin_emulate_int (int data, int op_size, int count, void *loc)
+void
+plugin_free_intr (plugin_t *plugin, int vec)
 {
-    callback_t *next = ints;
-    int reflect = 0;
+    struct intr_t *intr, *dummy;
 
-    UNUSED(count);
-    UNUSED(loc);
-    UNUSED(op_size);
+    if ((intr = ints[vec]) == NULL)
+        return;
 
-    do
+    if (intr->plugin == plugin)
     {
-        for (; next; next = next->next_type)
-            if (data >= next->base && data < (next->base+next->range))
+       dummy = intr;
+       ints[vec] = intr->next;
+       free (dummy);
+    }
+    else
+        for (; intr != NULL; intr = intr->next)
+        {
+            if (intr->next == NULL)
                 break;
 
-        if (!next)
-            break;
+            if (intr->next->plugin == plugin)
+            {
+                dummy = intr->next;
+                intr->next = intr->next->next;
+                free (dummy);
 
-        if (next->handler (EVT_INT, data, 0, 0, NULL))
-            reflect = 1;
+                break;
+            }
+        }
+
+    if (ints[vec] == NULL)
+        vm_release_intr (vec);
+
+    return;
+}
 
-        next = next->next_type;
-    } while (!conflict[EVT_INT]);
+
+int
+plugin_emulate_int (int vec)
+{
+    struct intr_t *intr;
+    int reflect = 0;
+
+    for (intr = ints[vec]; intr != NULL; intr = intr->next)
+    {
+        if (intr->handler (EVT_INT, vec, 0, 0, NULL))
+            reflect = 1;
+    }
 
     return reflect;
 }
@@ -521,7 +676,7 @@
 
 
 /************************************************************************/
-/* Interrupt handling                                                   */
+/* Hardware interrupt handling                                          */
 /************************************************************************/
 
 static iac_handler_t plugin_iac_handler = NULL;
@@ -540,7 +695,7 @@
     if (plugin_iac_handler)
     {
         fprintf (stderr, "Two interrupt sources announced!\n");
-        vm_abort();
+        vm_abort ();
     }
 
     plugin_iac_handler = handler;
@@ -553,10 +708,10 @@
     if (!plugin_iac_handler)
     {
         fprintf (stderr, "No interrupt source was announced!\n");
-        vm_abort();
+        vm_abort ();
     }
 
-    return plugin_iac_handler();
+    return plugin_iac_handler ();
 }
 
 
@@ -578,7 +733,16 @@
 /* Plugin pending                                                       */
 /************************************************************************/
 
-struct plugin_pending
+/*
+ * NOTE:  This code was explicitly written to be reentrant using atomic
+ *        XCHG, because it will usually be called from signal handlers and
+ *        the like.  None of the other plugin functions are reentrant, so
+ *        a plugin wanting to perform plugin operations after reception
+ *        of a signal should always use these functions to pend for CPU
+ *        time.
+ */
+
+static struct plugin_pending
 {
     void (*func)(void);
     struct plugin_pending *next;
@@ -613,15 +777,25 @@
     return;
 }
 
-  void
-plugin_register_elapsed( void (*funct)(Bit64u) )
+
+
+/************************************************************************/
+/* Timing control                                                       */
+/************************************************************************/
+
+static void (*save_funct)(Bit64u) = NULL;
+
+
+void
+plugin_register_elapsed (void (*funct)(Bit64u))
 {
-  save_funct = funct;
+    save_funct = funct;
 }
 
-  void
-plugin_call_elapsed( Bit64u elapsed )
+
+void
+plugin_call_elapsed (Bit64u elapsed)
 {
-  if (save_funct)
-    save_funct(elapsed);
+    if (save_funct)
+        save_funct (elapsed);
 }
diff -Nur plex86-old/user/plugin.h plex86/user/plugin.h
--- plex86-old/user/plugin.h    Mon Jul 31 19:30:49 2000
+++ plex86/user/plugin.h        Mon Jul 31 23:59:16 2000
@@ -34,27 +34,12 @@
 
 typedef enum
 {
-    EVT_INPORT, EVT_OUTPORT, EVT_INT,
-    EVT_MAX
+    EVT_INPORT, EVT_OUTPORT, EVT_INT
 } event_t;
 
-static const int conflict[EVT_MAX] = { 1, 1, 1, };
-
 typedef int (*handler_t)
     (event_t event, int data, int op_size, int count, void *loc);
 
-struct _plugin_t;
-
-typedef struct _callback_t
-{
-    event_t   type;
-    handler_t handler;
-    int base, range;
-    struct _plugin_t   *plugin;
-    struct _callback_t *next_type;
-    struct _callback_t *next_plug;
-} callback_t;
-
 typedef struct _plugin_t
 {
     int  initialized;
@@ -63,7 +48,6 @@
     char *name, *args, *argv[MAX_ARGC];
     int  (*init)(struct _plugin_t *plugin, int argc, char *argv[]);
     void (*fini)(void);
-    callback_t *callbacks;
     struct _plugin_t *next;
 } plugin_t;
 
@@ -74,11 +58,15 @@
 void plugin_init_all (void);
 void plugin_fini_all (void);
 
-callback_t *plugin_alloc (plugin_t *plugin, event_t event, handler_t handler, int 
base, int range);
-void plugin_free  (callback_t *callback);
-int plugin_emulate (event_t event, int data, int op_size, int count, void *loc);
-int plugin_emulate_inport (int data, int op_size, int count, void *loc);
-int plugin_emulate_outport (int data, int op_size, int count, void *loc);
+int plugin_alloc_inp (plugin_t *plugin, handler_t handler, int base, int  range);
+int plugin_alloc_outp (plugin_t *plugin, handler_t handler, int base, int  range);
+void plugin_free_inp (plugin_t *plugin, int base, int range);
+void plugin_free_outp (plugin_t *plugin, int base, int range);
+int plugin_emulate_inport (int port, int op_size, int count, void *loc);
+int plugin_emulate_outport (int port, int op_size, int count, void *loc);
+int plugin_alloc_intr (plugin_t *plugin, handler_t handler, int vec);
+void plugin_free_intr (plugin_t *plugin, int vec);
+int plugin_emulate_int (int vec);
 
 typedef int  (*iac_handler_t)(void);
 typedef void (*plugin_pending_t)(void);
@@ -87,8 +75,8 @@
 void plugin_announce_iac_handler (iac_handler_t handler);
 void plugin_enqueue (plugin_pending_t func);
 void plugin_handle_pending (void);
-void plugin_register_elapsed( void (*funct)(Bit64u) );
-void plugin_call_elapsed( Bit64u elapsed );
+void plugin_register_elapsed (void (*funct)(Bit64u));
+void plugin_call_elapsed (Bit64u elapsed);
 
 void plugin_abort (void);
 
diff -Nur plex86-old/user/plugins/bochs/iodev/devices.cc 
plex86/user/plugins/bochs/iodev/devices.cc
--- plex86-old/user/plugins/bochs/iodev/devices.cc      Mon Jul 31 19:30:49 2000
+++ plex86/user/plugins/bochs/iodev/devices.cc  Tue Aug  1 00:06:54 2000
@@ -457,7 +457,7 @@
   read_handler_id[addr] = handle;
 
 #ifdef PLEX86
-  plugin_alloc (bx_plugin, EVT_INPORT, bx_plex86_io, (int) addr, 1);
+  plugin_alloc_inp (bx_plugin, bx_plex86_io, (int) addr, 1);
 #endif //PLEX86
 }
 
@@ -502,7 +502,7 @@
   write_handler_id[addr] = handle;
 
 #ifdef PLEX86
-  plugin_alloc (bx_plugin, EVT_OUTPORT, bx_plex86_io, (int) addr, 1);
+  plugin_alloc_outp (bx_plugin, bx_plex86_io, (int) addr, 1);
 #endif //PLEX86
 }
 
diff -Nur plex86-old/user/plugins/ice/server.c plex86/user/plugins/ice/server.c
--- plex86-old/user/plugins/ice/server.c        Mon Jul 31 19:30:49 2000
+++ plex86/user/plugins/ice/server.c    Tue Aug  1 00:16:26 2000
@@ -31,24 +31,27 @@
 int   old_thread_from_wait;
 int   port_num;
 
-callback_t *ice_exceptions;
+plugin_t *ice_plugin;
 
 int
 plugin_init (plugin_t *plugin, int argc, char *argv[])
 {
+    int i;
+
     if (argc < 1)
     {
        fprintf (stderr, "ice: usage: plugin = plugin-ice.so port");
         return 1;
     }
 
-    port_num = atoi (argv[0]);
+    ice_plugin = plugin;
+    port_num   = atoi (argv[0]);
 
-    if (!(ice_exceptions = plugin_alloc (plugin, EVT_INT, mywait, 0, 17)))
-    {
-        fprintf(stderr, "ice: failed allocation of exceptions; aborting\n");
-        return 1;
-    }
+    for (i = 0; i < 17; i++)
+        if (! plugin_alloc_intr (plugin, mywait, i))
+        {
+            fprintf(stderr, "ice: warning: failed allocation of interrupt 0x%x\n", i);
+        }
 
     fetch_inferior_registers (0);
 
@@ -61,7 +64,11 @@
 void
 plugin_fini (void)
 {
-    plugin_free (ice_exceptions);
+    int i;
+
+    for (i = 0; i < 17; i++)
+        plugin_free_intr (ice_plugin, i);
+
     remote_close ();
     return;
 }
diff -Nur plex86-old/user/user.c plex86/user/user.c
--- plex86-old/user/user.c      Mon Jul 31 19:30:49 2000
+++ plex86/user/user.c  Tue Aug  1 00:04:40 2000
@@ -236,7 +236,7 @@
         case VMMessageIOInRequest:
         {
             IO_msg_t *io_msg = (IO_msg_t *) user_msgs.msg;
-            plugin_emulate (EVT_INPORT, io_msg->port, io_msg->len, 1, &io_msg->data);
+            plugin_emulate_inport (io_msg->port, io_msg->len, 1, &io_msg->data);
 
             // Change message type; most data stays the same
             user_msgs.header.msg_type = VMMessageIOInResponse;
@@ -246,7 +246,7 @@
         case VMMessageIOOutRequest:
         {
             IO_msg_t *io_msg = (IO_msg_t *) user_msgs.msg;
-            plugin_emulate (EVT_OUTPORT, io_msg->port, io_msg->len, 1, &io_msg->data);
+            plugin_emulate_outport (io_msg->port, io_msg->len, 1, &io_msg->data);
 
             // No response required
             user_msgs.header.msg_type = VMMessageRunGuest;
@@ -267,7 +267,7 @@
         case VMMessageIntRequest:
         {
             INT_msg_t *int_msg = (INT_msg_t *) user_msgs.msg;
-            int_msg->reflect = plugin_emulate (EVT_INT, int_msg->vector, 0, 0, NULL);
+            int_msg->reflect = plugin_emulate_int (int_msg->vector);
 
             user_msgs.header.msg_type = VMMessageIntResponse;
             break;

Reply via email to