|
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 |
|
23 #include <errno.h> |
|
24 |
|
25 #include "SDL_config.h" |
|
26 |
|
27 /* RISC OS semiphores based on linux code */ |
|
28 |
|
29 |
|
30 #include "SDL_timer.h" |
|
31 #include "SDL_thread.h" |
|
32 #include "SDL_systhread_c.h" |
|
33 |
|
34 #if !SDL_THREADS_DISABLED |
|
35 |
|
36 SDL_sem *SDL_CreateSemaphore(Uint32 initial_value) |
|
37 { |
|
38 SDL_SetError("SDL not configured with thread support"); |
|
39 return (SDL_sem *)0; |
|
40 } |
|
41 |
|
42 void SDL_DestroySemaphore(SDL_sem *sem) |
|
43 { |
|
44 return; |
|
45 } |
|
46 |
|
47 int SDL_SemTryWait(SDL_sem *sem) |
|
48 { |
|
49 SDL_SetError("SDL not configured with thread support"); |
|
50 return -1; |
|
51 } |
|
52 |
|
53 int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) |
|
54 { |
|
55 SDL_SetError("SDL not configured with thread support"); |
|
56 return -1; |
|
57 } |
|
58 |
|
59 int SDL_SemWait(SDL_sem *sem) |
|
60 { |
|
61 SDL_SetError("SDL not configured with thread support"); |
|
62 return -1; |
|
63 } |
|
64 |
|
65 Uint32 SDL_SemValue(SDL_sem *sem) |
|
66 { |
|
67 return 0; |
|
68 } |
|
69 |
|
70 int SDL_SemPost(SDL_sem *sem) |
|
71 { |
|
72 SDL_SetError("SDL not configured with thread support"); |
|
73 return -1; |
|
74 } |
|
75 |
|
76 #else |
|
77 |
|
78 |
|
79 #include <unistd.h> /* For getpid() */ |
|
80 #include <pthread.h> |
|
81 #include <semaphore.h> |
|
82 |
|
83 struct SDL_semaphore { |
|
84 sem_t *sem; |
|
85 sem_t sem_data; |
|
86 }; |
|
87 |
|
88 /* Create a semaphore, initialized with value */ |
|
89 SDL_sem *SDL_CreateSemaphore(Uint32 initial_value) |
|
90 { |
|
91 SDL_sem *sem = (SDL_sem *) SDL_malloc(sizeof(SDL_sem)); |
|
92 if ( sem ) { |
|
93 if ( sem_init(&sem->sem_data, 0, initial_value) < 0 ) { |
|
94 SDL_SetError("sem_init() failed"); |
|
95 SDL_free(sem); |
|
96 sem = NULL; |
|
97 } else { |
|
98 sem->sem = &sem->sem_data; |
|
99 } |
|
100 } else { |
|
101 SDL_OutOfMemory(); |
|
102 } |
|
103 return sem; |
|
104 } |
|
105 |
|
106 void SDL_DestroySemaphore(SDL_sem *sem) |
|
107 { |
|
108 if ( sem ) { |
|
109 sem_destroy(sem->sem); |
|
110 SDL_free(sem); |
|
111 } |
|
112 } |
|
113 |
|
114 int SDL_SemTryWait(SDL_sem *sem) |
|
115 { |
|
116 int retval; |
|
117 |
|
118 if ( ! sem ) { |
|
119 SDL_SetError("Passed a NULL semaphore"); |
|
120 return -1; |
|
121 } |
|
122 retval = SDL_MUTEX_TIMEDOUT; |
|
123 if ( sem_trywait(sem->sem) == 0 ) { |
|
124 retval = 0; |
|
125 } |
|
126 return retval; |
|
127 } |
|
128 |
|
129 int SDL_SemWait(SDL_sem *sem) |
|
130 { |
|
131 int retval; |
|
132 |
|
133 if ( ! sem ) { |
|
134 SDL_SetError("Passed a NULL semaphore"); |
|
135 return -1; |
|
136 } |
|
137 |
|
138 while ( ((retval = sem_wait(sem->sem)) == -1) && (errno == EINTR) ) {} |
|
139 if ( retval < 0 ) { |
|
140 SDL_SetError("sem_wait() failed"); |
|
141 } |
|
142 return retval; |
|
143 } |
|
144 |
|
145 int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) |
|
146 { |
|
147 int retval; |
|
148 |
|
149 if ( ! sem ) { |
|
150 SDL_SetError("Passed a NULL semaphore"); |
|
151 return -1; |
|
152 } |
|
153 |
|
154 /* Try the easy cases first */ |
|
155 if ( timeout == 0 ) { |
|
156 return SDL_SemTryWait(sem); |
|
157 } |
|
158 if ( timeout == SDL_MUTEX_MAXWAIT ) { |
|
159 return SDL_SemWait(sem); |
|
160 } |
|
161 |
|
162 /* Ack! We have to busy wait... */ |
|
163 timeout += SDL_GetTicks(); |
|
164 do { |
|
165 retval = SDL_SemTryWait(sem); |
|
166 if ( retval == 0 ) { |
|
167 break; |
|
168 } |
|
169 SDL_Delay(1); |
|
170 } while ( SDL_GetTicks() < timeout ); |
|
171 |
|
172 return retval; |
|
173 } |
|
174 |
|
175 Uint32 SDL_SemValue(SDL_sem *sem) |
|
176 { |
|
177 int ret = 0; |
|
178 if ( sem ) { |
|
179 sem_getvalue(sem->sem, &ret); |
|
180 if ( ret < 0 ) { |
|
181 ret = 0; |
|
182 } |
|
183 } |
|
184 return (Uint32)ret; |
|
185 } |
|
186 |
|
187 int SDL_SemPost(SDL_sem *sem) |
|
188 { |
|
189 int retval; |
|
190 |
|
191 if ( ! sem ) { |
|
192 SDL_SetError("Passed a NULL semaphore"); |
|
193 return -1; |
|
194 } |
|
195 |
|
196 retval = sem_post(sem->sem); |
|
197 if ( retval < 0 ) { |
|
198 SDL_SetError("sem_post() failed"); |
|
199 } |
|
200 return retval; |
|
201 } |
|
202 |
|
203 #endif /* !SDL_THREADS_DISABLED */ |