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