Ok, here is my first attempt. White the patch below oskit-mach should 
work. Unfortunately there is a (some?) bug(s). Under heavy net load 
oskit-mach traps after some time. Maybe someone know what I have done wrong.

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 -c -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/09/20 18:27:09
***************
*** 21,26 ****
--- 21,27 ----
  #include <oskit/dev/dev.h>
  
  #include <oskit/machine/pc/pit.h>
+ #include <oskit/machine/base_irq.h> /* base_irq_softint_* */
  
  #include <machine/mach_param.h>       /* HZ */
  #include <machine/spl.h>
*************** softclock_oskit (void)
*** 53,59 ****
        osenv_intr_disable();
        for (th = timer_head; th; th = th->next)
                (*th->func)();
!       osenv_intr_enable();
  }
  
  /*
--- 54,65 ----
        osenv_intr_disable();
        for (th = timer_head; th; th = th->next)
                (*th->func)();
! 
!       base_irq_softint_disable ();
!       softint_handler (NULL);
!       base_irq_softint_enabled ();
! 
!       osenv_intr_enable ();
  }
  
  /*




*** /dev/null   Wed May  2 00:58:33 2001
--- osenv_softirq.c     Thu Sep 20 18:01:18 2001
***************
*** 0 ****
--- 1,287 ----
+ /*
+  * 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.
+  */
+ 
+ /*
+  * Software Interrupt management.
+  */
+ #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;
+ 
+ /*
+  * 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 (!base_irq_softint_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;
+   base_irq_softint_disable();
+   osenv_mem_free(temp, 0, sizeof(struct softint_handler));
+ }
+ 
+ static spl_t osenv_intr_spl;
+ 
+ /*
+  * 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);
+   base_irq_softint_request(); 
+ 
+   setsoftclock ();
+ }
+ 
+ /*
+  * These chain to the base_irq_softint routines. They are the equiv
+  * of osenv_intr_enable() and osenv_intr_disable().
+  */
+ extern spl_t curr_ipl;
+ void
+ osenv_softintr_enable(void)
+ {
+   spl_t s = osenv_intr_spl;
+   osenv_intr_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_intr_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_intr_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