PERFORCE change 184932 for review

John Baldwin jhb at FreeBSD.org
Wed Oct 20 14:19:51 UTC 2010


http://p4web.freebsd.org/@@184932?ac=10

Change 184932 by jhb at jhb_jhbbsd on 2010/10/20 14:19:23

	Add an intr_handler_drain() to attempt to supply similar semantics
	to Linux's synchronize_irq().

Affected files ...

.. //depot/projects/smpng/sys/kern/kern_intr.c#105 edit
.. //depot/projects/smpng/sys/sys/interrupt.h#31 edit

Differences ...

==== //depot/projects/smpng/sys/kern/kern_intr.c#105 (text+ko) ====

@@ -720,6 +720,57 @@
 }
 
 /*
+ * If an interrupt handler is currently running, wait for it to finish
+ * executing.
+ */
+void
+intr_handler_drain(void *cookie)
+{
+	struct intr_handler *ih;
+	struct intr_event *ie;
+	struct intr_thread *it;
+
+	ih = (struct intr_handler *)cookie;
+	if (ih == NULL || cold)
+		return;
+	ie = ih->ih_event;
+	KASSERT(ie != NULL,
+	    ("interrupt handler \"%s\" has a NULL interrupt event",
+	    ih->ih_name));
+
+	/* XXX: Punt on handlers that only have a filter for now. */
+	if (ih->ih_handler == NULL)
+		return;
+
+#ifdef INTR_FILTER
+	if (ih->ih_thread)
+		it = ih->ih_thread;
+	else
+#endif
+		it = ie->ie_thread;
+
+	mtx_lock(&ie->ie_lock);
+	thread_lock(it->it_thread);
+
+	/* If the thread is idle, then the interrupt handler is not running. */
+	if (!TD_AWAITING_INTR(it->it_thread)) {
+		ih->ih_flags |= IH_DRAINING;
+
+		/*
+		 * Ensure the thread will process the handler list
+		 * again if it has already passed this handler.
+		 */
+		it->it_need = 1;
+		thread_unlock(it->it_thread);
+
+		while (ih->ih_flags & IH_DRAINING)
+			msleep(ih, &ie->ie_lock, 0, "idrain", 0);
+	} else
+		thread_unlock(it->it_thread);
+	mtx_unlock(&ie->ie_lock);
+}
+
+/*
  * Return the ie_source field from the intr_event an intr_handler is
  * associated with.
  */
@@ -1152,7 +1203,7 @@
 	if (ih->ih_flags & IH_DEAD) {
 		mtx_lock(&ie->ie_lock);
 		TAILQ_REMOVE(&ie->ie_handlers, ih, ih_next);
-		ih->ih_flags &= ~IH_DEAD;
+		ih->ih_flags &= ~(IH_DEAD | IH_DRAINING);
 		wakeup(ih);
 		mtx_unlock(&ie->ie_lock);
 		return;
@@ -1168,6 +1219,13 @@
 	ih->ih_handler(ih->ih_argument);
 	if (!(ih->ih_flags & IH_MPSAFE))
 		mtx_unlock(&Giant);
+
+	if (ih->ih_flags & IH_DRAINING) {
+		mtx_lock(&ie->ie_lock);
+		ih->ih_flags &= ~IH_DRAINING;
+		wakeup(ih);
+		mtx_unlock(&ie->ie_lock);
+	}
 }
 #endif
 
@@ -1188,7 +1246,7 @@
 		if (ih->ih_flags & IH_DEAD) {
 			mtx_lock(&ie->ie_lock);
 			TAILQ_REMOVE(&ie->ie_handlers, ih, ih_next);
-			ih->ih_flags &= ~IH_DEAD;
+			ih->ih_flags &= ~(IH_DEAD | IH_DRAINING);
 			wakeup(ih);
 			mtx_unlock(&ie->ie_lock);
 			continue;
@@ -1220,6 +1278,13 @@
 		ih->ih_handler(ih->ih_argument);
 		if (!(ih->ih_flags & IH_MPSAFE))
 			mtx_unlock(&Giant);
+
+		if (ih->ih_flags & IH_DRAINING) {
+			mtx_lock(&ie->ie_lock);
+			ih->ih_flags &= ~IH_DRAINING;
+			wakeup(ih);
+			mtx_unlock(&ie->ie_lock);
+		}
 	}
 }
 
@@ -1684,7 +1749,7 @@
 	db_printsym((uintptr_t)ih->ih_handler, DB_STGY_PROC);
 	db_printf("(%p)", ih->ih_argument);
 	if (ih->ih_need ||
-	    (ih->ih_flags & (IH_EXCLUSIVE | IH_ENTROPY | IH_DEAD |
+	    (ih->ih_flags & (IH_EXCLUSIVE | IH_ENTROPY | IH_DEAD | IH_DRAINING |
 	    IH_MPSAFE)) != 0) {
 		db_printf(" {");
 		comma = 0;
@@ -1706,6 +1771,12 @@
 			db_printf("DEAD");
 			comma = 1;
 		}
+		if (ih->ih_flags & IH_DRAINING) {
+			if (comma)
+				db_printf(", ");
+			db_printf("DRAINING");
+			comma = 1;
+		}
 		if (ih->ih_flags & IH_MPSAFE) {
 			if (comma)
 				db_printf(", ");

==== //depot/projects/smpng/sys/sys/interrupt.h#31 (text+ko) ====

@@ -59,6 +59,7 @@
 #define	IH_EXCLUSIVE	0x00000002	/* Exclusive interrupt. */
 #define	IH_ENTROPY	0x00000004	/* Device is a good entropy source. */
 #define	IH_DEAD		0x00000008	/* Handler should be removed. */
+#define	IH_DRAINING	0x00000010	/* Has waiting drainer. */
 #define	IH_MPSAFE	0x80000000	/* Handler does not need Giant. */
 
 /*
@@ -175,6 +176,7 @@
 int	intr_event_handle(struct intr_event *ie, struct trapframe *frame);
 int	intr_event_remove_handler(void *cookie);
 int	intr_getaffinity(int irq, void *mask);
+void	intr_handler_drain(void *cookie);
 void	*intr_handler_source(void *cookie);
 int	intr_setaffinity(int irq, void *mask);
 int	swi_add(struct intr_event **eventp, const char *name,


More information about the p4-projects mailing list