Merge upstream updates
authorKees Bakker <kees@ijzerbout.nl>
Sat, 08 Oct 2011 12:45:10 +0200
changeset 6012 0291eb4caec4
parent 6011 83a21d3bd5c1 (current diff)
parent 5974 13e67468b846 (diff)
child 6013 b253cc3c4276
Merge upstream updates
--- a/configure.in	Wed Sep 28 21:42:02 2011 +0200
+++ b/configure.in	Sat Oct 08 12:45:10 2011 +0200
@@ -1642,6 +1642,30 @@
             ])
             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"
 
--- a/include/SDL_config.h.in	Wed Sep 28 21:42:02 2011 +0200
+++ b/include/SDL_config.h.in	Sat Oct 08 12:45:10 2011 +0200
@@ -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
@@ -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 */
--- a/include/SDL_thread.h	Wed Sep 28 21:42:02 2011 +0200
+++ b/include/SDL_thread.h	Sat Oct 08 12:45:10 2011 +0200
@@ -102,7 +102,7 @@
  *  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);
 
@@ -111,27 +111,51 @@
 /**
  *  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.
  */
 extern DECLSPEC SDL_threadID SDLCALL SDL_ThreadID(void);
--- a/src/audio/SDL_audio.c	Wed Sep 28 21:42:02 2011 +0200
+++ b/src/audio/SDL_audio.c	Sat Oct 08 12:45:10 2011 +0200
@@ -1033,12 +1033,14 @@
     /* 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);
--- a/src/main/beos/SDL_BeApp.cc	Wed Sep 28 21:42:02 2011 +0200
+++ b/src/main/beos/SDL_BeApp.cc	Sat Oct 08 12:45:10 2011 +0200
@@ -60,7 +60,7 @@
 {
     /* 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);
--- a/src/thread/SDL_systhread.h	Wed Sep 28 21:42:02 2011 +0200
+++ b/src/thread/SDL_systhread.h	Sat Oct 08 12:45:10 2011 +0200
@@ -40,7 +40,7 @@
 #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);
--- a/src/thread/SDL_thread.c	Wed Sep 28 21:42:02 2011 +0200
+++ b/src/thread/SDL_thread.c	Sat Oct 08 12:45:10 2011 +0200
@@ -188,25 +188,19 @@
 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);
 
@@ -217,12 +211,14 @@
 #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;
@@ -239,9 +235,20 @@
     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);
     }
@@ -250,6 +257,7 @@
     args->info = thread;
     args->wait = SDL_CreateSemaphore(0);
     if (args->wait == NULL) {
+        SDL_free(thread->name);
         SDL_free(thread);
         SDL_free(args);
         return (NULL);
@@ -270,6 +278,7 @@
     } else {
         /* Oops, failed.  Gotta free everything */
         SDL_DelThread(thread);
+        SDL_free(thread->name);
         SDL_free(thread);
         thread = NULL;
     }
@@ -293,6 +302,12 @@
     return id;
 }
 
+const char *
+SDL_GetThreadName(SDL_Thread * thread)
+{
+    return thread->name;
+}
+
 int
 SDL_SetThreadPriority(SDL_ThreadPriority priority)
 {
@@ -308,6 +323,7 @@
             *status = thread->status;
         }
         SDL_DelThread(thread);
+        SDL_free(thread->name);
         SDL_free(thread);
     }
 }
--- a/src/thread/SDL_thread_c.h	Wed Sep 28 21:42:02 2011 +0200
+++ b/src/thread/SDL_thread_c.h	Sat Oct 08 12:45:10 2011 +0200
@@ -51,6 +51,7 @@
     SYS_ThreadHandle handle;
     int status;
     SDL_error errbuf;
+    char *name;
     void *data;
 };
 
--- a/src/thread/beos/SDL_systhread.c	Wed Sep 28 21:42:02 2011 +0200
+++ b/src/thread/beos/SDL_systhread.c	Sat Oct 08 12:45:10 2011 +0200
@@ -65,8 +65,13 @@
 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");
@@ -77,8 +82,9 @@
 }
 
 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);
 }
--- a/src/thread/generic/SDL_systhread.c	Wed Sep 28 21:42:02 2011 +0200
+++ b/src/thread/generic/SDL_systhread.c	Sat Oct 08 12:45:10 2011 +0200
@@ -33,7 +33,7 @@
 }
 
 void
-SDL_SYS_SetupThread(void)
+SDL_SYS_SetupThread(const char *name)
 {
     return;
 }
--- a/src/thread/irix/SDL_systhread.c	Wed Sep 28 21:42:02 2011 +0200
+++ b/src/thread/irix/SDL_systhread.c	Sat Oct 08 12:45:10 2011 +0200
@@ -50,7 +50,7 @@
 }
 
 void
-SDL_SYS_SetupThread(void)
+SDL_SYS_SetupThread(const char *name)
 {
     int i;
     sigset_t mask;
--- a/src/thread/nds/SDL_systhread.c	Wed Sep 28 21:42:02 2011 +0200
+++ b/src/thread/nds/SDL_systhread.c	Sat Oct 08 12:45:10 2011 +0200
@@ -38,7 +38,7 @@
 }
 
 void
-SDL_SYS_SetupThread(void)
+SDL_SYS_SetupThread(const char *name)
 {
     return;
 }
--- a/src/thread/pthread/SDL_systhread.c	Wed Sep 28 21:42:02 2011 +0200
+++ b/src/thread/pthread/SDL_systhread.c	Sat Oct 08 12:45:10 2011 +0200
@@ -21,6 +21,11 @@
 #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>
@@ -28,6 +33,7 @@
 #include <sys/syscall.h>
 #endif
 
+#include "SDL_platform.h"
 #include "SDL_thread.h"
 #include "../SDL_thread_c.h"
 #include "../SDL_systhread.h"
@@ -68,11 +74,20 @@
 }
 
 void
-SDL_SYS_SetupThread(void)
+SDL_SYS_SetupThread(const char *name)
 {
     int i;
     sigset_t mask;
 
+#if ( (__MACOSX__ && (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060)) || \
+      (__IPHONEOS__ && (__IPHONE_OS_VERSION_MAX_ALLOWED >= 30200)) )
+    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) {
--- a/src/thread/windows/SDL_systhread.c	Wed Sep 28 21:42:02 2011 +0200
+++ b/src/thread/windows/SDL_systhread.c	Sat Oct 08 12:45:10 2011 +0200
@@ -146,10 +146,40 @@
     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(void)
+SDL_SYS_SetupThread(const char *name)
 {
-    return;
+#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
--- a/src/timer/SDL_timer.c	Wed Sep 28 21:42:02 2011 +0200
+++ b/src/timer/SDL_timer.c	Sat Oct 08 12:45:10 2011 +0200
@@ -209,6 +209,7 @@
     SDL_TimerData *data = &SDL_timer_data;
 
     if (!data->active) {
+        const char *name = "SDLTimer";
         data->timermap_lock = SDL_CreateMutex();
         if (!data->timermap_lock) {
             return -1;
@@ -224,9 +225,9 @@
         /* !!! FIXME: this is nasty. */
 #if (defined(__WIN32__) && !defined(_WIN32_WCE)) && !defined(HAVE_LIBC)
 #undef SDL_CreateThread
-        data->thread = SDL_CreateThread(SDL_TimerThread, data, NULL, NULL);
+        data->thread = SDL_CreateThread(SDL_TimerThread, name, data, NULL, NULL);
 #else
-        data->thread = SDL_CreateThread(SDL_TimerThread, data);
+        data->thread = SDL_CreateThread(SDL_TimerThread, name, data);
 #endif
         if (!data->thread) {
             SDL_TimerQuit();
--- a/src/video/x11/SDL_x11touch.c	Wed Sep 28 21:42:02 2011 +0200
+++ b/src/video/x11/SDL_x11touch.c	Sat Oct 08 12:45:10 2011 +0200
@@ -38,55 +38,57 @@
 #ifdef SDL_INPUT_LINUXEV
   FILE *fd;
   fd = fopen("/proc/bus/input/devices","r");
-  
+
   char c;
   int i = 0;
+  int tsfd;
   char line[256];
   char tstr[256];
   int vendor = -1,product = -1,event = -1;
   while(!feof(fd)) {
     if(fgets(line,256,fd) <=0) continue;
     if(line[0] == '\n') {
-    if(vendor == 1386 || vendor==1){
+      if(vendor == 1386 || vendor==1) {
+
+        sprintf(tstr,"/dev/input/event%i",event);
 
-	sprintf(tstr,"/dev/input/event%i",event);
+        tsfd = open( tstr, O_RDONLY | O_NONBLOCK );
+        if ( tsfd == -1 )
+            continue;   /* Maybe not enough permissions ? */
 
-	SDL_Touch touch;
-	touch.pressure_max = 0;
-	touch.pressure_min = 0;
-	touch.id = event; 
-	
+        SDL_Touch touch;
+        touch.pressure_max = 0;
+        touch.pressure_min = 0;
+        touch.id = event; 
 
-	touch.driverdata = SDL_malloc(sizeof(EventTouchData));
-	EventTouchData* data = (EventTouchData*)(touch.driverdata);
+        touch.driverdata = SDL_malloc(sizeof(EventTouchData));
+        EventTouchData* data = (EventTouchData*)(touch.driverdata);
 
-	data->x = -1;
-	data->y = -1;
-	data->pressure = -1;
-	data->finger = 0;
-	data->up = SDL_FALSE;
-    data->down = SDL_FALSE;
-	
+        data->x = -1;
+        data->y = -1;
+        data->pressure = -1;
+        data->finger = 0;
+        data->up = SDL_FALSE;
+        data->down = SDL_FALSE;
 
-	data->eventStream = open(tstr, 
-				 O_RDONLY | O_NONBLOCK);
-	ioctl (data->eventStream, EVIOCGNAME (sizeof (tstr)), tstr);
+        data->eventStream = tsfd;
+        ioctl (data->eventStream, EVIOCGNAME (sizeof (tstr)), tstr);
 
-	int abs[5];
-	ioctl(data->eventStream,EVIOCGABS(0),abs);	
-	touch.x_min = abs[1];
-	touch.x_max = abs[2];
-	touch.native_xres = touch.x_max - touch.x_min;
-	ioctl(data->eventStream,EVIOCGABS(ABS_Y),abs);	
-	touch.y_min = abs[1];
-	touch.y_max = abs[2];
-	touch.native_yres = touch.y_max - touch.y_min;
-	ioctl(data->eventStream,EVIOCGABS(ABS_PRESSURE),abs);	
-	touch.pressure_min = abs[1];
-	touch.pressure_max = abs[2];
-	touch.native_pressureres = touch.pressure_max - touch.pressure_min;
+        int abs[5];
+        ioctl(data->eventStream,EVIOCGABS(0),abs);	
+        touch.x_min = abs[1];
+        touch.x_max = abs[2];
+        touch.native_xres = touch.x_max - touch.x_min;
+        ioctl(data->eventStream,EVIOCGABS(ABS_Y),abs);	
+        touch.y_min = abs[1];
+        touch.y_max = abs[2];
+        touch.native_yres = touch.y_max - touch.y_min;
+        ioctl(data->eventStream,EVIOCGABS(ABS_PRESSURE),abs);	
+        touch.pressure_min = abs[1];
+        touch.pressure_max = abs[2];
+        touch.native_pressureres = touch.pressure_max - touch.pressure_min;
 
-	SDL_AddTouch(&touch, tstr);
+        SDL_AddTouch(&touch, tstr);
       }
       vendor = -1;
       product = -1;
@@ -95,20 +97,20 @@
     else if(line[0] == 'I') {
       i = 1;
       while(line[i]) {
-	sscanf(&line[i],"Vendor=%x",&vendor);
-	sscanf(&line[i],"Product=%x",&product);
-	i++;
+        sscanf(&line[i],"Vendor=%x",&vendor);
+        sscanf(&line[i],"Product=%x",&product);
+        i++;
       }
     }
     else if(line[0] == 'H') {
       i = 1;
       while(line[i]) {
-	sscanf(&line[i],"event%d",&event);
-	i++;
+        sscanf(&line[i],"event%d",&event);
+        i++;
       }
     }
   }
-  
+
   close(fd);
 #endif
 }
--- a/test/test-automation/tests/testaudio/testaudio.c	Wed Sep 28 21:42:02 2011 +0200
+++ b/test/test-automation/tests/testaudio/testaudio.c	Sat Oct 08 12:45:10 2011 +0200
@@ -1,5 +1,6 @@
 /**
- * Original code: automated SDL rect test written by Edgar Simo "bobbens"
+ * Original code: automated SDL audio test written by Edgar Simo "bobbens"
+ * New/updated tests: aschiffler at ferzkopp dot net
  */
 
 #include <stdio.h>
@@ -10,10 +11,10 @@
 
 /* Test cases */
 static const TestCaseReference test1 =
-		(TestCaseReference){ "audio_printOutputDevices", "Checks available output (non-capture) device names.", TEST_ENABLED, TEST_REQUIRES_AUDIO, 0};
+		(TestCaseReference){ "audio_enumerateAndNameAudioDevices", "Enumerate and name available audio devices (output and capture)", TEST_ENABLED, TEST_REQUIRES_AUDIO, 0};
 
 static const TestCaseReference test2 =
-		(TestCaseReference){ "audio_printInputDevices", "Checks available input (capture) device names.", TEST_ENABLED, TEST_REQUIRES_AUDIO, 0};
+		(TestCaseReference){ "audio_enumerateAndNameAudioDevicesNegativeTests", "Netative tests around enumeration and naming of audio devices.", TEST_ENABLED, TEST_REQUIRES_AUDIO, 0};
 
 static const TestCaseReference test3 =
 		(TestCaseReference){ "audio_printAudioDrivers", "Checks available audio driver names.", TEST_ENABLED, TEST_REQUIRES_AUDIO, 0};
@@ -31,7 +32,7 @@
 	return (TestCaseReference **)testSuite;
 }
 
-// Fixture
+/* Fixture */
 
 void
 SetUp(void *arg)
@@ -51,49 +52,94 @@
 /* Test case functions */
 
 /**
- * @brief Checks available output (non-capture) device names.
+ * \brief Enumerate and name available audio devices (output and capture).
+ * 
+ * \sa http://wiki.libsdl.org/moin.cgi/SDL_GetNumAudioDevices
+ * \sa http://wiki.libsdl.org/moin.cgi/SDL_GetAudioDeviceName
  */
-int audio_printOutputDevices()
+int audio_enumerateAndNameAudioDevices()
 {
    int ret;
-   int i, n;
-   const char *name;
+   int t, tt;
+   int i, n, nn;
+   const char *name, *nameAgain;
 
-   /* Get number of devices. */
-   n = SDL_GetNumAudioDevices(0);
-   AssertTrue(n>=0, "Number of output devices < 0, reported as %i", n);
+   /* Iterate over types: t=0 output device, t=1 input/capture device */
+   for (t=0; t<2; t++) {
    
-   /* List devices. */
-   if (n>0)
-   {
-      for (i=0; i<n; i++) {
-         name = SDL_GetAudioDeviceName(i, 0);
-         AssertTrue(name != NULL, "name != NULL");
-         AssertTrue(strlen(name)>0, "name blank");
+      /* Get number of devices. */
+      n = SDL_GetNumAudioDevices(t);
+      AssertTrue(n>=0, 
+         "Number of %s devices < 0, reported as %i: %s", 
+         (t) ? "output" : "capture",
+         n, 
+         SDL_GetError());
+
+      /* Variation of non-zero type */
+      if (t==1) {
+         tt = t + RandomIntegerInRange(1,10);
+         nn = SDL_GetNumAudioDevices(tt);
+         AssertTrue(n==nn, "SDL_GetNumAudioDevices(%i) : expected same number of audio devices %i, got %i", tt, n, nn);
+         nn = SDL_GetNumAudioDevices(-tt);
+         AssertTrue(n==nn, "SDL_GetNumAudioDevices(%i) : expected same number of audio devices %i, got %i", -tt, n, nn);
+      } 
+   
+      /* List devices. */
+      if (n>0) {
+         for (i=0; i<n; i++) {
+            name = SDL_GetAudioDeviceName(i, t);
+            AssertTrue(name != NULL, "SDL_GetAudioDeviceName(%i, %i): returned NULL name", i, t);
+            AssertTrue(strlen(name)>0, "SDL_GetAudioDeviceName(%i, %i): returned empty name string", i, t);
+            if (t==1) {
+               /* Also try non-zero type */
+               nameAgain = SDL_GetAudioDeviceName(i, tt);
+               AssertTrue(nameAgain != NULL, "SDL_GetAudioDeviceName(%i, %i): returned NULL name", i, tt);
+               AssertTrue(strlen(nameAgain)>0, "SDL_GetAudioDeviceName(%i, %i): returned empty name string", i, tt);
+               AssertTrue(strcmp(name, nameAgain)==0, 
+                  "SDL_GetAudioDeviceName(%i, %i): returned unexpected name string %s, expected %s", 
+                  i, tt, nameAgain, name);
+            }
+         }
       }
    }
 }
 
 /**
- * @brief Checks available input (capture) device names.
+ * \brief Negative tests around enumeration and naming of audio devices.
+ * 
+ * \sa http://wiki.libsdl.org/moin.cgi/SDL_GetNumAudioDevices
+ * \sa http://wiki.libsdl.org/moin.cgi/SDL_GetAudioDeviceName
  */
-int audio_printInputDevices()
+int audio_enumerateAndNameAudioDevicesNegativeTests()
 {
    int ret;
-   int i, n;
+   int t;
+   int i, j, no, nc;
    const char *name;
-
+      
    /* Get number of devices. */
-   n = SDL_GetNumAudioDevices(1);
-   AssertTrue(n>=0, "Number of input devices < 0, reported as %i", n);
+   no = SDL_GetNumAudioDevices(0);
+   nc = SDL_GetNumAudioDevices(1);
    
-   /* List devices. */
-   if (n>0)
-   {
-      for (i=0; i<n; i++) {
-         name = SDL_GetAudioDeviceName(i, 1);
-         AssertTrue(name != NULL, "name != NULL");
-         AssertTrue(strlen(name)>0, "name empty");
+   /* Invalid device index when getting name */
+   for (t=0; t<2; t++) {
+      /* Negative device index */
+      i = -1;
+      name = SDL_GetAudioDeviceName(i, t);
+      AssertTrue(name == NULL, "SDL_GetAudioDeviceName(%i, %i): returned a name, should return NULL", i, t);
+      
+      /* Device index past range */
+      for (j=0; j<3; j++) {
+         i = (t) ? nc+j : no+j;
+         name = SDL_GetAudioDeviceName(i, t);
+         AssertTrue(name == NULL, "SDL_GetAudioDeviceName(%i, %i): returned a name, should return NULL", i, t);
+      }
+      
+      /* Capture index past capture range but within output range */
+      if ((no>0) && (no>nc) && (t==1)) {
+         i = no-1;
+         name = SDL_GetAudioDeviceName(i, t);
+         AssertTrue(name == NULL, "SDL_GetAudioDeviceName(%i, %i): returned a name, should return NULL", i, t);
       }
    }
 }
--- a/test/testatomic.c	Wed Sep 28 21:42:02 2011 +0200
+++ b/test/testatomic.c	Sat Oct 08 12:45:10 2011 +0200
@@ -143,7 +143,7 @@
     SDL_AtomicSet(&threadsRunning, NThreads);
 
     while (T--)
-        SDL_CreateThread(adder, NULL);
+        SDL_CreateThread(adder, "Adder", NULL);
  
     while (SDL_AtomicGet(&threadsRunning) > 0)
         SDL_SemWait(threadDone);
@@ -618,7 +618,7 @@
 #ifdef TEST_SPINLOCK_FIFO
     /* Start a monitoring thread */
     if (lock_free) {
-        SDL_CreateThread(FIFO_Watcher, &queue);
+        SDL_CreateThread(FIFO_Watcher, "FIFOWatcher", &queue);
     }
 #endif
 
@@ -627,9 +627,11 @@
     SDL_zero(readerData);
     SDL_AtomicSet(&readersRunning, NUM_READERS);
     for (i = 0; i < NUM_READERS; ++i) {
+        char name[64];
+        SDL_snprintf(name, sizeof (name), "FIFOReader%d", i);
         readerData[i].queue = &queue;
         readerData[i].lock_free = lock_free;
-        SDL_CreateThread(FIFO_Reader, &readerData[i]);
+        SDL_CreateThread(FIFO_Reader, name, &readerData[i]);
     }
 
     /* Start up the writers */
@@ -637,10 +639,12 @@
     SDL_zero(writerData);
     SDL_AtomicSet(&writersRunning, NUM_WRITERS);
     for (i = 0; i < NUM_WRITERS; ++i) {
+        char name[64];
+        SDL_snprintf(name, sizeof (name), "FIFOWriter%d", i);
         writerData[i].queue = &queue;
         writerData[i].index = i;
         writerData[i].lock_free = lock_free;
-        SDL_CreateThread(FIFO_Writer, &writerData[i]);
+        SDL_CreateThread(FIFO_Writer, name, &writerData[i]);
     }
  
     /* Wait for the writers */
--- a/test/testerror.c	Wed Sep 28 21:42:02 2011 +0200
+++ b/test/testerror.c	Sat Oct 08 12:45:10 2011 +0200
@@ -58,7 +58,7 @@
     SDL_SetError("No worries");
 
     alive = 1;
-    thread = SDL_CreateThread(ThreadFunc, "#1");
+    thread = SDL_CreateThread(ThreadFunc, NULL, "#1");
     if (thread == NULL) {
         fprintf(stderr, "Couldn't create thread: %s\n", SDL_GetError());
         quit(1);
--- a/test/testlock.c	Wed Sep 28 21:42:02 2011 +0200
+++ b/test/testlock.c	Sat Oct 08 12:45:10 2011 +0200
@@ -112,7 +112,9 @@
     printf("Main thread: %lu\n", mainthread);
     atexit(printid);
     for (i = 0; i < maxproc; ++i) {
-        if ((threads[i] = SDL_CreateThread(Run, NULL)) == NULL)
+        char name[64];
+        SDL_snprintf(name, sizeof (name), "Worker%d", i);
+        if ((threads[i] = SDL_CreateThread(Run, name, NULL)) == NULL)
             fprintf(stderr, "Couldn't create thread!\n");
     }
     signal(SIGINT, terminate);
--- a/test/testsem.c	Wed Sep 28 21:42:02 2011 +0200
+++ b/test/testsem.c	Sat Oct 08 12:45:10 2011 +0200
@@ -100,7 +100,9 @@
            init_sem);
     /* Create all the threads */
     for (i = 0; i < NUM_THREADS; ++i) {
-        threads[i] = SDL_CreateThread(ThreadFunc, (void *) i);
+        char name[64];
+        SDL_snprintf(name, sizeof (name), "Thread%u", (unsigned int) i);
+        threads[i] = SDL_CreateThread(ThreadFunc, name, (void *) i);
     }
 
     /* Wait 10 seconds */
--- a/test/testthread.c	Wed Sep 28 21:42:02 2011 +0200
+++ b/test/testthread.c	Sat Oct 08 12:45:10 2011 +0200
@@ -63,7 +63,7 @@
     }
 
     alive = 1;
-    thread = SDL_CreateThread(ThreadFunc, "#1");
+    thread = SDL_CreateThread(ThreadFunc, "One", "#1");
     if (thread == NULL) {
         fprintf(stderr, "Couldn't create thread: %s\n", SDL_GetError());
         quit(1);
@@ -75,7 +75,7 @@
 
     alive = 1;
     signal(SIGTERM, killed);
-    thread = SDL_CreateThread(ThreadFunc, "#2");
+    thread = SDL_CreateThread(ThreadFunc, "Two", "#2");
     if (thread == NULL) {
         fprintf(stderr, "Couldn't create thread: %s\n", SDL_GetError());
         quit(1);
--- a/test/threadwin.c	Wed Sep 28 21:42:02 2011 +0200
+++ b/test/threadwin.c	Sat Oct 08 12:45:10 2011 +0200
@@ -296,8 +296,8 @@
     SDL_SetEventFilter(FilterEvents, NULL);
 
     /* Create the event handling threads */
-    mouse_thread = SDL_CreateThread(HandleMouse, NULL);
-    keybd_thread = SDL_CreateThread(HandleKeyboard, NULL);
+    mouse_thread = SDL_CreateThread(HandleMouse, "MouseHandler", NULL);
+    keybd_thread = SDL_CreateThread(HandleKeyboard, "KeyboardHandler", NULL);
 
     /* Set the surface pixels and refresh! */
     for (i = 0; i < 256; ++i) {
--- a/test/torturethread.c	Wed Sep 28 21:42:02 2011 +0200
+++ b/test/torturethread.c	Sat Oct 08 12:45:10 2011 +0200
@@ -52,8 +52,10 @@
     fprintf(stderr, "Creating Thread %d\n", tid);
 
     for (i = 0; i < NUMTHREADS; i++) {
+        char name[64];
+        SDL_snprintf(name, sizeof (name), "Child%d_%d", tid, i);
         flags[i] = 0;
-        sub_threads[i] = SDL_CreateThread(SubThreadFunc, &flags[i]);
+        sub_threads[i] = SDL_CreateThread(SubThreadFunc, name, &flags[i]);
     }
 
     printf("Thread '%d' waiting for signal\n", tid);
@@ -86,8 +88,10 @@
 
     signal(SIGSEGV, SIG_DFL);
     for (i = 0; i < NUMTHREADS; i++) {
+        char name[64];
+        SDL_snprintf(name, sizeof (name), "Parent%d", i);
         time_for_threads_to_die[i] = 0;
-        threads[i] = SDL_CreateThread(ThreadFunc, (void *) (uintptr_t) i);
+        threads[i] = SDL_CreateThread(ThreadFunc, name, (void*) (uintptr_t) i);
 
         if (threads[i] == NULL) {
             fprintf(stderr, "Couldn't create thread: %s\n", SDL_GetError());