Fixes #2022, do not resume on Android when surfaceChanged

If the app is in landscape mode and the user presses the power button, a pause
is followed immediately by a surfaceChanged event because the lock screen
is shown in portrait mode. This triggers a "false" resume.
So, we just pause and resume following the onWindowFocusChanged events.

Also, wait for SDL_APP_WILLENTERBACKGROUND and SDL_APP_DIDENTERBACKGROUND before
blocking the event pump.
This commit is contained in:
Gabriel Jacobo
2013-08-12 11:13:50 -03:00
commit dad420670f
859 changed files with 310893 additions and 0 deletions

View File

@@ -0,0 +1,61 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2013 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(const char *name);
/* 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);
/* Get the thread local storage for this thread */
extern SDL_TLSData *SDL_SYS_GetTLSData();
/* Set the thread local storage for this thread */
extern int SDL_SYS_SetTLSData(SDL_TLSData *data);
#endif /* _SDL_systhread_h */
/* vi: set ts=4 sw=4 expandtab: */

409
src/thread/SDL_thread.c Normal file
View File

@@ -0,0 +1,409 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2013 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_thread.h"
#include "SDL_thread_c.h"
#include "SDL_systhread.h"
#include "../SDL_error_c.h"
SDL_TLSID
SDL_TLSCreate()
{
static SDL_atomic_t SDL_tls_id;
return SDL_AtomicIncRef(&SDL_tls_id)+1;
}
void *
SDL_TLSGet(SDL_TLSID id)
{
SDL_TLSData *storage;
storage = SDL_SYS_GetTLSData();
if (!storage || id == 0 || id > storage->limit) {
return NULL;
}
return storage->array[id-1].data;
}
int
SDL_TLSSet(SDL_TLSID id, const void *value, void (*destructor)(void *))
{
SDL_TLSData *storage;
if (id == 0) {
return SDL_InvalidParamError("id");
}
storage = SDL_SYS_GetTLSData();
if (!storage || (id > storage->limit)) {
unsigned int i, oldlimit, newlimit;
oldlimit = storage ? storage->limit : 0;
newlimit = (id + TLS_ALLOC_CHUNKSIZE);
storage = (SDL_TLSData *)SDL_realloc(storage, sizeof(*storage)+(newlimit-1)*sizeof(storage->array[0]));
if (!storage) {
return SDL_OutOfMemory();
}
storage->limit = newlimit;
for (i = oldlimit; i < newlimit; ++i) {
storage->array[i].data = NULL;
storage->array[i].destructor = NULL;
}
if (SDL_SYS_SetTLSData(storage) != 0) {
return -1;
}
}
storage->array[id-1].data = SDL_const_cast(void*, value);
storage->array[id-1].destructor = destructor;
return 0;
}
static void
SDL_TLSCleanup()
{
SDL_TLSData *storage;
storage = SDL_SYS_GetTLSData();
if (storage) {
unsigned int i;
for (i = 0; i < storage->limit; ++i) {
if (storage->array[i].destructor) {
storage->array[i].destructor(storage->array[i].data);
}
}
SDL_SYS_SetTLSData(NULL);
SDL_free(storage);
}
}
/* This is a generic implementation of thread-local storage which doesn't
require additional OS support.
It is not especially efficient and doesn't clean up thread-local storage
as threads exit. If there is a real OS that doesn't support thread-local
storage this implementation should be improved to be production quality.
*/
typedef struct SDL_TLSEntry {
SDL_threadID thread;
SDL_TLSData *storage;
struct SDL_TLSEntry *next;
} SDL_TLSEntry;
static SDL_mutex *SDL_generic_TLS_mutex;
static SDL_TLSEntry *SDL_generic_TLS;
SDL_TLSData *
SDL_Generic_GetTLSData()
{
SDL_threadID thread = SDL_ThreadID();
SDL_TLSEntry *entry;
SDL_TLSData *storage = NULL;
if (!SDL_generic_TLS_mutex) {
static SDL_SpinLock tls_lock;
SDL_AtomicLock(&tls_lock);
if (!SDL_generic_TLS_mutex) {
SDL_mutex *mutex = SDL_CreateMutex();
SDL_MemoryBarrierRelease();
SDL_generic_TLS_mutex = mutex;
if (!SDL_generic_TLS_mutex) {
SDL_AtomicUnlock(&tls_lock);
return NULL;
}
}
SDL_AtomicUnlock(&tls_lock);
}
SDL_MemoryBarrierAcquire();
SDL_LockMutex(SDL_generic_TLS_mutex);
for (entry = SDL_generic_TLS; entry; entry = entry->next) {
if (entry->thread == thread) {
storage = entry->storage;
break;
}
}
SDL_UnlockMutex(SDL_generic_TLS_mutex);
return storage;
}
int
SDL_Generic_SetTLSData(SDL_TLSData *storage)
{
SDL_threadID thread = SDL_ThreadID();
SDL_TLSEntry *prev, *entry;
/* SDL_Generic_GetTLSData() is always called first, so we can assume SDL_generic_TLS_mutex */
SDL_LockMutex(SDL_generic_TLS_mutex);
prev = NULL;
for (entry = SDL_generic_TLS; entry; entry = entry->next) {
if (entry->thread == thread) {
if (storage) {
entry->storage = storage;
} else {
if (prev) {
prev->next = entry->next;
} else {
SDL_generic_TLS = entry->next;
}
SDL_free(entry);
}
break;
}
prev = entry;
}
if (!entry) {
entry = (SDL_TLSEntry *)SDL_malloc(sizeof(*entry));
if (entry) {
entry->thread = thread;
entry->storage = storage;
entry->next = SDL_generic_TLS;
SDL_generic_TLS = entry;
}
}
SDL_UnlockMutex(SDL_generic_TLS_mutex);
if (!entry) {
return SDL_OutOfMemory();
}
return 0;
}
/* Routine to get the thread-specific error variable */
SDL_error *
SDL_GetErrBuf(void)
{
static SDL_SpinLock tls_lock;
static SDL_bool tls_being_created;
static SDL_TLSID tls_errbuf;
static SDL_error SDL_global_errbuf;
const SDL_error *ALLOCATION_IN_PROGRESS = (SDL_error *)-1;
SDL_error *errbuf;
/* tls_being_created is there simply to prevent recursion if SDL_TLSCreate() fails.
It also means it's possible for another thread to also use SDL_global_errbuf,
but that's very unlikely and hopefully won't cause issues.
*/
if (!tls_errbuf && !tls_being_created) {
SDL_AtomicLock(&tls_lock);
if (!tls_errbuf) {
SDL_TLSID slot;
tls_being_created = SDL_TRUE;
slot = SDL_TLSCreate();
tls_being_created = SDL_FALSE;
SDL_MemoryBarrierRelease();
tls_errbuf = slot;
}
SDL_AtomicUnlock(&tls_lock);
}
if (!tls_errbuf) {
return &SDL_global_errbuf;
}
SDL_MemoryBarrierAcquire();
errbuf = (SDL_error *)SDL_TLSGet(tls_errbuf);
if (errbuf == ALLOCATION_IN_PROGRESS) {
return &SDL_global_errbuf;
}
if (!errbuf) {
/* Mark that we're in the middle of allocating our buffer */
SDL_TLSSet(tls_errbuf, ALLOCATION_IN_PROGRESS, NULL);
errbuf = (SDL_error *)SDL_malloc(sizeof(*errbuf));
if (!errbuf) {
SDL_TLSSet(tls_errbuf, NULL, NULL);
return &SDL_global_errbuf;
}
SDL_zerop(errbuf);
SDL_TLSSet(tls_errbuf, errbuf, SDL_free);
}
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 = (thread_args *) data;
int (SDLCALL * userfunc) (void *) = args->func;
void *userdata = args->data;
int *statusloc = &args->info->status;
/* Perform any system-dependent setup - this function may not fail */
SDL_SYS_SetupThread(args->info->name);
/* Get the thread id */
args->info->threadid = SDL_ThreadID();
/* Wake up the parent thread */
SDL_SemPost(args->wait);
/* Run the function */
*statusloc = userfunc(userdata);
/* Clean up thread-local storage */
SDL_TLSCleanup();
}
#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
#undef SDL_CreateThread
DECLSPEC SDL_Thread *SDLCALL
SDL_CreateThread(int (SDLCALL * fn) (void *),
const char *name, void *data,
pfnSDL_CurrentBeginThread pfnBeginThread,
pfnSDL_CurrentEndThread pfnEndThread)
#else
DECLSPEC SDL_Thread *SDLCALL
SDL_CreateThread(int (SDLCALL * fn) (void *),
const char *name, 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 */
if (name != NULL) {
thread->name = SDL_strdup(name);
if (thread->name == NULL) {
SDL_OutOfMemory();
SDL_free(thread);
return (NULL);
}
}
/* Set up the arguments for the thread */
args = (thread_args *) SDL_malloc(sizeof(*args));
if (args == NULL) {
SDL_OutOfMemory();
if (thread->name) {
SDL_free(thread->name);
}
SDL_free(thread);
return (NULL);
}
args->func = fn;
args->data = data;
args->info = thread;
args->wait = SDL_CreateSemaphore(0);
if (args->wait == NULL) {
if (thread->name) {
SDL_free(thread->name);
}
SDL_free(thread);
SDL_free(args);
return (NULL);
}
/* 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 */
if (thread->name) {
SDL_free(thread->name);
}
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;
}
const char *
SDL_GetThreadName(SDL_Thread * thread)
{
if (thread) {
return thread->name;
} else {
return NULL;
}
}
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;
}
if (thread->name) {
SDL_free(thread->name);
}
SDL_free(thread);
}
}
/* vi: set ts=4 sw=4 expandtab: */

85
src/thread/SDL_thread_c.h Normal file
View File

@@ -0,0 +1,85 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2013 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_WINDOWS
#include "windows/SDL_systhread_c.h"
#elif SDL_THREAD_PSP
#include "psp/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;
char *name;
void *data;
};
/* This is the function called to run a thread */
extern void SDL_RunThread(void *data);
/* This is the system-independent thread local storage structure */
typedef struct {
unsigned int limit;
struct {
void *data;
void (*destructor)(void*);
} array[1];
} SDL_TLSData;
/* This is how many TLS entries we allocate at once */
#define TLS_ALLOC_CHUNKSIZE 4
/* Get cross-platform, slow, thread local storage for this thread.
This is only intended as a fallback if getting real thread-local
storage fails or isn't supported on this platform.
*/
extern SDL_TLSData *SDL_Generic_GetTLSData();
/* Set cross-platform, slow, thread local storage for this thread.
This is only intended as a fallback if getting real thread-local
storage fails or isn't supported on this platform.
*/
extern int SDL_Generic_SetTLSData(SDL_TLSData *data);
#endif /* _SDL_thread_c_h */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -0,0 +1,151 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2013 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"
#ifdef SDL_THREAD_BEOS
/* 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) {
return SDL_SetError("Passed a NULL semaphore");
}
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:
retval = SDL_SetError("acquire_sem() failed");
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) {
return SDL_SetError("Passed a NULL semaphore");
}
if (release_sem(sem->id) != B_NO_ERROR) {
return SDL_SetError("release_sem() failed");
}
return 0;
}
#endif /* SDL_THREAD_BEOS */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -0,0 +1,126 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2013 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"
#ifdef SDL_THREAD_BEOS
/* 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)
{
/* The docs say the thread name can't be longer than B_OS_NAME_LENGTH. */
const char *threadname = thread->name ? thread->name : "SDL Thread";
char name[B_OS_NAME_LENGTH];
SDL_snprintf(name, sizeof (name), "%s", threadname);
name[sizeof (name) - 1] = '\0';
/* Create the thread and go! */
thread->handle = spawn_thread(RunThread, name, B_NORMAL_PRIORITY, args);
if ((thread->handle == B_NO_MORE_THREADS) ||
(thread->handle == B_NO_MEMORY)) {
return SDL_SetError("Not enough resources to create thread");
}
resume_thread(thread->handle);
return (0);
}
void
SDL_SYS_SetupThread(const char *name)
{
/* We set the thread name during SDL_SYS_CreateThread(). */
/* 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_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);
}
#endif /* SDL_THREAD_BEOS */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -0,0 +1,32 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2013 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: */

View File

@@ -0,0 +1,70 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2013 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_thread_c.h"
#if SDL_THREAD_BEOS
#include <support/TLS.h>
static int32 thread_local_storage = B_NO_MEMORY;
static SDL_bool generic_local_storage = SDL_FALSE;
SDL_TLSData *
SDL_SYS_GetTLSData()
{
if (thread_local_storage == B_NO_MEMORY && !generic_local_storage) {
static SDL_SpinLock lock;
SDL_AtomicLock(&lock);
if (thread_local_storage == B_NO_MEMORY && !generic_local_storage) {
int32 storage = tls_allocate();
if (storage != B_NO_MEMORY) {
SDL_MemoryBarrierRelease();
thread_local_storage = storage;
} else {
generic_local_storage = SDL_TRUE;
}
}
SDL_AtomicUnlock(&lock);
}
if (generic_local_storage) {
return SDL_Generic_GetTLSData();
}
SDL_MemoryBarrierAcquire();
return (SDL_TLSData *)tls_get(thread_local_storage);
}
int
SDL_SYS_SetTLSData(SDL_TLSData *data)
{
if (generic_local_storage) {
return SDL_Generic_SetTLSData(data);
}
tls_set(thread_local_storage, data);
return 0;
}
#endif /* SDL_THREAD_BEOS */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -0,0 +1,220 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2013 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) {
return SDL_SetError("Passed a NULL condition variable");
}
/* 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) {
return SDL_SetError("Passed a NULL condition variable");
}
/* 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) {
return SDL_SetError("Passed a NULL condition variable");
}
/* 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://web.archive.org/web/20010914175514/http://www-classic.be.com/aboutbe/benewsletter/volume_III/Issue40.html#Workshop
*/
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: */

View File

@@ -0,0 +1,165 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2013 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 mutex */
int
SDL_LockMutex(SDL_mutex * mutex)
{
#if SDL_THREADS_DISABLED
return 0;
#else
SDL_threadID this_thread;
if (mutex == NULL) {
return SDL_SetError("Passed a NULL mutex");
}
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 */
}
/* try Lock the mutex */
int
SDL_TryLockMutex(SDL_mutex * mutex)
{
#if SDL_THREADS_DISABLED
return 0;
#else
int retval = 0;
SDL_threadID this_thread;
if (mutex == NULL) {
return SDL_SetError("Passed a NULL mutex");
}
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.
*/
retval = SDL_SemWait(mutex->sem);
if (retval == 0) {
mutex->owner = this_thread;
mutex->recursive = 0;
}
}
return retval;
#endif /* SDL_THREADS_DISABLED */
}
/* Unlock the mutex */
int
SDL_mutexV(SDL_mutex * mutex)
{
#if SDL_THREADS_DISABLED
return 0;
#else
if (mutex == NULL) {
return SDL_SetError("Passed a NULL mutex");
}
/* If we don't own the mutex, we can't unlock it */
if (SDL_ThreadID() != mutex->owner) {
return SDL_SetError("mutex not owned by this thread");
}
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: */

View File

@@ -0,0 +1,22 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2013 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: */

View File

@@ -0,0 +1,217 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2013 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 built with thread support");
return (SDL_sem *) 0;
}
void
SDL_DestroySemaphore(SDL_sem * sem)
{
}
int
SDL_SemTryWait(SDL_sem * sem)
{
return SDL_SetError("SDL not built with thread support");
}
int
SDL_SemWaitTimeout(SDL_sem * sem, Uint32 timeout)
{
return SDL_SetError("SDL not built with thread support");
}
int
SDL_SemWait(SDL_sem * sem)
{
return SDL_SetError("SDL not built with thread support");
}
Uint32
SDL_SemValue(SDL_sem * sem)
{
return 0;
}
int
SDL_SemPost(SDL_sem * sem)
{
return SDL_SetError("SDL not built with thread support");
}
#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_LockMutex(sem->count_lock);
SDL_UnlockMutex(sem->count_lock);
SDL_DestroyMutex(sem->count_lock);
}
SDL_free(sem);
}
}
int
SDL_SemTryWait(SDL_sem * sem)
{
int retval;
if (!sem) {
return SDL_SetError("Passed a NULL semaphore");
}
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) {
return SDL_SetError("Passed a NULL semaphore");
}
/* 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) {
return SDL_SetError("Passed a NULL semaphore");
}
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: */

View File

@@ -0,0 +1,65 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2013 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"
#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)
#endif /* SDL_PASSED_BEGINTHREAD_ENDTHREAD */
{
return SDL_SetError("Threads are not supported on this platform");
}
void
SDL_SYS_SetupThread(const char *name)
{
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: */

View File

@@ -0,0 +1,26 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2013 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: */

View File

@@ -0,0 +1,38 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2013 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_c.h"
SDL_TLSData *
SDL_SYS_GetTLSData()
{
return SDL_Generic_GetTLSData();
}
int
SDL_SYS_SetTLSData(SDL_TLSData *data)
{
return SDL_Generic_SetTLSData(data);
}
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -0,0 +1,220 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2013 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) {
return SDL_SetError("Passed a NULL condition variable");
}
/* 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) {
return SDL_SetError("Passed a NULL condition variable");
}
/* 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) {
return SDL_SetError("Passed a NULL condition variable");
}
/* 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: */

View File

@@ -0,0 +1,132 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2013 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) {
return SDL_SetError("Passed a NULL mutex");
}
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) {
return SDL_SetError("Passed a NULL mutex");
}
/* If we don't own the mutex, we can't unlock it */
if (SDL_ThreadID() != mutex->owner) {
return SDL_SetError("mutex not owned by this thread");
}
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: */

View File

@@ -0,0 +1,22 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2013 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: */

156
src/thread/psp/SDL_syssem.c Normal file
View File

@@ -0,0 +1,156 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2013 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.
*/
/* Semaphore functions for the PSP. */
#include <stdio.h>
#include <stdlib.h>
#include "SDL_error.h"
#include "SDL_thread.h"
#include <pspthreadman.h>
#include <pspkerror.h>
struct SDL_semaphore {
SceUID semid;
};
/* Create a semaphore */
SDL_sem *SDL_CreateSemaphore(Uint32 initial_value)
{
SDL_sem *sem;
sem = (SDL_sem *) malloc(sizeof(*sem));
if (sem != NULL) {
/* TODO: Figure out the limit on the maximum value. */
sem->semid = sceKernelCreateSema("SDL sema", 0, initial_value, 255, NULL);
if (sem->semid < 0) {
SDL_SetError("Couldn't create semaphore");
free(sem);
sem = NULL;
}
} else {
SDL_OutOfMemory();
}
return sem;
}
/* Free the semaphore */
void SDL_DestroySemaphore(SDL_sem *sem)
{
if (sem != NULL) {
if (sem->semid > 0) {
sceKernelDeleteSema(sem->semid);
sem->semid = 0;
}
free(sem);
}
}
/* TODO: This routine is a bit overloaded.
* If the timeout is 0 then just poll the semaphore; if it's SDL_MUTEX_MAXWAIT, pass
* NULL to sceKernelWaitSema() so that it waits indefinitely; and if the timeout
* is specified, convert it to microseconds. */
int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
{
Uint32 *pTimeout;
unsigned int res;
if (sem == NULL) {
SDL_SetError("Passed a NULL sem");
return 0;
}
if (timeout == 0) {
res = sceKernelPollSema(sem->semid, 1);
if (res < 0) {
return SDL_MUTEX_TIMEDOUT;
}
return 0;
}
if (timeout == SDL_MUTEX_MAXWAIT) {
pTimeout = NULL;
} else {
timeout *= 1000; /* Convert to microseconds. */
pTimeout = &timeout;
}
res = sceKernelWaitSema(sem->semid, 1, pTimeout);
switch (res) {
case SCE_KERNEL_ERROR_OK:
return 0;
case SCE_KERNEL_ERROR_WAIT_TIMEOUT:
return SDL_MUTEX_TIMEDOUT;
default:
return SDL_SetError("WaitForSingleObject() failed");
}
}
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)
{
SceKernelSemaInfo info;
if (sem == NULL) {
SDL_SetError("Passed a NULL sem");
return 0;
}
if (sceKernelReferSemaStatus(sem->semid, &info) >= 0) {
return info.currentCount;
}
return 0;
}
int SDL_SemPost(SDL_sem *sem)
{
int res;
if (sem == NULL) {
return SDL_SetError("Passed a NULL sem");
}
res = sceKernelSignalSema(sem->semid, 1);
if (res < 0) {
return SDL_SetError("sceKernelSignalSema() failed");
}
return 0;
}
/* vim: ts=4 sw=4
*/

View File

@@ -0,0 +1,102 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2013 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.
*/
/* PSP thread management routines for SDL */
#include <stdio.h>
#include <stdlib.h>
#include "SDL_error.h"
#include "SDL_thread.h"
#include "../SDL_systhread.h"
#include "../SDL_thread_c.h"
#include <pspkerneltypes.h>
#include <pspthreadman.h>
static int ThreadEntry(SceSize args, void *argp)
{
SDL_RunThread(*(void **) argp);
return 0;
}
int SDL_SYS_CreateThread(SDL_Thread *thread, void *args)
{
SceKernelThreadInfo status;
int priority = 32;
/* Set priority of new thread to the same as the current thread */
status.size = sizeof(SceKernelThreadInfo);
if (sceKernelReferThreadStatus(sceKernelGetThreadId(), &status) == 0) {
priority = status.currentPriority;
}
thread->handle = sceKernelCreateThread("SDL thread", ThreadEntry,
priority, 0x8000,
PSP_THREAD_ATTR_VFPU, NULL);
if (thread->handle < 0) {
return SDL_SetError("sceKernelCreateThread() failed");
}
sceKernelStartThread(thread->handle, 4, &args);
return 0;
}
void SDL_SYS_SetupThread(const char *name)
{
/* Do nothing. */
}
SDL_threadID SDL_ThreadID(void)
{
return (SDL_threadID) sceKernelGetThreadId();
}
void SDL_SYS_WaitThread(SDL_Thread *thread)
{
sceKernelWaitThreadEnd(thread->handle, NULL);
sceKernelDeleteThread(thread->handle);
}
void SDL_SYS_KillThread(SDL_Thread *thread)
{
sceKernelTerminateDeleteThread(thread->handle);
}
int SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority)
{
int value;
if (priority == SDL_THREAD_PRIORITY_LOW) {
value = 19;
} else if (priority == SDL_THREAD_PRIORITY_HIGH) {
value = -20;
} else {
value = 0;
}
return sceKernelChangeThreadPriority(sceKernelGetThreadId(),value);
}
/* vim: ts=4 sw=4
*/

View File

@@ -0,0 +1,24 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2013 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 <pspkerneltypes.h>
typedef SceUID SYS_ThreadHandle;

View File

@@ -0,0 +1,148 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2013 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) {
return SDL_SetError("Passed a NULL condition variable");
}
retval = 0;
if (pthread_cond_signal(&cond->cond) != 0) {
return SDL_SetError("pthread_cond_signal() failed");
}
return retval;
}
/* Restart all threads that are waiting on the condition variable */
int
SDL_CondBroadcast(SDL_cond * cond)
{
int retval;
if (!cond) {
return SDL_SetError("Passed a NULL condition variable");
}
retval = 0;
if (pthread_cond_broadcast(&cond->cond) != 0) {
return SDL_SetError("pthread_cond_broadcast() failed");
}
return retval;
}
int
SDL_CondWaitTimeout(SDL_cond * cond, SDL_mutex * mutex, Uint32 ms)
{
int retval;
struct timeval delta;
struct timespec abstime;
if (!cond) {
return SDL_SetError("Passed a NULL condition variable");
}
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:
retval = SDL_SetError("pthread_cond_timedwait() failed");
}
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)
{
if (!cond) {
return SDL_SetError("Passed a NULL condition variable");
} else if (pthread_cond_wait(&cond->cond, &mutex->id) != 0) {
return SDL_SetError("pthread_cond_wait() failed");
}
return 0;
}
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -0,0 +1,193 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2013 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 <errno.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_LockMutex(SDL_mutex * mutex)
{
#if FAKE_RECURSIVE_MUTEX
pthread_t this_thread;
#endif
if (mutex == NULL) {
return SDL_SetError("Passed a NULL mutex");
}
#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 {
return SDL_SetError("pthread_mutex_lock() failed");
}
}
#else
if (pthread_mutex_lock(&mutex->id) < 0) {
return SDL_SetError("pthread_mutex_lock() failed");
}
#endif
return 0;
}
int
SDL_TryLockMutex(SDL_mutex * mutex)
{
int retval;
#if FAKE_RECURSIVE_MUTEX
pthread_t this_thread;
#endif
if (mutex == NULL) {
return SDL_SetError("Passed a NULL mutex");
}
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 if (errno == EBUSY) {
retval = SDL_MUTEX_TIMEDOUT;
} else {
retval = SDL_SetError("pthread_mutex_trylock() failed");
}
}
#else
if (pthread_mutex_trylock(&mutex->id) != 0) {
if (errno == EBUSY) {
retval = SDL_MUTEX_TIMEDOUT;
} else {
retval = SDL_SetError("pthread_mutex_trylock() failed");
}
}
#endif
return retval;
}
int
SDL_UnlockMutex(SDL_mutex * mutex)
{
if (mutex == NULL) {
return SDL_SetError("Passed a NULL mutex");
}
#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 {
return SDL_SetError("mutex not owned by this thread");
}
#else
if (pthread_mutex_unlock(&mutex->id) < 0) {
return SDL_SetError("pthread_mutex_unlock() failed");
}
#endif /* FAKE_RECURSIVE_MUTEX */
return 0;
}
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -0,0 +1,32 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2013 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: */

View File

@@ -0,0 +1,199 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2013 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 <sys/time.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) {
return SDL_SetError("Passed a NULL semaphore");
}
retval = SDL_MUTEX_TIMEDOUT;
if (sem_trywait(&sem->sem) == 0) {
retval = 0;
}
return retval;
}
int
SDL_SemWait(SDL_sem * sem)
{
int retval;
if (!sem) {
return SDL_SetError("Passed a NULL semaphore");
}
retval = sem_wait(&sem->sem);
if (retval < 0) {
retval = SDL_SetError("sem_wait() failed");
}
return retval;
}
int
SDL_SemWaitTimeout(SDL_sem * sem, Uint32 timeout)
{
int retval;
#ifdef HAVE_SEM_TIMEDWAIT
struct timeval now;
struct timespec ts_timeout;
#else
Uint32 end;
#endif
if (!sem) {
return SDL_SetError("Passed a NULL semaphore");
}
/* Try the easy cases first */
if (timeout == 0) {
return SDL_SemTryWait(sem);
}
if (timeout == SDL_MUTEX_MAXWAIT) {
return SDL_SemWait(sem);
}
#ifdef HAVE_SEM_TIMEDWAIT
/* 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) {
if (errno == ETIMEDOUT) {
retval = SDL_MUTEX_TIMEDOUT;
} else {
SDL_SetError(strerror(errno));
}
}
#else
end = SDL_GetTicks() + timeout;
while ((retval = SDL_SemTryWait(sem)) == SDL_MUTEX_TIMEDOUT) {
if ((SDL_GetTicks() - end) >= 0) {
break;
}
SDL_Delay(0);
}
#endif /* HAVE_SEM_TIMEDWAIT */
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) {
return SDL_SetError("Passed a NULL semaphore");
}
retval = sem_post(&sem->sem);
if (retval < 0) {
SDL_SetError("sem_post() failed");
}
return retval;
}
#endif /* __MACOSX__ */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -0,0 +1,207 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2013 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>
#if HAVE_PTHREAD_NP_H
#include <pthread_np.h>
#endif
#include <signal.h>
#ifdef __LINUX__
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/syscall.h>
#include <unistd.h>
#endif /* __LINUX__ */
#if defined(__LINUX__) || defined(__MACOSX__) || defined(__IPHONEOS__)
#include <dlfcn.h>
#ifndef RTLD_DEFAULT
#define RTLD_DEFAULT NULL
#endif
#endif
#include "SDL_platform.h"
#include "SDL_thread.h"
#include "../SDL_thread_c.h"
#include "../SDL_systhread.h"
#ifdef __ANDROID__
#include "../../core/android/SDL_android.h"
#endif
#include "SDL_assert.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)
{
#ifdef __ANDROID__
Android_JNI_SetupThread();
#endif
SDL_RunThread(data);
return NULL;
}
#if defined(__MACOSX__) || defined(__IPHONEOS__)
static SDL_bool checked_setname = SDL_FALSE;
static int (*ppthread_setname_np)(const char*) = NULL;
#elif defined(__LINUX__)
static SDL_bool checked_setname = SDL_FALSE;
static int (*ppthread_setname_np)(pthread_t, const char*) = NULL;
#endif
int
SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
{
pthread_attr_t type;
/* do this here before any threads exist, so there's no race condition. */
#if defined(__MACOSX__) || defined(__IPHONEOS__) || defined(__LINUX__)
if (!checked_setname) {
void *fn = dlsym(RTLD_DEFAULT, "pthread_setname_np");
#if defined(__MACOSX__) || defined(__IPHONEOS__)
ppthread_setname_np = (int(*)(const char*)) fn;
#elif defined(__LINUX__)
ppthread_setname_np = (int(*)(pthread_t, const char*)) fn;
#endif
checked_setname = SDL_TRUE;
}
#endif
/* Set the thread attributes */
if (pthread_attr_init(&type) != 0) {
return SDL_SetError("Couldn't initialize pthread attributes");
}
pthread_attr_setdetachstate(&type, PTHREAD_CREATE_JOINABLE);
/* Create the thread and go! */
if (pthread_create(&thread->handle, &type, RunThread, args) != 0) {
return SDL_SetError("Not enough resources to create thread");
}
return 0;
}
void
SDL_SYS_SetupThread(const char *name)
{
int i;
sigset_t mask;
if (name != NULL) {
#if defined(__MACOSX__) || defined(__IPHONEOS__) || defined(__LINUX__)
SDL_assert(checked_setname);
if (ppthread_setname_np != NULL) {
#if defined(__MACOSX__) || defined(__IPHONEOS__)
ppthread_setname_np(name);
#elif defined(__LINUX__)
ppthread_setname_np(pthread_self(), name);
#endif
}
#elif HAVE_PTHREAD_SETNAME_NP
pthread_setname_np(pthread_self(), name);
#elif HAVE_PTHREAD_SET_NAME_NP
pthread_set_name_np(pthread_self(), name);
#endif
}
/* 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!
*/
return SDL_SetError("setpriority() failed");
}
return 0;
#else
struct sched_param sched;
int policy;
pthread_t thread = pthread_self();
if (pthread_getschedparam(thread, &policy, &sched) < 0) {
return SDL_SetError("pthread_getschedparam() failed");
}
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) {
return SDL_SetError("pthread_setschedparam() failed");
}
return 0;
#endif /* linux */
}
void
SDL_SYS_WaitThread(SDL_Thread * thread)
{
pthread_join(thread->handle, 0);
}
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -0,0 +1,27 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2013 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: */

View File

@@ -0,0 +1,69 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2013 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_thread_c.h"
#include <pthread.h>
#define INVALID_PTHREAD_KEY ((pthread_key_t)-1)
static pthread_key_t thread_local_storage = INVALID_PTHREAD_KEY;
static SDL_bool generic_local_storage = SDL_FALSE;
SDL_TLSData *
SDL_SYS_GetTLSData()
{
if (thread_local_storage == INVALID_PTHREAD_KEY && !generic_local_storage) {
static SDL_SpinLock lock;
SDL_AtomicLock(&lock);
if (thread_local_storage == INVALID_PTHREAD_KEY && !generic_local_storage) {
pthread_key_t storage;
if (pthread_key_create(&storage, NULL) == 0) {
SDL_MemoryBarrierRelease();
thread_local_storage = storage;
} else {
generic_local_storage = SDL_TRUE;
}
}
SDL_AtomicUnlock(&lock);
}
if (generic_local_storage) {
return SDL_Generic_GetTLSData();
}
SDL_MemoryBarrierAcquire();
return (SDL_TLSData *)pthread_getspecific(thread_local_storage);
}
int
SDL_SYS_SetTLSData(SDL_TLSData *data)
{
if (generic_local_storage) {
return SDL_Generic_SetTLSData(data);
}
if (pthread_setspecific(thread_local_storage, data) != 0) {
return SDL_SetError("pthread_setspecific() failed");
}
return 0;
}
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -0,0 +1,106 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2013 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"
#if SDL_THREAD_WINDOWS
/* 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 */
/* On SMP systems, a non-zero spin count generally helps performance */
InitializeCriticalSectionAndSpinCount(&mutex->cs, 2000);
} 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_LockMutex(SDL_mutex * mutex)
{
if (mutex == NULL) {
return SDL_SetError("Passed a NULL mutex");
}
EnterCriticalSection(&mutex->cs);
return (0);
}
/* TryLock the mutex */
int
SDL_TryLockMutex(SDL_mutex * mutex)
{
int retval = 0;
if (mutex == NULL) {
return SDL_SetError("Passed a NULL mutex");
}
if (TryEnterCriticalSection(&mutex->cs) == 0) {
retval = SDL_MUTEX_TIMEDOUT;
}
return retval;
}
/* Unlock the mutex */
int
SDL_UnlockMutex(SDL_mutex * mutex)
{
if (mutex == NULL) {
return SDL_SetError("Passed a NULL mutex");
}
LeaveCriticalSection(&mutex->cs);
return (0);
}
#endif /* SDL_THREAD_WINDOWS */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -0,0 +1,148 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2013 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"
#if SDL_THREAD_WINDOWS
/* Semaphore functions using the Win32 API */
#include "../../core/windows/SDL_windows.h"
#include "SDL_thread.h"
struct SDL_semaphore
{
HANDLE id;
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 */
sem->id = CreateSemaphore(NULL, initial_value, 32 * 1024, NULL);
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) {
CloseHandle(sem->id);
sem->id = 0;
}
SDL_free(sem);
}
}
int
SDL_SemWaitTimeout(SDL_sem * sem, Uint32 timeout)
{
int retval;
DWORD dwMilliseconds;
if (!sem) {
return SDL_SetError("Passed a NULL sem");
}
if (timeout == SDL_MUTEX_MAXWAIT) {
dwMilliseconds = INFINITE;
} else {
dwMilliseconds = (DWORD) timeout;
}
switch (WaitForSingleObject(sem->id, dwMilliseconds)) {
case WAIT_OBJECT_0:
InterlockedDecrement(&sem->count);
retval = 0;
break;
case WAIT_TIMEOUT:
retval = SDL_MUTEX_TIMEDOUT;
break;
default:
retval = SDL_SetError("WaitForSingleObject() failed");
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) {
return SDL_SetError("Passed a NULL sem");
}
/* 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 (ReleaseSemaphore(sem->id, 1, NULL) == FALSE) {
InterlockedDecrement(&sem->count); /* restore */
return SDL_SetError("ReleaseSemaphore() failed");
}
return 0;
}
#endif /* SDL_THREAD_WINDOWS */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -0,0 +1,219 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2013 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"
#if SDL_THREAD_WINDOWS
/* 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
/* We'll use the C library from this DLL */
#include <process.h>
/* Cygwin gcc-3 ... MingW64 (even with a i386 host) does this like MSVC. */
#if (defined(__MINGW32__) && (__GNUC__ < 4))
typedef unsigned long (__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
RunThread(void *data)
{
pThreadStartParms pThreadParms = (pThreadStartParms) data;
pfnSDL_CurrentEndThread pfnEndThread = pThreadParms->pfnCurrentEndThread;
void *args = pThreadParms->args;
SDL_free(pThreadParms);
SDL_RunThread(args);
if (pfnEndThread != NULL)
pfnEndThread(0);
return (0);
}
static DWORD WINAPI
RunThreadViaCreateThread(LPVOID data)
{
return RunThread(data);
}
static unsigned __stdcall
RunThreadViaBeginThreadEx(void *data)
{
return (unsigned) RunThread(data);
}
#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
int
SDL_SYS_CreateThread(SDL_Thread * thread, void *args,
pfnSDL_CurrentBeginThread pfnBeginThread,
pfnSDL_CurrentEndThread pfnEndThread)
{
#elif defined(__CYGWIN__)
int
SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
{
pfnSDL_CurrentBeginThread pfnBeginThread = NULL;
pfnSDL_CurrentEndThread pfnEndThread = NULL;
#else
int
SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
{
pfnSDL_CurrentBeginThread pfnBeginThread = _beginthreadex;
pfnSDL_CurrentEndThread pfnEndThread = _endthreadex;
#endif /* SDL_PASSED_BEGINTHREAD_ENDTHREAD */
pThreadStartParms pThreadParms =
(pThreadStartParms) SDL_malloc(sizeof(tThreadStartParms));
if (!pThreadParms) {
return SDL_OutOfMemory();
}
/* 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) {
unsigned threadid = 0;
thread->handle = (SYS_ThreadHandle)
((size_t) pfnBeginThread(NULL, 0, RunThreadViaBeginThreadEx,
pThreadParms, 0, &threadid));
} else {
DWORD threadid = 0;
thread->handle = CreateThread(NULL, 0, RunThreadViaCreateThread,
pThreadParms, 0, &threadid);
}
if (thread->handle == NULL) {
return SDL_SetError("Not enough resources to create thread");
}
return 0;
}
#ifdef _MSC_VER
#pragma pack(push,8)
typedef struct tagTHREADNAME_INFO
{
DWORD dwType; /* must be 0x1000 */
LPCSTR szName; /* pointer to name (in user addr space) */
DWORD dwThreadID; /* thread ID (-1=caller thread) */
DWORD dwFlags; /* reserved for future use, must be zero */
} THREADNAME_INFO;
#pragma pack(pop)
#endif
void
SDL_SYS_SetupThread(const char *name)
{
if (name != NULL) {
#if 0 /* !!! FIXME: __except needs C runtime, which we don't link against. */
#ifdef _MSC_VER /* !!! FIXME: can we do SEH on other compilers yet? */
/* This magic tells the debugger to name a thread if it's listening. */
THREADNAME_INFO inf;
inf.dwType = 0x1000;
inf.szName = name;
inf.dwThreadID = (DWORD) -1;
inf.dwFlags = 0;
__try
{
RaiseException(0x406D1388, 0, sizeof(inf)/sizeof(DWORD), (DWORD*)&inf);
}
__except(EXCEPTION_CONTINUE_EXECUTION)
{
/* The program itself should ignore this bogus exception. */
}
#endif
#endif
}
}
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)) {
return WIN_SetError("SetThreadPriority()");
}
return 0;
}
void
SDL_SYS_WaitThread(SDL_Thread * thread)
{
WaitForSingleObject(thread->handle, INFINITE);
CloseHandle(thread->handle);
}
#endif /* SDL_THREAD_WINDOWS */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -0,0 +1,32 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2013 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: */

View File

@@ -0,0 +1,72 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2013 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_thread_c.h"
#if SDL_THREAD_WINDOWS
#include "../../core/windows/SDL_windows.h"
static DWORD thread_local_storage = TLS_OUT_OF_INDEXES;
static SDL_bool generic_local_storage = SDL_FALSE;
SDL_TLSData *
SDL_SYS_GetTLSData()
{
if (thread_local_storage == TLS_OUT_OF_INDEXES && !generic_local_storage) {
static SDL_SpinLock lock;
SDL_AtomicLock(&lock);
if (thread_local_storage == TLS_OUT_OF_INDEXES && !generic_local_storage) {
DWORD storage = TlsAlloc();
if (storage != TLS_OUT_OF_INDEXES) {
SDL_MemoryBarrierRelease();
thread_local_storage = storage;
} else {
generic_local_storage = SDL_TRUE;
}
}
SDL_AtomicUnlock(&lock);
}
if (generic_local_storage) {
return SDL_Generic_GetTLSData();
}
SDL_MemoryBarrierAcquire();
return (SDL_TLSData *)TlsGetValue(thread_local_storage);
}
int
SDL_SYS_SetTLSData(SDL_TLSData *data)
{
if (generic_local_storage) {
return SDL_Generic_SetTLSData(data);
}
if (!TlsSetValue(thread_local_storage, data)) {
return SDL_SetError("TlsSetValue() failed");
}
return 0;
}
#endif /* SDL_THREAD_WINDOWS */
/* vi: set ts=4 sw=4 expandtab: */