diff options
Diffstat (limited to 'src/pulsecore')
-rw-r--r-- | src/pulsecore/atomic.h | 231 | ||||
-rw-r--r-- | src/pulsecore/cli-command.c | 32 | ||||
-rw-r--r-- | src/pulsecore/hashmap.c | 8 | ||||
-rw-r--r-- | src/pulsecore/macro.h | 58 | ||||
-rw-r--r-- | src/pulsecore/protocol-esound.c | 2 | ||||
-rw-r--r-- | src/pulsecore/protocol-native.c | 1 |
6 files changed, 302 insertions, 30 deletions
diff --git a/src/pulsecore/atomic.h b/src/pulsecore/atomic.h index c2c99888..ad3dca30 100644 --- a/src/pulsecore/atomic.h +++ b/src/pulsecore/atomic.h @@ -36,7 +36,7 @@ * On gcc >= 4.1 we use the builtin atomic functions. otherwise we use * libatomic_ops */ - +# #ifndef PACKAGE #error "Please include config.h before including this file!" #endif @@ -182,6 +182,235 @@ static inline int pa_atomic_ptr_cmpxchg(pa_atomic_ptr_t *a, void *old_p, void* n return result; } +#elif defined(ATOMIC_ARM_INLINE_ASM) + +/* + These should only be enabled if we have ARMv6 or better. +*/ + +typedef struct pa_atomic { + volatile int value; +} pa_atomic_t; + +#define PA_ATOMIC_INIT(v) { .value = (v) } + +static inline void pa_memory_barrier(void) { +#ifdef ATOMIC_ARM_MEMORY_BARRIER_ENABLED + asm volatile ("mcr p15, 0, r0, c7, c10, 5 @ dmb"); +#endif +} + +static inline int pa_atomic_load(const pa_atomic_t *a) { + pa_memory_barrier(); + return a->value; +} + +static inline void pa_atomic_store(pa_atomic_t *a, int i) { + a->value = i; + pa_memory_barrier(); +} + +/* Returns the previously set value */ +static inline int pa_atomic_add(pa_atomic_t *a, int i) { + unsigned long not_exclusive; + int new_val, old_val; + + pa_memory_barrier(); + do { + asm volatile ("ldrex %0, [%3]\n" + "add %2, %0, %4\n" + "strex %1, %2, [%3]\n" + : "=&r" (old_val), "=&r" (not_exclusive), "=&r" (new_val) + : "r" (&a->value), "Ir" (i) + : "cc"); + } while(not_exclusive); + pa_memory_barrier(); + + return old_val; +} + +/* Returns the previously set value */ +static inline int pa_atomic_sub(pa_atomic_t *a, int i) { + unsigned long not_exclusive; + int new_val, old_val; + + pa_memory_barrier(); + do { + asm volatile ("ldrex %0, [%3]\n" + "sub %2, %0, %4\n" + "strex %1, %2, [%3]\n" + : "=&r" (old_val), "=&r" (not_exclusive), "=&r" (new_val) + : "r" (&a->value), "Ir" (i) + : "cc"); + } while(not_exclusive); + pa_memory_barrier(); + + return old_val; +} + +static inline int pa_atomic_inc(pa_atomic_t *a) { + return pa_atomic_add(a, 1); +} + +static inline int pa_atomic_dec(pa_atomic_t *a) { + return pa_atomic_sub(a, 1); +} + +static inline int pa_atomic_cmpxchg(pa_atomic_t *a, int old_i, int new_i) { + unsigned long not_equal, not_exclusive; + + pa_memory_barrier(); + do { + asm volatile ("ldrex %0, [%2]\n" + "subs %0, %0, %3\n" + "mov %1, %0\n" + "strexeq %0, %4, [%2]\n" + : "=&r" (not_exclusive), "=&r" (not_equal) + : "r" (&a->value), "Ir" (old_i), "r" (new_i) + : "cc"); + } while(not_exclusive && !not_equal); + pa_memory_barrier(); + + return !not_equal; +} + +typedef struct pa_atomic_ptr { + volatile unsigned long value; +} pa_atomic_ptr_t; + +#define PA_ATOMIC_PTR_INIT(v) { .value = (long) (v) } + +static inline void* pa_atomic_ptr_load(const pa_atomic_ptr_t *a) { + pa_memory_barrier(); + return (void*) a->value; +} + +static inline void pa_atomic_ptr_store(pa_atomic_ptr_t *a, void *p) { + a->value = (unsigned long) p; + pa_memory_barrier(); +} + +static inline int pa_atomic_ptr_cmpxchg(pa_atomic_ptr_t *a, void *old_p, void* new_p) { + unsigned long not_equal, not_exclusive; + + pa_memory_barrier(); + do { + asm volatile ("ldrex %0, [%2]\n" + "subs %0, %0, %3\n" + "mov %1, %0\n" + "strexeq %0, %4, [%2]\n" + : "=&r" (not_exclusive), "=&r" (not_equal) + : "r" (&a->value), "Ir" (old_p), "r" (new_p) + : "cc"); + } while(not_exclusive && !not_equal); + pa_memory_barrier(); + + return !not_equal; +} + +#elif defined(ATOMIC_ARM_LINUX_HELPERS) + +/* See file arch/arm/kernel/entry-armv.S in your kernel sources for more + information about these functions. The arm kernel helper functions first + appeared in 2.6.16. + Apply --disable-atomic-arm-linux-helpers flag to confugure if you prefere + inline asm implementation or you have an obsolete Linux kernel. +*/ +/* Memory barrier */ +typedef void (__kernel_dmb_t)(void); +#define __kernel_dmb (*(__kernel_dmb_t *)0xffff0fa0) + +static inline void pa_memory_barrier(void) { +#ifndef ATOMIC_ARM_MEMORY_BARRIER_ENABLED + __kernel_dmb(); +#endif +} + +/* Atomic exchange (__kernel_cmpxchg_t contains memory barriers if needed) */ +typedef int (__kernel_cmpxchg_t)(int oldval, int newval, volatile int *ptr); +#define __kernel_cmpxchg (*(__kernel_cmpxchg_t *)0xffff0fc0) + +/* This is just to get rid of all warnings */ +typedef int (__kernel_cmpxchg_u_t)(unsigned long oldval, unsigned long newval, volatile unsigned long *ptr); +#define __kernel_cmpxchg_u (*(__kernel_cmpxchg_u_t *)0xffff0fc0) + +typedef struct pa_atomic { + volatile int value; +} pa_atomic_t; + +#define PA_ATOMIC_INIT(v) { .value = (v) } + +static inline int pa_atomic_load(const pa_atomic_t *a) { + pa_memory_barrier(); + return a->value; +} + +static inline void pa_atomic_store(pa_atomic_t *a, int i) { + a->value = i; + pa_memory_barrier(); +} + +/* Returns the previously set value */ +static inline int pa_atomic_add(pa_atomic_t *a, int i) { + int old_val; + do { + old_val = a->value; + } while(__kernel_cmpxchg(old_val, old_val + i, &a->value)); + return old_val; +} + +/* Returns the previously set value */ +static inline int pa_atomic_sub(pa_atomic_t *a, int i) { + int old_val; + do { + old_val = a->value; + } while(__kernel_cmpxchg(old_val, old_val - i, &a->value)); + return old_val; +} + +/* Returns the previously set value */ +static inline int pa_atomic_inc(pa_atomic_t *a) { + return pa_atomic_add(a, 1); +} + +/* Returns the previously set value */ +static inline int pa_atomic_dec(pa_atomic_t *a) { + return pa_atomic_sub(a, 1); +} + +/* Returns non-zero when the operation was successful. */ +static inline int pa_atomic_cmpxchg(pa_atomic_t *a, int old_i, int new_i) { + int failed = 1; + do { + failed = __kernel_cmpxchg(old_i, new_i, &a->value); + } while(failed && a->value == old_i); + return !failed; +} + +typedef struct pa_atomic_ptr { + volatile unsigned long value; +} pa_atomic_ptr_t; + +#define PA_ATOMIC_PTR_INIT(v) { .value = (unsigned long) (v) } + +static inline void* pa_atomic_ptr_load(const pa_atomic_ptr_t *a) { + pa_memory_barrier(); + return (void*) a->value; +} + +static inline void pa_atomic_ptr_store(pa_atomic_ptr_t *a, void *p) { + a->value = (unsigned long) p; + pa_memory_barrier(); +} + +static inline int pa_atomic_ptr_cmpxchg(pa_atomic_ptr_t *a, void *old_p, void* new_p) { + int failed = 1; + do { + failed = __kernel_cmpxchg_u((unsigned long) old_p, (unsigned long) new_p, &a->value); + } while(failed && a->value == old_p); + return !failed; +} + #else /* libatomic_ops based implementation */ diff --git a/src/pulsecore/cli-command.c b/src/pulsecore/cli-command.c index 73b6619c..20510fc1 100644 --- a/src/pulsecore/cli-command.c +++ b/src/pulsecore/cli-command.c @@ -31,6 +31,7 @@ #include <stdlib.h> #include <errno.h> #include <unistd.h> +#include <ltdl.h> #include <pulse/xmalloc.h> @@ -1318,8 +1319,35 @@ int pa_cli_command_execute_line_stateful(pa_core *c, const char *s, pa_strbuf *b } else { const char *filename = cs+l+strspn(cs+l, whitespace); - *ifstate = access(filename, F_OK) == 0 ? IFSTATE_TRUE : IFSTATE_FALSE; - pa_log_debug("Checking for existance of '%s': %s", filename, *ifstate == IFSTATE_TRUE ? "success" : "failure"); + /* Search DL_SEARCH_PATH unless the filename is absolute */ + if (filename[0] == PA_PATH_SEP_CHAR) { + + *ifstate = access(filename, F_OK) == 0 ? IFSTATE_TRUE : IFSTATE_FALSE; + pa_log_debug("Checking for existance of '%s': %s", filename, *ifstate == IFSTATE_TRUE ? "success" : "failure"); + + } else { + const char *paths, *state = NULL; + char *p; + + if (!(paths = lt_dlgetsearchpath())) + return -1; + + while ((p = pa_split(paths, ":", &state))) { + char *pathname; + + pathname = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", p, filename); + pa_xfree(p); + + *ifstate = access(pathname, F_OK) == 0 ? IFSTATE_TRUE : IFSTATE_FALSE; + pa_log_debug("Checking for existance of '%s': %s", pathname, *ifstate == IFSTATE_TRUE ? "success" : "failure"); + + pa_xfree(pathname); + + if (*ifstate == IFSTATE_TRUE) + break; + } + } + } } else { pa_strbuf_printf(buf, "Invalid meta command: %s\n", cs); diff --git a/src/pulsecore/hashmap.c b/src/pulsecore/hashmap.c index f5589664..c9d5632c 100644 --- a/src/pulsecore/hashmap.c +++ b/src/pulsecore/hashmap.c @@ -71,7 +71,7 @@ pa_hashmap *pa_hashmap_new(pa_hash_func_t hash_func, pa_compare_func_t compare_f return h; } -static void remove(pa_hashmap *h, struct hashmap_entry *e) { +static void remove_entry(pa_hashmap *h, struct hashmap_entry *e) { pa_assert(h); pa_assert(e); @@ -103,7 +103,7 @@ void pa_hashmap_free(pa_hashmap*h, void (*free_func)(void *p, void *userdata), v while (h->first_entry) { if (free_func) free_func(h->first_entry->value, userdata); - remove(h, h->first_entry); + remove_entry(h, h->first_entry); } pa_xfree(h->data); @@ -182,7 +182,7 @@ void* pa_hashmap_remove(pa_hashmap *h, const void *key) { return NULL; data = e->value; - remove(h, e); + remove_entry(h, e); return data; } @@ -220,7 +220,7 @@ void* pa_hashmap_steal_first(pa_hashmap *h) { return NULL; data = h->first_entry->value; - remove(h, h->first_entry); + remove_entry(h, h->first_entry); return data; } diff --git a/src/pulsecore/macro.h b/src/pulsecore/macro.h index 60ab025c..1bf2cfbb 100644 --- a/src/pulsecore/macro.h +++ b/src/pulsecore/macro.h @@ -29,6 +29,8 @@ #include <assert.h> #include <limits.h> #include <unistd.h> +#include <stdio.h> +#include <stdlib.h> #include <pulsecore/log.h> #include <pulsecore/gccmacro.h> @@ -137,35 +139,47 @@ typedef int pa_bool_t; #define PA_PRETTY_FUNCTION "" #endif -#define pa_return_if_fail(expr) \ - do { \ - if (!(expr)) { \ - pa_log_debug("%s: Assertion <%s> failed.\n", PA_PRETTY_FUNCTION, #expr ); \ - return; \ - } \ - } while(0) - -#define pa_return_val_if_fail(expr, val) \ - do { \ - if (!(expr)) { \ - pa_log_debug("%s: Assertion <%s> failed.\n", PA_PRETTY_FUNCTION, #expr ); \ - return (val); \ - } \ - } while(0) +#define pa_return_if_fail(expr) \ + do { \ + if (PA_UNLIKELY(!(expr))) { \ + pa_log_debug("Assertion '%s' failed at %s:%u, function %s.\n", #expr , __FILE__, __LINE__, PA_PRETTY_FUNCTION); \ + return; \ + } \ + } while(FALSE) + +#define pa_return_val_if_fail(expr, val) \ + do { \ + if (PA_UNLIKELY(!(expr))) { \ + pa_log_debug("Assertion '%s' failed at %s:%u, function %s.\n", #expr , __FILE__, __LINE__, PA_PRETTY_FUNCTION); \ + return (val); \ + } \ + } while(FALSE) #define pa_return_null_if_fail(expr) pa_return_val_if_fail(expr, NULL) -#define pa_assert assert - -#define pa_assert_not_reached() pa_assert(!"Should not be reached.") - -/* An assert which guarantees side effects of x */ +/* An assert which guarantees side effects of x, i.e. is never + * optimized away */ +#define pa_assert_se(expr) \ + do { \ + if (PA_UNLIKELY(!(expr))) { \ + pa_log_error("Assertion '%s' failed at %s:%u, function %s(). Aborting.", #expr , __FILE__, __LINE__, PA_PRETTY_FUNCTION); \ + abort(); \ + } \ + } while (FALSE) + +/* An assert that may be optimized away by defining NDEBUG */ #ifdef NDEBUG -#define pa_assert_se(x) x +#define pa_assert(expr) do {} while (FALSE) #else -#define pa_assert_se(x) pa_assert(x) +#define pa_assert(expr) pa_assert_se(expr) #endif +#define pa_assert_not_reached() \ + do { \ + pa_log_error("Code should not be reached at %s:%u, function %s(). Aborting.", __FILE__, __LINE__, PA_PRETTY_FUNCTION); \ + abort(); \ + } while (FALSE) + #define PA_PTR_TO_UINT(p) ((unsigned int) (unsigned long) (p)) #define PA_UINT_TO_PTR(u) ((void*) (unsigned long) (u)) diff --git a/src/pulsecore/protocol-esound.c b/src/pulsecore/protocol-esound.c index 972e8e1a..59a4208f 100644 --- a/src/pulsecore/protocol-esound.c +++ b/src/pulsecore/protocol-esound.c @@ -72,7 +72,7 @@ #define RECORD_BUFFER_SECONDS (5) #define RECORD_BUFFER_FRAGMENTS (100) -#define MAX_CACHE_SAMPLE_SIZE (1024000) +#define MAX_CACHE_SAMPLE_SIZE (2048000) #define SCACHE_PREFIX "esound." diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index 811cc805..0ac3ec1f 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -1193,6 +1193,7 @@ static void source_output_moved_cb(pa_source_output *o) { pa_tagstruct_putu32(t, s->index); pa_tagstruct_putu32(t, o->source->index); pa_tagstruct_puts(t, o->source->name); + pa_tagstruct_put_boolean(t, pa_source_get_state(o->source) == PA_SOURCE_SUSPENDED); pa_pstream_send_tagstruct(s->connection->pstream, t); } |