Good news. The applied patch seems to work correctly. I tested oskit-mach 
for about an hour with a stress test. No panics:) 
Please look through the patch, and tell me how far away from a good patch
I am.

wagi



Index: osenv_timer.c
===================================================================
RCS file: /cvsroot/hurd/gnumach/oskit/pc/Attic/osenv_timer.c,v
retrieving revision 1.1.2.1
diff -p -c -r1.1.2.1 osenv_timer.c
*** osenv_timer.c       1999/11/25 23:27:56     1.1.2.1
--- osenv_timer.c       2001/09/29 11:40:09
*************** softclock_oskit (void)
*** 54,59 ****
--- 54,63 ----
        for (th = timer_head; th; th = th->next)
                (*th->func)();
        osenv_intr_enable();
+ 
+       osenv_softintr_disable();
+       softint_handler(NULL);
+       osenv_softintr_enable();
  }
  
  /*



*** /dev/null   Wed May  2 00:58:33 2001
--- osenv_softirq.c     Sat Sep 29 13:36:39 2001
***************
*** 0 ****
--- 1,261 ----
+ /*
+  * 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 <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)
+ {
+   osenv_intr_disable ();
+   
+   while (softint_pending) 
+     {
+       int i;
+       struct softint_handler *current;
+       
+       for (i = 0; i < SOFT_IRQ_COUNT; i++) 
+       {
+         if (softint_pending & (1 << i)) 
+           {
+             softint_pending &= ~(1 << i);
+             
+             current = softint_handlers[i];
+             osenv_intr_enable ();
+             while (current) 
+               {
+                 current->func (current->data);
+                 current = current->next;
+               }
+             osenv_intr_disable ();
+           }
+       }
+     }
+   
+   assert (!osenv_softintr_enabled ());
+   osenv_intr_enable ();
+ }
+ 
+ 
+ /* 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_intr_enabled ();
+   if (enabled)
+     osenv_intr_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_intr_enable ();
+       return OSKIT_ERANGE;
+     }
+   
+   softint_allocated |= (1 << i);
+   *out_irq = i;
+   
+   if (enabled)
+     osenv_intr_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 = SPL0;
+   splx (s);
+ }
+ 
+ void
+ osenv_softintr_disable (void)
+ {
+   /* We can be called with interrupts already disabled!  */
+   if (curr_ipl > SPLIO)
+     /* 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 < SPLIO)
+     /* 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 < SPLIO;
+ }


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

Reply via email to