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