mirror of
https://github.com/encounter/SDL.git
synced 2025-12-11 22:44:17 +00:00
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:
148
src/thread/pthread/SDL_syscond.c
Normal file
148
src/thread/pthread/SDL_syscond.c
Normal 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: */
|
||||
193
src/thread/pthread/SDL_sysmutex.c
Normal file
193
src/thread/pthread/SDL_sysmutex.c
Normal 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: */
|
||||
32
src/thread/pthread/SDL_sysmutex_c.h
Normal file
32
src/thread/pthread/SDL_sysmutex_c.h
Normal 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: */
|
||||
199
src/thread/pthread/SDL_syssem.c
Normal file
199
src/thread/pthread/SDL_syssem.c
Normal 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: */
|
||||
207
src/thread/pthread/SDL_systhread.c
Normal file
207
src/thread/pthread/SDL_systhread.c
Normal 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: */
|
||||
27
src/thread/pthread/SDL_systhread_c.h
Normal file
27
src/thread/pthread/SDL_systhread_c.h
Normal 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: */
|
||||
69
src/thread/pthread/SDL_systls.c
Normal file
69
src/thread/pthread/SDL_systls.c
Normal 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: */
|
||||
Reference in New Issue
Block a user