SDL_thread.c File Reference
`#include "../SDL_internal.h"`
`#include "SDL_assert.h"`
`#include "SDL_thread.h"`
`#include "SDL_thread_c.h"`
`#include "SDL_systhread.h"`
`#include "../SDL_error_c.h"`
Include dependency graph for SDL_thread.c:

Go to the source code of this file.

## Data Structures

struct | SDL_TLSEntry
struct | thread_args

## Macros

#define | SDL_CreateThread SDL_CreateThread_REAL

## Functions

SDL_TLSID | SDL_TLSCreate ()
| Create an identifier that is globally visible to all threads but refers to data that is thread-specific. More...
void * | SDL_TLSGet (SDL_TLSID id)
| Get the value associated with a thread local storage ID for the current thread. More...
int | SDL_TLSSet (SDL_TLSID id, const void *value, void(*destructor)(void *))
| Set the value associated with a thread local storage ID for the current thread. More...
static void | SDL_TLSCleanup ()
SDL_TLSData * | SDL_Generic_GetTLSData ()
int | SDL_Generic_SetTLSData (SDL_TLSData *storage)
SDL_error * | SDL_GetErrBuf (void)
void | SDL_RunThread (void *data)
SDL_Thread * | SDL_CreateThread (int(*fn)(void *), const char *name, void *data)
SDL_threadID | SDL_GetThreadID (SDL_Thread *thread)
const char * | SDL_GetThreadName (SDL_Thread *thread)
int | SDL_SetThreadPriority (SDL_ThreadPriority priority)
void | SDL_WaitThread (SDL_Thread *thread, int *status)
void | SDL_DetachThread (SDL_Thread *thread)

## Variables

static SDL_mutex * | SDL_generic_TLS_mutex
static SDL_TLSEntry * | SDL_generic_TLS

## Macro Definition Documentation

#define SDL_CreateThread SDL_CreateThread_REAL

Definition at line 303 of file SDL_thread.c.

## Function Documentation

SDL_Thread* SDL_CreateThread | ( | int(*)(void *) | fn,
|  | const char * | name,
|  | void * | data
| ) |  |

Definition at line 314 of file SDL_thread.c.

References thread_args::data, thread_args::func, thread_args::info, SDL_Thread::name, NULL, SDL_AtomicSet, SDL_CreateSemaphore, SDL_DestroySemaphore, SDL_free(), SDL_malloc, SDL_OutOfMemory, SDL_SemWait, SDL_strdup, SDL_SYS_CreateThread(), SDL_THREAD_STATE_ALIVE, SDL_zerop, SDL_Thread::state, SDL_Thread::status, SDL_TLSEntry::thread, and thread_args::wait.

{
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_zerop(thread);
thread->status = -1;
SDL_AtomicSet(&thread->state, SDL_THREAD_STATE_ALIVE);
/* 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_Thread::state
SDL_atomic_t state
Definition: SDL_thread_c.h:59
SDL_Thread::name
char * name
Definition: SDL_thread_c.h:61
SDL_CreateSemaphore
#define SDL_CreateSemaphore
Definition: SDL_dynapi_overrides.h:270
data
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1967
thread_args
Definition: SDL_thread.c:255
name
GLuint const GLchar * name
Definition: SDL_opengl_glext.h:660
SDL_Thread::status
int status
Definition: SDL_thread_c.h:58
SDL_zerop
#define SDL_zerop(x)
Definition: SDL_stdinc.h:356
SDL_THREAD_STATE_ALIVE
Definition: SDL_thread_c.h:47
SDL_free
void SDL_free(void *mem)
thread_args::func
int(* func)(void *)
Definition: SDL_thread.c:257
NULL
#define NULL
Definition: begin_code.h:143
SDL_OutOfMemory
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
thread_args::info
SDL_Thread * info
Definition: SDL_thread.c:259
thread_args::wait
SDL_sem * wait
Definition: SDL_thread.c:260
SDL_strdup
#define SDL_strdup
Definition: SDL_dynapi_overrides.h:403
SDL_SemWait
#define SDL_SemWait
Definition: SDL_dynapi_overrides.h:272
SDL_DestroySemaphore
#define SDL_DestroySemaphore
Definition: SDL_dynapi_overrides.h:271
SDL_AtomicSet
#define SDL_AtomicSet
Definition: SDL_dynapi_overrides.h:73
SDL_Thread
Definition: SDL_thread_c.h:54
SDL_malloc
#define SDL_malloc
Definition: SDL_dynapi_overrides.h:380
thread_args::data
void * data
Definition: SDL_thread.c:258
SDL_SYS_CreateThread
int SDL_SYS_CreateThread(SDL_Thread *thread, void *args)
Definition: SDL_systhread.c:35

void SDL_DetachThread | ( | SDL_Thread * | thread | ) |

A thread may be "detached" to signify that it should not remain until another thread has called SDL_WaitThread() on it. Detaching a thread is useful for long-running threads that nothing needs to synchronize with or further manage. When a detached thread is done, it simply goes away.

There is no way to recover the return code of a detached thread. If you need this, don't detach the thread and instead use SDL_WaitThread().

Once a thread is detached, you should usually assume the SDL_Thread isn't safe to reference again, as it will become invalid immediately upon the detached thread's exit, instead of remaining until someone has called SDL_WaitThread() to finally clean it up. As such, don't detach the same thread more than once.

If a thread has already exited when passed to SDL_DetachThread(), it will stop waiting for a call to SDL_WaitThread() and clean up immediately. It is not safe to detach a thread that might be used with SDL_WaitThread().

You may not call SDL_WaitThread() on a thread that has been detached. Use either that function or this one, but not both, or behavior is undefined.

It is safe to pass NULL to this function; it is a no-op.

Definition at line 434 of file SDL_thread.c.

References NULL, SDL_assert, SDL_AtomicCAS, SDL_AtomicGet, SDL_SYS_DetachThread(), SDL_THREAD_STATE_ALIVE, SDL_THREAD_STATE_CLEANED, SDL_THREAD_STATE_DETACHED, SDL_THREAD_STATE_ZOMBIE, SDL_WaitThread(), and SDL_Thread::state.

{
if (!thread) {
return;
}
/* Grab dibs if the state is alive+joinable. */
if (SDL_AtomicCAS(&thread->state, SDL_THREAD_STATE_ALIVE, SDL_THREAD_STATE_DETACHED)) {
SDL_SYS_DetachThread(thread);
} else {
/* all other states are pretty final, see where we landed. */
const int thread_state = SDL_AtomicGet(&thread->state);
if ((thread_state == SDL_THREAD_STATE_DETACHED) || (thread_state == SDL_THREAD_STATE_CLEANED)) {
return; /* already detached (you shouldn't call this twice!) */
} else if (thread_state == SDL_THREAD_STATE_ZOMBIE) {
SDL_WaitThread(thread, NULL); /* already done, clean it up. */
} else {
SDL_assert(0 && "Unexpected thread state");
}
}
}
SDL_Thread::state
SDL_atomic_t state
Definition: SDL_thread_c.h:59
SDL_THREAD_STATE_ZOMBIE
Definition: SDL_thread_c.h:49
SDL_THREAD_STATE_DETACHED
Definition: SDL_thread_c.h:48
SDL_AtomicCAS
#define SDL_AtomicCAS
Definition: SDL_dynapi_overrides.h:72
SDL_THREAD_STATE_CLEANED
Definition: SDL_thread_c.h:50
SDL_THREAD_STATE_ALIVE
Definition: SDL_thread_c.h:47
SDL_SYS_DetachThread
void SDL_SYS_DetachThread(SDL_Thread *thread)
Definition: SDL_systhread.c:66
SDL_assert
#define SDL_assert(condition)
Definition: SDL_assert.h:167
NULL
#define NULL
Definition: begin_code.h:143
SDL_WaitThread
void SDL_WaitThread(SDL_Thread *thread, int *status)
Definition: SDL_thread.c:419
SDL_AtomicGet
#define SDL_AtomicGet
Definition: SDL_dynapi_overrides.h:74

SDL_TLSData* SDL_Generic_GetTLSData | ( |  | ) |

Definition at line 123 of file SDL_thread.c.

References mutex, SDL_TLSEntry::next, NULL, SDL_AtomicLock, SDL_AtomicUnlock, SDL_CreateMutex, SDL_LockMutex, SDL_MemoryBarrierAcquire, SDL_MemoryBarrierRelease, SDL_ThreadID, SDL_UnlockMutex, SDL_TLSEntry::storage, and SDL_TLSEntry::thread.

Referenced by SDL_SYS_GetTLSData().

{
SDL_threadID thread = SDL_ThreadID();
SDL_TLSEntry *entry;
SDL_TLSData *storage = NULL;
#if !SDL_THREADS_DISABLED
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);
}
#endif /* SDL_THREADS_DISABLED */
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;
}
}
#if !SDL_THREADS_DISABLED
SDL_UnlockMutex(SDL_generic_TLS_mutex);
#endif
return storage;
}
SDL_ThreadID
#define SDL_ThreadID
Definition: SDL_dynapi_overrides.h:479
SDL_TLSEntry::storage
SDL_TLSData * storage
Definition: SDL_thread.c:114
SDL_LockMutex
#define SDL_LockMutex
Definition: SDL_dynapi_overrides.h:266
SDL_generic_TLS_mutex
static SDL_mutex * SDL_generic_TLS_mutex
Definition: SDL_thread.c:118
SDL_AtomicLock
#define SDL_AtomicLock
Definition: SDL_dynapi_overrides.h:70
SDL_MemoryBarrierRelease
#define SDL_MemoryBarrierRelease()
Definition: SDL_atomic.h:180
SDL_CreateMutex
#define SDL_CreateMutex
Definition: SDL_dynapi_overrides.h:265
SDL_TLSData
Definition: SDL_thread_c.h:69
SDL_TLSEntry::thread
SDL_threadID thread
Definition: SDL_thread.c:113
mutex
static SDL_mutex * mutex
Definition: testlock.c:23
SDL_MemoryBarrierAcquire
#define SDL_MemoryBarrierAcquire()
Definition: SDL_atomic.h:181
SDL_TLSEntry::next
struct SDL_TLSEntry * next
Definition: SDL_thread.c:115
SDL_mutex
Definition: SDL_sysmutex.c:29
SDL_AtomicUnlock
#define SDL_AtomicUnlock
Definition: SDL_dynapi_overrides.h:71
SDL_TLSEntry
Definition: SDL_thread.c:112
NULL
#define NULL
Definition: begin_code.h:143
SDL_generic_TLS
static SDL_TLSEntry * SDL_generic_TLS
Definition: SDL_thread.c:119
SDL_UnlockMutex
#define SDL_UnlockMutex
Definition: SDL_dynapi_overrides.h:268
SDL_SpinLock
int SDL_SpinLock
Definition: SDL_atomic.h:89
SDL_threadID
unsigned long SDL_threadID
Definition: SDL_thread.h:49

int SDL_Generic_SetTLSData | ( | SDL_TLSData * | storage | ) |

Definition at line 162 of file SDL_thread.c.

References SDL_TLSEntry::next, NULL, SDL_free(), SDL_generic_TLS, SDL_LockMutex, SDL_malloc, SDL_OutOfMemory, SDL_ThreadID, SDL_UnlockMutex, SDL_TLSEntry::storage, and SDL_TLSEntry::thread.

Referenced by SDL_SYS_SetTLSData().

{
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;
}
SDL_ThreadID
#define SDL_ThreadID
Definition: SDL_dynapi_overrides.h:479
SDL_TLSEntry::storage
SDL_TLSData * storage
Definition: SDL_thread.c:114
SDL_LockMutex
#define SDL_LockMutex
Definition: SDL_dynapi_overrides.h:266
SDL_generic_TLS_mutex
static SDL_mutex * SDL_generic_TLS_mutex
Definition: SDL_thread.c:118
SDL_TLSEntry::thread
SDL_threadID thread
Definition: SDL_thread.c:113
SDL_TLSEntry::next
struct SDL_TLSEntry * next
Definition: SDL_thread.c:115
SDL_free
void SDL_free(void *mem)
SDL_TLSEntry
Definition: SDL_thread.c:112
NULL
#define NULL
Definition: begin_code.h:143
SDL_OutOfMemory
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_generic_TLS
static SDL_TLSEntry * SDL_generic_TLS
Definition: SDL_thread.c:119
SDL_UnlockMutex
#define SDL_UnlockMutex
Definition: SDL_dynapi_overrides.h:268
SDL_malloc
#define SDL_malloc
Definition: SDL_dynapi_overrides.h:380
SDL_threadID
unsigned long SDL_threadID
Definition: SDL_thread.h:49

SDL_error* SDL_GetErrBuf | ( | void |  | ) |

Definition at line 205 of file SDL_thread.c.

References NULL, SDL_AtomicLock, SDL_AtomicUnlock, SDL_FALSE, SDL_free(), SDL_malloc, SDL_MemoryBarrierAcquire, SDL_MemoryBarrierRelease, SDL_TLSCreate(), SDL_TLSGet(), SDL_TLSSet(), SDL_TRUE, and SDL_zerop.

Referenced by SDL_ClearError(), SDL_GetErrorMsg(), and SDL_SetError().

{
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;
}
SDL_TLSSet
int SDL_TLSSet(SDL_TLSID id, const void *value, void(*destructor)(void *))
Set the value associated with a thread local storage ID for the current thread.
Definition: SDL_thread.c:52
SDL_AtomicLock
#define SDL_AtomicLock
Definition: SDL_dynapi_overrides.h:70
SDL_MemoryBarrierRelease
#define SDL_MemoryBarrierRelease()
Definition: SDL_atomic.h:180
SDL_TLSGet
void * SDL_TLSGet(SDL_TLSID id)
Get the value associated with a thread local storage ID for the current thread.
Definition: SDL_thread.c:40
SDL_error
Definition: SDL_error_c.h:33
SDL_zerop
#define SDL_zerop(x)
Definition: SDL_stdinc.h:356
SDL_MemoryBarrierAcquire
#define SDL_MemoryBarrierAcquire()
Definition: SDL_atomic.h:181
SDL_TLSID
unsigned int SDL_TLSID
Definition: SDL_thread.h:52
SDL_AtomicUnlock
#define SDL_AtomicUnlock
Definition: SDL_dynapi_overrides.h:71
SDL_bool
SDL_bool
Definition: SDL_stdinc.h:126
SDL_free
void SDL_free(void *mem)
SDL_TRUE
Definition: SDL_stdinc.h:129
NULL
#define NULL
Definition: begin_code.h:143
SDL_TLSCreate
SDL_TLSID SDL_TLSCreate()
Create an identifier that is globally visible to all threads but refers to data that is thread-specif...
Definition: SDL_thread.c:33
SDL_FALSE
Definition: SDL_stdinc.h:128
SDL_malloc
#define SDL_malloc
Definition: SDL_dynapi_overrides.h:380
SDL_SpinLock
int SDL_SpinLock
Definition: SDL_atomic.h:89

SDL_threadID SDL_GetThreadID | ( | SDL_Thread * | thread | ) |

Get the thread identifier for the specified thread.

Equivalent to SDL_ThreadID() if the specified thread is NULL.

Definition at line 390 of file SDL_thread.c.

References SDL_ThreadID, and SDL_Thread::threadid.

{
SDL_threadID id;
if (thread) {
id = thread->threadid;
} else {
id = SDL_ThreadID();
}
return id;
}
SDL_ThreadID
#define SDL_ThreadID
Definition: SDL_dynapi_overrides.h:479
id
GLuint id
Definition: SDL_opengl_glext.h:528
SDL_Thread::threadid
SDL_threadID threadid
Definition: SDL_thread_c.h:56
SDL_threadID
unsigned long SDL_threadID
Definition: SDL_thread.h:49

const char* SDL_GetThreadName | ( | SDL_Thread * | thread | ) |

Get the thread name, as it was specified in SDL_CreateThread(). This function returns a pointer to a UTF-8 string that names the specified thread, or NULL if it doesn't have a name. This is internal memory, not to be free()'d by the caller, and remains valid until the specified thread is cleaned up by SDL_WaitThread().

Definition at line 403 of file SDL_thread.c.

References SDL_Thread::name, and NULL.

{
if (thread) {
return thread->name;
} else {
return NULL;
}
}
SDL_Thread::name
char * name
Definition: SDL_thread_c.h:61
NULL
#define NULL
Definition: begin_code.h:143

void SDL_RunThread | ( | void * | data | ) |

Definition at line 264 of file SDL_thread.c.

References thread_args::data, thread_args::func, thread_args::info, SDL_AtomicCAS, SDL_free(), SDL_SemPost, SDL_SYS_SetupThread(), SDL_THREAD_STATE_ALIVE, SDL_THREAD_STATE_CLEANED, SDL_THREAD_STATE_DETACHED, SDL_THREAD_STATE_ZOMBIE, SDL_ThreadID, SDL_TLSCleanup(), SDLCALL, SDL_TLSEntry::thread, and thread_args::wait.

Referenced by RunThread().

{
thread_args *args = (thread_args *) data;
int (SDLCALL * userfunc) (void *) = args->func;
void *userdata = args->data;
SDL_Thread *thread = args->info;
int *statusloc = &thread->status;
/* Perform any system-dependent setup - this function may not fail */
SDL_SYS_SetupThread(thread->name);
/* Get the thread id */
thread->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();
/* Mark us as ready to be joined (or detached) */
if (!SDL_AtomicCAS(&thread->state, SDL_THREAD_STATE_ALIVE, SDL_THREAD_STATE_ZOMBIE)) {
/* Clean up if something already detached us. */
if (SDL_AtomicCAS(&thread->state, SDL_THREAD_STATE_DETACHED, SDL_THREAD_STATE_CLEANED)) {
if (thread->name) {
SDL_free(thread->name);
}
SDL_free(thread);
}
}
}
SDL_ThreadID
#define SDL_ThreadID
Definition: SDL_dynapi_overrides.h:479
SDL_THREAD_STATE_ZOMBIE
Definition: SDL_thread_c.h:49
SDL_THREAD_STATE_DETACHED
Definition: SDL_thread_c.h:48
SDL_AtomicCAS
#define SDL_AtomicCAS
Definition: SDL_dynapi_overrides.h:72
data
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1967
thread_args
Definition: SDL_thread.c:255
SDL_Thread::status
int status
Definition: SDL_thread_c.h:58
SDL_THREAD_STATE_CLEANED
Definition: SDL_thread_c.h:50
SDL_SemPost
#define SDL_SemPost
Definition: SDL_dynapi_overrides.h:275
SDL_THREAD_STATE_ALIVE
Definition: SDL_thread_c.h:47
SDL_free
void SDL_free(void *mem)
SDL_TLSCleanup
static void SDL_TLSCleanup()
Definition: SDL_thread.c:86
thread_args::func
int(* func)(void *)
Definition: SDL_thread.c:257
thread_args::info
SDL_Thread * info
Definition: SDL_thread.c:259
thread_args::wait
SDL_sem * wait
Definition: SDL_thread.c:260
SDL_SYS_SetupThread
void SDL_SYS_SetupThread(const char *name)
Definition: SDL_systhread.c:42
SDL_Thread
Definition: SDL_thread_c.h:54
thread_args::data
void * data
Definition: SDL_thread.c:258
SDLCALL
#define SDLCALL
Definition: SDL_internal.h:31

int SDL_SetThreadPriority | ( | SDL_ThreadPriority | priority | ) |

Set the priority for the current thread

Definition at line 413 of file SDL_thread.c.

References SDL_SYS_SetThreadPriority().

{
return SDL_SYS_SetThreadPriority(priority);
}
SDL_SYS_SetThreadPriority
int SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority)
Definition: SDL_systhread.c:54

static void SDL_TLSCleanup | ( |  | ) |

static

Definition at line 86 of file SDL_thread.c.

References SDL_TLSData::array, SDL_TLSData::data, SDL_TLSData::destructor, i, SDL_TLSData::limit, NULL, SDL_free(), SDL_SYS_GetTLSData(), and SDL_SYS_SetTLSData().

Referenced by SDL_RunThread().

{
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);
}
}
SDL_TLSData::data
void * data
Definition: SDL_thread_c.h:72
SDL_TLSData
Definition: SDL_thread_c.h:69
SDL_TLSData::limit
unsigned int limit
Definition: SDL_thread_c.h:70
SDL_SYS_SetTLSData
int SDL_SYS_SetTLSData(SDL_TLSData *data)
Definition: SDL_systls.c:33
SDL_SYS_GetTLSData
SDL_TLSData * SDL_SYS_GetTLSData()
Definition: SDL_systls.c:27
SDL_free
void SDL_free(void *mem)
i
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:42
NULL
#define NULL
Definition: begin_code.h:143
SDL_TLSData::array
struct SDL_TLSData::@27 array[1]
SDL_TLSData::destructor
void(* destructor)(void *)
Definition: SDL_thread_c.h:73

SDL_TLSID SDL_TLSCreate | ( | void |  | ) |

Create an identifier that is globally visible to all threads but refers to data that is thread-specific.

Returns
  The newly created thread local storage identifier, or 0 on error

static SDL_SpinLock tls_lock;
static SDL_TLSID thread_local_storage;
void SetMyThreadData(void *value)
{
if (!thread_local_storage) {
SDL_AtomicLock(&tls_lock);
if (!thread_local_storage) {
thread_local_storage = SDL_TLSCreate();
}
SDL_AtomicUnlock(&tls_lock);
}
SDL_TLSSet(thread_local_storage, value, 0);
}
void *GetMyThreadData(void)
{
return SDL_TLSGet(thread_local_storage);
}

See also
  SDL_TLSGet()
  SDL_TLSSet()

Definition at line 33 of file SDL_thread.c.

References SDL_AtomicIncRef.

Referenced by SDL_GetErrBuf().

{
static SDL_atomic_t SDL_tls_id;
return SDL_AtomicIncRef(&SDL_tls_id)+1;
}
SDL_atomic_t
A type representing an atomic integer value. It is a struct so people don&#39;t accidentally use numeric ...
Definition: SDL_atomic.h:189
SDL_AtomicIncRef
#define SDL_AtomicIncRef(a)
Increment an atomic variable used as a reference count.
Definition: SDL_atomic.h:225

void* SDL_TLSGet | ( | SDL_TLSID | id | ) |

Get the value associated with a thread local storage ID for the current thread.

Parameters

  id | The thread local storage ID

Returns
  The value associated with the ID for the current thread, or NULL if no value has been set.

See also
  SDL_TLSCreate()
  SDL_TLSSet()

Definition at line 40 of file SDL_thread.c.

References SDL_TLSData::array, SDL_TLSData::data, SDL_TLSData::limit, NULL, and SDL_SYS_GetTLSData().

Referenced by SDL_GetErrBuf().

{
SDL_TLSData *storage;
storage = SDL_SYS_GetTLSData();
if (!storage || id == 0 || id > storage->limit) {
return NULL;
}
return storage->array[id-1].data;
}
SDL_TLSData::data
void * data
Definition: SDL_thread_c.h:72
SDL_TLSData
Definition: SDL_thread_c.h:69
SDL_TLSData::limit
unsigned int limit
Definition: SDL_thread_c.h:70
SDL_SYS_GetTLSData
SDL_TLSData * SDL_SYS_GetTLSData()
Definition: SDL_systls.c:27
NULL
#define NULL
Definition: begin_code.h:143
SDL_TLSData::array
struct SDL_TLSData::@27 array[1]

int SDL_TLSSet | ( | SDL_TLSID | id,
|  | const void * | value,
|  | void(*)(void *) | destructor
| ) |  |

Set the value associated with a thread local storage ID for the current thread.

Parameters

  id | The thread local storage ID
  value | The value to associate with the ID for the current thread
  destructor | A function called when the thread exits, to free the value.

Returns
  0 on success, -1 on error

See also
  SDL_TLSCreate()
  SDL_TLSGet()

Definition at line 52 of file SDL_thread.c.

References SDL_TLSData::array, SDL_TLSData::data, SDL_TLSData::destructor, i, SDL_TLSData::limit, NULL, SDL_const_cast, SDL_InvalidParamError, SDL_OutOfMemory, SDL_realloc, SDL_SYS_GetTLSData(), SDL_SYS_SetTLSData(), and TLS_ALLOC_CHUNKSIZE.

Referenced by SDL_GetErrBuf().

{
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;
}
SDL_const_cast
#define SDL_const_cast(type, expression)
Definition: SDL_stdinc.h:110
TLS_ALLOC_CHUNKSIZE
#define TLS_ALLOC_CHUNKSIZE
Definition: SDL_thread_c.h:78
SDL_TLSData::data
void * data
Definition: SDL_thread_c.h:72
SDL_TLSData
Definition: SDL_thread_c.h:69
SDL_TLSData::limit
unsigned int limit
Definition: SDL_thread_c.h:70
SDL_SYS_SetTLSData
int SDL_SYS_SetTLSData(SDL_TLSData *data)
Definition: SDL_systls.c:33
SDL_InvalidParamError
#define SDL_InvalidParamError(param)
Definition: SDL_error.h:54
SDL_realloc
#define SDL_realloc
Definition: SDL_dynapi_overrides.h:382
SDL_SYS_GetTLSData
SDL_TLSData * SDL_SYS_GetTLSData()
Definition: SDL_systls.c:27
value
GLsizei const GLfloat * value
Definition: SDL_opengl_glext.h:698
i
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:42
NULL
#define NULL
Definition: begin_code.h:143
SDL_OutOfMemory
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_TLSData::array
struct SDL_TLSData::@27 array[1]
SDL_TLSData::destructor
void(* destructor)(void *)
Definition: SDL_thread_c.h:73

void SDL_WaitThread | ( | SDL_Thread * | thread,
|  | int * | status
| ) |  |

Wait for a thread to finish. Threads that haven't been detached will remain (as a "zombie") until this function cleans them up. Not doing so is a resource leak.

Once a thread has been cleaned up through this function, the SDL_Thread that references it becomes invalid and should not be referenced again. As such, only one thread may call SDL_WaitThread() on another.

The return code for the thread function is placed in the area pointed to by `status`, if `status` is not NULL.

You may not wait on a thread that has been used in a call to SDL_DetachThread(). Use either that function or this one, but not both, or behavior is undefined.

It is safe to pass NULL to this function; it is a no-op.

Definition at line 419 of file SDL_thread.c.

References SDL_Thread::name, SDL_free(), SDL_SYS_WaitThread(), and SDL_Thread::status.

Referenced by SDL_DetachThread().

{
if (thread) {
SDL_SYS_WaitThread(thread);
if (status) {
*status = thread->status;
}
if (thread->name) {
SDL_free(thread->name);
}
SDL_free(thread);
}
}
SDL_Thread::name
char * name
Definition: SDL_thread_c.h:61
SDL_Thread::status
int status
Definition: SDL_thread_c.h:58
SDL_SYS_WaitThread
void SDL_SYS_WaitThread(SDL_Thread *thread)
Definition: SDL_systhread.c:60
SDL_free
void SDL_free(void *mem)

## Variable Documentation

SDL_TLSEntry* SDL_generic_TLS

static

Definition at line 119 of file SDL_thread.c.

Referenced by SDL_Generic_SetTLSData().

SDL_mutex* SDL_generic_TLS_mutex

static

Definition at line 118 of file SDL_thread.c.