146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    SDL - Simple DirectMedia Layer
346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Copyright (C) 1997-2006 Sam Lantinga
446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    This library is free software; you can redistribute it and/or
646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    modify it under the terms of the GNU Lesser General Public
746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    License as published by the Free Software Foundation; either
846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    version 2.1 of the License, or (at your option) any later version.
946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
1046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    This library is distributed in the hope that it will be useful,
1146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    but WITHOUT ANY WARRANTY; without even the implied warranty of
1246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Lesser General Public License for more details.
1446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
1546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    You should have received a copy of the GNU Lesser General Public
1646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    License along with this library; if not, write to the Free Software
1746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
1846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
1946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Sam Lantinga
2046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    slouken@libsdl.org
2146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
2246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
2346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <errno.h>
2446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
2546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_config.h"
2646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
2746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* An implementation of semaphores using mutexes and condition variables */
2846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
2946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_timer.h"
3046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_thread.h"
3146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_systhread_c.h"
3246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
3346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
3446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if SDL_THREADS_DISABLED
3546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
3646be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerSDL_sem *SDL_CreateSemaphore(Uint32 initial_value)
3746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
3846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_SetError("SDL not configured with thread support");
3946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return (SDL_sem *)0;
4046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
4146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
4246be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid SDL_DestroySemaphore(SDL_sem *sem)
4346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
4446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return;
4546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
4646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
4746be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerint SDL_SemTryWait(SDL_sem *sem)
4846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
4946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_SetError("SDL not configured with thread support");
5046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return -1;
5146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
5246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
5346be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerint SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
5446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
5546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_SetError("SDL not configured with thread support");
5646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return -1;
5746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
5846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
5946be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerint SDL_SemWait(SDL_sem *sem)
6046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
6146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_SetError("SDL not configured with thread support");
6246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return -1;
6346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
6446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
6546be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerUint32 SDL_SemValue(SDL_sem *sem)
6646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
6746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return 0;
6846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
6946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
7046be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerint SDL_SemPost(SDL_sem *sem)
7146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
7246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_SetError("SDL not configured with thread support");
7346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return -1;
7446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
7546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
7646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else
7746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
7846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <kos/sem.h>
7946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
8046be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstruct SDL_semaphore
8146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
8246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	semaphore_t sem;
8346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner};
8446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
8546be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerSDL_sem *SDL_CreateSemaphore(Uint32 initial_value)
8646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
8746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return (SDL_sem *)sem_create(initial_value);
8846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
8946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
9046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* WARNING:
9146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner   You cannot call this function when another thread is using the semaphore.
9246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
9346be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid SDL_DestroySemaphore(SDL_sem *sem)
9446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
9546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if ( ! sem ) {
9646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		SDL_SetError("Passed a NULL semaphore");
9746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		return;
9846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
9946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
10046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	sem_destroy(&sem->sem);
10146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
10246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
10346be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerint SDL_SemTryWait(SDL_sem *sem)
10446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
10546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int retval;
10646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
10746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if ( ! sem ) {
10846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		SDL_SetError("Passed a NULL semaphore");
10946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		return -1;
11046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
11146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
11246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	retval = sem_trywait(&sem->sem);
11346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if (retval==0) return 0;
11446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	else return SDL_MUTEX_TIMEDOUT;
11546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
11646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return retval;
11746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
11846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
11946be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerint SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
12046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
12146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int retval;
12246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
12346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if ( ! sem ) {
12446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		SDL_SetError("Passed a NULL semaphore");
12546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		return -1;
12646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
12746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
12846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* A timeout of 0 is an easy case */
12946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if ( timeout == 0 ) {
13046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		return SDL_SemTryWait(sem);
13146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
13246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
13346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	retval = sem_wait_timed(&sem->sem,timeout);
13446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if (retval==-1) retval= SDL_MUTEX_TIMEDOUT;
13546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
13646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return retval;
13746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
13846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
13946be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerint SDL_SemWait(SDL_sem *sem)
14046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
14146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int retval;
14246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
14346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if ( ! sem ) {
14446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		SDL_SetError("Passed a NULL semaphore");
14546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		return -1;
14646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
14746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
14846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	while ( ((retval = sem_wait(&sem->sem)) == -1) && (errno == EINTR) ) {}
14946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return retval;
15046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
15146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
15246be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerUint32 SDL_SemValue(SDL_sem *sem)
15346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
15446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if ( ! sem ) {
15546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		SDL_SetError("Passed a NULL semaphore");
15646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		return -1;
15746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
15846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
15946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return sem_count(&sem->sem);
16046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
16146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
16246be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerint SDL_SemPost(SDL_sem *sem)
16346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
16446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if ( ! sem ) {
16546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		SDL_SetError("Passed a NULL semaphore");
16646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		return -1;
16746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
16846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
16946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	sem_signal(&sem->sem);
17046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return 0;
17146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
17246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
17346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* SDL_THREADS_DISABLED */
174