Path: blob/master/thirdparty/sdl/thread/pthread/SDL_syssem.c
10279 views
/*1Simple DirectMedia Layer2Copyright (C) 1997-2025 Sam Lantinga <[email protected]>34This software is provided 'as-is', without any express or implied5warranty. In no event will the authors be held liable for any damages6arising from the use of this software.78Permission is granted to anyone to use this software for any purpose,9including commercial applications, and to alter it and redistribute it10freely, subject to the following restrictions:11121. The origin of this software must not be misrepresented; you must not13claim that you wrote the original software. If you use this software14in a product, an acknowledgment in the product documentation would be15appreciated but is not required.162. Altered source versions must be plainly marked as such, and must not be17misrepresented as being the original software.183. This notice may not be removed or altered from any source distribution.19*/20#include "SDL_internal.h"2122#include <errno.h>23#include <pthread.h>24#include <semaphore.h>25#include <sys/time.h>26#include <time.h>2728// Wrapper around POSIX 1003.1b semaphores2930#if defined(SDL_PLATFORM_MACOS) || defined(SDL_PLATFORM_IOS)31// macOS doesn't support sem_getvalue() as of version 10.432#include "../generic/SDL_syssem.c"33#else3435struct SDL_Semaphore36{37sem_t sem;38};3940// Create a semaphore, initialized with value41SDL_Semaphore *SDL_CreateSemaphore(Uint32 initial_value)42{43SDL_Semaphore *sem = (SDL_Semaphore *)SDL_malloc(sizeof(SDL_Semaphore));44if (sem) {45if (sem_init(&sem->sem, 0, initial_value) < 0) {46SDL_SetError("sem_init() failed");47SDL_free(sem);48sem = NULL;49}50}51return sem;52}5354void SDL_DestroySemaphore(SDL_Semaphore *sem)55{56if (sem) {57sem_destroy(&sem->sem);58SDL_free(sem);59}60}6162bool SDL_WaitSemaphoreTimeoutNS(SDL_Semaphore *sem, Sint64 timeoutNS)63{64#ifdef HAVE_SEM_TIMEDWAIT65#ifndef HAVE_CLOCK_GETTIME66struct timeval now;67#endif68struct timespec ts_timeout;69#else70Uint64 stop_time;71#endif7273if (!sem) {74return true;75}7677// Try the easy cases first78if (timeoutNS == 0) {79return (sem_trywait(&sem->sem) == 0);80}8182if (timeoutNS < 0) {83int rc;84do {85rc = sem_wait(&sem->sem);86} while (rc < 0 && errno == EINTR);8788return (rc == 0);89}9091#ifdef HAVE_SEM_TIMEDWAIT92/* Setup the timeout. sem_timedwait doesn't wait for93* a lapse of time, but until we reach a certain time.94* This time is now plus the timeout.95*/96#ifdef HAVE_CLOCK_GETTIME97clock_gettime(CLOCK_REALTIME, &ts_timeout);9899// Add our timeout to current time100ts_timeout.tv_sec += (timeoutNS / SDL_NS_PER_SECOND);101ts_timeout.tv_nsec += (timeoutNS % SDL_NS_PER_SECOND);102#else103gettimeofday(&now, NULL);104105// Add our timeout to current time106ts_timeout.tv_sec = now.tv_sec + (timeoutNS / SDL_NS_PER_SECOND);107ts_timeout.tv_nsec = SDL_US_TO_NS(now.tv_usec) + (timeoutNS % SDL_NS_PER_SECOND);108#endif109110// Wrap the second if needed111while (ts_timeout.tv_nsec >= 1000000000) {112ts_timeout.tv_sec += 1;113ts_timeout.tv_nsec -= 1000000000;114}115116// Wait.117int rc;118do {119rc = sem_timedwait(&sem->sem, &ts_timeout);120} while (rc < 0 && errno == EINTR);121122return (rc == 0);123#else124stop_time = SDL_GetTicksNS() + timeoutNS;125while (sem_trywait(&sem->sem) != 0) {126if (SDL_GetTicksNS() >= stop_time) {127return false;128}129SDL_DelayNS(100);130}131return true;132#endif // HAVE_SEM_TIMEDWAIT133}134135Uint32 SDL_GetSemaphoreValue(SDL_Semaphore *sem)136{137int ret = 0;138139if (!sem) {140return 0;141}142143sem_getvalue(&sem->sem, &ret);144if (ret < 0) {145ret = 0;146}147return (Uint32)ret;148}149150void SDL_SignalSemaphore(SDL_Semaphore *sem)151{152if (!sem) {153return;154}155156sem_post(&sem->sem);157}158159#endif // SDL_PLATFORM_MACOS160161162