From ed03f3a3f0a5c3b55c21258770b4982d1a8e3ac3 Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Tue, 24 May 2005 21:22:05 +0000 Subject: [PATCH] (add missing file related to last commit) Get rid of bus_{disable,enable}_intr(), it wasn't generic enough for our needs. Implement some generic atomic.h functions to aid in the implementation of a low level mutex. Implement a generic low level sleep-mutex serializer, kern/lwkt_serialize.c. The serializer is designed to be a replacement for SPL calls but may also be used for other very low level work (e.g. lockmgr interlocks). Add a serializer argument to BUS_SETUP_INTR(). When non-NULL, the interrupt handler will no longer be protected by an SPL so e.g. spl*() will no longer protect against that device's interrupts. The IF queueing and dequeueing mechanisms may no longer depend on outside SPL state because network driver interrupt handlers are no longer required to enter splnet(). Use critical sections for the moment. The IFQ and IFF_OACTIVE interactions are not yet MP safe. --- sys/kern/lwkt_serialize.c | 136 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 sys/kern/lwkt_serialize.c diff --git a/sys/kern/lwkt_serialize.c b/sys/kern/lwkt_serialize.c new file mode 100644 index 0000000000..1ae4bc4b23 --- /dev/null +++ b/sys/kern/lwkt_serialize.c @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2005 The DragonFly Project. All rights reserved. + * + * This code is derived from software contributed to The DragonFly Project + * by Matthew Dillon + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name of The DragonFly Project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific, prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $DragonFly: src/sys/kern/lwkt_serialize.c,v 1.1 2005/05/24 21:22:05 dillon Exp $ + */ +/* + * This API provides a fast locked-bus-cycle-based serializer. It's + * basically a low level NON-RECURSIVE exclusive lock that can be held across + * a blocking condition. It is NOT a mutex. + * + * This serializer is primarily designed for low level situations and + * interrupt/device interaction. There are two primary facilities. First, + * the serializer facility itself. Second, an integrated interrupt handler + * disablement facility. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void lwkt_serialize_sleep(void *info); +static void lwkt_serialize_wakeup(void *info); + +void +lwkt_serialize_init(lwkt_serialize_t s) +{ + atomic_intr_init(&s->interlock); +#ifdef INVARIANTS + s->last_td = NULL; +#endif +} + +void +lwkt_serialize_enter(lwkt_serialize_t s) +{ +#ifdef INVARIANTS + KKASSERT(s->last_td != curthread); +#endif + atomic_intr_cond_enter(&s->interlock, lwkt_serialize_sleep, s); +#ifdef INVARIANTS + s->last_td = curthread; +#endif +} + +void +lwkt_serialize_exit(lwkt_serialize_t s) +{ +#ifdef INVARIANTS + s->last_td = NULL; +#endif + atomic_intr_cond_exit(&s->interlock, lwkt_serialize_wakeup, s); +} + +/* + * Interrupt handler disablement support, used by drivers. Non-stackable + * (uses bit 30). + */ +void +lwkt_serialize_handler_disable(lwkt_serialize_t s) +{ + atomic_intr_handler_disable(&s->interlock); +} + +void +lwkt_serialize_handler_enable(lwkt_serialize_t s) +{ + atomic_intr_handler_enable(&s->interlock); +} + +void +lwkt_serialize_handler_call(lwkt_serialize_t s, void (*func)(void *), void *arg) +{ + if (atomic_intr_handler_is_enabled(&s->interlock)) { + atomic_intr_cond_enter(&s->interlock, lwkt_serialize_sleep, s); + if (atomic_intr_handler_is_enabled(&s->interlock) == 0) + func(arg); + atomic_intr_cond_exit(&s->interlock, lwkt_serialize_sleep, s); + } +} + +/* + * Helper functions + */ +static void +lwkt_serialize_sleep(void *info) +{ + lwkt_serialize_t s = info; + tsleep(s, 0, "slize", 0); +} + +static void +lwkt_serialize_wakeup(void *info) +{ + wakeup(info); +} + -- 2.41.0