src/thread/irix/SDL_syssem.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 29 May 2006 04:04:35 +0000
branchSDL-1.3
changeset 1668 4da1ee79c9af
parent 1662 782fd950bd46
permissions -rw-r--r--
more tweaking indent options
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2006 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Lesser General Public
     7     License as published by the Free Software Foundation; either
     8     version 2.1 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Lesser General Public License for more details.
    14 
    15     You should have received a copy of the GNU Lesser General Public
    16     License along with this library; if not, write to the Free Software
    17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 #include "SDL_config.h"
    23 
    24 #include "SDL_thread.h"
    25 #include "SDL_timer.h"
    26 
    27 
    28 #include <stdio.h>
    29 #include <stdlib.h>
    30 #include <sys/types.h>
    31 #include <sys/ipc.h>
    32 #include <sys/sem.h>
    33 #include <errno.h>
    34 
    35 #include "SDL_error.h"
    36 #include "SDL_thread.h"
    37 
    38 
    39 struct SDL_semaphore
    40 {
    41     int id;
    42 };
    43 
    44 /* Not defined by many operating systems, use configure to detect */
    45 /*
    46 #if !defined(HAVE_SEMUN)
    47 union semun {
    48 	int val;
    49 	struct semid_ds *buf;
    50 	ushort *array;
    51 };
    52 #endif
    53 */
    54 
    55 static struct sembuf op_trywait[2] = {
    56     {0, -1, (IPC_NOWAIT | SEM_UNDO)}    /* Decrement semaphore, no block */
    57 };
    58 static struct sembuf op_wait[2] = {
    59     {0, -1, SEM_UNDO}           /* Decrement semaphore */
    60 };
    61 static struct sembuf op_post[1] = {
    62     {0, 1, (IPC_NOWAIT | SEM_UNDO)}     /* Increment semaphore */
    63 };
    64 
    65 /* Create a blockable semaphore */
    66 SDL_sem *
    67 SDL_CreateSemaphore(Uint32 initial_value)
    68 {
    69     extern int _creating_thread_lock;   /* SDL_threads.c */
    70     SDL_sem *sem;
    71     union semun init;
    72 
    73     sem = (SDL_sem *) SDL_malloc(sizeof(*sem));
    74     if (sem == NULL) {
    75         SDL_OutOfMemory();
    76         return (NULL);
    77     }
    78     sem->id = semget(IPC_PRIVATE, 1, (0600 | IPC_CREAT));
    79     if (sem->id < 0) {
    80         SDL_SetError("Couldn't create semaphore");
    81         SDL_free(sem);
    82         return (NULL);
    83     }
    84     init.val = initial_value;   /* Initialize semaphore */
    85     semctl(sem->id, 0, SETVAL, init);
    86     return (sem);
    87 }
    88 
    89 void
    90 SDL_DestroySemaphore(SDL_sem * sem)
    91 {
    92     if (sem) {
    93 #ifdef __IRIX__
    94         semctl(sem->id, 0, IPC_RMID);
    95 #else
    96         union semun dummy;
    97         dummy.val = 0;
    98         semctl(sem->id, 0, IPC_RMID, dummy);
    99 #endif
   100         SDL_free(sem);
   101     }
   102 }
   103 
   104 int
   105 SDL_SemTryWait(SDL_sem * sem)
   106 {
   107     int retval;
   108 
   109     if (!sem) {
   110         SDL_SetError("Passed a NULL semaphore");
   111         return -1;
   112     }
   113 
   114     retval = 0;
   115   tryagain:
   116     if (semop(sem->id, op_trywait, 1) < 0) {
   117         if (errno == EINTR) {
   118             goto tryagain;
   119         }
   120         retval = SDL_MUTEX_TIMEDOUT;
   121     }
   122     return retval;
   123 }
   124 
   125 int
   126 SDL_SemWait(SDL_sem * sem)
   127 {
   128     int retval;
   129 
   130     if (!sem) {
   131         SDL_SetError("Passed a NULL semaphore");
   132         return -1;
   133     }
   134 
   135     retval = 0;
   136   tryagain:
   137     if (semop(sem->id, op_wait, 1) < 0) {
   138         if (errno == EINTR) {
   139             goto tryagain;
   140         }
   141         SDL_SetError("Semaphore operation error");
   142         retval = -1;
   143     }
   144     return retval;
   145 }
   146 
   147 int
   148 SDL_SemWaitTimeout(SDL_sem * sem, Uint32 timeout)
   149 {
   150     int retval;
   151 
   152     if (!sem) {
   153         SDL_SetError("Passed a NULL semaphore");
   154         return -1;
   155     }
   156 
   157     /* Try the easy cases first */
   158     if (timeout == 0) {
   159         return SDL_SemTryWait(sem);
   160     }
   161     if (timeout == SDL_MUTEX_MAXWAIT) {
   162         return SDL_SemWait(sem);
   163     }
   164 
   165     /* Ack!  We have to busy wait... */
   166     timeout += SDL_GetTicks();
   167     do {
   168         retval = SDL_SemTryWait(sem);
   169         if (retval == 0) {
   170             break;
   171         }
   172         SDL_Delay(1);
   173     }
   174     while (SDL_GetTicks() < timeout);
   175 
   176     return retval;
   177 }
   178 
   179 Uint32
   180 SDL_SemValue(SDL_sem * sem)
   181 {
   182     int semval;
   183     Uint32 value;
   184 
   185     value = 0;
   186     if (sem) {
   187       tryagain:
   188 #ifdef __IRIX__
   189         semval = semctl(sem->id, 0, GETVAL);
   190 #else
   191         {
   192             union semun arg;
   193             arg.val = 0;
   194             semval = semctl(sem->id, 0, GETVAL, arg);
   195         }
   196 #endif
   197         if (semval < 0) {
   198             if (errno == EINTR) {
   199                 goto tryagain;
   200             }
   201         } else {
   202             value = (Uint32) semval;
   203         }
   204     }
   205     return value;
   206 }
   207 
   208 int
   209 SDL_SemPost(SDL_sem * sem)
   210 {
   211     int retval;
   212 
   213     if (!sem) {
   214         SDL_SetError("Passed a NULL semaphore");
   215         return -1;
   216     }
   217 
   218     retval = 0;
   219   tryagain:
   220     if (semop(sem->id, op_post, 1) < 0) {
   221         if (errno == EINTR) {
   222             goto tryagain;
   223         }
   224         SDL_SetError("Semaphore operation error");
   225         retval = -1;
   226     }
   227     return retval;
   228 }
   229 
   230 /* vi: set ts=4 sw=4 expandtab: */