sdl

FORK: Simple Directmedia Layer
git clone https://git.neptards.moe/neptards/sdl.git
Log | Files | Refs

SDL_syssem.c (4850B)


      1 /*
      2   Simple DirectMedia Layer
      3   Copyright (C) 1997-2020 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 #include <time.h>
     28 
     29 #include "SDL_thread.h"
     30 #include "SDL_timer.h"
     31 
     32 /* Wrapper around POSIX 1003.1b semaphores */
     33 
     34 #if defined(__MACOSX__) || defined(__IPHONEOS__)
     35 /* Mac OS X doesn't support sem_getvalue() as of version 10.4 */
     36 #include "../generic/SDL_syssem.c"
     37 #else
     38 
     39 struct SDL_semaphore
     40 {
     41     sem_t sem;
     42 };
     43 
     44 /* Create a semaphore, initialized with value */
     45 SDL_sem *
     46 SDL_CreateSemaphore(Uint32 initial_value)
     47 {
     48     SDL_sem *sem = (SDL_sem *) SDL_malloc(sizeof(SDL_sem));
     49     if (sem) {
     50         if (sem_init(&sem->sem, 0, initial_value) < 0) {
     51             SDL_SetError("sem_init() failed");
     52             SDL_free(sem);
     53             sem = NULL;
     54         }
     55     } else {
     56         SDL_OutOfMemory();
     57     }
     58     return sem;
     59 }
     60 
     61 void
     62 SDL_DestroySemaphore(SDL_sem * sem)
     63 {
     64     if (sem) {
     65         sem_destroy(&sem->sem);
     66         SDL_free(sem);
     67     }
     68 }
     69 
     70 int
     71 SDL_SemTryWait(SDL_sem * sem)
     72 {
     73     int retval;
     74 
     75     if (!sem) {
     76         return SDL_SetError("Passed a NULL semaphore");
     77     }
     78     retval = SDL_MUTEX_TIMEDOUT;
     79     if (sem_trywait(&sem->sem) == 0) {
     80         retval = 0;
     81     }
     82     return retval;
     83 }
     84 
     85 int
     86 SDL_SemWait(SDL_sem * sem)
     87 {
     88     int retval;
     89 
     90     if (!sem) {
     91         return SDL_SetError("Passed a NULL semaphore");
     92     }
     93 
     94     do {
     95         retval = sem_wait(&sem->sem);
     96     } while (retval < 0 && errno == EINTR);
     97 
     98     if (retval < 0) {
     99         retval = SDL_SetError("sem_wait() failed");
    100     }
    101     return retval;
    102 }
    103 
    104 int
    105 SDL_SemWaitTimeout(SDL_sem * sem, Uint32 timeout)
    106 {
    107     int retval;
    108 #ifdef HAVE_SEM_TIMEDWAIT
    109 #ifndef HAVE_CLOCK_GETTIME
    110     struct timeval now;
    111 #endif
    112     struct timespec ts_timeout;
    113 #else
    114     Uint32 end;
    115 #endif
    116 
    117     if (!sem) {
    118         return SDL_SetError("Passed a NULL semaphore");
    119     }
    120 
    121     /* Try the easy cases first */
    122     if (timeout == 0) {
    123         return SDL_SemTryWait(sem);
    124     }
    125     if (timeout == SDL_MUTEX_MAXWAIT) {
    126         return SDL_SemWait(sem);
    127     }
    128 
    129 #ifdef HAVE_SEM_TIMEDWAIT
    130     /* Setup the timeout. sem_timedwait doesn't wait for
    131     * a lapse of time, but until we reach a certain time.
    132     * This time is now plus the timeout.
    133     */
    134 #ifdef HAVE_CLOCK_GETTIME
    135     clock_gettime(CLOCK_REALTIME, &ts_timeout);
    136 
    137     /* Add our timeout to current time */
    138     ts_timeout.tv_nsec += (timeout % 1000) * 1000000;
    139     ts_timeout.tv_sec += timeout / 1000;
    140 #else
    141     gettimeofday(&now, NULL);
    142 
    143     /* Add our timeout to current time */
    144     ts_timeout.tv_sec = now.tv_sec + (timeout / 1000);
    145     ts_timeout.tv_nsec = (now.tv_usec + (timeout % 1000) * 1000) * 1000;
    146 #endif
    147 
    148     /* Wrap the second if needed */
    149     if (ts_timeout.tv_nsec > 1000000000) {
    150         ts_timeout.tv_sec += 1;
    151         ts_timeout.tv_nsec -= 1000000000;
    152     }
    153 
    154     /* Wait. */
    155     do {
    156         retval = sem_timedwait(&sem->sem, &ts_timeout);
    157     } while (retval < 0 && errno == EINTR);
    158 
    159     if (retval < 0) {
    160         if (errno == ETIMEDOUT) {
    161             retval = SDL_MUTEX_TIMEDOUT;
    162         } else {
    163             SDL_SetError("sem_timedwait returned an error: %s", strerror(errno));
    164         }
    165     }
    166 #else
    167     end = SDL_GetTicks() + timeout;
    168     while ((retval = SDL_SemTryWait(sem)) == SDL_MUTEX_TIMEDOUT) {
    169         if (SDL_TICKS_PASSED(SDL_GetTicks(), end)) {
    170             break;
    171         }
    172         SDL_Delay(1);
    173     }
    174 #endif /* HAVE_SEM_TIMEDWAIT */
    175 
    176     return retval;
    177 }
    178 
    179 Uint32
    180 SDL_SemValue(SDL_sem * sem)
    181 {
    182     int ret = 0;
    183     if (sem) {
    184         sem_getvalue(&sem->sem, &ret);
    185         if (ret < 0) {
    186             ret = 0;
    187         }
    188     }
    189     return (Uint32) ret;
    190 }
    191 
    192 int
    193 SDL_SemPost(SDL_sem * sem)
    194 {
    195     int retval;
    196 
    197     if (!sem) {
    198         return SDL_SetError("Passed a NULL semaphore");
    199     }
    200 
    201     retval = sem_post(&sem->sem);
    202     if (retval < 0) {
    203         SDL_SetError("sem_post() failed");
    204     }
    205     return retval;
    206 }
    207 
    208 #endif /* __MACOSX__ */
    209 /* vi: set ts=4 sw=4 expandtab: */