It's still working! And it's much more faster than before, since there are no
blockings in the traphandler anymore. I hope that's still correct. I also changed
all enable/disable calls from intr to softintr. 

> I'm glad to hear it's working for you, but that's still not quite the way
> I'd like to see it.  (The only errors I see are in the conservative
> direction, i.e. it works fine, it just blocks interrupts more of the time
> than it needs to.)  Again, thanks a lot for hacking on this and being so
> receptive to feedback about your code.

No problem at all. You know exactly how to do it. I don't, so listen to what you 
have to say and learn.

> Personally, I'd use ffs rather than iterating from 0 to check the mask (ffs
> is optimized to a single x86 instruction).

That's a really cool function!

wagi




Index: pc/osenv_timer.c
===================================================================
RCS file: /cvsroot/hurd/gnumach/oskit/pc/Attic/osenv_timer.c,v
retrieving revision 1.1.2.1
diff -p -u -r1.1.2.1 osenv_timer.c
--- pc/osenv_timer.c    1999/11/25 23:27:56     1.1.2.1
+++ pc/osenv_timer.c    2001/10/01 22:57:11
@@ -54,6 +54,8 @@ softclock_oskit (void)
        for (th = timer_head; th; th = th->next)
                (*th->func)();
        osenv_intr_enable();
+
+       softint_handler(NULL);
 }
 
 /*


--- /dev/null   Wed May  2 00:58:33 2001
+++ osenv_softirq.c     Tue Oct  2 00:57:56 2001
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2000 University of Utah and the Flux Group.
+ * All rights reserved.
+ * 
+ * This file is part of the Flux OSKit.  The OSKit is free software, also known
+ * as "open source;" you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License (GPL), version 2, as published by the Free
+ * Software Foundation (FSF).  To explore alternate licensing terms, contact
+ * the University of Utah at [EMAIL PROTECTED] or +1-801-585-3271.
+ * 
+ * The OSKit is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GPL for more details.  You should have
+ * received a copy of the GPL along with the OSKit; see the file COPYING.  If
+ * not, write to the FSF, 59 Temple Place #330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * oskit Software Interrupt management for Mach.
+ */
+
+#include <oskit/error.h>
+#include <oskit/debug.h>
+#include <oskit/dev/dev.h>
+#include <oskit/dev/softirq.h>
+#include <oskit/machine/base_irq.h>
+#include <stdio.h>
+#include <string.h> /* ffs */
+
+#include <machine/spl.h>
+#include "ds_oskit.h"
+
+
+/* Linked list of functions for a software interrupt.  */
+struct softint_handler {
+  void   (*func)(void *);
+  void   *data;
+  struct softint_handler *next;
+  int    flags;
+};
+
+/* Array of pointers to lists of interrupt handlers.  */
+static struct softint_handler *softint_handlers[SOFT_IRQ_COUNT];
+
+/* Mask of allocated vectors, for the benefit of osenv_softirq_request()  */
+static unsigned int softint_allocated = ((1 << OSENV_SOFT_IRQ_SOFTWARE) 
+                                        | (1 << OSENV_SOFT_IRQ_PTHREAD));
+                                        
+/* Pending softirqs that have been software scheduled.  */
+static volatile unsigned int softint_pending;
+                                        
+static spl_t osenv_softintr_spl;
+extern spl_t curr_ipl;
+
+/* This will override the stub function in the kernel library.  It is the
+   entrypoint from the hardware interrupt handler, and is invoked when
+   it is safe to deliver a software interrupt, and one or more software
+   interrupts is pending.  
+ 
+   Called with hardware interrupts enabled and software interrupts disabled.  
+   Upon return to the caller, hardware interrupts will be disabled again and
+   software interrupts will be renabled.  
+   
+   The handler will be invoked with hardware interrupts enabled.  Since
+   software interrupts are still disabled, if the handler results in a context
+   switch, software interrupts will need to be renabled.  The pthreads
+   code does this in its software interrupt handler, but I think thats the
+   wrong place since some other operation could result in a context switch,
+   which would leave softints disabled.  Perhaps there needs to be something
+   in the context switch code?
+   
+   A software interrupt handler should obviously not allocate or deallocate
+   a software interrupt.  It may schedule one of course.  */
+void
+softint_handler (struct trap_state *ts)
+{
+  while (softint_pending) 
+    {
+      int i;
+      struct softint_handler *current;
+      
+      i = ffs (softint_pending) - 1;
+      if (softint_pending & (1 << i))
+       {
+         softint_pending &= ~(1 << i);
+         
+         current = softint_handlers[i];
+         while (current) 
+           {
+             current->func (current->data);
+             current = current->next;
+           }
+       }
+    }  
+}
+
+
+/* Allocate a (well-known) software interrupt handler.  */
+oskit_error_t
+osenv_softirq_alloc (int irq, void (*handler)(void *), void *data, int flags)
+{
+  struct softint_handler *temp, **p;
+
+  if (irq < 0 || irq >= SOFT_IRQ_COUNT)
+    return OSKIT_EINVAL;
+  
+  /* Do this to ensure that the free vectors are explicitly allocated
+     before having a handler assigned.  */
+  if ((irq >= SOFT_IRQ_FREEBASE) && !(softint_allocated & (1 << irq)))
+    return OSKIT_EINVAL;
+  
+  /* This is a blocking operation, so to avoid races we need to do it
+     before we start mucking with data structures.  */
+  temp = osenv_mem_alloc (sizeof(struct softint_handler), 0, 1);
+  if (temp == NULL) 
+    return OSKIT_ENOMEM;
+  temp->func = handler;
+  temp->data = data;
+  temp->next = NULL;
+  temp->flags = flags;
+  
+  /* Do this first.  */
+  base_irq_softint_handler = softint_handler;
+  
+  /* Note that we only hook in the new handler after its structure has been 
+     fully initialized;  this way we don't have to disable interrupts, because 
+     interrupt-level code only scans the list.  */
+  for (p = &softint_handlers[irq]; *p != NULL; p = &(*p)->next)
+    ;
+  *p = temp;
+  
+  return 0;
+}
+
+/*  Request an unused software interrupt handler vector. This just reserves
+    and returns the vector number for use with osenv_softirq_alloc() above. */
+oskit_error_t
+osenv_softirq_alloc_vector (int *out_irq)
+{
+  int i, enabled;
+  
+  /* Go ahead and block interrupts, cause its easy.  */
+  enabled = osenv_softintr_enabled ();
+  if (enabled)
+    osenv_softintr_disable ();
+  
+  /*  Search for an empty slot above the well-known vectors.  */
+  for (i = SOFT_IRQ_FREEBASE; i < SOFT_IRQ_COUNT; i++) 
+    {
+      if (! (softint_allocated & (1 << i)))
+       break;
+    }
+  if (i == SOFT_IRQ_COUNT) 
+    {
+      if (enabled)
+       osenv_softintr_enable ();
+      return OSKIT_ERANGE;
+    }
+  
+  softint_allocated |= (1 << i);
+  *out_irq = i;
+  
+  if (enabled)
+    osenv_softintr_enable ();
+  return 0;
+}
+
+/* Free up a vector.  */
+oskit_error_t
+osenv_softirq_free_vector (int irq)
+{
+  /* Must be allocated */
+  if (! (softint_allocated & (1 << irq)))
+    return OSKIT_EINVAL;
+  
+  /* Must no longer be in use */
+  if (softint_handlers[irq])
+    return OSKIT_EINVAL;
+  
+  softint_allocated &= ~(1 << irq);
+  
+  return 0;
+}
+
+/* Deallocate a software interrupt.  Need a handle so know WHICH 
+   interrupt handler to remove.  */
+void
+osenv_softirq_free (int irq, void (*handler)(void *), void *data)
+{
+  struct softint_handler *temp, **p;
+  
+  osenv_assert (irq >= 0 && irq < SOFT_IRQ_COUNT);
+  
+  /* Find and unlink the handler from the list.  */
+  p = &softint_handlers[irq];
+  while (((temp = *p) != NULL) 
+        && (temp->func != handler || temp->data != data))
+    p = &temp->next;
+  
+  /* not found?  */
+  if (temp == NULL) 
+    {
+      osenv_log (OSENV_LOG_WARNING,
+                "osenv_softirq_free: handler not registered!\n");
+      return;
+    }
+  
+  /* remove it!  */
+  *p = temp->next;
+  osenv_softintr_disable ();
+  osenv_mem_free (temp, 0, sizeof(struct softint_handler));
+}
+
+/* Schedule a software interrupt to be delivered next time its appropriate.  */
+void
+osenv_softirq_schedule (int irq)
+{
+  osenv_assert (softint_handlers[irq]);
+
+  softint_pending |= (1 << irq);
+  setsoftclock ();
+}
+
+void
+osenv_softintr_enable (void)
+{
+  spl_t s = osenv_softintr_spl;
+  osenv_softintr_spl = SPL1;
+  splx (s);
+}
+
+void
+osenv_softintr_disable (void)
+{
+  /* We can be called with interrupts already disabled!  */
+  if (curr_ipl > SPL1)
+    /* We are already at higher priority than oskit code normally runs.
+       I think this only happens in the calls from oskit_rtc_{get,set}.
+       On the assumption that osenv_intr_enable will be called in
+       parity from the sameqq interrupt level, we will want to stay at the
+       same high interrupt level.  */
+    osenv_softintr_spl = curr_ipl;
+  else if (curr_ipl < SPL1)
+    /* We are at a level where oskit interrupts are enabled, so we must go
+       to splio.  osenv_intr_enable we will return to the current level.  */
+    osenv_softintr_spl = splsoftclock ();
+}
+
+int
+osenv_softintr_enabled (void)
+{
+  return curr_ipl < SPL1;
+}


_______________________________________________
Bug-hurd mailing list
[EMAIL PROTECTED]
http://mail.gnu.org/mailman/listinfo/bug-hurd

Reply via email to