Plan 9 from Bell Labs’s /usr/web/sources/patch/applied/usbuhci-iso-deadlock/readme

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


There's a deadlock in isoio() on a multiprocessor, arising  from a
conflict in order of acquiring locks.  (Not just theory: I've seen
it happen on my dual-processor Epia system.)  Consider this scenario:

isoio() on cpu1:
1 isoio calls sleep(&e->wr, isoready, e) /sys/src/9/pc/usbuhci.c:1173
2	sleep calls lock(&e->wr) /sys/src/9/port/proc.c:740
3	sleep calls isoready(e) /sys/src/9/port/proc.c:755
4		isoready calls ilock(&ctlr->activends) /sys/src/9/pc/usbuhci.c:1093
5		isoready calls iunlock(&ctlr->activends) /sys/src/9/pc/usbuhci.c:1095
6	sleep calls unlock(&e->wr) /sys/src/9/port/proc.c:762

interrupt() on cpu0:
7 interrupt calls ilock(&ctlr->activends) /sys/src/9/pc/usbuhci.c:1043
8 interrupt calls cleaniso(e, ) /sys/src/9/pc/usbuhci.c:1052
9	cleaniso calls wakeup(&e->wr) /sys/src/9/pc/usbuhci.c:1015
10		wakeup calls lock(&e->wr) /sys/src/9/port/proc.c:864
11		wakeup calls unlock(&e->wr) /sys/src/9/port/proc.c:876
12 interrupt calls iunlock(&ctlr->activends) /sys/src/9/pc/usbuhci.c:1055

An interleaving of events containing 2 - 7 - 10 - 4 leads to deadlock.

I developed a fix which involved locking the individual endpoints instead
of locking ctlr->activends, but when I checked it with Sape he pointed
out that a simple revision to isoreadyx() would mean that it can be
called without locking at all.  So here's a simple patch based on Sape's
suggestion.  (Tested by playing audio for 24 hours on the above dual-
processor system, without incident.)

-- Richard Miller

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to [email protected].