SDL 2.0
SDL_syssem.c
Go to the documentation of this file.
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2019 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_internal.h"
22
23#include <errno.h>
24#include <pthread.h>
25#include <semaphore.h>
26#include <sys/time.h>
27#include <time.h>
28
29#include "SDL_thread.h"
30#include "SDL_timer.h"
31
32/* Wrapper around POSIX 1003.1b semaphores */
33
34#if defined(__MACOSX__) || defined(__IPHONEOS__)
35/* Mac OS X doesn't support sem_getvalue() as of version 10.4 */
36#include "../generic/SDL_syssem.c"
37#else
38
39struct SDL_semaphore
40{
41 sem_t sem;
42};
43
44/* Create a semaphore, initialized with value */
45SDL_sem *
47{
48 SDL_sem *sem = (SDL_sem *) SDL_malloc(sizeof(SDL_sem));
49 if (sem) {
50 if (sem_init(&sem->sem, 0, initial_value) < 0) {
51 SDL_SetError("sem_init() failed");
53 sem = NULL;
54 }
55 } else {
57 }
58 return sem;
59}
60
61void
63{
64 if (sem) {
65 sem_destroy(&sem->sem);
67 }
68}
69
70int
72{
73 int retval;
74
75 if (!sem) {
76 return SDL_SetError("Passed a NULL semaphore");
77 }
79 if (sem_trywait(&sem->sem) == 0) {
80 retval = 0;
81 }
82 return retval;
83}
84
85int
86SDL_SemWait(SDL_sem * sem)
87{
88 int retval;
89
90 if (!sem) {
91 return SDL_SetError("Passed a NULL semaphore");
92 }
93
94 do {
95 retval = sem_wait(&sem->sem);
96 } while (retval < 0 && errno == EINTR);
97
98 if (retval < 0) {
99 retval = SDL_SetError("sem_wait() failed");
100 }
101 return retval;
102}
103
104int
106{
107 int retval;
108#ifdef HAVE_SEM_TIMEDWAIT
109#ifndef HAVE_CLOCK_GETTIME
110 struct timeval now;
111#endif
112 struct timespec ts_timeout;
113#else
114 Uint32 end;
115#endif
116
117 if (!sem) {
118 return SDL_SetError("Passed a NULL semaphore");
119 }
120
121 /* Try the easy cases first */
122 if (timeout == 0) {
123 return SDL_SemTryWait(sem);
124 }
125 if (timeout == SDL_MUTEX_MAXWAIT) {
126 return SDL_SemWait(sem);
127 }
128
129#ifdef HAVE_SEM_TIMEDWAIT
130 /* Setup the timeout. sem_timedwait doesn't wait for
131 * a lapse of time, but until we reach a certain time.
132 * This time is now plus the timeout.
133 */
134#ifdef HAVE_CLOCK_GETTIME
135 clock_gettime(CLOCK_REALTIME, &ts_timeout);
136
137 /* Add our timeout to current time */
138 ts_timeout.tv_nsec += (timeout % 1000) * 1000000;
139 ts_timeout.tv_sec += timeout / 1000;
140#else
141 gettimeofday(&now, NULL);
142
143 /* Add our timeout to current time */
144 ts_timeout.tv_sec = now.tv_sec + (timeout / 1000);
145 ts_timeout.tv_nsec = (now.tv_usec + (timeout % 1000) * 1000) * 1000;
146#endif
147
148 /* Wrap the second if needed */
149 if (ts_timeout.tv_nsec > 1000000000) {
150 ts_timeout.tv_sec += 1;
151 ts_timeout.tv_nsec -= 1000000000;
152 }
153
154 /* Wait. */
155 do {
156 retval = sem_timedwait(&sem->sem, &ts_timeout);
157 } while (retval < 0 && errno == EINTR);
158
159 if (retval < 0) {
160 if (errno == ETIMEDOUT) {
162 } else {
163 SDL_SetError("sem_timedwait returned an error: %s", strerror(errno));
164 }
165 }
166#else
170 break;
171 }
172 SDL_Delay(1);
173 }
174#endif /* HAVE_SEM_TIMEDWAIT */
175
176 return retval;
177}
178
179Uint32
181{
182 int ret = 0;
183 if (sem) {
184 sem_getvalue(&sem->sem, &ret);
185 if (ret < 0) {
186 ret = 0;
187 }
188 }
189 return (Uint32) ret;
190}
191
192int
193SDL_SemPost(SDL_sem * sem)
194{
195 int retval;
196
197 if (!sem) {
198 return SDL_SetError("Passed a NULL semaphore");
199 }
200
201 retval = sem_post(&sem->sem);
202 if (retval < 0) {
203 SDL_SetError("sem_post() failed");
204 }
205 return retval;
206}
207
208#endif /* __MACOSX__ */
209/* vi: set ts=4 sw=4 expandtab: */
#define SDL_SetError
#define SDL_malloc
#define SDL_free
#define SDL_Delay
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
#define SDL_MUTEX_TIMEDOUT
Definition: SDL_mutex.h:44
#define SDL_MUTEX_MAXWAIT
Definition: SDL_mutex.h:49
GLuint GLuint end
Definition: SDL_opengl.h:1571
GLbitfield GLuint64 timeout
uint32_t Uint32
Definition: SDL_stdinc.h:203
Uint32 SDL_GetTicks(void)
Get the number of milliseconds since the SDL library initialization.
#define SDL_TICKS_PASSED(A, B)
Compare SDL ticks values, and return true if A has passed B.
Definition: SDL_timer.h:56
#define NULL
Definition: begin_code.h:167
int SDL_SemWait(SDL_sem *sem)
Definition: SDL_syssem.c:180
int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
Definition: SDL_syssem.c:150
SDL_sem * SDL_CreateSemaphore(Uint32 initial_value)
Definition: SDL_syssem.c:85
void SDL_DestroySemaphore(SDL_sem *sem)
Definition: SDL_syssem.c:111
int SDL_SemPost(SDL_sem *sem)
Definition: SDL_syssem.c:200
Uint32 SDL_SemValue(SDL_sem *sem)
Definition: SDL_syssem.c:186
int SDL_SemTryWait(SDL_sem *sem)
Definition: SDL_syssem.c:130
SDL_bool retval
static SDL_sem * sem
Definition: testsem.c:23