src/thread/pthread/SDL_syssem.c
author Ryan C. Gordon <icculus@icculus.org>
Thu, 13 Oct 2011 01:08:30 -0400
changeset 5981 75caa8a7d559
parent 5535 96594ac5fd1a
child 6138 4c64952a58fb
permissions -rw-r--r--
Fixed a whole slew of compiler warnings that -Wall exposed.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2011 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_config.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 
    38 struct SDL_semaphore
    39 {
    40     sem_t sem;
    41 };
    42 
    43 /* Create a semaphore, initialized with value */
    44 SDL_sem *
    45 SDL_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 
    60 void
    61 SDL_DestroySemaphore(SDL_sem * sem)
    62 {
    63     if (sem) {
    64         sem_destroy(&sem->sem);
    65         SDL_free(sem);
    66     }
    67 }
    68 
    69 int
    70 SDL_SemTryWait(SDL_sem * sem)
    71 {
    72     int retval;
    73 
    74     if (!sem) {
    75         SDL_SetError("Passed a NULL semaphore");
    76         return -1;
    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         SDL_SetError("Passed a NULL semaphore");
    92         return -1;
    93     }
    94 
    95     retval = sem_wait(&sem->sem);
    96     if (retval < 0) {
    97         SDL_SetError("sem_wait() failed");
    98     }
    99     return retval;
   100 }
   101 
   102 int
   103 SDL_SemWaitTimeout(SDL_sem * sem, Uint32 timeout)
   104 {
   105     int retval;
   106     struct timeval now;
   107     struct timespec ts_timeout;
   108 
   109     if (!sem) {
   110         SDL_SetError("Passed a NULL semaphore");
   111         return -1;
   112     }
   113 
   114     /* Try the easy cases first */
   115     if (timeout == 0) {
   116         return SDL_SemTryWait(sem);
   117     }
   118     if (timeout == SDL_MUTEX_MAXWAIT) {
   119         return SDL_SemWait(sem);
   120     }
   121 
   122     /* Setup the timeout. sem_timedwait doesn't wait for
   123     * a lapse of time, but until we reach a certain time.
   124     * This time is now plus the timeout.
   125     */
   126     gettimeofday(&now, NULL);
   127 
   128     /* Add our timeout to current time */
   129     now.tv_usec += (timeout % 1000) * 1000;
   130     now.tv_sec += timeout / 1000;
   131 
   132     /* Wrap the second if needed */
   133     if ( now.tv_usec >= 1000000 ) {
   134         now.tv_usec -= 1000000;
   135         now.tv_sec ++;
   136     }
   137 
   138     /* Convert to timespec */
   139     ts_timeout.tv_sec = now.tv_sec;
   140     ts_timeout.tv_nsec = now.tv_usec * 1000;
   141 
   142     /* Wait. */
   143     do {
   144         retval = sem_timedwait(&sem->sem, &ts_timeout);
   145     } while (retval < 0 && errno == EINTR);
   146 
   147     if (retval < 0) {
   148         SDL_SetError("sem_timedwait() failed");
   149     }
   150 
   151     return retval;
   152 }
   153 
   154 Uint32
   155 SDL_SemValue(SDL_sem * sem)
   156 {
   157     int ret = 0;
   158     if (sem) {
   159         sem_getvalue(&sem->sem, &ret);
   160         if (ret < 0) {
   161             ret = 0;
   162         }
   163     }
   164     return (Uint32) ret;
   165 }
   166 
   167 int
   168 SDL_SemPost(SDL_sem * sem)
   169 {
   170     int retval;
   171 
   172     if (!sem) {
   173         SDL_SetError("Passed a NULL semaphore");
   174         return -1;
   175     }
   176 
   177     retval = sem_post(&sem->sem);
   178     if (retval < 0) {
   179         SDL_SetError("sem_post() failed");
   180     }
   181     return retval;
   182 }
   183 
   184 #endif /* __MACOSX__ */
   185 /* vi: set ts=4 sw=4 expandtab: */