DF-2679 / fix_iterations.log
DF-2679 fix.diff iteration record (fix validation is part of the evidence)
v1 (initial): bus_topo_lock EXCL at make_device publish + all three
devclass_delete_device call sites (incl. the device_set_devclass(0)
probe-loop site); SHARED held across walk+fields+dispatch+SYSCTL_OUT
in both readers.
RESULT: kernel #1 (14:58:28) deadlocked under the identical stress:
spin_lock_ex: AcpiOsWaitSemaphore, indefinite wait (58 secs)!
...
ssleep() at ssleep+0x38e
AcpiOsWaitSemaphore() ...
AcpiUtAcquireMutex() ... AcpiNsGetNode() ...
Debugger("panic")
-> AB-BA between SHARED holders sleeping in copyout/dispatch and
attach-side EXCL waiters under ACPI mutexes.
v2: make_device no longer locked; readers release before SYSCTL_OUT
(strings snapshotted to locals under the lock).
RESULT: kernel #2 (15:16:12) still deadlocked, with the exact cycle:
AcpiOsWaitSemaphore() ... AcpiUtAcquireMutex()
AcpiGetObjectInfo()
acpi_child_pnpinfo_str_method()
Debugger("panic")
-> walker holds topo SHARED across bus_child_pnpinfo_str dispatch
(needs ACPI namespace mutex) while an ACPI-side thread blocked on
topo EXCL holds that mutex; the remaining EXCL site reachable under
ACPI mutexes is device_probe_child()'s device_set_devclass(child,0)
(called per failed probe inside attach/probe contexts).
v3 (final, in fix.diff): v2 minus the device_set_devclass(0) EXCL wrap
(probe-loop hot path; the transient nameunit churn there is the
pre-existing narrow race, not the demonstrated crash). EXCL remains
only in device_delete_child's unpublish+free tail and device_detach's
devclass_delete_device wrap; readers hold SHARED across
walk+snapshot+dispatch only.