src/thread/pthread/SDL_syssem.c
author Ryan C. Gordon
Mon, 23 Jan 2017 12:06:10 -0500
changeset 10837 c2f241c2f6ad
parent 10737 3406a0f8b041
child 11811 5d94cb6b24d3
permissions -rw-r--r--
audio: Fix same bug as last commit, but for _mm_bslli_si128 vs _mm_slli_si128.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2017 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     retval = sem_wait(&sem->sem);
    95     if (retval < 0) {
    96         retval = SDL_SetError("sem_wait() failed");
    97     }
    98     return retval;
    99 }
   100 
   101 int
   102 SDL_SemWaitTimeout(SDL_sem * sem, Uint32 timeout)
   103 {
   104     int retval;
   105 #ifdef HAVE_SEM_TIMEDWAIT
   106 #ifndef HAVE_CLOCK_GETTIME
   107     struct timeval now;
   108 #endif
   109     struct timespec ts_timeout;
   110 #else
   111     Uint32 end;
   112 #endif
   113 
   114     if (!sem) {
   115         return SDL_SetError("Passed a NULL semaphore");
   116     }
   117 
   118     /* Try the easy cases first */
   119     if (timeout == 0) {
   120         return SDL_SemTryWait(sem);
   121     }
   122     if (timeout == SDL_MUTEX_MAXWAIT) {
   123         return SDL_SemWait(sem);
   124     }
   125 
   126 #ifdef HAVE_SEM_TIMEDWAIT
   127     /* Setup the timeout. sem_timedwait doesn't wait for
   128     * a lapse of time, but until we reach a certain time.
   129     * This time is now plus the timeout.
   130     */
   131 #ifdef HAVE_CLOCK_GETTIME
   132     clock_gettime(CLOCK_REALTIME, &ts_timeout);
   133 
   134     /* Add our timeout to current time */
   135     ts_timeout.tv_nsec += (timeout % 1000) * 1000000;
   136     ts_timeout.tv_sec += timeout / 1000;
   137 #else
   138     gettimeofday(&now, NULL);
   139 
   140     /* Add our timeout to current time */
   141     ts_timeout.tv_sec = now.tv_sec + (timeout / 1000);
   142     ts_timeout.tv_nsec = (now.tv_usec + (timeout % 1000) * 1000) * 1000;
   143 #endif
   144 
   145     /* Wrap the second if needed */
   146     if (ts_timeout.tv_nsec > 1000000000) {
   147         ts_timeout.tv_sec += 1;
   148         ts_timeout.tv_nsec -= 1000000000;
   149     }
   150 
   151     /* Wait. */
   152     do {
   153         retval = sem_timedwait(&sem->sem, &ts_timeout);
   154     } while (retval < 0 && errno == EINTR);
   155 
   156     if (retval < 0) {
   157         if (errno == ETIMEDOUT) {
   158             retval = SDL_MUTEX_TIMEDOUT;
   159         } else {
   160             SDL_SetError("sem_timedwait returned an error: %s", strerror(errno));
   161         }
   162     }
   163 #else
   164     end = SDL_GetTicks() + timeout;
   165     while ((retval = SDL_SemTryWait(sem)) == SDL_MUTEX_TIMEDOUT) {
   166         if (SDL_TICKS_PASSED(SDL_GetTicks(), end)) {
   167             break;
   168         }
   169         SDL_Delay(1);
   170     }
   171 #endif /* HAVE_SEM_TIMEDWAIT */
   172 
   173     return retval;
   174 }
   175 
   176 Uint32
   177 SDL_SemValue(SDL_sem * sem)
   178 {
   179     int ret = 0;
   180     if (sem) {
   181         sem_getvalue(&sem->sem, &ret);
   182         if (ret < 0) {
   183             ret = 0;
   184         }
   185     }
   186     return (Uint32) ret;
   187 }
   188 
   189 int
   190 SDL_SemPost(SDL_sem * sem)
   191 {
   192     int retval;
   193 
   194     if (!sem) {
   195         return SDL_SetError("Passed a NULL semaphore");
   196     }
   197 
   198     retval = sem_post(&sem->sem);
   199     if (retval < 0) {
   200         SDL_SetError("sem_post() failed");
   201     }
   202     return retval;
   203 }
   204 
   205 #endif /* __MACOSX__ */
   206 /* vi: set ts=4 sw=4 expandtab: */