2006-08-29 19:51:14 +00:00
|
|
|
/***
|
|
|
|
|
This file is part of PulseAudio.
|
2007-01-04 13:43:45 +00:00
|
|
|
|
2007-02-13 15:35:19 +00:00
|
|
|
Copyright 2006 Lennart Poettering
|
|
|
|
|
|
2006-08-29 19:51:14 +00:00
|
|
|
PulseAudio is free software; you can redistribute it and/or modify
|
|
|
|
|
it under the terms of the GNU Lesser General Public License as published
|
2009-03-03 20:23:02 +00:00
|
|
|
by the Free Software Foundation; either version 2.1 of the License,
|
2006-08-29 19:51:14 +00:00
|
|
|
or (at your option) any later version.
|
2007-01-04 13:43:45 +00:00
|
|
|
|
2006-08-29 19:51:14 +00:00
|
|
|
PulseAudio is distributed in the hope that it will be useful, but
|
|
|
|
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
|
General Public License for more details.
|
2007-01-04 13:43:45 +00:00
|
|
|
|
2006-08-29 19:51:14 +00:00
|
|
|
You should have received a copy of the GNU Lesser General Public License
|
2014-11-26 14:14:51 +01:00
|
|
|
along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
|
2006-08-29 19:51:14 +00:00
|
|
|
***/
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
|
#include <config.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#include <pthread.h>
|
2007-10-28 19:13:50 +00:00
|
|
|
#include <errno.h>
|
2006-08-29 19:51:14 +00:00
|
|
|
|
|
|
|
|
#include <pulse/xmalloc.h>
|
2020-09-24 12:07:07 +03:00
|
|
|
|
|
|
|
|
#include <pulsecore/core-error.h>
|
2007-10-28 19:13:50 +00:00
|
|
|
#include <pulsecore/macro.h>
|
2006-08-29 19:51:14 +00:00
|
|
|
|
|
|
|
|
#include "mutex.h"
|
|
|
|
|
|
|
|
|
|
struct pa_mutex {
|
|
|
|
|
pthread_mutex_t mutex;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct pa_cond {
|
|
|
|
|
pthread_cond_t cond;
|
|
|
|
|
};
|
|
|
|
|
|
2013-06-27 19:28:09 +02:00
|
|
|
pa_mutex* pa_mutex_new(bool recursive, bool inherit_priority) {
|
2006-08-29 19:51:14 +00:00
|
|
|
pa_mutex *m;
|
|
|
|
|
pthread_mutexattr_t attr;
|
2013-09-28 09:12:01 +05:30
|
|
|
#ifdef HAVE_PTHREAD_PRIO_INHERIT
|
2007-10-28 19:13:50 +00:00
|
|
|
int r;
|
2013-09-28 09:12:01 +05:30
|
|
|
#endif
|
2006-08-29 19:51:14 +00:00
|
|
|
|
2007-10-28 19:13:50 +00:00
|
|
|
pa_assert_se(pthread_mutexattr_init(&attr) == 0);
|
2006-08-29 19:51:14 +00:00
|
|
|
|
|
|
|
|
if (recursive)
|
2007-10-28 19:13:50 +00:00
|
|
|
pa_assert_se(pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) == 0);
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_PTHREAD_PRIO_INHERIT
|
2011-11-14 11:58:25 +01:00
|
|
|
if (inherit_priority) {
|
|
|
|
|
r = pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT);
|
|
|
|
|
pa_assert(r == 0 || r == ENOTSUP);
|
|
|
|
|
}
|
2007-10-28 19:13:50 +00:00
|
|
|
#endif
|
2006-08-29 19:51:14 +00:00
|
|
|
|
|
|
|
|
m = pa_xnew(pa_mutex, 1);
|
|
|
|
|
|
2007-10-28 19:13:50 +00:00
|
|
|
#ifndef HAVE_PTHREAD_PRIO_INHERIT
|
|
|
|
|
pa_assert_se(pthread_mutex_init(&m->mutex, &attr) == 0);
|
|
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
if ((r = pthread_mutex_init(&m->mutex, &attr))) {
|
|
|
|
|
|
|
|
|
|
/* If this failed, then this was probably due to non-available
|
|
|
|
|
* priority inheritance. In which case we fall back to normal
|
|
|
|
|
* mutexes. */
|
|
|
|
|
pa_assert(r == ENOTSUP && inherit_priority);
|
|
|
|
|
|
|
|
|
|
pa_assert_se(pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_NONE) == 0);
|
|
|
|
|
pa_assert_se(pthread_mutex_init(&m->mutex, &attr) == 0);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2006-08-29 19:51:14 +00:00
|
|
|
return m;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void pa_mutex_free(pa_mutex *m) {
|
2007-10-28 19:13:50 +00:00
|
|
|
pa_assert(m);
|
2006-08-29 19:51:14 +00:00
|
|
|
|
2007-10-28 19:13:50 +00:00
|
|
|
pa_assert_se(pthread_mutex_destroy(&m->mutex) == 0);
|
2006-08-29 19:51:14 +00:00
|
|
|
pa_xfree(m);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void pa_mutex_lock(pa_mutex *m) {
|
2007-10-28 19:13:50 +00:00
|
|
|
pa_assert(m);
|
2006-08-29 19:51:14 +00:00
|
|
|
|
2007-10-28 19:13:50 +00:00
|
|
|
pa_assert_se(pthread_mutex_lock(&m->mutex) == 0);
|
2006-08-29 19:51:14 +00:00
|
|
|
}
|
|
|
|
|
|
2013-06-27 19:28:09 +02:00
|
|
|
bool pa_mutex_try_lock(pa_mutex *m) {
|
2007-11-24 16:24:16 +00:00
|
|
|
int r;
|
|
|
|
|
pa_assert(m);
|
|
|
|
|
|
|
|
|
|
if ((r = pthread_mutex_trylock(&m->mutex)) != 0) {
|
|
|
|
|
pa_assert(r == EBUSY);
|
2013-06-27 19:28:09 +02:00
|
|
|
return false;
|
2007-11-24 16:24:16 +00:00
|
|
|
}
|
|
|
|
|
|
2013-06-27 19:28:09 +02:00
|
|
|
return true;
|
2007-11-24 16:24:16 +00:00
|
|
|
}
|
|
|
|
|
|
2006-08-29 19:51:14 +00:00
|
|
|
void pa_mutex_unlock(pa_mutex *m) {
|
2020-09-24 12:07:07 +03:00
|
|
|
int err;
|
|
|
|
|
|
2007-10-28 19:13:50 +00:00
|
|
|
pa_assert(m);
|
2006-08-29 19:51:14 +00:00
|
|
|
|
2020-11-23 17:01:01 -05:00
|
|
|
if ((err = pthread_mutex_unlock(&m->mutex)) != 0) {
|
2020-09-24 12:07:07 +03:00
|
|
|
pa_log("pthread_mutex_unlock() failed: %s", pa_cstrerror(err));
|
|
|
|
|
pa_assert_not_reached();
|
|
|
|
|
}
|
2006-08-29 19:51:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pa_cond *pa_cond_new(void) {
|
|
|
|
|
pa_cond *c;
|
|
|
|
|
|
|
|
|
|
c = pa_xnew(pa_cond, 1);
|
2007-10-28 19:13:50 +00:00
|
|
|
pa_assert_se(pthread_cond_init(&c->cond, NULL) == 0);
|
2006-08-29 19:51:14 +00:00
|
|
|
return c;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void pa_cond_free(pa_cond *c) {
|
2007-10-28 19:13:50 +00:00
|
|
|
pa_assert(c);
|
2006-08-29 19:51:14 +00:00
|
|
|
|
2007-10-28 19:13:50 +00:00
|
|
|
pa_assert_se(pthread_cond_destroy(&c->cond) == 0);
|
2006-08-29 19:51:14 +00:00
|
|
|
pa_xfree(c);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void pa_cond_signal(pa_cond *c, int broadcast) {
|
2007-10-28 19:13:50 +00:00
|
|
|
pa_assert(c);
|
2006-08-29 19:51:14 +00:00
|
|
|
|
|
|
|
|
if (broadcast)
|
2007-10-28 19:13:50 +00:00
|
|
|
pa_assert_se(pthread_cond_broadcast(&c->cond) == 0);
|
2006-08-29 19:51:14 +00:00
|
|
|
else
|
2007-10-28 19:13:50 +00:00
|
|
|
pa_assert_se(pthread_cond_signal(&c->cond) == 0);
|
2006-08-29 19:51:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int pa_cond_wait(pa_cond *c, pa_mutex *m) {
|
2007-10-28 19:13:50 +00:00
|
|
|
pa_assert(c);
|
|
|
|
|
pa_assert(m);
|
2006-08-29 19:51:14 +00:00
|
|
|
|
|
|
|
|
return pthread_cond_wait(&c->cond, &m->mutex);
|
|
|
|
|
}
|
2009-01-23 23:57:47 +01:00
|
|
|
|
2013-06-27 19:28:09 +02:00
|
|
|
pa_mutex* pa_static_mutex_get(pa_static_mutex *s, bool recursive, bool inherit_priority) {
|
2009-01-23 23:57:47 +01:00
|
|
|
pa_mutex *m;
|
|
|
|
|
|
|
|
|
|
pa_assert(s);
|
|
|
|
|
|
|
|
|
|
/* First, check if already initialized and short cut */
|
|
|
|
|
if ((m = pa_atomic_ptr_load(&s->ptr)))
|
|
|
|
|
return m;
|
|
|
|
|
|
|
|
|
|
/* OK, not initialized, so let's allocate, and fill in */
|
|
|
|
|
m = pa_mutex_new(recursive, inherit_priority);
|
|
|
|
|
if ((pa_atomic_ptr_cmpxchg(&s->ptr, NULL, m)))
|
|
|
|
|
return m;
|
|
|
|
|
|
2009-04-21 21:24:33 +02:00
|
|
|
pa_mutex_free(m);
|
|
|
|
|
|
2009-01-23 23:57:47 +01:00
|
|
|
/* Him, filling in failed, so someone else must have filled in
|
|
|
|
|
* already */
|
|
|
|
|
pa_assert_se(m = pa_atomic_ptr_load(&s->ptr));
|
|
|
|
|
return m;
|
|
|
|
|
}
|