From 6fadaf66c8ee9917dcdfae7067ab2496b860339b Mon Sep 17 00:00:00 2001 From: Misaki Kasumi Date: Wed, 2 Oct 2024 22:06:43 +0800 Subject: [PATCH] osdep: remove semaphore-mac It is only used in one place in ao_coreaudio_utils.c, and can be replaced by condvar. Removing it can reduce the maintenance burden. --- audio/out/ao_coreaudio.c | 9 +++ audio/out/ao_coreaudio_exclusive.c | 7 ++ audio/out/ao_coreaudio_utils.c | 24 +++--- audio/out/ao_coreaudio_utils.h | 6 ++ meson.build | 1 - osdep/semaphore-mac.c | 117 ----------------------------- osdep/semaphore.h | 38 ---------- 7 files changed, 35 insertions(+), 167 deletions(-) delete mode 100644 osdep/semaphore-mac.c delete mode 100644 osdep/semaphore.h diff --git a/audio/out/ao_coreaudio.c b/audio/out/ao_coreaudio.c index 1b0f99a9d1a9a..1d43aca24d770 100644 --- a/audio/out/ao_coreaudio.c +++ b/audio/out/ao_coreaudio.c @@ -34,6 +34,9 @@ #define IDLE_TIME 7 * NSEC_PER_SEC struct priv { + // This must be put in the front + struct coreaudio_cb_sem sem; + AudioDeviceID device; AudioUnit audio_unit; @@ -543,6 +546,12 @@ const struct ao_driver audio_out_coreaudio = { .hotplug_uninit = hotplug_uninit, .list_devs = ca_get_device_list, .priv_size = sizeof(struct priv), + .priv_defaults = &(const struct priv){ + .sem = (struct coreaudio_cb_sem){ + .mutex = MP_STATIC_MUTEX_INITIALIZER, + .cond = MP_STATIC_COND_INITIALIZER, + } + }, .options = (const struct m_option[]){ {"change-physical-format", OPT_BOOL(change_physical_format)}, {0} diff --git a/audio/out/ao_coreaudio_exclusive.c b/audio/out/ao_coreaudio_exclusive.c index dbe7b94ed73d1..4b973c48cc11b 100644 --- a/audio/out/ao_coreaudio_exclusive.c +++ b/audio/out/ao_coreaudio_exclusive.c @@ -52,6 +52,9 @@ #include "audio/out/ao_coreaudio_utils.h" struct priv { + // This must be put in the front + struct coreaudio_cb_sem sem; + AudioDeviceID device; // selected device bool paused; @@ -459,6 +462,10 @@ const struct ao_driver audio_out_coreaudio_exclusive = { .list_devs = ca_get_device_list, .priv_size = sizeof(struct priv), .priv_defaults = &(const struct priv){ + .sem = (struct coreaudio_cb_sem){ + .mutex = MP_STATIC_MUTEX_INITIALIZER, + .cond = MP_STATIC_COND_INITIALIZER, + }, .hog_pid = -1, .stream = 0, .stream_idx = -1, diff --git a/audio/out/ao_coreaudio_utils.c b/audio/out/ao_coreaudio_utils.c index f06d3fae26852..aaaa6396a9f2b 100644 --- a/audio/out/ao_coreaudio_utils.c +++ b/audio/out/ao_coreaudio_utils.c @@ -25,7 +25,6 @@ #include "audio/out/ao_coreaudio_utils.h" #include "osdep/timer.h" #include "osdep/endian.h" -#include "osdep/semaphore.h" #include "audio/format.h" #if HAVE_COREAUDIO || HAVE_AVFOUNDATION @@ -460,23 +459,23 @@ static OSStatus ca_change_format_listener( const AudioObjectPropertyAddress addresses[], void *data) { - mp_sem_t *sem = data; - mp_sem_post(sem); + struct coreaudio_cb_sem *sem = data; + mp_mutex_lock(&sem->mutex); + mp_cond_broadcast(&sem->cond); + mp_mutex_unlock(&sem->mutex); return noErr; } bool ca_change_physical_format_sync(struct ao *ao, AudioStreamID stream, AudioStreamBasicDescription change_format) { + struct coreaudio_cb_sem *sem = ao->priv; + OSStatus err = noErr; bool format_set = false; ca_print_asbd(ao, "setting stream physical format:", &change_format); - mp_sem_t wakeup; - if (mp_sem_init(&wakeup, 0, 0)) - MP_HANDLE_OOM(0); - AudioStreamBasicDescription prev_format; err = CA_GET(stream, kAudioStreamPropertyPhysicalFormat, &prev_format); CHECK_CA_ERROR("can't get current physical format"); @@ -492,9 +491,11 @@ bool ca_change_physical_format_sync(struct ao *ao, AudioStreamID stream, err = AudioObjectAddPropertyListener(stream, &p_addr, ca_change_format_listener, - &wakeup); + sem); CHECK_CA_ERROR("can't add property listener during format change"); + mp_mutex_lock(&sem->mutex); + /* Change the format. */ err = CA_SET(stream, kAudioStreamPropertyPhysicalFormat, &change_format); CHECK_CA_WARN("error changing physical format"); @@ -512,12 +513,14 @@ bool ca_change_physical_format_sync(struct ao *ao, AudioStreamID stream, if (format_set) break; - if (mp_sem_timedwait(&wakeup, wait_until)) { + if (mp_cond_timedwait_until(&sem->cond, &sem->mutex, wait_until)) { MP_VERBOSE(ao, "reached timeout\n"); break; } } + mp_mutex_unlock(&sem->mutex); + ca_print_asbd(ao, "actual format in use:", &actual_format); if (!format_set) { @@ -530,11 +533,10 @@ bool ca_change_physical_format_sync(struct ao *ao, AudioStreamID stream, err = AudioObjectRemovePropertyListener(stream, &p_addr, ca_change_format_listener, - &wakeup); + sem); CHECK_CA_ERROR("can't remove property listener"); coreaudio_error: - mp_sem_destroy(&wakeup); return format_set; } #endif diff --git a/audio/out/ao_coreaudio_utils.h b/audio/out/ao_coreaudio_utils.h index d11506c059b53..85f674b7be10f 100644 --- a/audio/out/ao_coreaudio_utils.h +++ b/audio/out/ao_coreaudio_utils.h @@ -28,6 +28,12 @@ #include "audio/out/ao.h" #include "internal.h" #include "osdep/utils-mac.h" +#include "osdep/threads.h" + +struct coreaudio_cb_sem { + mp_mutex mutex; + mp_cond cond; +}; bool check_ca_st(struct ao *ao, int level, OSStatus code, const char *message); diff --git a/meson.build b/meson.build index b4d6af5428fa7..d163d898adf43 100644 --- a/meson.build +++ b/meson.build @@ -251,7 +251,6 @@ sources = files( ## osdep 'osdep/io.c', - 'osdep/semaphore-mac.c', 'osdep/subprocess.c', 'osdep/timer.c', diff --git a/osdep/semaphore-mac.c b/osdep/semaphore-mac.c deleted file mode 100644 index bfb4d571f0aca..0000000000000 --- a/osdep/semaphore-mac.c +++ /dev/null @@ -1,117 +0,0 @@ -/* Copyright (C) 2017 the mpv developers - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "osdep/semaphore.h" - -#ifdef MP_SEMAPHORE_EMULATION - -#include -#include -#include -#include -#include - -#include -#include "io.h" -#include "timer.h" - -int mp_sem_init(mp_sem_t *sem, int pshared, unsigned int value) -{ - if (pshared) { - errno = ENOSYS; - return -1; - } - if (value > INT_MAX) { - errno = EINVAL; - return -1; - } - if (mp_make_wakeup_pipe(sem->wakeup_pipe) < 0) - return -1; - sem->count = 0; - mp_mutex_init(&sem->lock); - return 0; -} - -int mp_sem_wait(mp_sem_t *sem) -{ - return mp_sem_timedwait(sem, -1); -} - -int mp_sem_trywait(mp_sem_t *sem) -{ - int r = -1; - mp_mutex_lock(&sem->lock); - if (sem->count == 0) { - char buf[1024]; - ssize_t s = read(sem->wakeup_pipe[0], buf, sizeof(buf)); - if (s > 0 && s <= INT_MAX - sem->count) // can't handle overflows correctly - sem->count += s; - } - if (sem->count > 0) { - sem->count -= 1; - r = 0; - } - mp_mutex_unlock(&sem->lock); - if (r < 0) - errno = EAGAIN; - return r; -} - -int mp_sem_timedwait(mp_sem_t *sem, int64_t until) -{ - while (1) { - if (!mp_sem_trywait(sem)) - return 0; - - int timeout = 0; - if (until == -1) { - timeout = -1; - } else if (until >= 0) { - timeout = (until - mp_time_ns()) / MP_TIME_MS_TO_NS(1); - timeout = MPCLAMP(timeout, 0, INT_MAX); - } else { - assert(false && "Invalid mp_time value!"); - } - - struct pollfd fd = {.fd = sem->wakeup_pipe[0], .events = POLLIN}; - int r = poll(&fd, 1, timeout); - if (r < 0) - return -1; - if (r == 0) { - errno = ETIMEDOUT; - return -1; - } - } -} - -int mp_sem_post(mp_sem_t *sem) -{ - if (write(sem->wakeup_pipe[1], &(char){0}, 1) == 1) - return 0; - // Actually we can't handle overflow fully correctly, because we can't - // check sem->count atomically, while still being AS-safe. - errno = EOVERFLOW; - return -1; -} - -int mp_sem_destroy(mp_sem_t *sem) -{ - close(sem->wakeup_pipe[0]); - close(sem->wakeup_pipe[1]); - mp_mutex_destroy(&sem->lock); - return 0; -} - -#endif diff --git a/osdep/semaphore.h b/osdep/semaphore.h deleted file mode 100644 index 3448fb20b05ac..0000000000000 --- a/osdep/semaphore.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef MP_SEMAPHORE_H_ -#define MP_SEMAPHORE_H_ - -#ifdef __APPLE__ - -#include -#include - -// macOS provides non-working empty stubs, so we emulate them. -// This should be AS-safe, but cancellation issues were ignored. -// sem_getvalue() is not provided. -// sem_post() won't always correctly return an error on overflow. -// Process-shared semantics are not provided. - - -#define MP_SEMAPHORE_EMULATION - -#include "osdep/threads.h" - -#define MP_SEM_VALUE_MAX 4096 - -typedef struct { - int wakeup_pipe[2]; - mp_mutex lock; - // protected by lock - unsigned int count; -} mp_sem_t; - -int mp_sem_init(mp_sem_t *sem, int pshared, unsigned int value); -int mp_sem_wait(mp_sem_t *sem); -int mp_sem_trywait(mp_sem_t *sem); -int mp_sem_timedwait(mp_sem_t *sem, int64_t until); -int mp_sem_post(mp_sem_t *sem); -int mp_sem_destroy(mp_sem_t *sem); - -#endif - -#endif