ALSA: seq: Use RCU for the port subscriber list

Each sequencer port keeps two subscriber groups (c_src and c_dest),
each protected by both an rwlock (list_lock) and a rw_semaphore
(list_mutex).  The rwlock is taken read-side in the event delivery hot
path (__deliver_to_subscribers()) for delivering every event to
subscribers, while the mutex serializes subscribe/unsubscribe and
covers the sleepable delivery and query walks.

Subscriptions change rarely but delivery happens constantly, so this is
a textbook read-mostly case.  Convert the subscriber list traversal to
RCU and drop the rwlock entirely while keeping the existing list_mutex
for serializing the writers.  The atomic delivery path now runs
lock-free under rcu_read_lock() instead of contending on the shared
rwlock.

Along with the conversion to RCU, the subscriber lists are switched
from list_head to hlist so that removal can use hlist_del_init_rcu():
it keeps the ->next pointer intact for concurrent readers while
clearing ->pprev, which lets the double-deletion guard (added in
commit 13d5e5d472) keep detecting an already-removed entry via
hlist_unhashed().

Dropping write_lock_irq() from the writers is safe: no writer runs in
atomic/IRQ context, and the sole atomic reader now uses RCU, which is
IRQ-safe.  Port lifetime handling (use_lock/closing drain in
port_delete()) is orthogonal and unchanged.

Note that the conversion to RCU has another merit: it automatically
"fixes" the (rather false) lockdep warnings for the doubly read-locks
of the same subscriber list, too.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
Link: https://patch.msgid.link/20260810133711.42483-2-tiwai@suse.de
This commit is contained in:
Takashi Iwai 2026-08-10 15:37:02 +02:00
commit a9760db775
3 changed files with 41 additions and 44 deletions