mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 09:36:22 +02:00
ALSA: Add simple refcount helper functions
There are many open-code to manage the same pattern for refcount + wakeup sync at closing. Let's provide the common helper functions to replace the open-code. - The recount is kept in struct snd_refcount, where it's initialized by snd_refcount_init(). - The user can simply reference or unreference via snd_refcount_get() and snd_refcount_put() functions - The user can wait for the all usages gone by snd_refcount_sync() Note that here we use atomic_t instead of refcount_t since the current users allow reusing the refcount after sync again. The design of refcount_t prevents exactly this behavior, so it doesn't fit. Signed-off-by: Takashi Iwai <tiwai@suse.de> Link: https://patch.msgid.link/20260610154538.51076-2-tiwai@suse.de
This commit is contained in:
parent
03a1085906
commit
dcca9b6064
|
|
@ -75,6 +75,27 @@ struct snd_device {
|
|||
|
||||
#define snd_device(n) list_entry(n, struct snd_device, list)
|
||||
|
||||
/*
|
||||
* A simple reference counter with a wait queue;
|
||||
* typically used for usage counts, and you can synchronize at finishing
|
||||
* via snd_refcount_sync(), which is woken up when the refcount reaches to
|
||||
* zero again.
|
||||
*/
|
||||
struct snd_refcount {
|
||||
atomic_t count;
|
||||
wait_queue_head_t waiter;
|
||||
};
|
||||
|
||||
void snd_refcount_init(struct snd_refcount *ref);
|
||||
|
||||
static inline void snd_refcount_get(struct snd_refcount *ref)
|
||||
{
|
||||
atomic_inc(&ref->count);
|
||||
}
|
||||
|
||||
void snd_refcount_put(struct snd_refcount *ref);
|
||||
void snd_refcount_sync(struct snd_refcount *ref);
|
||||
|
||||
/* main structure for soundcard */
|
||||
|
||||
struct snd_card {
|
||||
|
|
|
|||
|
|
@ -174,3 +174,27 @@ void snd_fasync_free(struct snd_fasync *fasync)
|
|||
kfree(fasync);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_fasync_free);
|
||||
|
||||
/*
|
||||
* generic refcount helper
|
||||
*/
|
||||
|
||||
void snd_refcount_init(struct snd_refcount *ref)
|
||||
{
|
||||
atomic_set(&ref->count, 0);
|
||||
init_waitqueue_head(&ref->waiter);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_refcount_init);
|
||||
|
||||
void snd_refcount_put(struct snd_refcount *ref)
|
||||
{
|
||||
if (atomic_dec_and_test(&ref->count))
|
||||
wake_up(&ref->waiter);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_refcount_put);
|
||||
|
||||
void snd_refcount_sync(struct snd_refcount *ref)
|
||||
{
|
||||
wait_event(ref->waiter, !atomic_read(&ref->count));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_refcount_sync);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user