Skip to content
This repository has been archived by the owner on Feb 11, 2021. It is now read-only.

Commit

Permalink
1.3 API CHANGE: Add support for naming threads.
Browse files Browse the repository at this point in the history
  • Loading branch information
icculus committed Oct 2, 2011
1 parent 8d80321 commit 1772c81
Show file tree
Hide file tree
Showing 22 changed files with 182 additions and 44 deletions.
24 changes: 24 additions & 0 deletions configure.in
Expand Up @@ -1642,6 +1642,30 @@ AC_HELP_STRING([--enable-pthread-sem], [use pthread semaphores [[default=yes]]])
])
AC_MSG_RESULT($has_pthread_spin_trylock)

AC_CHECK_HEADER(pthread_np.h, have_pthread_np_h=yes)
if test x$have_pthread_np_h = xyes; then
AC_DEFINE(HAVE_PTHREAD_NP_H, 1, [ ])
fi

# Check to see if pthread naming is available
AC_MSG_CHECKING(for pthread_setname_np)
AC_TRY_LINK_FUNC(pthread_setname_np, [
has_pthread_setname_np=yes
AC_DEFINE(HAVE_PTHREAD_SETNAME_NP, 1, [ ])
],[
has_pthread_setname_np=no
])
AC_MSG_RESULT($has_pthread_setname_np)

AC_MSG_CHECKING(for pthread_set_name_np)
AC_TRY_LINK_FUNC(pthread_set_name_np, [
has_pthread_set_name_np=yes
AC_DEFINE(HAVE_PTHREAD_SET_NAME_NP, 1, [ ])
],[
has_pthread_set_name_np=no
])
AC_MSG_RESULT($has_pthread_set_name_np)

# Restore the compiler flags and libraries
CFLAGS="$ac_save_cflags"; LIBS="$ac_save_libs"

Expand Down
3 changes: 3 additions & 0 deletions include/SDL_config.h.in
Expand Up @@ -69,6 +69,7 @@
#undef HAVE_ICONV_H
#undef HAVE_SIGNAL_H
#undef HAVE_ALTIVEC_H
#undef HAVE_PTHREAD_NP_H

/* C library functions */
#undef HAVE_MALLOC
Expand Down Expand Up @@ -148,6 +149,8 @@
#undef HAVE_GETPAGESIZE
#undef HAVE_MPROTECT
#undef HAVE_ICONV
#undef HAVE_PTHREAD_SETNAME_NP
#undef HAVE_PTHREAD_SET_NAME_NP

#else
/* We may need some replacement for stdarg.h here */
Expand Down
32 changes: 28 additions & 4 deletions include/SDL_thread.h
Expand Up @@ -102,7 +102,7 @@ typedef void (__cdecl * pfnSDL_CurrentEndThread) (unsigned code);
* Create a thread.
*/
extern DECLSPEC SDL_Thread *SDLCALL
SDL_CreateThread(SDL_ThreadFunction fn, void *data,
SDL_CreateThread(SDL_ThreadFunction fn, const char *name, void *data,
pfnSDL_CurrentBeginThread pfnBeginThread,
pfnSDL_CurrentEndThread pfnEndThread);

Expand All @@ -111,26 +111,50 @@ SDL_CreateThread(SDL_ThreadFunction fn, void *data,
/**
* Create a thread.
*/
#define SDL_CreateThread(fn, data) SDL_CreateThread(fn, data, NULL, NULL)
#define SDL_CreateThread(fn, name, data) SDL_CreateThread(fn, name, data, NULL, NULL)

#else

/**
* Create a thread.
*/
#define SDL_CreateThread(fn, data) SDL_CreateThread(fn, data, _beginthreadex, _endthreadex)
#define SDL_CreateThread(fn, name, data) SDL_CreateThread(fn, name, data, _beginthreadex, _endthreadex)

#endif
#else

/**
* Create a thread.
*
* Thread naming is a little complicated: Most systems have very small
* limits for the string length (BeOS has 32 bytes, Linux currently has 16,
* Visual C++ 6.0 has nine!), and possibly other arbitrary rules. You'll
* have to see what happens with your system's debugger. The name should be
* UTF-8 (but using the naming limits of C identifiers is a better bet).
* There are no requirements for thread naming conventions, so long as the
* string is null-terminated UTF-8, but these guidelines are helpful in
* choosing a name:
*
* http://stackoverflow.com/questions/149932/naming-conventions-for-threads
*
* If a system imposes requirements, SDL will try to munge the string for
* it (truncate, etc), but the original string contents will be available
* from SDL_GetThreadName().
*/
extern DECLSPEC SDL_Thread *SDLCALL
SDL_CreateThread(SDL_ThreadFunction fn, void *data);
SDL_CreateThread(SDL_ThreadFunction fn, const char *name, void *data);

#endif

/**
* 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().
*/
extern DECLSPEC const char *SDLCALL SDL_GetThreadName(SDL_Thread *thread);

/**
* Get the thread identifier for the current thread.
*/
Expand Down
6 changes: 4 additions & 2 deletions src/audio/SDL_audio.c
Expand Up @@ -1033,12 +1033,14 @@ open_audio_device(const char *devname, int iscapture,
/* Start the audio thread if necessary */
if (!current_audio.impl.ProvidesOwnCallbackThread) {
/* Start the audio thread */
char name[64];
SDL_snprintf(name, sizeof (name), "SDLAudioDev%d", (int) (id + 1));
/* !!! FIXME: this is nasty. */
#if (defined(__WIN32__) && !defined(_WIN32_WCE)) && !defined(HAVE_LIBC)
#undef SDL_CreateThread
device->thread = SDL_CreateThread(SDL_RunAudio, device, NULL, NULL);
device->thread = SDL_CreateThread(SDL_RunAudio, name, device, NULL, NULL);
#else
device->thread = SDL_CreateThread(SDL_RunAudio, device);
device->thread = SDL_CreateThread(SDL_RunAudio, name, device);
#endif
if (device->thread == NULL) {
SDL_CloseAudioDevice(id + 1);
Expand Down
2 changes: 1 addition & 1 deletion src/main/beos/SDL_BeApp.cc
Expand Up @@ -60,7 +60,7 @@ SDL_InitBeApp(void)
{
/* Create the BApplication that handles appserver interaction */
if (SDL_BeAppActive <= 0) {
SDL_AppThread = SDL_CreateThread(StartBeApp, NULL);
SDL_AppThread = SDL_CreateThread(StartBeApp, "SDLApplication", NULL);
if (SDL_AppThread == NULL) {
SDL_SetError("Couldn't create BApplication thread");
return (-1);
Expand Down
2 changes: 1 addition & 1 deletion src/thread/SDL_systhread.h
Expand Up @@ -40,7 +40,7 @@ extern int SDL_SYS_CreateThread(SDL_Thread * thread, void *args);
#endif

/* This function does any necessary setup in the child thread */
extern void SDL_SYS_SetupThread(void);
extern void SDL_SYS_SetupThread(const char *name);

/* This function sets the current thread priority */
extern int SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority);
Expand Down
42 changes: 29 additions & 13 deletions src/thread/SDL_thread.c
Expand Up @@ -188,25 +188,19 @@ typedef struct
void
SDL_RunThread(void *data)
{
thread_args *args;
int (SDLCALL * userfunc) (void *);
void *userdata;
int *statusloc;
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 cannot fail, and cannot use SDL_SetError()
*/
SDL_SYS_SetupThread();
SDL_SYS_SetupThread(args->info->name);

/* Get the thread id */
args = (thread_args *) data;
args->info->threadid = SDL_ThreadID();

/* Figure out what function to run */
userfunc = args->func;
userdata = args->data;
statusloc = &args->info->status;

/* Wake up the parent thread */
SDL_SemPost(args->wait);

Expand All @@ -217,12 +211,14 @@ SDL_RunThread(void *data)
#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
#undef SDL_CreateThread
DECLSPEC SDL_Thread *SDLCALL
SDL_CreateThread(int (SDLCALL * fn) (void *), void *data,
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 *), void *data)
SDL_CreateThread(int (SDLCALL * fn) (void *),
const char *name, void *data)
#endif
{
SDL_Thread *thread;
Expand All @@ -238,10 +234,21 @@ SDL_CreateThread(int (SDLCALL * fn) (void *), void *data)
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();
SDL_free(thread->name);
SDL_free(thread);
return (NULL);
}
Expand All @@ -250,6 +257,7 @@ SDL_CreateThread(int (SDLCALL * fn) (void *), void *data)
args->info = thread;
args->wait = SDL_CreateSemaphore(0);
if (args->wait == NULL) {
SDL_free(thread->name);
SDL_free(thread);
SDL_free(args);
return (NULL);
Expand All @@ -270,6 +278,7 @@ SDL_CreateThread(int (SDLCALL * fn) (void *), void *data)
} else {
/* Oops, failed. Gotta free everything */
SDL_DelThread(thread);
SDL_free(thread->name);
SDL_free(thread);
thread = NULL;
}
Expand All @@ -293,6 +302,12 @@ SDL_GetThreadID(SDL_Thread * thread)
return id;
}

const char *
SDL_GetThreadName(SDL_Thread * thread)
{
return thread->name;
}

int
SDL_SetThreadPriority(SDL_ThreadPriority priority)
{
Expand All @@ -308,6 +323,7 @@ SDL_WaitThread(SDL_Thread * thread, int *status)
*status = thread->status;
}
SDL_DelThread(thread);
SDL_free(thread->name);
SDL_free(thread);
}
}
Expand Down
1 change: 1 addition & 0 deletions src/thread/SDL_thread_c.h
Expand Up @@ -51,6 +51,7 @@ struct SDL_Thread
SYS_ThreadHandle handle;
int status;
SDL_error errbuf;
char *name;
void *data;
};

Expand Down
10 changes: 8 additions & 2 deletions src/thread/beos/SDL_systhread.c
Expand Up @@ -65,8 +65,13 @@ RunThread(void *data)
int
SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
{
/* The docs say the thread name can't be longer than B_OS_NAME_LENGTH. */
char name[B_OS_NAME_LENGTH];
SDL_snprintf(name, sizeof (name), "%s", thread->name);
name[sizeof (name) - 1] = '\0';

/* Create the thread and go! */
thread->handle = spawn_thread(RunThread, "SDL", B_NORMAL_PRIORITY, args);
thread->handle = spawn_thread(RunThread, name, B_NORMAL_PRIORITY, args);
if ((thread->handle == B_NO_MORE_THREADS) ||
(thread->handle == B_NO_MEMORY)) {
SDL_SetError("Not enough resources to create thread");
Expand All @@ -77,8 +82,9 @@ SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
}

void
SDL_SYS_SetupThread(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);
}
Expand Down
2 changes: 1 addition & 1 deletion src/thread/generic/SDL_systhread.c
Expand Up @@ -33,7 +33,7 @@ SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
}

void
SDL_SYS_SetupThread(void)
SDL_SYS_SetupThread(const char *name)
{
return;
}
Expand Down
2 changes: 1 addition & 1 deletion src/thread/irix/SDL_systhread.c
Expand Up @@ -50,7 +50,7 @@ SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
}

void
SDL_SYS_SetupThread(void)
SDL_SYS_SetupThread(const char *name)
{
int i;
sigset_t mask;
Expand Down
2 changes: 1 addition & 1 deletion src/thread/nds/SDL_systhread.c
Expand Up @@ -38,7 +38,7 @@ SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
}

void
SDL_SYS_SetupThread(void)
SDL_SYS_SetupThread(const char *name)
{
return;
}
Expand Down
23 changes: 22 additions & 1 deletion src/thread/pthread/SDL_systhread.c
Expand Up @@ -21,13 +21,19 @@
#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>
#endif

#include "SDL_platform.h"
#include "SDL_thread.h"
#include "../SDL_thread_c.h"
#include "../SDL_systhread.h"
Expand Down Expand Up @@ -67,12 +73,27 @@ SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
return (0);
}

/* make pthread_setname_np() a weak reference even without SDK support. */
#if __MACOSX__ && (MAC_OS_X_VERSION_MAX_ALLOWED < 1060)
int pthread_setname_np(const char*) __attribute__((weak_import,visibility("default")));
#elif __IPHONEOS__ && (__IPHONE_OS_VERSION_MAX_ALLOWED < 30200)
int pthread_setname_np(const char*) __attribute__((weak_import));
#endif

void
SDL_SYS_SetupThread(void)
SDL_SYS_SetupThread(const char *name)
{
int i;
sigset_t mask;

#if __MACOSX__ || __IPHONEOS__
if (pthread_setname_np != NULL) { pthread_setname_np(name); }
#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) {
Expand Down

0 comments on commit 1772c81

Please sign in to comment.