- Added SDL, libjpeg and libpng
- Added Android project and Java files
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* These are functions that need to be implemented by a port of SDL */
|
||||
|
||||
#ifndef _SDL_systhread_h
|
||||
#define _SDL_systhread_h
|
||||
|
||||
#include "SDL_thread.h"
|
||||
|
||||
/* This function creates a thread, passing args to SDL_RunThread(),
|
||||
saves a system-dependent thread id in thread->id, and returns 0
|
||||
on success.
|
||||
*/
|
||||
#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
|
||||
extern int SDL_SYS_CreateThread(SDL_Thread * thread, void *args,
|
||||
pfnSDL_CurrentBeginThread pfnBeginThread,
|
||||
pfnSDL_CurrentEndThread pfnEndThread);
|
||||
#else
|
||||
extern int SDL_SYS_CreateThread(SDL_Thread * thread, void *args);
|
||||
#endif
|
||||
|
||||
/* This function does any necessary setup in the child thread */
|
||||
extern void SDL_SYS_SetupThread(void);
|
||||
|
||||
/* This function sets the current thread priority */
|
||||
extern int SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority);
|
||||
|
||||
/* This function waits for the thread to finish and frees any data
|
||||
allocated by SDL_SYS_CreateThread()
|
||||
*/
|
||||
extern void SDL_SYS_WaitThread(SDL_Thread * thread);
|
||||
|
||||
#endif /* _SDL_systhread_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,315 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* System independent thread management routines for SDL */
|
||||
|
||||
#include "SDL_mutex.h"
|
||||
#include "SDL_thread.h"
|
||||
#include "SDL_thread_c.h"
|
||||
#include "SDL_systhread.h"
|
||||
|
||||
#define ARRAY_CHUNKSIZE 32
|
||||
/* The array of threads currently active in the application
|
||||
(except the main thread)
|
||||
The manipulation of an array here is safer than using a linked list.
|
||||
*/
|
||||
static int SDL_maxthreads = 0;
|
||||
static int SDL_numthreads = 0;
|
||||
static SDL_Thread **SDL_Threads = NULL;
|
||||
static SDL_mutex *thread_lock = NULL;
|
||||
|
||||
static int
|
||||
SDL_ThreadsInit(void)
|
||||
{
|
||||
int retval;
|
||||
|
||||
retval = 0;
|
||||
thread_lock = SDL_CreateMutex();
|
||||
if (thread_lock == NULL) {
|
||||
retval = -1;
|
||||
}
|
||||
return (retval);
|
||||
}
|
||||
|
||||
/* This should never be called...
|
||||
If this is called by SDL_Quit(), we don't know whether or not we should
|
||||
clean up threads here. If any threads are still running after this call,
|
||||
they will no longer have access to any per-thread data.
|
||||
*/
|
||||
#if 0
|
||||
static void
|
||||
SDL_ThreadsQuit(void)
|
||||
{
|
||||
SDL_mutex *mutex;
|
||||
|
||||
mutex = thread_lock;
|
||||
thread_lock = NULL;
|
||||
if (mutex != NULL) {
|
||||
SDL_DestroyMutex(mutex);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Routines for manipulating the thread list */
|
||||
static void
|
||||
SDL_AddThread(SDL_Thread * thread)
|
||||
{
|
||||
/* WARNING:
|
||||
If the very first threads are created simultaneously, then
|
||||
there could be a race condition causing memory corruption.
|
||||
In practice, this isn't a problem because by definition there
|
||||
is only one thread running the first time this is called.
|
||||
*/
|
||||
if (!thread_lock) {
|
||||
if (SDL_ThreadsInit() < 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
SDL_mutexP(thread_lock);
|
||||
|
||||
/* Expand the list of threads, if necessary */
|
||||
#ifdef DEBUG_THREADS
|
||||
printf("Adding thread (%d already - %d max)\n",
|
||||
SDL_numthreads, SDL_maxthreads);
|
||||
#endif
|
||||
if (SDL_numthreads == SDL_maxthreads) {
|
||||
SDL_Thread **threads;
|
||||
threads = (SDL_Thread **) SDL_realloc(SDL_Threads,
|
||||
(SDL_maxthreads +
|
||||
ARRAY_CHUNKSIZE) *
|
||||
(sizeof *threads));
|
||||
if (threads == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
goto done;
|
||||
}
|
||||
SDL_maxthreads += ARRAY_CHUNKSIZE;
|
||||
SDL_Threads = threads;
|
||||
}
|
||||
SDL_Threads[SDL_numthreads++] = thread;
|
||||
done:
|
||||
SDL_mutexV(thread_lock);
|
||||
}
|
||||
|
||||
static void
|
||||
SDL_DelThread(SDL_Thread * thread)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!thread_lock) {
|
||||
return;
|
||||
}
|
||||
SDL_mutexP(thread_lock);
|
||||
for (i = 0; i < SDL_numthreads; ++i) {
|
||||
if (thread == SDL_Threads[i]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i < SDL_numthreads) {
|
||||
if (--SDL_numthreads > 0) {
|
||||
while (i < SDL_numthreads) {
|
||||
SDL_Threads[i] = SDL_Threads[i + 1];
|
||||
++i;
|
||||
}
|
||||
} else {
|
||||
SDL_maxthreads = 0;
|
||||
SDL_free(SDL_Threads);
|
||||
SDL_Threads = NULL;
|
||||
}
|
||||
#ifdef DEBUG_THREADS
|
||||
printf("Deleting thread (%d left - %d max)\n",
|
||||
SDL_numthreads, SDL_maxthreads);
|
||||
#endif
|
||||
}
|
||||
SDL_mutexV(thread_lock);
|
||||
|
||||
#if 0 /* There could be memory corruption if another thread is starting */
|
||||
if (SDL_Threads == NULL) {
|
||||
SDL_ThreadsQuit();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* The default (non-thread-safe) global error variable */
|
||||
static SDL_error SDL_global_error;
|
||||
|
||||
/* Routine to get the thread-specific error variable */
|
||||
SDL_error *
|
||||
SDL_GetErrBuf(void)
|
||||
{
|
||||
SDL_error *errbuf;
|
||||
|
||||
errbuf = &SDL_global_error;
|
||||
if (SDL_Threads) {
|
||||
int i;
|
||||
SDL_threadID this_thread;
|
||||
|
||||
this_thread = SDL_ThreadID();
|
||||
SDL_mutexP(thread_lock);
|
||||
for (i = 0; i < SDL_numthreads; ++i) {
|
||||
if (this_thread == SDL_Threads[i]->threadid) {
|
||||
errbuf = &SDL_Threads[i]->errbuf;
|
||||
break;
|
||||
}
|
||||
}
|
||||
SDL_mutexV(thread_lock);
|
||||
}
|
||||
return (errbuf);
|
||||
}
|
||||
|
||||
|
||||
/* Arguments and callback to setup and run the user thread function */
|
||||
typedef struct
|
||||
{
|
||||
int (SDLCALL * func) (void *);
|
||||
void *data;
|
||||
SDL_Thread *info;
|
||||
SDL_sem *wait;
|
||||
} thread_args;
|
||||
|
||||
void
|
||||
SDL_RunThread(void *data)
|
||||
{
|
||||
thread_args *args;
|
||||
int (SDLCALL * userfunc) (void *);
|
||||
void *userdata;
|
||||
int *statusloc;
|
||||
|
||||
/* Perform any system-dependent setup
|
||||
- this function cannot fail, and cannot use SDL_SetError()
|
||||
*/
|
||||
SDL_SYS_SetupThread();
|
||||
|
||||
/* Get the thread id */
|
||||
args = (thread_args *) data;
|
||||
args->info->threadid = SDL_ThreadID();
|
||||
|
||||
/* Figure out what function to run */
|
||||
userfunc = args->func;
|
||||
userdata = args->data;
|
||||
statusloc = &args->info->status;
|
||||
|
||||
/* Wake up the parent thread */
|
||||
SDL_SemPost(args->wait);
|
||||
|
||||
/* Run the function */
|
||||
*statusloc = userfunc(userdata);
|
||||
}
|
||||
|
||||
#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
|
||||
#undef SDL_CreateThread
|
||||
DECLSPEC SDL_Thread *SDLCALL
|
||||
SDL_CreateThread(int (SDLCALL * fn) (void *), void *data,
|
||||
pfnSDL_CurrentBeginThread pfnBeginThread,
|
||||
pfnSDL_CurrentEndThread pfnEndThread)
|
||||
#else
|
||||
DECLSPEC SDL_Thread *SDLCALL
|
||||
SDL_CreateThread(int (SDLCALL * fn) (void *), void *data)
|
||||
#endif
|
||||
{
|
||||
SDL_Thread *thread;
|
||||
thread_args *args;
|
||||
int ret;
|
||||
|
||||
/* Allocate memory for the thread info structure */
|
||||
thread = (SDL_Thread *) SDL_malloc(sizeof(*thread));
|
||||
if (thread == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
return (NULL);
|
||||
}
|
||||
SDL_memset(thread, 0, (sizeof *thread));
|
||||
thread->status = -1;
|
||||
|
||||
/* Set up the arguments for the thread */
|
||||
args = (thread_args *) SDL_malloc(sizeof(*args));
|
||||
if (args == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
SDL_free(thread);
|
||||
return (NULL);
|
||||
}
|
||||
args->func = fn;
|
||||
args->data = data;
|
||||
args->info = thread;
|
||||
args->wait = SDL_CreateSemaphore(0);
|
||||
if (args->wait == NULL) {
|
||||
SDL_free(thread);
|
||||
SDL_free(args);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Add the thread to the list of available threads */
|
||||
SDL_AddThread(thread);
|
||||
|
||||
/* Create the thread and go! */
|
||||
#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
|
||||
ret = SDL_SYS_CreateThread(thread, args, pfnBeginThread, pfnEndThread);
|
||||
#else
|
||||
ret = SDL_SYS_CreateThread(thread, args);
|
||||
#endif
|
||||
if (ret >= 0) {
|
||||
/* Wait for the thread function to use arguments */
|
||||
SDL_SemWait(args->wait);
|
||||
} else {
|
||||
/* Oops, failed. Gotta free everything */
|
||||
SDL_DelThread(thread);
|
||||
SDL_free(thread);
|
||||
thread = NULL;
|
||||
}
|
||||
SDL_DestroySemaphore(args->wait);
|
||||
SDL_free(args);
|
||||
|
||||
/* Everything is running now */
|
||||
return (thread);
|
||||
}
|
||||
|
||||
SDL_threadID
|
||||
SDL_GetThreadID(SDL_Thread * thread)
|
||||
{
|
||||
SDL_threadID id;
|
||||
|
||||
if (thread) {
|
||||
id = thread->threadid;
|
||||
} else {
|
||||
id = SDL_ThreadID();
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SetThreadPriority(SDL_ThreadPriority priority)
|
||||
{
|
||||
return SDL_SYS_SetThreadPriority(priority);
|
||||
}
|
||||
|
||||
void
|
||||
SDL_WaitThread(SDL_Thread * thread, int *status)
|
||||
{
|
||||
if (thread) {
|
||||
SDL_SYS_WaitThread(thread);
|
||||
if (status) {
|
||||
*status = thread->status;
|
||||
}
|
||||
SDL_DelThread(thread);
|
||||
SDL_free(thread);
|
||||
}
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifndef _SDL_thread_c_h
|
||||
#define _SDL_thread_c_h
|
||||
|
||||
/* Need the definitions of SYS_ThreadHandle */
|
||||
#if SDL_THREADS_DISABLED
|
||||
#include "generic/SDL_systhread_c.h"
|
||||
#elif SDL_THREAD_BEOS
|
||||
#include "beos/SDL_systhread_c.h"
|
||||
#elif SDL_THREAD_EPOC
|
||||
#include "epoc/SDL_systhread_c.h"
|
||||
#elif SDL_THREAD_PTHREAD
|
||||
#include "pthread/SDL_systhread_c.h"
|
||||
#elif SDL_THREAD_SPROC
|
||||
#include "irix/SDL_systhread_c.h"
|
||||
#elif SDL_THREAD_WINDOWS
|
||||
#include "windows/SDL_systhread_c.h"
|
||||
#elif SDL_THREAD_NDS
|
||||
#include "nds/SDL_systhread_c.h"
|
||||
#else
|
||||
#error Need thread implementation for this platform
|
||||
#include "generic/SDL_systhread_c.h"
|
||||
#endif
|
||||
#include "../SDL_error_c.h"
|
||||
|
||||
/* This is the system-independent thread info structure */
|
||||
struct SDL_Thread
|
||||
{
|
||||
SDL_threadID threadid;
|
||||
SYS_ThreadHandle handle;
|
||||
int status;
|
||||
SDL_error errbuf;
|
||||
void *data;
|
||||
};
|
||||
|
||||
/* This is the function called to run a thread */
|
||||
extern void SDL_RunThread(void *data);
|
||||
|
||||
#endif /* _SDL_thread_c_h */
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* Semaphores in the BeOS environment */
|
||||
|
||||
#include <be/kernel/OS.h>
|
||||
|
||||
#include "SDL_thread.h"
|
||||
|
||||
|
||||
struct SDL_semaphore
|
||||
{
|
||||
sem_id id;
|
||||
};
|
||||
|
||||
/* Create a counting semaphore */
|
||||
SDL_sem *
|
||||
SDL_CreateSemaphore(Uint32 initial_value)
|
||||
{
|
||||
SDL_sem *sem;
|
||||
|
||||
sem = (SDL_sem *) SDL_malloc(sizeof(*sem));
|
||||
if (sem) {
|
||||
sem->id = create_sem(initial_value, "SDL semaphore");
|
||||
if (sem->id < B_NO_ERROR) {
|
||||
SDL_SetError("create_sem() failed");
|
||||
SDL_free(sem);
|
||||
sem = NULL;
|
||||
}
|
||||
} else {
|
||||
SDL_OutOfMemory();
|
||||
}
|
||||
return (sem);
|
||||
}
|
||||
|
||||
/* Free the semaphore */
|
||||
void
|
||||
SDL_DestroySemaphore(SDL_sem * sem)
|
||||
{
|
||||
if (sem) {
|
||||
if (sem->id >= B_NO_ERROR) {
|
||||
delete_sem(sem->id);
|
||||
}
|
||||
SDL_free(sem);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SemWaitTimeout(SDL_sem * sem, Uint32 timeout)
|
||||
{
|
||||
int32 val;
|
||||
int retval;
|
||||
|
||||
if (!sem) {
|
||||
SDL_SetError("Passed a NULL semaphore");
|
||||
return -1;
|
||||
}
|
||||
|
||||
tryagain:
|
||||
if (timeout == SDL_MUTEX_MAXWAIT) {
|
||||
val = acquire_sem(sem->id);
|
||||
} else {
|
||||
timeout *= 1000; /* BeOS uses a timeout in microseconds */
|
||||
val = acquire_sem_etc(sem->id, 1, B_RELATIVE_TIMEOUT, timeout);
|
||||
}
|
||||
switch (val) {
|
||||
case B_INTERRUPTED:
|
||||
goto tryagain;
|
||||
case B_NO_ERROR:
|
||||
retval = 0;
|
||||
break;
|
||||
case B_TIMED_OUT:
|
||||
retval = SDL_MUTEX_TIMEDOUT;
|
||||
break;
|
||||
case B_WOULD_BLOCK:
|
||||
retval = SDL_MUTEX_TIMEDOUT;
|
||||
break;
|
||||
default:
|
||||
SDL_SetError("acquire_sem() failed");
|
||||
retval = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SemTryWait(SDL_sem * sem)
|
||||
{
|
||||
return SDL_SemWaitTimeout(sem, 0);
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SemWait(SDL_sem * sem)
|
||||
{
|
||||
return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT);
|
||||
}
|
||||
|
||||
/* Returns the current count of the semaphore */
|
||||
Uint32
|
||||
SDL_SemValue(SDL_sem * sem)
|
||||
{
|
||||
int32 count;
|
||||
Uint32 value;
|
||||
|
||||
value = 0;
|
||||
if (sem) {
|
||||
get_sem_count(sem->id, &count);
|
||||
if (count > 0) {
|
||||
value = (Uint32) count;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/* Atomically increases the semaphore's count (not blocking) */
|
||||
int
|
||||
SDL_SemPost(SDL_sem * sem)
|
||||
{
|
||||
if (!sem) {
|
||||
SDL_SetError("Passed a NULL semaphore");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (release_sem(sem->id) != B_NO_ERROR) {
|
||||
SDL_SetError("release_sem() failed");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* BeOS thread management routines for SDL */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <be/kernel/OS.h>
|
||||
|
||||
#include "SDL_mutex.h"
|
||||
#include "SDL_thread.h"
|
||||
#include "../SDL_thread_c.h"
|
||||
#include "../SDL_systhread.h"
|
||||
|
||||
|
||||
static int sig_list[] = {
|
||||
SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGALRM, SIGTERM, SIGWINCH, 0
|
||||
};
|
||||
|
||||
void
|
||||
SDL_MaskSignals(sigset_t * omask)
|
||||
{
|
||||
sigset_t mask;
|
||||
int i;
|
||||
|
||||
sigemptyset(&mask);
|
||||
for (i = 0; sig_list[i]; ++i) {
|
||||
sigaddset(&mask, sig_list[i]);
|
||||
}
|
||||
sigprocmask(SIG_BLOCK, &mask, omask);
|
||||
}
|
||||
|
||||
void
|
||||
SDL_UnmaskSignals(sigset_t * omask)
|
||||
{
|
||||
sigprocmask(SIG_SETMASK, omask, NULL);
|
||||
}
|
||||
|
||||
static int32
|
||||
RunThread(void *data)
|
||||
{
|
||||
SDL_RunThread(data);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
|
||||
{
|
||||
/* Create the thread and go! */
|
||||
thread->handle = spawn_thread(RunThread, "SDL", B_NORMAL_PRIORITY, args);
|
||||
if ((thread->handle == B_NO_MORE_THREADS) ||
|
||||
(thread->handle == B_NO_MEMORY)) {
|
||||
SDL_SetError("Not enough resources to create thread");
|
||||
return (-1);
|
||||
}
|
||||
resume_thread(thread->handle);
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
SDL_SYS_SetupThread(void)
|
||||
{
|
||||
/* Mask asynchronous signals for this thread */
|
||||
SDL_MaskSignals(NULL);
|
||||
}
|
||||
|
||||
SDL_threadID
|
||||
SDL_ThreadID(void)
|
||||
{
|
||||
return ((SDL_threadID) find_thread(NULL));
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SYS_SetThreadPriority(SDL_Thread * thread, SDL_ThreadPriority priority)
|
||||
{
|
||||
int32 value;
|
||||
|
||||
if (priority == SDL_THREAD_PRIORITY_LOW) {
|
||||
value = B_LOW_PRIORITY;
|
||||
} else if (priority == SDL_THREAD_PRIORITY_HIGH) {
|
||||
value = B_URGENT_DISPLAY_PRIORITY;
|
||||
} else {
|
||||
value = B_NORMAL_PRIORITY;
|
||||
}
|
||||
set_thread_priority(find_thread(NULL), value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_SYS_WaitThread(SDL_Thread * thread)
|
||||
{
|
||||
status_t the_status;
|
||||
|
||||
wait_for_thread(thread->handle, &the_status);
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#include <signal.h>
|
||||
#include <be/kernel/OS.h>
|
||||
|
||||
typedef thread_id SYS_ThreadHandle;
|
||||
|
||||
/* Functions needed to work with system threads in other portions of SDL */
|
||||
extern void SDL_MaskSignals(sigset_t * omask);
|
||||
extern void SDL_UnmaskSignals(sigset_t * omask);
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,223 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* An implementation of condition variables using semaphores and mutexes */
|
||||
/*
|
||||
This implementation borrows heavily from the BeOS condition variable
|
||||
implementation, written by Christopher Tate and Owen Smith. Thanks!
|
||||
*/
|
||||
|
||||
#include "SDL_thread.h"
|
||||
|
||||
struct SDL_cond
|
||||
{
|
||||
SDL_mutex *lock;
|
||||
int waiting;
|
||||
int signals;
|
||||
SDL_sem *wait_sem;
|
||||
SDL_sem *wait_done;
|
||||
};
|
||||
|
||||
/* Create a condition variable */
|
||||
SDL_cond *
|
||||
SDL_CreateCond(void)
|
||||
{
|
||||
SDL_cond *cond;
|
||||
|
||||
cond = (SDL_cond *) SDL_malloc(sizeof(SDL_cond));
|
||||
if (cond) {
|
||||
cond->lock = SDL_CreateMutex();
|
||||
cond->wait_sem = SDL_CreateSemaphore(0);
|
||||
cond->wait_done = SDL_CreateSemaphore(0);
|
||||
cond->waiting = cond->signals = 0;
|
||||
if (!cond->lock || !cond->wait_sem || !cond->wait_done) {
|
||||
SDL_DestroyCond(cond);
|
||||
cond = NULL;
|
||||
}
|
||||
} else {
|
||||
SDL_OutOfMemory();
|
||||
}
|
||||
return (cond);
|
||||
}
|
||||
|
||||
/* Destroy a condition variable */
|
||||
void
|
||||
SDL_DestroyCond(SDL_cond * cond)
|
||||
{
|
||||
if (cond) {
|
||||
if (cond->wait_sem) {
|
||||
SDL_DestroySemaphore(cond->wait_sem);
|
||||
}
|
||||
if (cond->wait_done) {
|
||||
SDL_DestroySemaphore(cond->wait_done);
|
||||
}
|
||||
if (cond->lock) {
|
||||
SDL_DestroyMutex(cond->lock);
|
||||
}
|
||||
SDL_free(cond);
|
||||
}
|
||||
}
|
||||
|
||||
/* Restart one of the threads that are waiting on the condition variable */
|
||||
int
|
||||
SDL_CondSignal(SDL_cond * cond)
|
||||
{
|
||||
if (!cond) {
|
||||
SDL_SetError("Passed a NULL condition variable");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* If there are waiting threads not already signalled, then
|
||||
signal the condition and wait for the thread to respond.
|
||||
*/
|
||||
SDL_LockMutex(cond->lock);
|
||||
if (cond->waiting > cond->signals) {
|
||||
++cond->signals;
|
||||
SDL_SemPost(cond->wait_sem);
|
||||
SDL_UnlockMutex(cond->lock);
|
||||
SDL_SemWait(cond->wait_done);
|
||||
} else {
|
||||
SDL_UnlockMutex(cond->lock);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Restart all threads that are waiting on the condition variable */
|
||||
int
|
||||
SDL_CondBroadcast(SDL_cond * cond)
|
||||
{
|
||||
if (!cond) {
|
||||
SDL_SetError("Passed a NULL condition variable");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* If there are waiting threads not already signalled, then
|
||||
signal the condition and wait for the thread to respond.
|
||||
*/
|
||||
SDL_LockMutex(cond->lock);
|
||||
if (cond->waiting > cond->signals) {
|
||||
int i, num_waiting;
|
||||
|
||||
num_waiting = (cond->waiting - cond->signals);
|
||||
cond->signals = cond->waiting;
|
||||
for (i = 0; i < num_waiting; ++i) {
|
||||
SDL_SemPost(cond->wait_sem);
|
||||
}
|
||||
/* Now all released threads are blocked here, waiting for us.
|
||||
Collect them all (and win fabulous prizes!) :-)
|
||||
*/
|
||||
SDL_UnlockMutex(cond->lock);
|
||||
for (i = 0; i < num_waiting; ++i) {
|
||||
SDL_SemWait(cond->wait_done);
|
||||
}
|
||||
} else {
|
||||
SDL_UnlockMutex(cond->lock);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Wait on the condition variable for at most 'ms' milliseconds.
|
||||
The mutex must be locked before entering this function!
|
||||
The mutex is unlocked during the wait, and locked again after the wait.
|
||||
|
||||
Typical use:
|
||||
|
||||
Thread A:
|
||||
SDL_LockMutex(lock);
|
||||
while ( ! condition ) {
|
||||
SDL_CondWait(cond, lock);
|
||||
}
|
||||
SDL_UnlockMutex(lock);
|
||||
|
||||
Thread B:
|
||||
SDL_LockMutex(lock);
|
||||
...
|
||||
condition = true;
|
||||
...
|
||||
SDL_CondSignal(cond);
|
||||
SDL_UnlockMutex(lock);
|
||||
*/
|
||||
int
|
||||
SDL_CondWaitTimeout(SDL_cond * cond, SDL_mutex * mutex, Uint32 ms)
|
||||
{
|
||||
int retval;
|
||||
|
||||
if (!cond) {
|
||||
SDL_SetError("Passed a NULL condition variable");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Obtain the protection mutex, and increment the number of waiters.
|
||||
This allows the signal mechanism to only perform a signal if there
|
||||
are waiting threads.
|
||||
*/
|
||||
SDL_LockMutex(cond->lock);
|
||||
++cond->waiting;
|
||||
SDL_UnlockMutex(cond->lock);
|
||||
|
||||
/* Unlock the mutex, as is required by condition variable semantics */
|
||||
SDL_UnlockMutex(mutex);
|
||||
|
||||
/* Wait for a signal */
|
||||
if (ms == SDL_MUTEX_MAXWAIT) {
|
||||
retval = SDL_SemWait(cond->wait_sem);
|
||||
} else {
|
||||
retval = SDL_SemWaitTimeout(cond->wait_sem, ms);
|
||||
}
|
||||
|
||||
/* Let the signaler know we have completed the wait, otherwise
|
||||
the signaler can race ahead and get the condition semaphore
|
||||
if we are stopped between the mutex unlock and semaphore wait,
|
||||
giving a deadlock. See the following URL for details:
|
||||
http://www-classic.be.com/aboutbe/benewsletter/volume_III/Issue40.html
|
||||
*/
|
||||
SDL_LockMutex(cond->lock);
|
||||
if (cond->signals > 0) {
|
||||
/* If we timed out, we need to eat a condition signal */
|
||||
if (retval > 0) {
|
||||
SDL_SemWait(cond->wait_sem);
|
||||
}
|
||||
/* We always notify the signal thread that we are done */
|
||||
SDL_SemPost(cond->wait_done);
|
||||
|
||||
/* Signal handshake complete */
|
||||
--cond->signals;
|
||||
}
|
||||
--cond->waiting;
|
||||
SDL_UnlockMutex(cond->lock);
|
||||
|
||||
/* Lock the mutex, as is required by condition variable semantics */
|
||||
SDL_LockMutex(mutex);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Wait on the condition variable forever */
|
||||
int
|
||||
SDL_CondWait(SDL_cond * cond, SDL_mutex * mutex)
|
||||
{
|
||||
return SDL_CondWaitTimeout(cond, mutex, SDL_MUTEX_MAXWAIT);
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* An implementation of mutexes using semaphores */
|
||||
|
||||
#include "SDL_thread.h"
|
||||
#include "SDL_systhread_c.h"
|
||||
|
||||
|
||||
struct SDL_mutex
|
||||
{
|
||||
int recursive;
|
||||
SDL_threadID owner;
|
||||
SDL_sem *sem;
|
||||
};
|
||||
|
||||
/* Create a mutex */
|
||||
SDL_mutex *
|
||||
SDL_CreateMutex(void)
|
||||
{
|
||||
SDL_mutex *mutex;
|
||||
|
||||
/* Allocate mutex memory */
|
||||
mutex = (SDL_mutex *) SDL_malloc(sizeof(*mutex));
|
||||
if (mutex) {
|
||||
/* Create the mutex semaphore, with initial value 1 */
|
||||
mutex->sem = SDL_CreateSemaphore(1);
|
||||
mutex->recursive = 0;
|
||||
mutex->owner = 0;
|
||||
if (!mutex->sem) {
|
||||
SDL_free(mutex);
|
||||
mutex = NULL;
|
||||
}
|
||||
} else {
|
||||
SDL_OutOfMemory();
|
||||
}
|
||||
return mutex;
|
||||
}
|
||||
|
||||
/* Free the mutex */
|
||||
void
|
||||
SDL_DestroyMutex(SDL_mutex * mutex)
|
||||
{
|
||||
if (mutex) {
|
||||
if (mutex->sem) {
|
||||
SDL_DestroySemaphore(mutex->sem);
|
||||
}
|
||||
SDL_free(mutex);
|
||||
}
|
||||
}
|
||||
|
||||
/* Lock the semaphore */
|
||||
int
|
||||
SDL_mutexP(SDL_mutex * mutex)
|
||||
{
|
||||
#if SDL_THREADS_DISABLED
|
||||
return 0;
|
||||
#else
|
||||
SDL_threadID this_thread;
|
||||
|
||||
if (mutex == NULL) {
|
||||
SDL_SetError("Passed a NULL mutex");
|
||||
return -1;
|
||||
}
|
||||
|
||||
this_thread = SDL_ThreadID();
|
||||
if (mutex->owner == this_thread) {
|
||||
++mutex->recursive;
|
||||
} else {
|
||||
/* The order of operations is important.
|
||||
We set the locking thread id after we obtain the lock
|
||||
so unlocks from other threads will fail.
|
||||
*/
|
||||
SDL_SemWait(mutex->sem);
|
||||
mutex->owner = this_thread;
|
||||
mutex->recursive = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
#endif /* SDL_THREADS_DISABLED */
|
||||
}
|
||||
|
||||
/* Unlock the mutex */
|
||||
int
|
||||
SDL_mutexV(SDL_mutex * mutex)
|
||||
{
|
||||
#if SDL_THREADS_DISABLED
|
||||
return 0;
|
||||
#else
|
||||
if (mutex == NULL) {
|
||||
SDL_SetError("Passed a NULL mutex");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* If we don't own the mutex, we can't unlock it */
|
||||
if (SDL_ThreadID() != mutex->owner) {
|
||||
SDL_SetError("mutex not owned by this thread");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mutex->recursive) {
|
||||
--mutex->recursive;
|
||||
} else {
|
||||
/* The order of operations is important.
|
||||
First reset the owner so another thread doesn't lock
|
||||
the mutex and set the ownership before we reset it,
|
||||
then release the lock semaphore.
|
||||
*/
|
||||
mutex->owner = 0;
|
||||
SDL_SemPost(mutex->sem);
|
||||
}
|
||||
return 0;
|
||||
#endif /* SDL_THREADS_DISABLED */
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,225 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* An implementation of semaphores using mutexes and condition variables */
|
||||
|
||||
#include "SDL_timer.h"
|
||||
#include "SDL_thread.h"
|
||||
#include "SDL_systhread_c.h"
|
||||
|
||||
|
||||
#if SDL_THREADS_DISABLED
|
||||
|
||||
SDL_sem *
|
||||
SDL_CreateSemaphore(Uint32 initial_value)
|
||||
{
|
||||
SDL_SetError("SDL not configured with thread support");
|
||||
return (SDL_sem *) 0;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_DestroySemaphore(SDL_sem * sem)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SemTryWait(SDL_sem * sem)
|
||||
{
|
||||
SDL_SetError("SDL not configured with thread support");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SemWaitTimeout(SDL_sem * sem, Uint32 timeout)
|
||||
{
|
||||
SDL_SetError("SDL not configured with thread support");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SemWait(SDL_sem * sem)
|
||||
{
|
||||
SDL_SetError("SDL not configured with thread support");
|
||||
return -1;
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_SemValue(SDL_sem * sem)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SemPost(SDL_sem * sem)
|
||||
{
|
||||
SDL_SetError("SDL not configured with thread support");
|
||||
return -1;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
struct SDL_semaphore
|
||||
{
|
||||
Uint32 count;
|
||||
Uint32 waiters_count;
|
||||
SDL_mutex *count_lock;
|
||||
SDL_cond *count_nonzero;
|
||||
};
|
||||
|
||||
SDL_sem *
|
||||
SDL_CreateSemaphore(Uint32 initial_value)
|
||||
{
|
||||
SDL_sem *sem;
|
||||
|
||||
sem = (SDL_sem *) SDL_malloc(sizeof(*sem));
|
||||
if (!sem) {
|
||||
SDL_OutOfMemory();
|
||||
return NULL;
|
||||
}
|
||||
sem->count = initial_value;
|
||||
sem->waiters_count = 0;
|
||||
|
||||
sem->count_lock = SDL_CreateMutex();
|
||||
sem->count_nonzero = SDL_CreateCond();
|
||||
if (!sem->count_lock || !sem->count_nonzero) {
|
||||
SDL_DestroySemaphore(sem);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return sem;
|
||||
}
|
||||
|
||||
/* WARNING:
|
||||
You cannot call this function when another thread is using the semaphore.
|
||||
*/
|
||||
void
|
||||
SDL_DestroySemaphore(SDL_sem * sem)
|
||||
{
|
||||
if (sem) {
|
||||
sem->count = 0xFFFFFFFF;
|
||||
while (sem->waiters_count > 0) {
|
||||
SDL_CondSignal(sem->count_nonzero);
|
||||
SDL_Delay(10);
|
||||
}
|
||||
SDL_DestroyCond(sem->count_nonzero);
|
||||
if (sem->count_lock) {
|
||||
SDL_mutexP(sem->count_lock);
|
||||
SDL_mutexV(sem->count_lock);
|
||||
SDL_DestroyMutex(sem->count_lock);
|
||||
}
|
||||
SDL_free(sem);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SemTryWait(SDL_sem * sem)
|
||||
{
|
||||
int retval;
|
||||
|
||||
if (!sem) {
|
||||
SDL_SetError("Passed a NULL semaphore");
|
||||
return -1;
|
||||
}
|
||||
|
||||
retval = SDL_MUTEX_TIMEDOUT;
|
||||
SDL_LockMutex(sem->count_lock);
|
||||
if (sem->count > 0) {
|
||||
--sem->count;
|
||||
retval = 0;
|
||||
}
|
||||
SDL_UnlockMutex(sem->count_lock);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SemWaitTimeout(SDL_sem * sem, Uint32 timeout)
|
||||
{
|
||||
int retval;
|
||||
|
||||
if (!sem) {
|
||||
SDL_SetError("Passed a NULL semaphore");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* A timeout of 0 is an easy case */
|
||||
if (timeout == 0) {
|
||||
return SDL_SemTryWait(sem);
|
||||
}
|
||||
|
||||
SDL_LockMutex(sem->count_lock);
|
||||
++sem->waiters_count;
|
||||
retval = 0;
|
||||
while ((sem->count == 0) && (retval != SDL_MUTEX_TIMEDOUT)) {
|
||||
retval = SDL_CondWaitTimeout(sem->count_nonzero,
|
||||
sem->count_lock, timeout);
|
||||
}
|
||||
--sem->waiters_count;
|
||||
if (retval == 0) {
|
||||
--sem->count;
|
||||
}
|
||||
SDL_UnlockMutex(sem->count_lock);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SemWait(SDL_sem * sem)
|
||||
{
|
||||
return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT);
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_SemValue(SDL_sem * sem)
|
||||
{
|
||||
Uint32 value;
|
||||
|
||||
value = 0;
|
||||
if (sem) {
|
||||
SDL_LockMutex(sem->count_lock);
|
||||
value = sem->count;
|
||||
SDL_UnlockMutex(sem->count_lock);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SemPost(SDL_sem * sem)
|
||||
{
|
||||
if (!sem) {
|
||||
SDL_SetError("Passed a NULL semaphore");
|
||||
return -1;
|
||||
}
|
||||
|
||||
SDL_LockMutex(sem->count_lock);
|
||||
if (sem->waiters_count > 0) {
|
||||
SDL_CondSignal(sem->count_nonzero);
|
||||
}
|
||||
++sem->count;
|
||||
SDL_UnlockMutex(sem->count_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* SDL_THREADS_DISABLED */
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* Thread management routines for SDL */
|
||||
|
||||
#include "SDL_thread.h"
|
||||
#include "../SDL_systhread.h"
|
||||
|
||||
int
|
||||
SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
|
||||
{
|
||||
SDL_SetError("Threads are not supported on this platform");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
void
|
||||
SDL_SYS_SetupThread(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_threadID
|
||||
SDL_ThreadID(void)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
SDL_SYS_WaitThread(SDL_Thread * thread)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* Stub until we implement threads on this platform */
|
||||
typedef int SYS_ThreadHandle;
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#include "SDL_thread.h"
|
||||
#include "SDL_timer.h"
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/sem.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "SDL_error.h"
|
||||
#include "SDL_thread.h"
|
||||
|
||||
|
||||
struct SDL_semaphore
|
||||
{
|
||||
int id;
|
||||
};
|
||||
|
||||
/* Not defined by many operating systems, use configure to detect */
|
||||
/*
|
||||
#if !defined(HAVE_SEMUN)
|
||||
union semun {
|
||||
int val;
|
||||
struct semid_ds *buf;
|
||||
ushort *array;
|
||||
};
|
||||
#endif
|
||||
*/
|
||||
|
||||
static struct sembuf op_trywait[2] = {
|
||||
{0, -1, (IPC_NOWAIT | SEM_UNDO)} /* Decrement semaphore, no block */
|
||||
};
|
||||
|
||||
static struct sembuf op_wait[2] = {
|
||||
{0, -1, SEM_UNDO} /* Decrement semaphore */
|
||||
};
|
||||
|
||||
static struct sembuf op_post[1] = {
|
||||
{0, 1, (IPC_NOWAIT | SEM_UNDO)} /* Increment semaphore */
|
||||
};
|
||||
|
||||
/* Create a blockable semaphore */
|
||||
SDL_sem *
|
||||
SDL_CreateSemaphore(Uint32 initial_value)
|
||||
{
|
||||
extern int _creating_thread_lock; /* SDL_threads.c */
|
||||
SDL_sem *sem;
|
||||
union semun init;
|
||||
|
||||
sem = (SDL_sem *) SDL_malloc(sizeof(*sem));
|
||||
if (sem == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
return (NULL);
|
||||
}
|
||||
sem->id = semget(IPC_PRIVATE, 1, (0600 | IPC_CREAT));
|
||||
if (sem->id < 0) {
|
||||
SDL_SetError("Couldn't create semaphore");
|
||||
SDL_free(sem);
|
||||
return (NULL);
|
||||
}
|
||||
init.val = initial_value; /* Initialize semaphore */
|
||||
semctl(sem->id, 0, SETVAL, init);
|
||||
return (sem);
|
||||
}
|
||||
|
||||
void
|
||||
SDL_DestroySemaphore(SDL_sem * sem)
|
||||
{
|
||||
if (sem) {
|
||||
#ifdef __IRIX__
|
||||
semctl(sem->id, 0, IPC_RMID);
|
||||
#else
|
||||
union semun dummy;
|
||||
dummy.val = 0;
|
||||
semctl(sem->id, 0, IPC_RMID, dummy);
|
||||
#endif
|
||||
SDL_free(sem);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SemTryWait(SDL_sem * sem)
|
||||
{
|
||||
int retval;
|
||||
|
||||
if (!sem) {
|
||||
SDL_SetError("Passed a NULL semaphore");
|
||||
return -1;
|
||||
}
|
||||
|
||||
retval = 0;
|
||||
tryagain:
|
||||
if (semop(sem->id, op_trywait, 1) < 0) {
|
||||
if (errno == EINTR) {
|
||||
goto tryagain;
|
||||
}
|
||||
retval = SDL_MUTEX_TIMEDOUT;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SemWait(SDL_sem * sem)
|
||||
{
|
||||
int retval;
|
||||
|
||||
if (!sem) {
|
||||
SDL_SetError("Passed a NULL semaphore");
|
||||
return -1;
|
||||
}
|
||||
|
||||
retval = 0;
|
||||
tryagain:
|
||||
if (semop(sem->id, op_wait, 1) < 0) {
|
||||
if (errno == EINTR) {
|
||||
goto tryagain;
|
||||
}
|
||||
SDL_SetError("Semaphore operation error");
|
||||
retval = -1;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SemWaitTimeout(SDL_sem * sem, Uint32 timeout)
|
||||
{
|
||||
int retval;
|
||||
|
||||
if (!sem) {
|
||||
SDL_SetError("Passed a NULL semaphore");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Try the easy cases first */
|
||||
if (timeout == 0) {
|
||||
return SDL_SemTryWait(sem);
|
||||
}
|
||||
if (timeout == SDL_MUTEX_MAXWAIT) {
|
||||
return SDL_SemWait(sem);
|
||||
}
|
||||
|
||||
/* Ack! We have to busy wait... */
|
||||
timeout += SDL_GetTicks();
|
||||
do {
|
||||
retval = SDL_SemTryWait(sem);
|
||||
if (retval == 0) {
|
||||
break;
|
||||
}
|
||||
SDL_Delay(1);
|
||||
} while (SDL_GetTicks() < timeout);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_SemValue(SDL_sem * sem)
|
||||
{
|
||||
int semval;
|
||||
Uint32 value;
|
||||
|
||||
value = 0;
|
||||
if (sem) {
|
||||
tryagain:
|
||||
#ifdef __IRIX__
|
||||
semval = semctl(sem->id, 0, GETVAL);
|
||||
#else
|
||||
{
|
||||
union semun arg;
|
||||
arg.val = 0;
|
||||
semval = semctl(sem->id, 0, GETVAL, arg);
|
||||
}
|
||||
#endif
|
||||
if (semval < 0) {
|
||||
if (errno == EINTR) {
|
||||
goto tryagain;
|
||||
}
|
||||
} else {
|
||||
value = (Uint32) semval;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SemPost(SDL_sem * sem)
|
||||
{
|
||||
int retval;
|
||||
|
||||
if (!sem) {
|
||||
SDL_SetError("Passed a NULL semaphore");
|
||||
return -1;
|
||||
}
|
||||
|
||||
retval = 0;
|
||||
tryagain:
|
||||
if (semop(sem->id, op_post, 1) < 0) {
|
||||
if (errno == EINTR) {
|
||||
goto tryagain;
|
||||
}
|
||||
SDL_SetError("Semaphore operation error");
|
||||
retval = -1;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* IRIX thread management routines for SDL */
|
||||
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/prctl.h>
|
||||
|
||||
#include "SDL_thread.h"
|
||||
#include "../SDL_systhread.h"
|
||||
|
||||
|
||||
static int sig_list[] = {
|
||||
SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGALRM, SIGTERM, SIGCLD, SIGWINCH,
|
||||
SIGVTALRM, SIGPROF, 0
|
||||
};
|
||||
|
||||
|
||||
int
|
||||
SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
|
||||
{
|
||||
/* Create the thread and go! */
|
||||
if (sproc(SDL_RunThread, PR_SALL, args) < 0) {
|
||||
SDL_SetError("Not enough resources to create thread");
|
||||
return (-1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
SDL_SYS_SetupThread(void)
|
||||
{
|
||||
int i;
|
||||
sigset_t mask;
|
||||
|
||||
/* Mask asynchronous signals for this thread */
|
||||
sigemptyset(&mask);
|
||||
for (i = 0; sig_list[i]; ++i) {
|
||||
sigaddset(&mask, sig_list[i]);
|
||||
}
|
||||
sigprocmask(SIG_BLOCK, &mask, NULL);
|
||||
}
|
||||
|
||||
SDL_threadID
|
||||
SDL_ThreadID(void)
|
||||
{
|
||||
return ((SDL_threadID) getpid());
|
||||
}
|
||||
|
||||
void
|
||||
SDL_WaitThread(SDL_Thread * thread, int *status)
|
||||
{
|
||||
errno = 0;
|
||||
while (errno != ECHILD) {
|
||||
waitpid(thread->handle, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
typedef pid_t SYS_ThreadHandle;
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifdef SAVE_RCSID
|
||||
static char rcsid =
|
||||
"@(#) $Id: SDL_syscond.c,v 1.2 2001/04/26 16:50:18 hercules Exp $";
|
||||
#endif
|
||||
|
||||
/* An implementation of condition variables using semaphores and mutexes */
|
||||
/*
|
||||
This implementation borrows heavily from the BeOS condition variable
|
||||
implementation, written by Christopher Tate and Owen Smith. Thanks!
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "SDL_error.h"
|
||||
#include "SDL_thread.h"
|
||||
|
||||
struct SDL_cond
|
||||
{
|
||||
SDL_mutex *lock;
|
||||
int waiting;
|
||||
int signals;
|
||||
SDL_sem *wait_sem;
|
||||
SDL_sem *wait_done;
|
||||
};
|
||||
|
||||
/* Create a condition variable */
|
||||
SDL_cond *
|
||||
SDL_CreateCond(void)
|
||||
{
|
||||
SDL_cond *cond;
|
||||
|
||||
cond = (SDL_cond *) malloc(sizeof(SDL_cond));
|
||||
if (cond) {
|
||||
cond->lock = SDL_CreateMutex();
|
||||
cond->wait_sem = SDL_CreateSemaphore(0);
|
||||
cond->wait_done = SDL_CreateSemaphore(0);
|
||||
cond->waiting = cond->signals = 0;
|
||||
if (!cond->lock || !cond->wait_sem || !cond->wait_done) {
|
||||
SDL_DestroyCond(cond);
|
||||
cond = NULL;
|
||||
}
|
||||
} else {
|
||||
SDL_OutOfMemory();
|
||||
}
|
||||
return (cond);
|
||||
}
|
||||
|
||||
/* Destroy a condition variable */
|
||||
void
|
||||
SDL_DestroyCond(SDL_cond * cond)
|
||||
{
|
||||
if (cond) {
|
||||
if (cond->wait_sem) {
|
||||
SDL_DestroySemaphore(cond->wait_sem);
|
||||
}
|
||||
if (cond->wait_done) {
|
||||
SDL_DestroySemaphore(cond->wait_done);
|
||||
}
|
||||
if (cond->lock) {
|
||||
SDL_DestroyMutex(cond->lock);
|
||||
}
|
||||
free(cond);
|
||||
}
|
||||
}
|
||||
|
||||
/* Restart one of the threads that are waiting on the condition variable */
|
||||
int
|
||||
SDL_CondSignal(SDL_cond * cond)
|
||||
{
|
||||
if (!cond) {
|
||||
SDL_SetError("Passed a NULL condition variable");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* If there are waiting threads not already signalled, then
|
||||
signal the condition and wait for the thread to respond.
|
||||
*/
|
||||
SDL_LockMutex(cond->lock);
|
||||
if (cond->waiting > cond->signals) {
|
||||
++cond->signals;
|
||||
SDL_SemPost(cond->wait_sem);
|
||||
SDL_UnlockMutex(cond->lock);
|
||||
SDL_SemWait(cond->wait_done);
|
||||
} else {
|
||||
SDL_UnlockMutex(cond->lock);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Restart all threads that are waiting on the condition variable */
|
||||
int
|
||||
SDL_CondBroadcast(SDL_cond * cond)
|
||||
{
|
||||
if (!cond) {
|
||||
SDL_SetError("Passed a NULL condition variable");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* If there are waiting threads not already signalled, then
|
||||
signal the condition and wait for the thread to respond.
|
||||
*/
|
||||
SDL_LockMutex(cond->lock);
|
||||
if (cond->waiting > cond->signals) {
|
||||
int i, num_waiting;
|
||||
|
||||
num_waiting = (cond->waiting - cond->signals);
|
||||
cond->signals = cond->waiting;
|
||||
for (i = 0; i < num_waiting; ++i) {
|
||||
SDL_SemPost(cond->wait_sem);
|
||||
}
|
||||
/* Now all released threads are blocked here, waiting for us.
|
||||
Collect them all (and win fabulous prizes!) :-)
|
||||
*/
|
||||
SDL_UnlockMutex(cond->lock);
|
||||
for (i = 0; i < num_waiting; ++i) {
|
||||
SDL_SemWait(cond->wait_done);
|
||||
}
|
||||
} else {
|
||||
SDL_UnlockMutex(cond->lock);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Wait on the condition variable for at most 'ms' milliseconds.
|
||||
The mutex must be locked before entering this function!
|
||||
The mutex is unlocked during the wait, and locked again after the wait.
|
||||
|
||||
Typical use:
|
||||
|
||||
Thread A:
|
||||
SDL_LockMutex(lock);
|
||||
while ( ! condition ) {
|
||||
SDL_CondWait(cond);
|
||||
}
|
||||
SDL_UnlockMutex(lock);
|
||||
|
||||
Thread B:
|
||||
SDL_LockMutex(lock);
|
||||
...
|
||||
condition = true;
|
||||
...
|
||||
SDL_UnlockMutex(lock);
|
||||
*/
|
||||
int
|
||||
SDL_CondWaitTimeout(SDL_cond * cond, SDL_mutex * mutex, Uint32 ms)
|
||||
{
|
||||
int retval;
|
||||
|
||||
if (!cond) {
|
||||
SDL_SetError("Passed a NULL condition variable");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Obtain the protection mutex, and increment the number of waiters.
|
||||
This allows the signal mechanism to only perform a signal if there
|
||||
are waiting threads.
|
||||
*/
|
||||
SDL_LockMutex(cond->lock);
|
||||
++cond->waiting;
|
||||
SDL_UnlockMutex(cond->lock);
|
||||
|
||||
/* Unlock the mutex, as is required by condition variable semantics */
|
||||
SDL_UnlockMutex(mutex);
|
||||
|
||||
/* Wait for a signal */
|
||||
if (ms == SDL_MUTEX_MAXWAIT) {
|
||||
retval = SDL_SemWait(cond->wait_sem);
|
||||
} else {
|
||||
retval = SDL_SemWaitTimeout(cond->wait_sem, ms);
|
||||
}
|
||||
|
||||
/* Let the signaler know we have completed the wait, otherwise
|
||||
the signaler can race ahead and get the condition semaphore
|
||||
if we are stopped between the mutex unlock and semaphore wait,
|
||||
giving a deadlock. See the following URL for details:
|
||||
http://www-classic.be.com/aboutbe/benewsletter/volume_III/Issue40.html
|
||||
*/
|
||||
SDL_LockMutex(cond->lock);
|
||||
if (cond->signals > 0) {
|
||||
/* If we timed out, we need to eat a condition signal */
|
||||
if (retval > 0) {
|
||||
SDL_SemWait(cond->wait_sem);
|
||||
}
|
||||
/* We always notify the signal thread that we are done */
|
||||
SDL_SemPost(cond->wait_done);
|
||||
|
||||
/* Signal handshake complete */
|
||||
--cond->signals;
|
||||
}
|
||||
--cond->waiting;
|
||||
SDL_UnlockMutex(cond->lock);
|
||||
|
||||
/* Lock the mutex, as is required by condition variable semantics */
|
||||
SDL_LockMutex(mutex);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Wait on the condition variable forever */
|
||||
int
|
||||
SDL_CondWait(SDL_cond * cond, SDL_mutex * mutex)
|
||||
{
|
||||
return SDL_CondWaitTimeout(cond, mutex, SDL_MUTEX_MAXWAIT);
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifdef SAVE_RCSID
|
||||
static char rcsid =
|
||||
"@(#) $Id: SDL_syscond_c.h,v 1.2 2001/04/26 16:50:18 hercules Exp $";
|
||||
#endif
|
||||
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifdef SAVE_RCSID
|
||||
static char rcsid =
|
||||
"@(#) $Id: SDL_sysmutex.c,v 1.2 2001/04/26 16:50:18 hercules Exp $";
|
||||
#endif
|
||||
|
||||
/* An implementation of mutexes using semaphores */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "SDL_error.h"
|
||||
#include "SDL_thread.h"
|
||||
#include "SDL_systhread_c.h"
|
||||
|
||||
|
||||
struct SDL_mutex
|
||||
{
|
||||
int recursive;
|
||||
SDL_threadID owner;
|
||||
SDL_sem *sem;
|
||||
};
|
||||
|
||||
/* Create a mutex */
|
||||
SDL_mutex *
|
||||
SDL_CreateMutex(void)
|
||||
{
|
||||
SDL_mutex *mutex;
|
||||
|
||||
/* Allocate mutex memory */
|
||||
mutex = (SDL_mutex *) malloc(sizeof(*mutex));
|
||||
if (mutex) {
|
||||
/* Create the mutex semaphore, with initial value 1 */
|
||||
mutex->sem = SDL_CreateSemaphore(1);
|
||||
mutex->recursive = 0;
|
||||
mutex->owner = 0;
|
||||
if (!mutex->sem) {
|
||||
free(mutex);
|
||||
mutex = NULL;
|
||||
}
|
||||
} else {
|
||||
SDL_OutOfMemory();
|
||||
}
|
||||
return mutex;
|
||||
}
|
||||
|
||||
/* Free the mutex */
|
||||
void
|
||||
SDL_DestroyMutex(SDL_mutex * mutex)
|
||||
{
|
||||
if (mutex) {
|
||||
if (mutex->sem) {
|
||||
SDL_DestroySemaphore(mutex->sem);
|
||||
}
|
||||
free(mutex);
|
||||
}
|
||||
}
|
||||
|
||||
/* Lock the semaphore */
|
||||
int
|
||||
SDL_mutexP(SDL_mutex * mutex)
|
||||
{
|
||||
#ifdef DISABLE_THREADS
|
||||
return 0;
|
||||
#else
|
||||
SDL_threadID this_thread;
|
||||
|
||||
if (mutex == NULL) {
|
||||
SDL_SetError("Passed a NULL mutex");
|
||||
return -1;
|
||||
}
|
||||
|
||||
this_thread = SDL_ThreadID();
|
||||
if (mutex->owner == this_thread) {
|
||||
++mutex->recursive;
|
||||
} else {
|
||||
/* The order of operations is important.
|
||||
We set the locking thread id after we obtain the lock
|
||||
so unlocks from other threads will fail.
|
||||
*/
|
||||
SDL_SemWait(mutex->sem);
|
||||
mutex->owner = this_thread;
|
||||
mutex->recursive = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
#endif /* DISABLE_THREADS */
|
||||
}
|
||||
|
||||
/* Unlock the mutex */
|
||||
int
|
||||
SDL_mutexV(SDL_mutex * mutex)
|
||||
{
|
||||
#ifdef DISABLE_THREADS
|
||||
return 0;
|
||||
#else
|
||||
if (mutex == NULL) {
|
||||
SDL_SetError("Passed a NULL mutex");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* If we don't own the mutex, we can't unlock it */
|
||||
if (SDL_ThreadID() != mutex->owner) {
|
||||
SDL_SetError("mutex not owned by this thread");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mutex->recursive) {
|
||||
--mutex->recursive;
|
||||
} else {
|
||||
/* The order of operations is important.
|
||||
First reset the owner so another thread doesn't lock
|
||||
the mutex and set the ownership before we reset it,
|
||||
then release the lock semaphore.
|
||||
*/
|
||||
mutex->owner = 0;
|
||||
SDL_SemPost(mutex->sem);
|
||||
}
|
||||
return 0;
|
||||
#endif /* DISABLE_THREADS */
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifdef SAVE_RCSID
|
||||
static char rcsid =
|
||||
"@(#) $Id: SDL_sysmutex_c.h,v 1.2 2001/04/26 16:50:18 hercules Exp $";
|
||||
#endif
|
||||
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifdef SAVE_RCSID
|
||||
static char rcsid =
|
||||
"@(#) $Id: SDL_syssem.c,v 1.2 2001/04/26 16:50:18 hercules Exp $";
|
||||
#endif
|
||||
|
||||
/* An implementation of semaphores using mutexes and condition variables */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "SDL_error.h"
|
||||
#include "SDL_timer.h"
|
||||
#include "SDL_thread.h"
|
||||
#include "SDL_systhread_c.h"
|
||||
|
||||
|
||||
#ifdef DISABLE_THREADS
|
||||
|
||||
SDL_sem *
|
||||
SDL_CreateSemaphore(Uint32 initial_value)
|
||||
{
|
||||
SDL_SetError("SDL not configured with thread support");
|
||||
return (SDL_sem *) 0;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_DestroySemaphore(SDL_sem * sem)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SemTryWait(SDL_sem * sem)
|
||||
{
|
||||
SDL_SetError("SDL not configured with thread support");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SemWaitTimeout(SDL_sem * sem, Uint32 timeout)
|
||||
{
|
||||
SDL_SetError("SDL not configured with thread support");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SemWait(SDL_sem * sem)
|
||||
{
|
||||
SDL_SetError("SDL not configured with thread support");
|
||||
return -1;
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_SemValue(SDL_sem * sem)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SemPost(SDL_sem * sem)
|
||||
{
|
||||
SDL_SetError("SDL not configured with thread support");
|
||||
return -1;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
struct SDL_semaphore
|
||||
{
|
||||
Uint32 count;
|
||||
Uint32 waiters_count;
|
||||
SDL_mutex *count_lock;
|
||||
SDL_cond *count_nonzero;
|
||||
};
|
||||
|
||||
SDL_sem *
|
||||
SDL_CreateSemaphore(Uint32 initial_value)
|
||||
{
|
||||
SDL_sem *sem;
|
||||
|
||||
sem = (SDL_sem *) malloc(sizeof(*sem));
|
||||
if (!sem) {
|
||||
SDL_OutOfMemory();
|
||||
return (0);
|
||||
}
|
||||
sem->count = initial_value;
|
||||
sem->waiters_count = 0;
|
||||
|
||||
sem->count_lock = SDL_CreateMutex();
|
||||
sem->count_nonzero = SDL_CreateCond();
|
||||
if (!sem->count_lock || !sem->count_nonzero) {
|
||||
SDL_DestroySemaphore(sem);
|
||||
return (0);
|
||||
}
|
||||
|
||||
return (sem);
|
||||
}
|
||||
|
||||
/* WARNING:
|
||||
You cannot call this function when another thread is using the semaphore.
|
||||
*/
|
||||
void
|
||||
SDL_DestroySemaphore(SDL_sem * sem)
|
||||
{
|
||||
if (sem) {
|
||||
sem->count = 0xFFFFFFFF;
|
||||
while (sem->waiters_count > 0) {
|
||||
SDL_CondSignal(sem->count_nonzero);
|
||||
SDL_Delay(10);
|
||||
}
|
||||
SDL_DestroyCond(sem->count_nonzero);
|
||||
SDL_mutexP(sem->count_lock);
|
||||
SDL_mutexV(sem->count_lock);
|
||||
SDL_DestroyMutex(sem->count_lock);
|
||||
free(sem);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SemTryWait(SDL_sem * sem)
|
||||
{
|
||||
int retval;
|
||||
|
||||
if (!sem) {
|
||||
SDL_SetError("Passed a NULL semaphore");
|
||||
return -1;
|
||||
}
|
||||
|
||||
retval = SDL_MUTEX_TIMEDOUT;
|
||||
SDL_LockMutex(sem->count_lock);
|
||||
if (sem->count > 0) {
|
||||
--sem->count;
|
||||
retval = 0;
|
||||
}
|
||||
SDL_UnlockMutex(sem->count_lock);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SemWaitTimeout(SDL_sem * sem, Uint32 timeout)
|
||||
{
|
||||
int retval;
|
||||
|
||||
if (!sem) {
|
||||
SDL_SetError("Passed a NULL semaphore");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* A timeout of 0 is an easy case */
|
||||
if (timeout == 0) {
|
||||
return SDL_SemTryWait(sem);
|
||||
}
|
||||
|
||||
SDL_LockMutex(sem->count_lock);
|
||||
++sem->waiters_count;
|
||||
retval = 0;
|
||||
while ((sem->count == 0) && (retval != SDL_MUTEX_TIMEDOUT)) {
|
||||
retval = SDL_CondWaitTimeout(sem->count_nonzero,
|
||||
sem->count_lock, timeout);
|
||||
}
|
||||
--sem->waiters_count;
|
||||
--sem->count;
|
||||
SDL_UnlockMutex(sem->count_lock);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SemWait(SDL_sem * sem)
|
||||
{
|
||||
return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT);
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_SemValue(SDL_sem * sem)
|
||||
{
|
||||
Uint32 value;
|
||||
|
||||
value = 0;
|
||||
if (sem) {
|
||||
SDL_LockMutex(sem->count_lock);
|
||||
value = sem->count;
|
||||
SDL_UnlockMutex(sem->count_lock);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SemPost(SDL_sem * sem)
|
||||
{
|
||||
if (!sem) {
|
||||
SDL_SetError("Passed a NULL semaphore");
|
||||
return -1;
|
||||
}
|
||||
|
||||
SDL_LockMutex(sem->count_lock);
|
||||
if (sem->waiters_count > 0) {
|
||||
SDL_CondSignal(sem->count_nonzero);
|
||||
}
|
||||
++sem->count;
|
||||
SDL_UnlockMutex(sem->count_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* DISABLE_THREADS */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifdef SAVE_RCSID
|
||||
static char rcsid =
|
||||
"@(#) $Id: SDL_syssem_c.h,v 1.2 2001/04/26 16:50:18 hercules Exp $";
|
||||
#endif
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifdef SAVE_RCSID
|
||||
static char rcsid =
|
||||
"@(#) $Id: SDL_systhread.c,v 1.2 2001/04/26 16:50:18 hercules Exp $";
|
||||
#endif
|
||||
|
||||
/* Thread management routines for SDL */
|
||||
|
||||
#include "SDL_error.h"
|
||||
#include "SDL_thread.h"
|
||||
#include "../SDL_systhread.h"
|
||||
|
||||
int
|
||||
SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
|
||||
{
|
||||
SDL_SetError("Threads are not supported on this platform");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
void
|
||||
SDL_SYS_SetupThread(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_threadID
|
||||
SDL_ThreadID(void)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
SDL_SYS_WaitThread(SDL_Thread * thread)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
SDL_SYS_KillThread(SDL_Thread * thread)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/* Stub until we implement threads on this platform */
|
||||
typedef int SYS_ThreadHandle;
|
||||
|
||||
#ifndef DISABLE_THREADS
|
||||
#define DISABLE_THREADS
|
||||
#endif
|
||||
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "SDL_thread.h"
|
||||
#include "SDL_sysmutex_c.h"
|
||||
|
||||
struct SDL_cond
|
||||
{
|
||||
pthread_cond_t cond;
|
||||
};
|
||||
|
||||
/* Create a condition variable */
|
||||
SDL_cond *
|
||||
SDL_CreateCond(void)
|
||||
{
|
||||
SDL_cond *cond;
|
||||
|
||||
cond = (SDL_cond *) SDL_malloc(sizeof(SDL_cond));
|
||||
if (cond) {
|
||||
if (pthread_cond_init(&cond->cond, NULL) < 0) {
|
||||
SDL_SetError("pthread_cond_init() failed");
|
||||
SDL_free(cond);
|
||||
cond = NULL;
|
||||
}
|
||||
}
|
||||
return (cond);
|
||||
}
|
||||
|
||||
/* Destroy a condition variable */
|
||||
void
|
||||
SDL_DestroyCond(SDL_cond * cond)
|
||||
{
|
||||
if (cond) {
|
||||
pthread_cond_destroy(&cond->cond);
|
||||
SDL_free(cond);
|
||||
}
|
||||
}
|
||||
|
||||
/* Restart one of the threads that are waiting on the condition variable */
|
||||
int
|
||||
SDL_CondSignal(SDL_cond * cond)
|
||||
{
|
||||
int retval;
|
||||
|
||||
if (!cond) {
|
||||
SDL_SetError("Passed a NULL condition variable");
|
||||
return -1;
|
||||
}
|
||||
|
||||
retval = 0;
|
||||
if (pthread_cond_signal(&cond->cond) != 0) {
|
||||
SDL_SetError("pthread_cond_signal() failed");
|
||||
retval = -1;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Restart all threads that are waiting on the condition variable */
|
||||
int
|
||||
SDL_CondBroadcast(SDL_cond * cond)
|
||||
{
|
||||
int retval;
|
||||
|
||||
if (!cond) {
|
||||
SDL_SetError("Passed a NULL condition variable");
|
||||
return -1;
|
||||
}
|
||||
|
||||
retval = 0;
|
||||
if (pthread_cond_broadcast(&cond->cond) != 0) {
|
||||
SDL_SetError("pthread_cond_broadcast() failed");
|
||||
retval = -1;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_CondWaitTimeout(SDL_cond * cond, SDL_mutex * mutex, Uint32 ms)
|
||||
{
|
||||
int retval;
|
||||
struct timeval delta;
|
||||
struct timespec abstime;
|
||||
|
||||
if (!cond) {
|
||||
SDL_SetError("Passed a NULL condition variable");
|
||||
return -1;
|
||||
}
|
||||
|
||||
gettimeofday(&delta, NULL);
|
||||
|
||||
abstime.tv_sec = delta.tv_sec + (ms / 1000);
|
||||
abstime.tv_nsec = (delta.tv_usec + (ms % 1000) * 1000) * 1000;
|
||||
if (abstime.tv_nsec > 1000000000) {
|
||||
abstime.tv_sec += 1;
|
||||
abstime.tv_nsec -= 1000000000;
|
||||
}
|
||||
|
||||
tryagain:
|
||||
retval = pthread_cond_timedwait(&cond->cond, &mutex->id, &abstime);
|
||||
switch (retval) {
|
||||
case EINTR:
|
||||
goto tryagain;
|
||||
break;
|
||||
case ETIMEDOUT:
|
||||
retval = SDL_MUTEX_TIMEDOUT;
|
||||
break;
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
SDL_SetError("pthread_cond_timedwait() failed");
|
||||
retval = -1;
|
||||
break;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Wait on the condition variable, unlocking the provided mutex.
|
||||
The mutex must be locked before entering this function!
|
||||
*/
|
||||
int
|
||||
SDL_CondWait(SDL_cond * cond, SDL_mutex * mutex)
|
||||
{
|
||||
int retval;
|
||||
|
||||
if (!cond) {
|
||||
SDL_SetError("Passed a NULL condition variable");
|
||||
return -1;
|
||||
}
|
||||
|
||||
retval = 0;
|
||||
if (pthread_cond_wait(&cond->cond, &mutex->id) != 0) {
|
||||
SDL_SetError("pthread_cond_wait() failed");
|
||||
retval = -1;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <pthread.h>
|
||||
|
||||
#include "SDL_thread.h"
|
||||
|
||||
#if !SDL_THREAD_PTHREAD_RECURSIVE_MUTEX && \
|
||||
!SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP
|
||||
#define FAKE_RECURSIVE_MUTEX 1
|
||||
#endif
|
||||
|
||||
struct SDL_mutex
|
||||
{
|
||||
pthread_mutex_t id;
|
||||
#if FAKE_RECURSIVE_MUTEX
|
||||
int recursive;
|
||||
pthread_t owner;
|
||||
#endif
|
||||
};
|
||||
|
||||
SDL_mutex *
|
||||
SDL_CreateMutex(void)
|
||||
{
|
||||
SDL_mutex *mutex;
|
||||
pthread_mutexattr_t attr;
|
||||
|
||||
/* Allocate the structure */
|
||||
mutex = (SDL_mutex *) SDL_calloc(1, sizeof(*mutex));
|
||||
if (mutex) {
|
||||
pthread_mutexattr_init(&attr);
|
||||
#if SDL_THREAD_PTHREAD_RECURSIVE_MUTEX
|
||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
||||
#elif SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP
|
||||
pthread_mutexattr_setkind_np(&attr, PTHREAD_MUTEX_RECURSIVE_NP);
|
||||
#else
|
||||
/* No extra attributes necessary */
|
||||
#endif
|
||||
if (pthread_mutex_init(&mutex->id, &attr) != 0) {
|
||||
SDL_SetError("pthread_mutex_init() failed");
|
||||
SDL_free(mutex);
|
||||
mutex = NULL;
|
||||
}
|
||||
} else {
|
||||
SDL_OutOfMemory();
|
||||
}
|
||||
return (mutex);
|
||||
}
|
||||
|
||||
void
|
||||
SDL_DestroyMutex(SDL_mutex * mutex)
|
||||
{
|
||||
if (mutex) {
|
||||
pthread_mutex_destroy(&mutex->id);
|
||||
SDL_free(mutex);
|
||||
}
|
||||
}
|
||||
|
||||
/* Lock the mutex */
|
||||
int
|
||||
SDL_mutexP(SDL_mutex * mutex)
|
||||
{
|
||||
int retval;
|
||||
#if FAKE_RECURSIVE_MUTEX
|
||||
pthread_t this_thread;
|
||||
#endif
|
||||
|
||||
if (mutex == NULL) {
|
||||
SDL_SetError("Passed a NULL mutex");
|
||||
return -1;
|
||||
}
|
||||
|
||||
retval = 0;
|
||||
#if FAKE_RECURSIVE_MUTEX
|
||||
this_thread = pthread_self();
|
||||
if (mutex->owner == this_thread) {
|
||||
++mutex->recursive;
|
||||
} else {
|
||||
/* The order of operations is important.
|
||||
We set the locking thread id after we obtain the lock
|
||||
so unlocks from other threads will fail.
|
||||
*/
|
||||
if (pthread_mutex_lock(&mutex->id) == 0) {
|
||||
mutex->owner = this_thread;
|
||||
mutex->recursive = 0;
|
||||
} else {
|
||||
SDL_SetError("pthread_mutex_lock() failed");
|
||||
retval = -1;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (pthread_mutex_lock(&mutex->id) < 0) {
|
||||
SDL_SetError("pthread_mutex_lock() failed");
|
||||
retval = -1;
|
||||
}
|
||||
#endif
|
||||
return retval;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_mutexV(SDL_mutex * mutex)
|
||||
{
|
||||
int retval;
|
||||
|
||||
if (mutex == NULL) {
|
||||
SDL_SetError("Passed a NULL mutex");
|
||||
return -1;
|
||||
}
|
||||
|
||||
retval = 0;
|
||||
#if FAKE_RECURSIVE_MUTEX
|
||||
/* We can only unlock the mutex if we own it */
|
||||
if (pthread_self() == mutex->owner) {
|
||||
if (mutex->recursive) {
|
||||
--mutex->recursive;
|
||||
} else {
|
||||
/* The order of operations is important.
|
||||
First reset the owner so another thread doesn't lock
|
||||
the mutex and set the ownership before we reset it,
|
||||
then release the lock semaphore.
|
||||
*/
|
||||
mutex->owner = 0;
|
||||
pthread_mutex_unlock(&mutex->id);
|
||||
}
|
||||
} else {
|
||||
SDL_SetError("mutex not owned by this thread");
|
||||
retval = -1;
|
||||
}
|
||||
|
||||
#else
|
||||
if (pthread_mutex_unlock(&mutex->id) < 0) {
|
||||
SDL_SetError("pthread_mutex_unlock() failed");
|
||||
retval = -1;
|
||||
}
|
||||
#endif /* FAKE_RECURSIVE_MUTEX */
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifndef _SDL_mutex_c_h
|
||||
#define _SDL_mutex_c_h
|
||||
|
||||
struct SDL_mutex
|
||||
{
|
||||
pthread_mutex_t id;
|
||||
};
|
||||
|
||||
#endif /* _SDL_mutex_c_h */
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
|
||||
#include "SDL_thread.h"
|
||||
#include "SDL_timer.h"
|
||||
|
||||
/* Wrapper around POSIX 1003.1b semaphores */
|
||||
|
||||
#if defined(__MACOSX__) || defined(__IPHONEOS__)
|
||||
/* Mac OS X doesn't support sem_getvalue() as of version 10.4 */
|
||||
#include "../generic/SDL_syssem.c"
|
||||
#else
|
||||
|
||||
struct SDL_semaphore
|
||||
{
|
||||
sem_t sem;
|
||||
};
|
||||
|
||||
/* Create a semaphore, initialized with value */
|
||||
SDL_sem *
|
||||
SDL_CreateSemaphore(Uint32 initial_value)
|
||||
{
|
||||
SDL_sem *sem = (SDL_sem *) SDL_malloc(sizeof(SDL_sem));
|
||||
if (sem) {
|
||||
if (sem_init(&sem->sem, 0, initial_value) < 0) {
|
||||
SDL_SetError("sem_init() failed");
|
||||
SDL_free(sem);
|
||||
sem = NULL;
|
||||
}
|
||||
} else {
|
||||
SDL_OutOfMemory();
|
||||
}
|
||||
return sem;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_DestroySemaphore(SDL_sem * sem)
|
||||
{
|
||||
if (sem) {
|
||||
sem_destroy(&sem->sem);
|
||||
SDL_free(sem);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SemTryWait(SDL_sem * sem)
|
||||
{
|
||||
int retval;
|
||||
|
||||
if (!sem) {
|
||||
SDL_SetError("Passed a NULL semaphore");
|
||||
return -1;
|
||||
}
|
||||
retval = SDL_MUTEX_TIMEDOUT;
|
||||
if (sem_trywait(&sem->sem) == 0) {
|
||||
retval = 0;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SemWait(SDL_sem * sem)
|
||||
{
|
||||
int retval;
|
||||
|
||||
if (!sem) {
|
||||
SDL_SetError("Passed a NULL semaphore");
|
||||
return -1;
|
||||
}
|
||||
|
||||
retval = sem_wait(&sem->sem);
|
||||
if (retval < 0) {
|
||||
SDL_SetError("sem_wait() failed");
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SemWaitTimeout(SDL_sem * sem, Uint32 timeout)
|
||||
{
|
||||
int retval;
|
||||
struct timeval now;
|
||||
struct timespec ts_timeout;
|
||||
|
||||
if (!sem) {
|
||||
SDL_SetError("Passed a NULL semaphore");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Try the easy cases first */
|
||||
if (timeout == 0) {
|
||||
return SDL_SemTryWait(sem);
|
||||
}
|
||||
if (timeout == SDL_MUTEX_MAXWAIT) {
|
||||
return SDL_SemWait(sem);
|
||||
}
|
||||
|
||||
/* Setup the timeout. sem_timedwait doesn't wait for
|
||||
* a lapse of time, but until we reach a certain time.
|
||||
* This time is now plus the timeout.
|
||||
*/
|
||||
gettimeofday(&now, NULL);
|
||||
|
||||
/* Add our timeout to current time */
|
||||
now.tv_usec += (timeout % 1000) * 1000;
|
||||
now.tv_sec += timeout / 1000;
|
||||
|
||||
/* Wrap the second if needed */
|
||||
if ( now.tv_usec >= 1000000 ) {
|
||||
now.tv_usec -= 1000000;
|
||||
now.tv_sec ++;
|
||||
}
|
||||
|
||||
/* Convert to timespec */
|
||||
ts_timeout.tv_sec = now.tv_sec;
|
||||
ts_timeout.tv_nsec = now.tv_usec * 1000;
|
||||
|
||||
/* Wait. */
|
||||
do {
|
||||
retval = sem_timedwait(&sem->sem, &ts_timeout);
|
||||
} while (retval < 0 && errno == EINTR);
|
||||
|
||||
if (retval < 0) {
|
||||
SDL_SetError("sem_timedwait() failed");
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_SemValue(SDL_sem * sem)
|
||||
{
|
||||
int ret = 0;
|
||||
if (sem) {
|
||||
sem_getvalue(&sem->sem, &ret);
|
||||
if (ret < 0) {
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
return (Uint32) ret;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SemPost(SDL_sem * sem)
|
||||
{
|
||||
int retval;
|
||||
|
||||
if (!sem) {
|
||||
SDL_SetError("Passed a NULL semaphore");
|
||||
return -1;
|
||||
}
|
||||
|
||||
retval = sem_post(&sem->sem);
|
||||
if (retval < 0) {
|
||||
SDL_SetError("sem_post() failed");
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
#endif /* __MACOSX__ */
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#ifdef __LINUX__
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/syscall.h>
|
||||
#endif
|
||||
|
||||
#include "SDL_thread.h"
|
||||
#include "../SDL_thread_c.h"
|
||||
#include "../SDL_systhread.h"
|
||||
|
||||
/* List of signals to mask in the subthreads */
|
||||
static const int sig_list[] = {
|
||||
SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGWINCH,
|
||||
SIGVTALRM, SIGPROF, 0
|
||||
};
|
||||
|
||||
|
||||
static void *
|
||||
RunThread(void *data)
|
||||
{
|
||||
SDL_RunThread(data);
|
||||
pthread_exit((void *) 0);
|
||||
return ((void *) 0); /* Prevent compiler warning */
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
|
||||
{
|
||||
pthread_attr_t type;
|
||||
|
||||
/* Set the thread attributes */
|
||||
if (pthread_attr_init(&type) != 0) {
|
||||
SDL_SetError("Couldn't initialize pthread attributes");
|
||||
return (-1);
|
||||
}
|
||||
pthread_attr_setdetachstate(&type, PTHREAD_CREATE_JOINABLE);
|
||||
|
||||
/* Create the thread and go! */
|
||||
if (pthread_create(&thread->handle, &type, RunThread, args) != 0) {
|
||||
SDL_SetError("Not enough resources to create thread");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
SDL_SYS_SetupThread(void)
|
||||
{
|
||||
int i;
|
||||
sigset_t mask;
|
||||
|
||||
/* Mask asynchronous signals for this thread */
|
||||
sigemptyset(&mask);
|
||||
for (i = 0; sig_list[i]; ++i) {
|
||||
sigaddset(&mask, sig_list[i]);
|
||||
}
|
||||
pthread_sigmask(SIG_BLOCK, &mask, 0);
|
||||
|
||||
#ifdef PTHREAD_CANCEL_ASYNCHRONOUS
|
||||
/* Allow ourselves to be asynchronously cancelled */
|
||||
{
|
||||
int oldstate;
|
||||
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
SDL_threadID
|
||||
SDL_ThreadID(void)
|
||||
{
|
||||
return ((SDL_threadID) pthread_self());
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority)
|
||||
{
|
||||
#ifdef __LINUX__
|
||||
int value;
|
||||
|
||||
if (priority == SDL_THREAD_PRIORITY_LOW) {
|
||||
value = 19;
|
||||
} else if (priority == SDL_THREAD_PRIORITY_HIGH) {
|
||||
value = -20;
|
||||
} else {
|
||||
value = 0;
|
||||
}
|
||||
if (setpriority(PRIO_PROCESS, syscall(SYS_gettid), value) < 0) {
|
||||
/* Note that this fails if you're trying to set high priority
|
||||
and you don't have root permission. BUT DON'T RUN AS ROOT!
|
||||
*/
|
||||
SDL_SetError("setpriority() failed");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
#else
|
||||
struct sched_param sched;
|
||||
int policy;
|
||||
pthread_t thread = pthread_self();
|
||||
|
||||
if (pthread_getschedparam(thread, &policy, &sched) < 0) {
|
||||
SDL_SetError("pthread_getschedparam() failed");
|
||||
return -1;
|
||||
}
|
||||
if (priority == SDL_THREAD_PRIORITY_LOW) {
|
||||
sched.sched_priority = sched_get_priority_min(policy);
|
||||
} else if (priority == SDL_THREAD_PRIORITY_HIGH) {
|
||||
sched.sched_priority = sched_get_priority_max(policy);
|
||||
} else {
|
||||
int min_priority = sched_get_priority_min(policy);
|
||||
int max_priority = sched_get_priority_max(policy);
|
||||
sched.sched_priority = (min_priority + (max_priority - min_priority) / 2);
|
||||
}
|
||||
if (pthread_setschedparam(thread, policy, &sched) < 0) {
|
||||
SDL_SetError("pthread_setschedparam() failed");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
#endif /* linux */
|
||||
}
|
||||
|
||||
void
|
||||
SDL_SYS_WaitThread(SDL_Thread * thread)
|
||||
{
|
||||
pthread_join(thread->handle, 0);
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
typedef pthread_t SYS_ThreadHandle;
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* Mutex functions using the Win32 API */
|
||||
|
||||
#include "../../core/windows/SDL_windows.h"
|
||||
|
||||
#include "SDL_mutex.h"
|
||||
|
||||
|
||||
struct SDL_mutex
|
||||
{
|
||||
CRITICAL_SECTION cs;
|
||||
};
|
||||
|
||||
/* Create a mutex */
|
||||
SDL_mutex *
|
||||
SDL_CreateMutex(void)
|
||||
{
|
||||
SDL_mutex *mutex;
|
||||
|
||||
/* Allocate mutex memory */
|
||||
mutex = (SDL_mutex *) SDL_malloc(sizeof(*mutex));
|
||||
if (mutex) {
|
||||
/* Initialize */
|
||||
#ifdef _WIN32_WCE
|
||||
InitializeCriticalSection(&mutex->cs);
|
||||
#else
|
||||
/* On SMP systems, a non-zero spin count generally helps performance */
|
||||
InitializeCriticalSectionAndSpinCount(&mutex->cs, 2000);
|
||||
#endif
|
||||
} else {
|
||||
SDL_OutOfMemory();
|
||||
}
|
||||
return (mutex);
|
||||
}
|
||||
|
||||
/* Free the mutex */
|
||||
void
|
||||
SDL_DestroyMutex(SDL_mutex * mutex)
|
||||
{
|
||||
if (mutex) {
|
||||
DeleteCriticalSection(&mutex->cs);
|
||||
SDL_free(mutex);
|
||||
}
|
||||
}
|
||||
|
||||
/* Lock the mutex */
|
||||
int
|
||||
SDL_mutexP(SDL_mutex * mutex)
|
||||
{
|
||||
if (mutex == NULL) {
|
||||
SDL_SetError("Passed a NULL mutex");
|
||||
return -1;
|
||||
}
|
||||
|
||||
EnterCriticalSection(&mutex->cs);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Unlock the mutex */
|
||||
int
|
||||
SDL_mutexV(SDL_mutex * mutex)
|
||||
{
|
||||
if (mutex == NULL) {
|
||||
SDL_SetError("Passed a NULL mutex");
|
||||
return -1;
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&mutex->cs);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* Semaphore functions using the Win32 API */
|
||||
|
||||
#include "../../core/windows/SDL_windows.h"
|
||||
|
||||
#include "SDL_thread.h"
|
||||
#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
|
||||
#include "win_ce_semaphore.h"
|
||||
#endif
|
||||
|
||||
|
||||
struct SDL_semaphore
|
||||
{
|
||||
#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
|
||||
SYNCHHANDLE id;
|
||||
#else
|
||||
HANDLE id;
|
||||
#endif
|
||||
LONG count;
|
||||
};
|
||||
|
||||
|
||||
/* Create a semaphore */
|
||||
SDL_sem *
|
||||
SDL_CreateSemaphore(Uint32 initial_value)
|
||||
{
|
||||
SDL_sem *sem;
|
||||
|
||||
/* Allocate sem memory */
|
||||
sem = (SDL_sem *) SDL_malloc(sizeof(*sem));
|
||||
if (sem) {
|
||||
/* Create the semaphore, with max value 32K */
|
||||
#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
|
||||
sem->id = CreateSemaphoreCE(NULL, initial_value, 32 * 1024, NULL);
|
||||
#else
|
||||
sem->id = CreateSemaphore(NULL, initial_value, 32 * 1024, NULL);
|
||||
#endif
|
||||
sem->count = initial_value;
|
||||
if (!sem->id) {
|
||||
SDL_SetError("Couldn't create semaphore");
|
||||
SDL_free(sem);
|
||||
sem = NULL;
|
||||
}
|
||||
} else {
|
||||
SDL_OutOfMemory();
|
||||
}
|
||||
return (sem);
|
||||
}
|
||||
|
||||
/* Free the semaphore */
|
||||
void
|
||||
SDL_DestroySemaphore(SDL_sem * sem)
|
||||
{
|
||||
if (sem) {
|
||||
if (sem->id) {
|
||||
#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
|
||||
CloseSynchHandle(sem->id);
|
||||
#else
|
||||
CloseHandle(sem->id);
|
||||
#endif
|
||||
sem->id = 0;
|
||||
}
|
||||
SDL_free(sem);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SemWaitTimeout(SDL_sem * sem, Uint32 timeout)
|
||||
{
|
||||
int retval;
|
||||
DWORD dwMilliseconds;
|
||||
|
||||
if (!sem) {
|
||||
SDL_SetError("Passed a NULL sem");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (timeout == SDL_MUTEX_MAXWAIT) {
|
||||
dwMilliseconds = INFINITE;
|
||||
} else {
|
||||
dwMilliseconds = (DWORD) timeout;
|
||||
}
|
||||
#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
|
||||
switch (WaitForSemaphoreCE(sem->id, dwMilliseconds)) {
|
||||
#else
|
||||
switch (WaitForSingleObject(sem->id, dwMilliseconds)) {
|
||||
#endif
|
||||
case WAIT_OBJECT_0:
|
||||
InterlockedDecrement(&sem->count);
|
||||
retval = 0;
|
||||
break;
|
||||
case WAIT_TIMEOUT:
|
||||
retval = SDL_MUTEX_TIMEDOUT;
|
||||
break;
|
||||
default:
|
||||
SDL_SetError("WaitForSingleObject() failed");
|
||||
retval = -1;
|
||||
break;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SemTryWait(SDL_sem * sem)
|
||||
{
|
||||
return SDL_SemWaitTimeout(sem, 0);
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SemWait(SDL_sem * sem)
|
||||
{
|
||||
return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT);
|
||||
}
|
||||
|
||||
/* Returns the current count of the semaphore */
|
||||
Uint32
|
||||
SDL_SemValue(SDL_sem * sem)
|
||||
{
|
||||
if (!sem) {
|
||||
SDL_SetError("Passed a NULL sem");
|
||||
return 0;
|
||||
}
|
||||
return (Uint32)sem->count;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SemPost(SDL_sem * sem)
|
||||
{
|
||||
if (!sem) {
|
||||
SDL_SetError("Passed a NULL sem");
|
||||
return -1;
|
||||
}
|
||||
/* Increase the counter in the first place, because
|
||||
* after a successful release the semaphore may
|
||||
* immediately get destroyed by another thread which
|
||||
* is waiting for this semaphore.
|
||||
*/
|
||||
InterlockedIncrement(&sem->count);
|
||||
#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
|
||||
if (ReleaseSemaphoreCE(sem->id, 1, NULL) == FALSE) {
|
||||
#else
|
||||
if (ReleaseSemaphore(sem->id, 1, NULL) == FALSE) {
|
||||
#endif
|
||||
InterlockedDecrement(&sem->count); /* restore */
|
||||
SDL_SetError("ReleaseSemaphore() failed");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* Win32 thread management routines for SDL */
|
||||
|
||||
#include "SDL_thread.h"
|
||||
#include "../SDL_thread_c.h"
|
||||
#include "../SDL_systhread.h"
|
||||
#include "SDL_systhread_c.h"
|
||||
|
||||
#ifndef SDL_PASSED_BEGINTHREAD_ENDTHREAD
|
||||
#ifndef _WIN32_WCE
|
||||
/* We'll use the C library from this DLL */
|
||||
#include <process.h>
|
||||
#endif
|
||||
|
||||
#if __GNUC__
|
||||
typedef uintptr_t (__cdecl * pfnSDL_CurrentBeginThread) (void *, unsigned,
|
||||
unsigned
|
||||
(__stdcall *
|
||||
func) (void *),
|
||||
void *arg,
|
||||
unsigned,
|
||||
unsigned
|
||||
*threadID);
|
||||
typedef void (__cdecl * pfnSDL_CurrentEndThread) (unsigned code);
|
||||
#elif defined(__WATCOMC__)
|
||||
/* This is for Watcom targets except OS2 */
|
||||
#if __WATCOMC__ < 1240
|
||||
#define __watcall
|
||||
#endif
|
||||
typedef unsigned long (__watcall * pfnSDL_CurrentBeginThread) (void *,
|
||||
unsigned,
|
||||
unsigned
|
||||
(__stdcall *
|
||||
func) (void
|
||||
*),
|
||||
void *arg,
|
||||
unsigned,
|
||||
unsigned
|
||||
*threadID);
|
||||
typedef void (__watcall * pfnSDL_CurrentEndThread) (unsigned code);
|
||||
#else
|
||||
typedef uintptr_t(__cdecl * pfnSDL_CurrentBeginThread) (void *, unsigned,
|
||||
unsigned (__stdcall *
|
||||
func) (void
|
||||
*),
|
||||
void *arg, unsigned,
|
||||
unsigned *threadID);
|
||||
typedef void (__cdecl * pfnSDL_CurrentEndThread) (unsigned code);
|
||||
#endif
|
||||
#endif /* !SDL_PASSED_BEGINTHREAD_ENDTHREAD */
|
||||
|
||||
|
||||
typedef struct ThreadStartParms
|
||||
{
|
||||
void *args;
|
||||
pfnSDL_CurrentEndThread pfnCurrentEndThread;
|
||||
} tThreadStartParms, *pThreadStartParms;
|
||||
|
||||
static DWORD __stdcall
|
||||
RunThread(void *data)
|
||||
{
|
||||
pThreadStartParms pThreadParms = (pThreadStartParms) data;
|
||||
pfnSDL_CurrentEndThread pfnCurrentEndThread = NULL;
|
||||
|
||||
// Call the thread function!
|
||||
SDL_RunThread(pThreadParms->args);
|
||||
|
||||
// Get the current endthread we have to use!
|
||||
if (pThreadParms) {
|
||||
pfnCurrentEndThread = pThreadParms->pfnCurrentEndThread;
|
||||
SDL_free(pThreadParms);
|
||||
}
|
||||
// Call endthread!
|
||||
if (pfnCurrentEndThread)
|
||||
(*pfnCurrentEndThread) (0);
|
||||
return (0);
|
||||
}
|
||||
|
||||
#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
|
||||
int
|
||||
SDL_SYS_CreateThread(SDL_Thread * thread, void *args,
|
||||
pfnSDL_CurrentBeginThread pfnBeginThread,
|
||||
pfnSDL_CurrentEndThread pfnEndThread)
|
||||
{
|
||||
#else
|
||||
int
|
||||
SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
|
||||
{
|
||||
#ifdef _WIN32_WCE
|
||||
pfnSDL_CurrentBeginThread pfnBeginThread = NULL;
|
||||
pfnSDL_CurrentEndThread pfnEndThread = NULL;
|
||||
#else
|
||||
pfnSDL_CurrentBeginThread pfnBeginThread = _beginthreadex;
|
||||
pfnSDL_CurrentEndThread pfnEndThread = _endthreadex;
|
||||
#endif
|
||||
#endif /* SDL_PASSED_BEGINTHREAD_ENDTHREAD */
|
||||
unsigned threadid;
|
||||
pThreadStartParms pThreadParms =
|
||||
(pThreadStartParms) SDL_malloc(sizeof(tThreadStartParms));
|
||||
if (!pThreadParms) {
|
||||
SDL_OutOfMemory();
|
||||
return (-1);
|
||||
}
|
||||
// Save the function which we will have to call to clear the RTL of calling app!
|
||||
pThreadParms->pfnCurrentEndThread = pfnEndThread;
|
||||
// Also save the real parameters we have to pass to thread function
|
||||
pThreadParms->args = args;
|
||||
|
||||
if (pfnBeginThread) {
|
||||
thread->handle =
|
||||
(SYS_ThreadHandle) pfnBeginThread(NULL, 0, RunThread,
|
||||
pThreadParms, 0, &threadid);
|
||||
} else {
|
||||
thread->handle =
|
||||
CreateThread(NULL, 0, RunThread, pThreadParms, 0, &threadid);
|
||||
}
|
||||
if (thread->handle == NULL) {
|
||||
SDL_SetError("Not enough resources to create thread");
|
||||
return (-1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
SDL_SYS_SetupThread(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_threadID
|
||||
SDL_ThreadID(void)
|
||||
{
|
||||
return ((SDL_threadID) GetCurrentThreadId());
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority)
|
||||
{
|
||||
int value;
|
||||
|
||||
if (priority == SDL_THREAD_PRIORITY_LOW) {
|
||||
value = THREAD_PRIORITY_LOWEST;
|
||||
} else if (priority == SDL_THREAD_PRIORITY_HIGH) {
|
||||
value = THREAD_PRIORITY_HIGHEST;
|
||||
} else {
|
||||
value = THREAD_PRIORITY_NORMAL;
|
||||
}
|
||||
if (!SetThreadPriority(GetCurrentThread(), value)) {
|
||||
WIN_SetError("SetThreadPriority()");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_SYS_WaitThread(SDL_Thread * thread)
|
||||
{
|
||||
WaitForSingleObject(thread->handle, INFINITE);
|
||||
CloseHandle(thread->handle);
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifndef _SDL_systhread_c_h
|
||||
#define _SDL_systhread_c_h
|
||||
|
||||
#include "../../core/windows/SDL_windows.h"
|
||||
|
||||
typedef HANDLE SYS_ThreadHandle;
|
||||
|
||||
#endif /* _SDL_systhread_c_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,227 @@
|
||||
/* win_ce_semaphore.c
|
||||
|
||||
Copyright (c) 1998, Johnson M. Hart
|
||||
(with corrections 2001 by Rainer Loritz)
|
||||
Permission is granted for any and all use providing that this
|
||||
copyright is properly acknowledged.
|
||||
There are no assurances of suitability for any use whatsoever.
|
||||
|
||||
WINDOWS CE: There is a collection of Windows CE functions to simulate
|
||||
semaphores using only a mutex and an event. As Windows CE events cannot
|
||||
be named, these simulated semaphores cannot be named either.
|
||||
|
||||
Implementation notes:
|
||||
1. All required internal data structures are allocated on the process's heap.
|
||||
2. Where appropriate, a new error code is returned (see the header
|
||||
file), or, if the error is a Win32 error, that code is unchanged.
|
||||
3. Notice the new handle type "SYNCHHANDLE" that has handles, counters,
|
||||
and other information. This structure will grow as new objects are added
|
||||
to this set; some members are specific to only one or two of the objects.
|
||||
4. Mutexes are used for critical sections. These could be replaced with
|
||||
CRITICAL_SECTION objects but then this would give up the time out
|
||||
capability.
|
||||
5. The implementation shows several interesting aspects of synchronization, some
|
||||
of which are specific to Win32 and some of which are general. These are pointed
|
||||
out in the comments as appropriate.
|
||||
6. The wait function emulates WaitForSingleObject only. An emulation of
|
||||
WaitForMultipleObjects is much harder to implement outside the kernel,
|
||||
and it is not clear how to handle a mixture of WCE semaphores and normal
|
||||
events and mutexes. */
|
||||
|
||||
#include "../../core/windows/SDL_windows.h"
|
||||
|
||||
#include "win_ce_semaphore.h"
|
||||
|
||||
static SYNCHHANDLE CleanUp(SYNCHHANDLE hSynch, DWORD Flags);
|
||||
|
||||
SYNCHHANDLE
|
||||
CreateSemaphoreCE(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, /* pointer to security attributes */
|
||||
LONG lInitialCount, /* initial count */
|
||||
LONG lMaximumCount, /* maximum count */
|
||||
LPCTSTR lpName)
|
||||
/* Semaphore for use with Windows CE that does not support them directly.
|
||||
Requires a counter, a mutex to protect the counter, and an
|
||||
autoreset event.
|
||||
|
||||
Here are the rules that must always hold between the autoreset event
|
||||
and the mutex (any violation of these rules by the CE semaphore functions
|
||||
will, in all likelihood, result in a defect):
|
||||
1. No thread can set, pulse, or reset the event,
|
||||
nor can it access any part of the SYNCHHANDLE structure,
|
||||
without first gaining ownership of the mutex.
|
||||
BUT, a thread can wait on the event without owning the mutex
|
||||
(this is clearly necessary or else the event could never be set).
|
||||
2. The event is in a signaled state if and only if the current semaphore
|
||||
count ("CurCount") is greater than zero.
|
||||
3. The semaphore count is always >= 0 and <= the maximum count */
|
||||
{
|
||||
SYNCHHANDLE hSynch = NULL, result = NULL;
|
||||
|
||||
__try {
|
||||
if (lInitialCount > lMaximumCount || lMaximumCount < 0
|
||||
|| lInitialCount < 0) {
|
||||
/* Bad parameters */
|
||||
SetLastError(SYNCH_ERROR);
|
||||
__leave;
|
||||
}
|
||||
|
||||
hSynch =
|
||||
HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, SYNCH_HANDLE_SIZE);
|
||||
if (hSynch == NULL)
|
||||
__leave;
|
||||
|
||||
hSynch->MaxCount = lMaximumCount;
|
||||
hSynch->CurCount = lInitialCount;
|
||||
hSynch->lpName = lpName;
|
||||
|
||||
hSynch->hMutex = CreateMutex(lpSemaphoreAttributes, FALSE, NULL);
|
||||
|
||||
WaitForSingleObject(hSynch->hMutex, INFINITE);
|
||||
/* Create the event. It is initially signaled if and only if the
|
||||
initial count is > 0 */
|
||||
hSynch->hEvent = CreateEvent(lpSemaphoreAttributes, FALSE,
|
||||
lInitialCount > 0, NULL);
|
||||
ReleaseMutex(hSynch->hMutex);
|
||||
hSynch->hSemph = NULL;
|
||||
}
|
||||
__finally {
|
||||
/* Return with the handle, or, if there was any error, return
|
||||
a null after closing any open handles and freeing any allocated memory. */
|
||||
result =
|
||||
CleanUp(hSynch, 6 /* An event and a mutex, but no semaphore. */ );
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
BOOL
|
||||
ReleaseSemaphoreCE(SYNCHHANDLE hSemCE, LONG cReleaseCount,
|
||||
LPLONG lpPreviousCount)
|
||||
/* Windows CE equivalent to ReleaseSemaphore. */
|
||||
{
|
||||
BOOL Result = TRUE;
|
||||
|
||||
/* Gain access to the object to assure that the release count
|
||||
would not cause the total count to exceed the maximum. */
|
||||
|
||||
__try {
|
||||
WaitForSingleObject(hSemCE->hMutex, INFINITE);
|
||||
/* reply only if asked to */
|
||||
if (lpPreviousCount != NULL)
|
||||
*lpPreviousCount = hSemCE->CurCount;
|
||||
if (hSemCE->CurCount + cReleaseCount > hSemCE->MaxCount
|
||||
|| cReleaseCount <= 0) {
|
||||
SetLastError(SYNCH_ERROR);
|
||||
Result = FALSE;
|
||||
__leave;
|
||||
}
|
||||
hSemCE->CurCount += cReleaseCount;
|
||||
|
||||
/* Set the autoreset event, releasing exactly one waiting thread, now or
|
||||
in the future. */
|
||||
|
||||
SetEvent(hSemCE->hEvent);
|
||||
}
|
||||
__finally {
|
||||
ReleaseMutex(hSemCE->hMutex);
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
DWORD
|
||||
WaitForSemaphoreCE(SYNCHHANDLE hSemCE, DWORD dwMilliseconds)
|
||||
/* Windows CE semaphore equivalent of WaitForSingleObject. */
|
||||
{
|
||||
DWORD WaitResult;
|
||||
|
||||
WaitResult = WaitForSingleObject(hSemCE->hMutex, dwMilliseconds);
|
||||
if (WaitResult != WAIT_OBJECT_0 && WaitResult != WAIT_ABANDONED_0)
|
||||
return WaitResult;
|
||||
while (hSemCE->CurCount <= 0) {
|
||||
|
||||
/* The count is 0, and the thread must wait on the event (which, by
|
||||
the rules, is currently reset) for semaphore resources to become
|
||||
available. First, of course, the mutex must be released so that another
|
||||
thread will be capable of setting the event. */
|
||||
|
||||
ReleaseMutex(hSemCE->hMutex);
|
||||
|
||||
/* Wait for the event to be signaled, indicating a semaphore state change.
|
||||
The event is autoreset and signaled with a SetEvent (not PulseEvent)
|
||||
so exactly one waiting thread (whether or not there is currently
|
||||
a waiting thread) is released as a result of the SetEvent. */
|
||||
|
||||
WaitResult = WaitForSingleObject(hSemCE->hEvent, dwMilliseconds);
|
||||
if (WaitResult != WAIT_OBJECT_0)
|
||||
return WaitResult;
|
||||
|
||||
/* This is where the properties of setting of an autoreset event is critical
|
||||
to assure that, even if the semaphore state changes between the
|
||||
preceding Wait and the next, and even if NO threads are waiting
|
||||
on the event at the time of the SetEvent, at least one thread
|
||||
will be released.
|
||||
Pulsing a manual reset event would appear to work, but it would have
|
||||
a defect which could appear if the semaphore state changed between
|
||||
the two waits. */
|
||||
|
||||
WaitResult = WaitForSingleObject(hSemCE->hMutex, dwMilliseconds);
|
||||
if (WaitResult != WAIT_OBJECT_0 && WaitResult != WAIT_ABANDONED_0)
|
||||
return WaitResult;
|
||||
|
||||
}
|
||||
/* The count is not zero and this thread owns the mutex. */
|
||||
|
||||
hSemCE->CurCount--;
|
||||
/* The event is now unsignaled, BUT, the semaphore count may not be
|
||||
zero, in which case the event should be signaled again
|
||||
before releasing the mutex. */
|
||||
|
||||
if (hSemCE->CurCount > 0)
|
||||
SetEvent(hSemCE->hEvent);
|
||||
ReleaseMutex(hSemCE->hMutex);
|
||||
return WaitResult;
|
||||
}
|
||||
|
||||
BOOL
|
||||
CloseSynchHandle(SYNCHHANDLE hSynch)
|
||||
/* Close a synchronization handle.
|
||||
Improvement: Test for a valid handle before dereferencing the handle. */
|
||||
{
|
||||
BOOL Result = TRUE;
|
||||
if (hSynch->hEvent != NULL)
|
||||
Result = Result && CloseHandle(hSynch->hEvent);
|
||||
if (hSynch->hMutex != NULL)
|
||||
Result = Result && CloseHandle(hSynch->hMutex);
|
||||
if (hSynch->hSemph != NULL)
|
||||
Result = Result && CloseHandle(hSynch->hSemph);
|
||||
HeapFree(GetProcessHeap(), 0, hSynch);
|
||||
return (Result);
|
||||
}
|
||||
|
||||
static SYNCHHANDLE
|
||||
CleanUp(SYNCHHANDLE hSynch, DWORD Flags)
|
||||
{ /* Prepare to return from a create of a synchronization handle.
|
||||
If there was any failure, free any allocated resources.
|
||||
"Flags" indicates which Win32 objects are required in the
|
||||
synchronization handle. */
|
||||
|
||||
BOOL ok = TRUE;
|
||||
|
||||
if (hSynch == NULL)
|
||||
return NULL;
|
||||
if ((Flags & 4) == 1 && (hSynch->hEvent == NULL))
|
||||
ok = FALSE;
|
||||
if ((Flags & 2) == 1 && (hSynch->hMutex == NULL))
|
||||
ok = FALSE;
|
||||
if ((Flags & 1) == 1 && (hSynch->hEvent == NULL))
|
||||
ok = FALSE;
|
||||
if (!ok) {
|
||||
CloseSynchHandle(hSynch);
|
||||
return NULL;
|
||||
}
|
||||
/* Everything worked */
|
||||
return hSynch;
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,25 @@
|
||||
/* win_ce_semaphore.h - header file to go with win_ce_semaphore.c */
|
||||
|
||||
typedef struct _SYNCH_HANDLE_STRUCTURE
|
||||
{
|
||||
HANDLE hEvent;
|
||||
HANDLE hMutex;
|
||||
HANDLE hSemph;
|
||||
LONG MaxCount;
|
||||
volatile LONG CurCount;
|
||||
LPCTSTR lpName;
|
||||
} SYNCH_HANDLE_STRUCTURE, *SYNCHHANDLE;
|
||||
|
||||
#define SYNCH_HANDLE_SIZE sizeof (SYNCH_HANDLE_STRUCTURE)
|
||||
|
||||
/* Error codes - all must have bit 29 set */
|
||||
#define SYNCH_ERROR 0X20000000 /* EXERCISE - REFINE THE ERROR NUMBERS */
|
||||
|
||||
extern SYNCHHANDLE CreateSemaphoreCE(LPSECURITY_ATTRIBUTES, LONG, LONG,
|
||||
LPCTSTR);
|
||||
|
||||
extern BOOL ReleaseSemaphoreCE(SYNCHHANDLE, LONG, LPLONG);
|
||||
extern DWORD WaitForSemaphoreCE(SYNCHHANDLE, DWORD);
|
||||
|
||||
extern BOOL CloseSynchHandle(SYNCHHANDLE);
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
Reference in New Issue
Block a user