153a5a1b3Sopenharmony_ci/*** 253a5a1b3Sopenharmony_ci This file is part of PulseAudio. 353a5a1b3Sopenharmony_ci 453a5a1b3Sopenharmony_ci Copyright 2006 Lennart Poettering 553a5a1b3Sopenharmony_ci Copyright 2013 Albert Zeyer 653a5a1b3Sopenharmony_ci 753a5a1b3Sopenharmony_ci PulseAudio is free software; you can redistribute it and/or modify 853a5a1b3Sopenharmony_ci it under the terms of the GNU Lesser General Public License as published 953a5a1b3Sopenharmony_ci by the Free Software Foundation; either version 2.1 of the License, 1053a5a1b3Sopenharmony_ci or (at your option) any later version. 1153a5a1b3Sopenharmony_ci 1253a5a1b3Sopenharmony_ci PulseAudio is distributed in the hope that it will be useful, but 1353a5a1b3Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 1453a5a1b3Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1553a5a1b3Sopenharmony_ci General Public License for more details. 1653a5a1b3Sopenharmony_ci 1753a5a1b3Sopenharmony_ci You should have received a copy of the GNU Lesser General Public License 1853a5a1b3Sopenharmony_ci along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. 1953a5a1b3Sopenharmony_ci***/ 2053a5a1b3Sopenharmony_ci 2153a5a1b3Sopenharmony_ci#ifdef HAVE_CONFIG_H 2253a5a1b3Sopenharmony_ci#include <config.h> 2353a5a1b3Sopenharmony_ci#endif 2453a5a1b3Sopenharmony_ci 2553a5a1b3Sopenharmony_ci#include <stdio.h> 2653a5a1b3Sopenharmony_ci#include <errno.h> 2753a5a1b3Sopenharmony_ci#include <pthread.h> 2853a5a1b3Sopenharmony_ci#include <semaphore.h> 2953a5a1b3Sopenharmony_ci#include <sys/types.h> 3053a5a1b3Sopenharmony_ci#include <unistd.h> 3153a5a1b3Sopenharmony_ci 3253a5a1b3Sopenharmony_ci#include <pulse/xmalloc.h> 3353a5a1b3Sopenharmony_ci#include <pulsecore/macro.h> 3453a5a1b3Sopenharmony_ci#include <pulsecore/atomic.h> 3553a5a1b3Sopenharmony_ci#include <pulsecore/core-util.h> 3653a5a1b3Sopenharmony_ci 3753a5a1b3Sopenharmony_ci#include "semaphore.h" 3853a5a1b3Sopenharmony_ci 3953a5a1b3Sopenharmony_ci/* OSX doesn't support unnamed semaphores (via sem_init). 4053a5a1b3Sopenharmony_ci * Thus, we use a counter to give them enumerated names. */ 4153a5a1b3Sopenharmony_cistatic pa_atomic_t id_counter = PA_ATOMIC_INIT(0); 4253a5a1b3Sopenharmony_ci 4353a5a1b3Sopenharmony_cistruct pa_semaphore { 4453a5a1b3Sopenharmony_ci sem_t *sem; 4553a5a1b3Sopenharmony_ci int id; 4653a5a1b3Sopenharmony_ci}; 4753a5a1b3Sopenharmony_ci 4853a5a1b3Sopenharmony_cistatic char *sem_name(char *fn, size_t l, int id) { 4953a5a1b3Sopenharmony_ci pa_snprintf(fn, l, "/pulse-sem-%u-%u", getpid(), id); 5053a5a1b3Sopenharmony_ci return fn; 5153a5a1b3Sopenharmony_ci} 5253a5a1b3Sopenharmony_ci 5353a5a1b3Sopenharmony_cipa_semaphore *pa_semaphore_new(unsigned value) { 5453a5a1b3Sopenharmony_ci pa_semaphore *s; 5553a5a1b3Sopenharmony_ci char fn[32]; 5653a5a1b3Sopenharmony_ci 5753a5a1b3Sopenharmony_ci s = pa_xnew(pa_semaphore, 1); 5853a5a1b3Sopenharmony_ci s->id = pa_atomic_inc(&id_counter); 5953a5a1b3Sopenharmony_ci sem_name(fn, sizeof(fn), s->id); 6053a5a1b3Sopenharmony_ci sem_unlink(fn); /* in case an old stale semaphore is left around */ 6153a5a1b3Sopenharmony_ci pa_assert_se(s->sem = sem_open(fn, O_CREAT|O_EXCL, 0700, value)); 6253a5a1b3Sopenharmony_ci pa_assert(s->sem != SEM_FAILED); 6353a5a1b3Sopenharmony_ci return s; 6453a5a1b3Sopenharmony_ci} 6553a5a1b3Sopenharmony_ci 6653a5a1b3Sopenharmony_civoid pa_semaphore_free(pa_semaphore *s) { 6753a5a1b3Sopenharmony_ci char fn[32]; 6853a5a1b3Sopenharmony_ci 6953a5a1b3Sopenharmony_ci pa_assert(s); 7053a5a1b3Sopenharmony_ci 7153a5a1b3Sopenharmony_ci pa_assert_se(sem_close(s->sem) == 0); 7253a5a1b3Sopenharmony_ci sem_name(fn, sizeof(fn), s->id); 7353a5a1b3Sopenharmony_ci pa_assert_se(sem_unlink(fn) == 0); 7453a5a1b3Sopenharmony_ci pa_xfree(s); 7553a5a1b3Sopenharmony_ci} 7653a5a1b3Sopenharmony_ci 7753a5a1b3Sopenharmony_civoid pa_semaphore_post(pa_semaphore *s) { 7853a5a1b3Sopenharmony_ci pa_assert(s); 7953a5a1b3Sopenharmony_ci pa_assert_se(sem_post(s->sem) == 0); 8053a5a1b3Sopenharmony_ci} 8153a5a1b3Sopenharmony_ci 8253a5a1b3Sopenharmony_civoid pa_semaphore_wait(pa_semaphore *s) { 8353a5a1b3Sopenharmony_ci int ret; 8453a5a1b3Sopenharmony_ci 8553a5a1b3Sopenharmony_ci pa_assert(s); 8653a5a1b3Sopenharmony_ci 8753a5a1b3Sopenharmony_ci do { 8853a5a1b3Sopenharmony_ci ret = sem_wait(s->sem); 8953a5a1b3Sopenharmony_ci } while (ret < 0 && errno == EINTR); 9053a5a1b3Sopenharmony_ci 9153a5a1b3Sopenharmony_ci pa_assert(ret == 0); 9253a5a1b3Sopenharmony_ci} 93