sound: Safely remove channel from list in one pass

The CHN_REMOVE_SAFE() macro did two traversals of the channel list to
remove a channel, one to check whether the channel is an element of the
list, and a second traversal through SLIST_REMOVE(). Reduce this to one
traversal, while still preventing a NULL dereference in case the channel
in question is not present in the list.

While here, rename the macro arguments to something more descriptive.

MFC after:	1 week
Reviewed by:	christos
Differential Revision:  https://reviews.freebsd.org/D48207
This commit is contained in:
Florian Walpen 2025-01-21 13:59:12 +02:00 committed by Christos Margiolis
parent 27ef5d48c7
commit 27b932e32f

View file

@ -175,6 +175,7 @@ struct pcm_channel {
#define CHN_LINK(y) y.link
#define CHN_EMPTY(x, y) SLIST_EMPTY(CHN_HEAD(x, y))
#define CHN_FIRST(x, y) SLIST_FIRST(CHN_HEAD(x, y))
#define CHN_NEXT(elm, list) SLIST_NEXT((elm), CHN_LINK(list))
#define CHN_FOREACH(x, y, z) \
SLIST_FOREACH(x, CHN_HEAD(y, z), CHN_LINK(z))
@ -188,8 +189,8 @@ struct pcm_channel {
#define CHN_INSERT_AFTER(x, y, z) \
SLIST_INSERT_AFTER(x, y, CHN_LINK(z))
#define CHN_REMOVE(x, y, z) \
SLIST_REMOVE(CHN_HEAD(x, z), y, pcm_channel, CHN_LINK(z))
#define CHN_REMOVE(holder, elm, list) \
SLIST_REMOVE(CHN_HEAD(holder, list), elm, pcm_channel, CHN_LINK(list))
#define CHN_INSERT_HEAD_SAFE(x, y, z) do { \
struct pcm_channel *t = NULL; \
@ -211,14 +212,18 @@ struct pcm_channel {
CHN_INSERT_AFTER(x, y, z); \
} while (0)
#define CHN_REMOVE_SAFE(x, y, z) do { \
struct pcm_channel *t = NULL; \
CHN_FOREACH(t, x, z) { \
if (t == y) \
break; \
} \
if (t == y) \
CHN_REMOVE(x, y, z); \
#define CHN_REMOVE_SAFE(holder, elm, list) do { \
if (CHN_FIRST(holder, list) == (elm)) { \
SLIST_REMOVE_HEAD(CHN_HEAD(holder, list), CHN_LINK(list)); \
} else { \
struct pcm_channel *t = NULL; \
CHN_FOREACH(t, holder, list) { \
if (CHN_NEXT(t, list) == (elm)) { \
SLIST_REMOVE_AFTER(t, CHN_LINK(list)); \
break; \
} \
} \
} \
} while (0)
#define CHN_INSERT_SORT(w, x, y, z) do { \