SDL-1.2.14
[sdl_omap.git] / src / thread / irix / SDL_syssem.c
CommitLineData
e14743d1 1/*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2009 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
39struct SDL_semaphore {
40 int id;
41};
42
43/* Not defined by many operating systems, use configure to detect */
44/*
45#if !defined(HAVE_SEMUN)
46union semun {
47 int val;
48 struct semid_ds *buf;
49 ushort *array;
50};
51#endif
52*/
53
54static struct sembuf op_trywait[2] = {
55 { 0, -1, (IPC_NOWAIT|SEM_UNDO) } /* Decrement semaphore, no block */
56};
57static struct sembuf op_wait[2] = {
58 { 0, -1, SEM_UNDO } /* Decrement semaphore */
59};
60static struct sembuf op_post[1] = {
61 { 0, 1, (IPC_NOWAIT|SEM_UNDO) } /* Increment semaphore */
62};
63
64/* Create a blockable semaphore */
65SDL_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
87void 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
101int 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
121int 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
142int 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
172Uint32 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
200int 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}