cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

SDL_syssem.c (4551B)


      1/*
      2  Simple DirectMedia Layer
      3  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
      4
      5  This software is provided 'as-is', without any express or implied
      6  warranty.  In no event will the authors be held liable for any damages
      7  arising from the use of this software.
      8
      9  Permission is granted to anyone to use this software for any purpose,
     10  including commercial applications, and to alter it and redistribute it
     11  freely, subject to the following restrictions:
     12
     13  1. The origin of this software must not be misrepresented; you must not
     14     claim that you wrote the original software. If you use this software
     15     in a product, an acknowledgment in the product documentation would be
     16     appreciated but is not required.
     17  2. Altered source versions must be plainly marked as such, and must not be
     18     misrepresented as being the original software.
     19  3. This notice may not be removed or altered from any source distribution.
     20*/
     21#include "../../SDL_internal.h"
     22
     23#include <errno.h>
     24#include <pthread.h>
     25#include <semaphore.h>
     26#include <sys/time.h>
     27
     28#include "SDL_thread.h"
     29#include "SDL_timer.h"
     30
     31/* Wrapper around POSIX 1003.1b semaphores */
     32
     33#if defined(__MACOSX__) || defined(__IPHONEOS__)
     34/* Mac OS X doesn't support sem_getvalue() as of version 10.4 */
     35#include "../generic/SDL_syssem.c"
     36#else
     37
     38struct SDL_semaphore
     39{
     40    sem_t sem;
     41};
     42
     43/* Create a semaphore, initialized with value */
     44SDL_sem *
     45SDL_CreateSemaphore(Uint32 initial_value)
     46{
     47    SDL_sem *sem = (SDL_sem *) SDL_malloc(sizeof(SDL_sem));
     48    if (sem) {
     49        if (sem_init(&sem->sem, 0, initial_value) < 0) {
     50            SDL_SetError("sem_init() failed");
     51            SDL_free(sem);
     52            sem = NULL;
     53        }
     54    } else {
     55        SDL_OutOfMemory();
     56    }
     57    return sem;
     58}
     59
     60void
     61SDL_DestroySemaphore(SDL_sem * sem)
     62{
     63    if (sem) {
     64        sem_destroy(&sem->sem);
     65        SDL_free(sem);
     66    }
     67}
     68
     69int
     70SDL_SemTryWait(SDL_sem * sem)
     71{
     72    int retval;
     73
     74    if (!sem) {
     75        return SDL_SetError("Passed a NULL semaphore");
     76    }
     77    retval = SDL_MUTEX_TIMEDOUT;
     78    if (sem_trywait(&sem->sem) == 0) {
     79        retval = 0;
     80    }
     81    return retval;
     82}
     83
     84int
     85SDL_SemWait(SDL_sem * sem)
     86{
     87    int retval;
     88
     89    if (!sem) {
     90        return SDL_SetError("Passed a NULL semaphore");
     91    }
     92
     93    retval = sem_wait(&sem->sem);
     94    if (retval < 0) {
     95        retval = SDL_SetError("sem_wait() failed");
     96    }
     97    return retval;
     98}
     99
    100int
    101SDL_SemWaitTimeout(SDL_sem * sem, Uint32 timeout)
    102{
    103    int retval;
    104#ifdef HAVE_SEM_TIMEDWAIT
    105    struct timeval now;
    106    struct timespec ts_timeout;
    107#else
    108    Uint32 end;
    109#endif
    110
    111    if (!sem) {
    112        return SDL_SetError("Passed a NULL semaphore");
    113    }
    114
    115    /* Try the easy cases first */
    116    if (timeout == 0) {
    117        return SDL_SemTryWait(sem);
    118    }
    119    if (timeout == SDL_MUTEX_MAXWAIT) {
    120        return SDL_SemWait(sem);
    121    }
    122
    123#ifdef HAVE_SEM_TIMEDWAIT
    124    /* Setup the timeout. sem_timedwait doesn't wait for
    125    * a lapse of time, but until we reach a certain time.
    126    * This time is now plus the timeout.
    127    */
    128    gettimeofday(&now, NULL);
    129
    130    /* Add our timeout to current time */
    131    now.tv_usec += (timeout % 1000) * 1000;
    132    now.tv_sec += timeout / 1000;
    133
    134    /* Wrap the second if needed */
    135    if ( now.tv_usec >= 1000000 ) {
    136        now.tv_usec -= 1000000;
    137        now.tv_sec ++;
    138    }
    139
    140    /* Convert to timespec */
    141    ts_timeout.tv_sec = now.tv_sec;
    142    ts_timeout.tv_nsec = now.tv_usec * 1000;
    143
    144    /* Wait. */
    145    do {
    146        retval = sem_timedwait(&sem->sem, &ts_timeout);
    147    } while (retval < 0 && errno == EINTR);
    148
    149    if (retval < 0) {
    150        if (errno == ETIMEDOUT) {
    151            retval = SDL_MUTEX_TIMEDOUT;
    152        } else {
    153            SDL_SetError("sem_timedwait returned an error: %s", strerror(errno));
    154        }
    155    }
    156#else
    157    end = SDL_GetTicks() + timeout;
    158    while ((retval = SDL_SemTryWait(sem)) == SDL_MUTEX_TIMEDOUT) {
    159        if (SDL_TICKS_PASSED(SDL_GetTicks(), end)) {
    160            break;
    161        }
    162        SDL_Delay(1);
    163    }
    164#endif /* HAVE_SEM_TIMEDWAIT */
    165
    166    return retval;
    167}
    168
    169Uint32
    170SDL_SemValue(SDL_sem * sem)
    171{
    172    int ret = 0;
    173    if (sem) {
    174        sem_getvalue(&sem->sem, &ret);
    175        if (ret < 0) {
    176            ret = 0;
    177        }
    178    }
    179    return (Uint32) ret;
    180}
    181
    182int
    183SDL_SemPost(SDL_sem * sem)
    184{
    185    int retval;
    186
    187    if (!sem) {
    188        return SDL_SetError("Passed a NULL semaphore");
    189    }
    190
    191    retval = sem_post(&sem->sem);
    192    if (retval < 0) {
    193        SDL_SetError("sem_post() failed");
    194    }
    195    return retval;
    196}
    197
    198#endif /* __MACOSX__ */
    199/* vi: set ts=4 sw=4 expandtab: */