1
mirror of https://github.com/mpv-player/mpv synced 2024-10-30 04:46:41 +01:00
mpv/osdep/semaphore_osx.c
wm4 bbfafb5614 Fix use of ISC license
The license text refers a "above copyright notice", so I guess it'd be
good to actually provide such a notice.

Add the license to some files that were missing it (since in theory, our
Copyright file says that such files are LGPL by default).

Remove the questionable remarks about the license in the client API.
2017-04-15 16:20:00 +02:00

124 lines
3.3 KiB
C

/* 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 <unistd.h>
#include <poll.h>
#include <limits.h>
#include <sys/time.h>
#include <errno.h>
#include "osdep/io.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;
pthread_mutex_init(&sem->lock, NULL);
return 0;
}
int mp_sem_wait(mp_sem_t *sem)
{
return mp_sem_timedwait(sem, NULL);
}
int mp_sem_trywait(mp_sem_t *sem)
{
int r = -1;
pthread_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;
}
pthread_mutex_unlock(&sem->lock);
if (r < 0)
errno = EAGAIN;
return r;
}
int mp_sem_timedwait(mp_sem_t *sem, const struct timespec *abs_timeout)
{
while (1) {
if (!mp_sem_trywait(sem))
return 0;
int timeout_ms = -1;
if (abs_timeout) {
timeout_ms = 0;
// OSX does not provide clock_gettime() either.
struct timeval tv;
gettimeofday(&tv, NULL);
if (abs_timeout->tv_sec >= tv.tv_sec) {
long long msec = (abs_timeout->tv_sec - tv.tv_sec) * 1000LL +
abs_timeout->tv_nsec / 1000LL / 1000LL - tv.tv_usec / 1000LL;
if (msec > INT_MAX)
msec = INT_MAX;
if (msec < 0)
msec = 0;
timeout_ms = msec;
}
}
struct pollfd fd = {.fd = sem->wakeup_pipe[0], .events = POLLIN};
int r = poll(&fd, 1, timeout_ms);
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]);
pthread_mutex_destroy(&sem->lock);
return 0;
}
#endif