mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-11-23 06:59:53 -05:00
Merge HUGE set of changes temporarily into a branch, to allow me to move them from one machine to another (lock-free and stuff)
git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1469 fefdeb5f-60dc-0310-8127-8f9354f1896f
This commit is contained in:
parent
6aeec56708
commit
00da37f2c4
72 changed files with 4389 additions and 1767 deletions
|
|
@ -26,7 +26,6 @@
|
|||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <pthread.h>
|
||||
#include <sched.h>
|
||||
#include <errno.h>
|
||||
|
|
@ -35,56 +34,50 @@
|
|||
#include <pulsecore/mutex.h>
|
||||
#include <pulsecore/once.h>
|
||||
#include <pulsecore/atomic.h>
|
||||
#include <pulsecore/macro.h>
|
||||
|
||||
#include "thread.h"
|
||||
|
||||
#define ASSERT_SUCCESS(x) do { \
|
||||
int _r = (x); \
|
||||
assert(_r == 0); \
|
||||
} while(0)
|
||||
|
||||
struct pa_thread {
|
||||
pthread_t id;
|
||||
pa_thread_func_t thread_func;
|
||||
void *userdata;
|
||||
pa_atomic_int_t running;
|
||||
pa_atomic_t running;
|
||||
};
|
||||
|
||||
struct pa_tls {
|
||||
pthread_key_t key;
|
||||
};
|
||||
|
||||
static pa_tls *thread_tls;
|
||||
static pa_once_t thread_tls_once = PA_ONCE_INIT;
|
||||
static pthread_key_t thread_key;
|
||||
static pthread_once_t thread_once = PTHREAD_ONCE_INIT;
|
||||
|
||||
static void tls_free_cb(void *p) {
|
||||
static void thread_free_cb(void *p) {
|
||||
pa_thread *t = p;
|
||||
|
||||
assert(t);
|
||||
pa_assert(t);
|
||||
|
||||
if (!t->thread_func)
|
||||
/* This is a foreign thread, we need to free the struct */
|
||||
pa_xfree(t);
|
||||
}
|
||||
|
||||
static void thread_tls_once_func(void) {
|
||||
thread_tls = pa_tls_new(tls_free_cb);
|
||||
assert(thread_tls);
|
||||
static void thread_once_func(void) {
|
||||
pa_assert_se(pthread_key_create(&thread_key, thread_free_cb) == 0);
|
||||
}
|
||||
|
||||
static void* internal_thread_func(void *userdata) {
|
||||
pa_thread *t = userdata;
|
||||
assert(t);
|
||||
pa_assert(t);
|
||||
|
||||
t->id = pthread_self();
|
||||
|
||||
pa_once(&thread_tls_once, thread_tls_once_func);
|
||||
|
||||
pa_tls_set(thread_tls, t);
|
||||
pthread_once(&thread_once, thread_once_func);
|
||||
pthread_setspecific(thread_key, t);
|
||||
|
||||
pa_atomic_inc(&t->running);
|
||||
t->thread_func(t->userdata);
|
||||
pa_atomic_add(&t->running, -2);
|
||||
pa_atomic_sub(&t->running, 2);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -92,7 +85,7 @@ static void* internal_thread_func(void *userdata) {
|
|||
pa_thread* pa_thread_new(pa_thread_func_t thread_func, void *userdata) {
|
||||
pa_thread *t;
|
||||
|
||||
assert(thread_func);
|
||||
pa_assert(thread_func);
|
||||
|
||||
t = pa_xnew(pa_thread, 1);
|
||||
t->thread_func = thread_func;
|
||||
|
|
@ -110,26 +103,26 @@ pa_thread* pa_thread_new(pa_thread_func_t thread_func, void *userdata) {
|
|||
}
|
||||
|
||||
int pa_thread_is_running(pa_thread *t) {
|
||||
assert(t);
|
||||
pa_assert(t);
|
||||
|
||||
/* Unfortunately there is no way to tell whether a "foreign"
|
||||
* thread is still running. See
|
||||
* http://udrepper.livejournal.com/16844.html for more
|
||||
* information */
|
||||
assert(t->thread_func);
|
||||
pa_assert(t->thread_func);
|
||||
|
||||
return pa_atomic_load(&t->running) > 0;
|
||||
}
|
||||
|
||||
void pa_thread_free(pa_thread *t) {
|
||||
assert(t);
|
||||
pa_assert(t);
|
||||
|
||||
pa_thread_join(t);
|
||||
pa_xfree(t);
|
||||
}
|
||||
|
||||
int pa_thread_join(pa_thread *t) {
|
||||
assert(t);
|
||||
pa_assert(t);
|
||||
|
||||
return pthread_join(t->id, NULL);
|
||||
}
|
||||
|
|
@ -137,9 +130,9 @@ int pa_thread_join(pa_thread *t) {
|
|||
pa_thread* pa_thread_self(void) {
|
||||
pa_thread *t;
|
||||
|
||||
pa_once(&thread_tls_once, thread_tls_once_func);
|
||||
pthread_once(&thread_once, thread_once_func);
|
||||
|
||||
if ((t = pa_tls_get(thread_tls)))
|
||||
if ((t = pthread_getspecific(thread_key)))
|
||||
return t;
|
||||
|
||||
/* This is a foreign thread, let's create a pthread structure to
|
||||
|
|
@ -151,19 +144,19 @@ pa_thread* pa_thread_self(void) {
|
|||
t->userdata = NULL;
|
||||
pa_atomic_store(&t->running, 2);
|
||||
|
||||
pa_tls_set(thread_tls, t);
|
||||
pthread_setspecific(thread_key, t);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
void* pa_thread_get_data(pa_thread *t) {
|
||||
assert(t);
|
||||
pa_assert(t);
|
||||
|
||||
return t->userdata;
|
||||
}
|
||||
|
||||
void pa_thread_set_data(pa_thread *t, void *userdata) {
|
||||
assert(t);
|
||||
pa_assert(t);
|
||||
|
||||
t->userdata = userdata;
|
||||
}
|
||||
|
|
@ -172,7 +165,7 @@ void pa_thread_yield(void) {
|
|||
#ifdef HAVE_PTHREAD_YIELD
|
||||
pthread_yield();
|
||||
#else
|
||||
ASSERT_SUCCESS(sched_yield());
|
||||
pa_assert_se(sched_yield() == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -190,14 +183,14 @@ pa_tls* pa_tls_new(pa_free_cb_t free_cb) {
|
|||
}
|
||||
|
||||
void pa_tls_free(pa_tls *t) {
|
||||
assert(t);
|
||||
pa_assert(t);
|
||||
|
||||
ASSERT_SUCCESS(pthread_key_delete(t->key));
|
||||
pa_assert_se(pthread_key_delete(t->key) == 0);
|
||||
pa_xfree(t);
|
||||
}
|
||||
|
||||
void *pa_tls_get(pa_tls *t) {
|
||||
assert(t);
|
||||
pa_assert(t);
|
||||
|
||||
return pthread_getspecific(t->key);
|
||||
}
|
||||
|
|
@ -206,7 +199,7 @@ void *pa_tls_set(pa_tls *t, void *userdata) {
|
|||
void *r;
|
||||
|
||||
r = pthread_getspecific(t->key);
|
||||
ASSERT_SUCCESS(pthread_setspecific(t->key, userdata));
|
||||
pa_assert_se(pthread_setspecific(t->key, userdata) == 0);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue