diff --git a/include/sound/core.h b/include/sound/core.h index 8b2ca95d13f7..a3f10294e834 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -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 { diff --git a/sound/core/misc.c b/sound/core/misc.c index 833124c8e4fa..4772b2a3b808 100644 --- a/sound/core/misc.c +++ b/sound/core/misc.c @@ -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);