svn commit: r285680 - head/sys/kern
Konstantin Belousov
kib at FreeBSD.org
Sat Jul 18 19:59:30 UTC 2015
Author: kib
Date: Sat Jul 18 19:59:29 2015
New Revision: 285680
URL: https://svnweb.freebsd.org/changeset/base/285680
Log:
Further cleanup after r285607.
Remove useless release semantic for some stores to it_need. For
stores where the release is needed, add a comment explaining why.
Fence after the atomic_cmpset() op on the it_need should be acquire
only, release is not needed (see above). The combination of
atomic_cmpset() + fence_acq() is better expressed there as
atomic_cmpset_acq().
Use atomic_cmpset() for swi' ih_need read and clear.
Discussed with: alc, bde
Reviewed by: bde
Comments wording provided by: bde
Sponsored by: The FreeBSD Foundation
MFC after: 2 weeks
Modified:
head/sys/kern/kern_intr.c
Modified: head/sys/kern/kern_intr.c
==============================================================================
--- head/sys/kern/kern_intr.c Sat Jul 18 18:49:44 2015 (r285679)
+++ head/sys/kern/kern_intr.c Sat Jul 18 19:59:29 2015 (r285680)
@@ -830,7 +830,7 @@ ok:
* again and remove this handler if it has already passed
* it on the list.
*/
- atomic_store_rel_int(&ie->ie_thread->it_need, 1);
+ ie->ie_thread->it_need = 1;
} else
TAILQ_REMOVE(&ie->ie_handlers, handler, ih_next);
thread_unlock(ie->ie_thread->it_thread);
@@ -897,6 +897,10 @@ intr_event_schedule_thread(struct intr_e
* Set it_need to tell the thread to keep running if it is already
* running. Then, lock the thread and see if we actually need to
* put it on the runqueue.
+ *
+ * Use store_rel to arrange that the store to ih_need in
+ * swi_sched() is before the store to it_need and prepare for
+ * transfer of this order to loads in the ithread.
*/
atomic_store_rel_int(&it->it_need, 1);
thread_lock(td);
@@ -976,7 +980,7 @@ ok:
* again and remove this handler if it has already passed
* it on the list.
*/
- atomic_store_rel_int(&it->it_need, 1);
+ it->it_need = 1;
} else
TAILQ_REMOVE(&ie->ie_handlers, handler, ih_next);
thread_unlock(it->it_thread);
@@ -1048,6 +1052,10 @@ intr_event_schedule_thread(struct intr_e
* Set it_need to tell the thread to keep running if it is already
* running. Then, lock the thread and see if we actually need to
* put it on the runqueue.
+ *
+ * Use store_rel to arrange that the store to ih_need in
+ * swi_sched() is before the store to it_need and prepare for
+ * transfer of this order to loads in the ithread.
*/
atomic_store_rel_int(&it->it_need, 1);
thread_lock(td);
@@ -1133,7 +1141,7 @@ swi_sched(void *cookie, int flags)
* running it will execute this handler on the next pass. Otherwise,
* it will execute it the next time it runs.
*/
- atomic_store_rel_int(&ih->ih_need, 1);
+ ih->ih_need = 1;
if (!(flags & SWI_DELAY)) {
PCPU_INC(cnt.v_soft);
@@ -1224,11 +1232,15 @@ intr_event_execute_handlers(struct proc
* handlers that have their need flag set. Hardware
* interrupt threads always invoke all of their handlers.
*/
- if (ie->ie_flags & IE_SOFT) {
- if (atomic_load_acq_int(&ih->ih_need) == 0)
+ if ((ie->ie_flags & IE_SOFT) != 0) {
+ /*
+ * ih_need can only be 0 or 1. Failed cmpset
+ * below means that there is no request to
+ * execute handlers, so a retry of the cmpset
+ * is not needed.
+ */
+ if (atomic_cmpset_int(&ih->ih_need, 1, 0) == 0)
continue;
- else
- atomic_store_rel_int(&ih->ih_need, 0);
}
/* Execute this handler. */
@@ -1326,16 +1338,13 @@ ithread_loop(void *arg)
* Service interrupts. If another interrupt arrives while
* we are running, it will set it_need to note that we
* should make another pass.
+ *
+ * The load_acq part of the following cmpset ensures
+ * that the load of ih_need in ithread_execute_handlers()
+ * is ordered after the load of it_need here.
*/
- while (atomic_cmpset_int(&ithd->it_need, 1, 0) != 0) {
- /*
- * This needs a release barrier to make sure
- * that this write posts before any of the
- * memory or device accesses in the handlers.
- */
- atomic_thread_fence_acq_rel();
+ while (atomic_cmpset_acq_int(&ithd->it_need, 1, 0) != 0)
ithread_execute_handlers(p, ie);
- }
WITNESS_WARN(WARN_PANIC, NULL, "suspending ithread");
mtx_assert(&Giant, MA_NOTOWNED);
@@ -1505,14 +1514,12 @@ ithread_loop(void *arg)
* Service interrupts. If another interrupt arrives while
* we are running, it will set it_need to note that we
* should make another pass.
+ *
+ * The load_acq part of the following cmpset ensures
+ * that the load of ih_need in ithread_execute_handlers()
+ * is ordered after the load of it_need here.
*/
- while (atomic_cmpset_int(&ithd->it_need, 1, 0) != 0) {
- /*
- * This needs a release barrier to make sure
- * that this write posts before any of the
- * memory or device accesses in the handlers.
- */
- atomic_thread_fence_acq_rel();
+ while (atomic_cmpset_acq_int(&ithd->it_need, 1, 0) != 0) {
if (priv)
priv_ithread_execute_handler(p, ih);
else
More information about the svn-src-all
mailing list