Home | History | Annotate | Download | only in irix
      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 (at) 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 	int id;
     41 };
     42 
     43 /* Not defined by many operating systems, use configure to detect */
     44 /*
     45 #if !defined(HAVE_SEMUN)
     46 union semun {
     47 	int val;
     48 	struct semid_ds *buf;
     49 	ushort *array;
     50 };
     51 #endif
     52 */
     53 
     54 static struct sembuf op_trywait[2] = {
     55 	{ 0, -1, (IPC_NOWAIT|SEM_UNDO) } /* Decrement semaphore, no block */
     56 };
     57 static struct sembuf op_wait[2] = {
     58 	{ 0, -1, SEM_UNDO }		/* Decrement semaphore */
     59 };
     60 static struct sembuf op_post[1] = {
     61 	{ 0, 1, (IPC_NOWAIT|SEM_UNDO) }	/* Increment semaphore */
     62 };
     63 
     64 /* Create a blockable semaphore */
     65 SDL_sem *SDL_CreateSemaphore(Uint32 initial_value)
     66 {
     67 	extern int _creating_thread_lock;	/* SDL_threads.c */
     68 	SDL_sem *sem;
     69 	union semun init;
     70 
     71 	sem = (SDL_sem *)SDL_malloc(sizeof(*sem));
     72 	if ( sem == NULL ) {
     73 		SDL_OutOfMemory();
     74 		return(NULL);
     75 	}
     76 	sem->id = semget(IPC_PRIVATE, 1, (0600|IPC_CREAT));
     77 	if ( sem->id < 0 ) {
     78 		SDL_SetError("Couldn't create semaphore");
     79 		SDL_free(sem);
     80 		return(NULL);
     81 	}
     82 	init.val = initial_value;	/* Initialize semaphore */
     83 	semctl(sem->id, 0, SETVAL, init);
     84 	return(sem);
     85 }
     86 
     87 void SDL_DestroySemaphore(SDL_sem *sem)
     88 {
     89 	if ( sem ) {
     90 #ifdef __IRIX__
     91 		semctl(sem->id, 0, IPC_RMID);
     92 #else
     93 		union semun dummy;
     94 		dummy.val = 0;
     95 		semctl(sem->id, 0, IPC_RMID, dummy);
     96 #endif
     97 		SDL_free(sem);
     98 	}
     99 }
    100 
    101 int SDL_SemTryWait(SDL_sem *sem)
    102 {
    103 	int retval;
    104 
    105 	if ( ! sem ) {
    106 		SDL_SetError("Passed a NULL semaphore");
    107 		return -1;
    108 	}
    109 
    110 	retval = 0;
    111   tryagain:
    112 	if ( semop(sem->id, op_trywait, 1) < 0 ) {
    113 		if ( errno == EINTR ) {
    114 			goto tryagain;
    115 		}
    116 		retval = SDL_MUTEX_TIMEDOUT;
    117 	}
    118 	return retval;
    119 }
    120 
    121 int SDL_SemWait(SDL_sem *sem)
    122 {
    123 	int retval;
    124 
    125 	if ( ! sem ) {
    126 		SDL_SetError("Passed a NULL semaphore");
    127 		return -1;
    128 	}
    129 
    130 	retval = 0;
    131   tryagain:
    132 	if ( semop(sem->id, op_wait, 1) < 0 ) {
    133 		if ( errno == EINTR ) {
    134 			goto tryagain;
    135 		}
    136 		SDL_SetError("Semaphore operation error");
    137 		retval = -1;
    138 	}
    139 	return retval;
    140 }
    141 
    142 int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
    143 {
    144 	int retval;
    145 
    146 	if ( ! sem ) {
    147 		SDL_SetError("Passed a NULL semaphore");
    148 		return -1;
    149 	}
    150 
    151 	/* Try the easy cases first */
    152 	if ( timeout == 0 ) {
    153 		return SDL_SemTryWait(sem);
    154 	}
    155 	if ( timeout == SDL_MUTEX_MAXWAIT ) {
    156 		return SDL_SemWait(sem);
    157 	}
    158 
    159 	/* Ack!  We have to busy wait... */
    160 	timeout += SDL_GetTicks();
    161 	do {
    162 		retval = SDL_SemTryWait(sem);
    163 		if ( retval == 0 ) {
    164 			break;
    165 		}
    166 		SDL_Delay(1);
    167 	} while ( SDL_GetTicks() < timeout );
    168 
    169 	return retval;
    170 }
    171 
    172 Uint32 SDL_SemValue(SDL_sem *sem)
    173 {
    174 	int semval;
    175 	Uint32 value;
    176 
    177 	value = 0;
    178 	if ( sem ) {
    179 	  tryagain:
    180 #ifdef __IRIX__
    181 		semval = semctl(sem->id, 0, GETVAL);
    182 #else
    183 		{
    184 		union semun arg;
    185 		arg.val = 0;
    186 		semval = semctl(sem->id, 0, GETVAL, arg);
    187 		}
    188 #endif
    189 		if ( semval < 0 ) {
    190 			if ( errno == EINTR ) {
    191 				goto tryagain;
    192 			}
    193 		} else {
    194 			value = (Uint32)semval;
    195 		}
    196 	}
    197 	return value;
    198 }
    199 
    200 int SDL_SemPost(SDL_sem *sem)
    201 {
    202 	int retval;
    203 
    204 	if ( ! sem ) {
    205 		SDL_SetError("Passed a NULL semaphore");
    206 		return -1;
    207 	}
    208 
    209 	retval = 0;
    210   tryagain:
    211 	if ( semop(sem->id, op_post, 1) < 0 ) {
    212 		if ( errno == EINTR ) {
    213 			goto tryagain;
    214 		}
    215 		SDL_SetError("Semaphore operation error");
    216 		retval = -1;
    217 	}
    218 	return retval;
    219 }
    220