Page MenuHomeFreeBSD

D16016.id44850.diff
No OneTemporary

D16016.id44850.diff

Index: sys/contrib/ck/include/ck_queue.h
===================================================================
--- sys/contrib/ck/include/ck_queue.h
+++ sys/contrib/ck/include/ck_queue.h
@@ -180,8 +180,14 @@
ck_pr_store_ptr(&(head)->cslh_first, elm); \
} while (0)
+#define CK_SLIST_INSERT_PREVPTR(prevp, slistelm, elm, field) do { \
+ (elm)->field.csle_next = (slistelm); \
+ ck_pr_fence_store(); \
+ ck_pr_store_ptr(prevp, elm); \
+} while (0)
+
#define CK_SLIST_REMOVE_AFTER(elm, field) do { \
- ck_pr_store_ptr(&(elm)->field.csle_next, \
+ ck_pr_store_ptr(&(elm)->field.csle_next, \
(elm)->field.csle_next->field.csle_next); \
} while (0)
@@ -190,7 +196,7 @@
CK_SLIST_REMOVE_HEAD((head), field); \
} else { \
struct type *curelm = (head)->cslh_first; \
- while (curelm->field.csle_next != (elm)) \
+ while (curelm->field.csle_next != (elm)) \
curelm = curelm->field.csle_next; \
CK_SLIST_REMOVE_AFTER(curelm, field); \
} \
@@ -199,6 +205,10 @@
#define CK_SLIST_REMOVE_HEAD(head, field) do { \
ck_pr_store_ptr(&(head)->cslh_first, \
(head)->cslh_first->field.csle_next); \
+} while (0)
+
+#define CK_SLIST_REMOVE_PREVPTR(prevp, elm, field) do { \
+ ck_pr_store_ptr(prevptr, (elm)->field.csle_next); \
} while (0)
#define CK_SLIST_MOVE(head1, head2, field) do { \
Index: sys/kern/kern_intr.c
===================================================================
--- sys/kern/kern_intr.c
+++ sys/kern/kern_intr.c
@@ -160,12 +160,13 @@
ie = ithd->it_event;
td = ithd->it_thread;
+ mtx_assert(&ie->ie_lock, MA_OWNED);
/* Determine the overall priority of this event. */
- if (TAILQ_EMPTY(&ie->ie_handlers))
+ if (CK_SLIST_EMPTY(&ie->ie_handlers))
pri = PRI_MAX_ITHD;
else
- pri = TAILQ_FIRST(&ie->ie_handlers)->ih_pri;
+ pri = CK_SLIST_FIRST(&ie->ie_handlers)->ih_pri;
/* Update name and priority. */
strlcpy(td->td_name, ie->ie_fullname, sizeof(td->td_name));
@@ -195,7 +196,7 @@
space = 1;
/* Run through all the handlers updating values. */
- TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) {
+ CK_SLIST_FOREACH(ih, &ie->ie_handlers, ih_next) {
if (strlen(ie->ie_fullname) + strlen(ih->ih_name) + 1 <
sizeof(ie->ie_fullname)) {
strcat(ie->ie_fullname, " ");
@@ -257,7 +258,7 @@
ie->ie_flags = flags;
ie->ie_irq = irq;
ie->ie_cpu = NOCPU;
- TAILQ_INIT(&ie->ie_handlers);
+ CK_SLIST_INIT(&ie->ie_handlers);
mtx_init(&ie->ie_lock, "intr event", NULL, MTX_DEF);
va_start(ap, fmt);
@@ -378,7 +379,7 @@
TAILQ_FOREACH(ie, &event_list, ie_list)
if (ie->ie_irq == irq &&
(ie->ie_flags & IE_SOFT) == 0 &&
- TAILQ_FIRST(&ie->ie_handlers) != NULL)
+ CK_SLIST_FIRST(&ie->ie_handlers) != NULL)
break;
mtx_unlock(&event_lock);
return (ie);
@@ -474,7 +475,7 @@
mtx_lock(&event_lock);
mtx_lock(&ie->ie_lock);
- if (!TAILQ_EMPTY(&ie->ie_handlers)) {
+ if (!CK_SLIST_EMPTY(&ie->ie_handlers)) {
mtx_unlock(&ie->ie_lock);
mtx_unlock(&event_lock);
return (EBUSY);
@@ -504,7 +505,7 @@
error = kproc_kthread_add(ithread_loop, ithd, &intrproc,
&td, RFSTOPPED | RFHIGHPID,
- 0, "intr", "%s", name);
+ 0, "intr", "%s", name);
if (error)
panic("kproc_create() failed with %d", error);
thread_lock(td);
@@ -539,6 +540,7 @@
enum intr_type flags, void **cookiep)
{
struct intr_handler *ih, *temp_ih;
+ struct intr_handler **prevptr;
struct intr_thread *it;
if (ie == NULL || name == NULL || (handler == NULL && filter == NULL))
@@ -561,9 +563,9 @@
/* We can only have one exclusive handler in a event. */
mtx_lock(&ie->ie_lock);
- if (!TAILQ_EMPTY(&ie->ie_handlers)) {
+ if (!CK_SLIST_EMPTY(&ie->ie_handlers)) {
if ((flags & INTR_EXCL) ||
- (TAILQ_FIRST(&ie->ie_handlers)->ih_flags & IH_EXCLUSIVE)) {
+ (CK_SLIST_FIRST(&ie->ie_handlers)->ih_flags & IH_EXCLUSIVE)) {
mtx_unlock(&ie->ie_lock);
free(ih, M_ITHREAD);
return (EINVAL);
@@ -588,14 +590,12 @@
}
/* Add the new handler to the event in priority order. */
- TAILQ_FOREACH(temp_ih, &ie->ie_handlers, ih_next) {
+ CK_SLIST_FOREACH_PREVPTR(temp_ih, prevptr, &ie->ie_handlers, ih_next) {
if (temp_ih->ih_pri > ih->ih_pri)
break;
}
- if (temp_ih == NULL)
- TAILQ_INSERT_TAIL(&ie->ie_handlers, ih, ih_next);
- else
- TAILQ_INSERT_BEFORE(temp_ih, ih, ih_next);
+ CK_SLIST_INSERT_PREVPTR(prevptr, temp_ih, ih, ih_next);
+
intr_event_update(ie);
CTR3(KTR_INTR, "%s: added %s to %s", __func__, ih->ih_name,
@@ -621,7 +621,7 @@
mtx_lock(&ie->ie_lock);
#ifdef INVARIANTS
- TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) {
+ CK_SLIST_FOREACH(ih, &ie->ie_handlers, ih_next) {
if (ih == cookie)
break;
}
@@ -721,15 +721,13 @@
return;
}
-
int
intr_event_remove_handler(void *cookie)
{
struct intr_handler *handler = (struct intr_handler *)cookie;
struct intr_event *ie;
-#ifdef INVARIANTS
struct intr_handler *ih;
-#endif
+ struct intr_handler **prevptr;
#ifdef notyet
int dead;
#endif
@@ -740,25 +738,26 @@
KASSERT(ie != NULL,
("interrupt handler \"%s\" has a NULL interrupt event",
handler->ih_name));
+
mtx_lock(&ie->ie_lock);
CTR3(KTR_INTR, "%s: removing %s from %s", __func__, handler->ih_name,
ie->ie_name);
-#ifdef INVARIANTS
- TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next)
+ CK_SLIST_FOREACH_PREVPTR(ih, prevptr, &ie->ie_handlers, ih_next) {
if (ih == handler)
- goto ok;
- mtx_unlock(&ie->ie_lock);
- panic("interrupt handler \"%s\" not found in interrupt event \"%s\"",
- ih->ih_name, ie->ie_name);
-ok:
-#endif
+ break;
+ }
+ if (ih == NULL) {
+ panic("interrupt handler \"%s\" not found in "
+ "interrupt event \"%s\"", handler->ih_name, ie->ie_name);
+ }
+
/*
* If there is no ithread, then just remove the handler and return.
* XXX: Note that an INTR_FAST handler might be running on another
* CPU!
*/
if (ie->ie_thread == NULL) {
- TAILQ_REMOVE(&ie->ie_handlers, handler, ih_next);
+ CK_SLIST_REMOVE_PREVPTR(prevptr, ih, ih_next);
mtx_unlock(&ie->ie_lock);
free(handler, M_ITHREAD);
return (0);
@@ -789,11 +788,12 @@
*/
atomic_store_rel_int(&ie->ie_thread->it_need, 1);
} else
- TAILQ_REMOVE(&ie->ie_handlers, handler, ih_next);
+ CK_SLIST_REMOVE_PREVPTR(prevptr, ih, ih_next);
thread_unlock(ie->ie_thread->it_thread);
while (handler->ih_flags & IH_DEAD)
msleep(handler, &ie->ie_lock, 0, "iev_rmh", 0);
intr_event_update(ie);
+
#ifdef notyet
/*
* XXX: This could be bad in the case of ppbus(8). Also, I think
@@ -801,8 +801,8 @@
* interrupt.
*/
dead = 1;
- TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) {
- if (!(ih->ih_flags & IH_FAST)) {
+ CK_SLIST_FOREACH(ih, &ie->ie_handlers, ih_next) {
+ if (ih->ih_handler != NULL) {
dead = 0;
break;
}
@@ -828,7 +828,7 @@
/*
* If no ithread or no handlers, then we have a stray interrupt.
*/
- if (ie == NULL || TAILQ_EMPTY(&ie->ie_handlers) ||
+ if (ie == NULL || CK_SLIST_EMPTY(&ie->ie_handlers) ||
ie->ie_thread == NULL)
return (EINVAL);
@@ -962,30 +962,35 @@
return (intr_event_remove_handler(cookie));
}
-
-/*
- * This is a public function for use by drivers that mux interrupt
- * handlers for child devices from their interrupt handler.
- */
-void
+static void
intr_event_execute_handlers(struct proc *p, struct intr_event *ie)
{
- struct intr_handler *ih, *ihn;
+ struct intr_handler *ih, *ihn, *ihp;
- TAILQ_FOREACH_SAFE(ih, &ie->ie_handlers, ih_next, ihn) {
+ ihp = NULL;
+ CK_SLIST_FOREACH_SAFE(ih, &ie->ie_handlers, ih_next, ihn) {
/*
* If this handler is marked for death, remove it from
* the list of handlers and wake up the sleeper.
*/
if (ih->ih_flags & IH_DEAD) {
mtx_lock(&ie->ie_lock);
- TAILQ_REMOVE(&ie->ie_handlers, ih, ih_next);
+ if (ihp == NULL)
+ CK_SLIST_REMOVE_HEAD(&ie->ie_handlers, ih_next);
+ else
+ CK_SLIST_REMOVE_AFTER(ihp, ih_next);
ih->ih_flags &= ~IH_DEAD;
wakeup(ih);
mtx_unlock(&ie->ie_lock);
continue;
}
+ /*
+ * Now that we know that the current element won't be removed
+ * update the previous element.
+ */
+ ihp = ih;
+
/* Skip filter only handlers */
if (ih->ih_handler == NULL)
continue;
@@ -1157,7 +1162,7 @@
#endif
/* An interrupt with no event or handlers is a stray interrupt. */
- if (ie == NULL || TAILQ_EMPTY(&ie->ie_handlers))
+ if (ie == NULL || CK_SLIST_EMPTY(&ie->ie_handlers))
return (EINVAL);
/*
@@ -1172,7 +1177,8 @@
critical_enter();
oldframe = td->td_intr_frame;
td->td_intr_frame = frame;
- TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) {
+
+ CK_SLIST_FOREACH(ih, &ie->ie_handlers, ih_next) {
if (ih->ih_filter == NULL) {
thread = 1;
continue;
@@ -1218,7 +1224,7 @@
if (ie->ie_post_filter != NULL)
ie->ie_post_filter(ie->ie_source);
}
-
+
/* Schedule the ithread if needed. */
if (thread) {
int error __unused;
@@ -1364,7 +1370,7 @@
db_printf("\n");
if (handlers)
- TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next)
+ CK_SLIST_FOREACH(ih, &ie->ie_handlers, ih_next)
db_dump_intrhand(ih);
}
@@ -1379,7 +1385,7 @@
verbose = strchr(modif, 'v') != NULL;
all = strchr(modif, 'a') != NULL;
TAILQ_FOREACH(ie, &event_list, ie_list) {
- if (!all && TAILQ_EMPTY(&ie->ie_handlers))
+ if (!all && CK_SLIST_EMPTY(&ie->ie_handlers))
continue;
db_dump_intr_event(ie, verbose);
if (db_pager_quit)
Index: sys/sys/interrupt.h
===================================================================
--- sys/sys/interrupt.h
+++ sys/sys/interrupt.h
@@ -33,6 +33,7 @@
#include <sys/_lock.h>
#include <sys/_mutex.h>
+#include <sys/ck.h>
struct intr_event;
struct intr_thread;
@@ -52,7 +53,7 @@
char ih_name[MAXCOMLEN + 1]; /* Name of handler. */
struct intr_event *ih_event; /* Event we are connected to. */
int ih_need; /* Needs service. */
- TAILQ_ENTRY(intr_handler) ih_next; /* Next handler for this event. */
+ CK_SLIST_ENTRY(intr_handler) ih_next; /* Next handler for this event. */
u_char ih_pri; /* Priority of this handler. */
struct intr_thread *ih_thread; /* Ithread for filtered handler. */
};
@@ -105,7 +106,7 @@
*/
struct intr_event {
TAILQ_ENTRY(intr_event) ie_list;
- TAILQ_HEAD(, intr_handler) ie_handlers; /* Interrupt handlers. */
+ CK_SLIST_HEAD(, intr_handler) ie_handlers; /* Interrupt handlers. */
char ie_name[MAXCOMLEN + 1]; /* Individual event name. */
char ie_fullname[MAXCOMLEN + 1];
struct mtx ie_lock;
@@ -174,7 +175,6 @@
int intr_event_describe_handler(struct intr_event *ie, void *cookie,
const char *descr);
int intr_event_destroy(struct intr_event *ie);
-void intr_event_execute_handlers(struct proc *p, struct intr_event *ie);
int intr_event_handle(struct intr_event *ie, struct trapframe *frame);
int intr_event_remove_handler(void *cookie);
int intr_getaffinity(int irq, int mode, void *mask);

File Metadata

Mime Type
text/plain
Expires
Fri, Apr 24, 9:12 AM (6 h, 46 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
32070395
Default Alt Text
D16016.id44850.diff (10 KB)

Event Timeline