1/*** 2 This file is part of PulseAudio. 3 4 Copyright 2006 Lennart Poettering 5 6 PulseAudio is free software; you can redistribute it and/or modify 7 it under the terms of the GNU Lesser General Public License as published 8 by the Free Software Foundation; either version 2.1 of the License, 9 or (at your option) any later version. 10 11 PulseAudio is distributed in the hope that it will be useful, but 12 WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 General Public License for more details. 15 16 You should have received a copy of the GNU Lesser General Public License 17 along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. 18***/ 19 20#ifdef HAVE_CONFIG_H 21#include <config.h> 22#endif 23 24#include <errno.h> 25#include <pthread.h> 26#include <semaphore.h> 27 28#include <pulse/xmalloc.h> 29#include <pulsecore/macro.h> 30 31#include "semaphore.h" 32 33struct pa_semaphore { 34 sem_t sem; 35}; 36 37pa_semaphore* pa_semaphore_new(unsigned value) { 38 pa_semaphore *s; 39 40 s = pa_xnew(pa_semaphore, 1); 41 pa_assert_se(sem_init(&s->sem, 0, value) == 0); 42 return s; 43} 44 45void pa_semaphore_free(pa_semaphore *s) { 46 pa_assert(s); 47 pa_assert_se(sem_destroy(&s->sem) == 0); 48 pa_xfree(s); 49} 50 51void pa_semaphore_post(pa_semaphore *s) { 52 pa_assert(s); 53 pa_assert_se(sem_post(&s->sem) == 0); 54} 55 56void pa_semaphore_wait(pa_semaphore *s) { 57 int ret; 58 pa_assert(s); 59 60 do { 61 ret = sem_wait(&s->sem); 62 } while (ret < 0 && errno == EINTR); 63 64 pa_assert(ret == 0); 65} 66 67pa_semaphore* pa_static_semaphore_get(pa_static_semaphore *s, unsigned value) { 68 pa_semaphore *m; 69 70 pa_assert(s); 71 72 /* First, check if already initialized and short cut */ 73 if ((m = pa_atomic_ptr_load(&s->ptr))) 74 return m; 75 76 /* OK, not initialized, so let's allocate, and fill in */ 77 m = pa_semaphore_new(value); 78 if ((pa_atomic_ptr_cmpxchg(&s->ptr, NULL, m))) 79 return m; 80 81 pa_semaphore_free(m); 82 83 /* Him, filling in failed, so someone else must have filled in 84 * already */ 85 pa_assert_se(m = pa_atomic_ptr_load(&s->ptr)); 86 return m; 87} 88