Implemented an API for thread-local storage: SDL_TLSCreate(), SDL_TLSSet(), SDL_TLSGet()
authorSam Lantinga <slouken@libsdl.org>
Wed, 10 Jul 2013 02:32:04 -0700
changeset 7391a29895dc5e9a
parent 7390 e4b98404baa4
child 7392 7e32fcb41b44
Implemented an API for thread-local storage: SDL_TLSCreate(), SDL_TLSSet(), SDL_TLSGet()
VisualC/SDL/SDL_VS2008.vcproj
VisualC/SDL/SDL_VS2010.vcxproj
VisualC/SDL/SDL_VS2012.vcxproj
Xcode-iOS/SDL/SDL.xcodeproj/project.pbxproj
Xcode/SDL/SDL.xcodeproj/project.pbxproj
configure
configure.in
include/SDL_thread.h
src/thread/SDL_thread.c
src/thread/beos/SDL_systls.c
src/thread/generic/SDL_systls.c
src/thread/pthread/SDL_systls.c
src/thread/windows/SDL_systls.c
test/testthread.c
     1.1 --- a/VisualC/SDL/SDL_VS2008.vcproj	Tue Jul 09 12:58:54 2013 -0700
     1.2 +++ b/VisualC/SDL/SDL_VS2008.vcproj	Wed Jul 10 02:32:04 2013 -0700
     1.3 @@ -1133,6 +1133,10 @@
     1.4  			>
     1.5  		</File>
     1.6  		<File
     1.7 +			RelativePath="..\..\src\thread\windows\SDL_systls.c"
     1.8 +			>
     1.9 +		</File>
    1.10 +		<File
    1.11  			RelativePath="..\..\src\thread\SDL_systhread.h"
    1.12  			>
    1.13  		</File>
     2.1 --- a/VisualC/SDL/SDL_VS2010.vcxproj	Tue Jul 09 12:58:54 2013 -0700
     2.2 +++ b/VisualC/SDL/SDL_VS2010.vcxproj	Wed Jul 10 02:32:04 2013 -0700
     2.3 @@ -438,6 +438,7 @@
     2.4      <ClCompile Include="..\..\src\power\windows\SDL_syspower.c" />
     2.5      <ClCompile Include="..\..\src\thread\windows\SDL_syssem.c" />
     2.6      <ClCompile Include="..\..\src\thread\windows\SDL_systhread.c" />
     2.7 +    <ClCompile Include="..\..\src\thread\windows\SDL_systls.c" />
     2.8      <ClCompile Include="..\..\src\timer\windows\SDL_systimer.c" />
     2.9      <ClCompile Include="..\..\src\thread\SDL_thread.c" />
    2.10      <ClCompile Include="..\..\src\timer\SDL_timer.c" />
    2.11 @@ -462,4 +463,4 @@
    2.12    <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
    2.13    <ImportGroup Label="ExtensionTargets">
    2.14    </ImportGroup>
    2.15 -</Project>
    2.16 \ No newline at end of file
    2.17 +</Project>
     3.1 --- a/VisualC/SDL/SDL_VS2012.vcxproj	Tue Jul 09 12:58:54 2013 -0700
     3.2 +++ b/VisualC/SDL/SDL_VS2012.vcxproj	Wed Jul 10 02:32:04 2013 -0700
     3.3 @@ -441,6 +441,7 @@
     3.4      <ClCompile Include="..\..\src\power\windows\SDL_syspower.c" />
     3.5      <ClCompile Include="..\..\src\thread\windows\SDL_syssem.c" />
     3.6      <ClCompile Include="..\..\src\thread\windows\SDL_systhread.c" />
     3.7 +    <ClCompile Include="..\..\src\thread\windows\SDL_systls.c" />
     3.8      <ClCompile Include="..\..\src\timer\windows\SDL_systimer.c" />
     3.9      <ClCompile Include="..\..\src\thread\SDL_thread.c" />
    3.10      <ClCompile Include="..\..\src\timer\SDL_timer.c" />
    3.11 @@ -466,4 +467,4 @@
    3.12    <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
    3.13    <ImportGroup Label="ExtensionTargets">
    3.14    </ImportGroup>
    3.15 -</Project>
    3.16 \ No newline at end of file
    3.17 +</Project>
     4.1 --- a/Xcode-iOS/SDL/SDL.xcodeproj/project.pbxproj	Tue Jul 09 12:58:54 2013 -0700
     4.2 +++ b/Xcode-iOS/SDL/SDL.xcodeproj/project.pbxproj	Wed Jul 10 02:32:04 2013 -0700
     4.3 @@ -76,6 +76,7 @@
     4.4  		93CB792613FC5F5300BD3E05 /* SDL_uikitviewcontroller.m in Sources */ = {isa = PBXBuildFile; fileRef = 93CB792513FC5F5300BD3E05 /* SDL_uikitviewcontroller.m */; };
     4.5  		AA0AD06216647BBB00CE5896 /* SDL_gamecontroller.c in Sources */ = {isa = PBXBuildFile; fileRef = AA0AD06116647BBB00CE5896 /* SDL_gamecontroller.c */; };
     4.6  		AA0AD06516647BD400CE5896 /* SDL_gamecontroller.h in Headers */ = {isa = PBXBuildFile; fileRef = AA0AD06416647BD400CE5896 /* SDL_gamecontroller.h */; };
     4.7 +		AA0F8495178D5F1A00823F9D /* SDL_systls.c in Sources */ = {isa = PBXBuildFile; fileRef = AA0F8494178D5F1A00823F9D /* SDL_systls.c */; };
     4.8  		AA126AD41617C5E7005ABC8F /* SDL_uikitmodes.h in Headers */ = {isa = PBXBuildFile; fileRef = AA126AD21617C5E6005ABC8F /* SDL_uikitmodes.h */; };
     4.9  		AA126AD51617C5E7005ABC8F /* SDL_uikitmodes.m in Sources */ = {isa = PBXBuildFile; fileRef = AA126AD31617C5E6005ABC8F /* SDL_uikitmodes.m */; };
    4.10  		AA628ADB159369E3005138DD /* SDL_rotate.c in Sources */ = {isa = PBXBuildFile; fileRef = AA628AD9159369E3005138DD /* SDL_rotate.c */; };
    4.11 @@ -268,6 +269,7 @@
    4.12  		93CB792513FC5F5300BD3E05 /* SDL_uikitviewcontroller.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_uikitviewcontroller.m; sourceTree = "<group>"; };
    4.13  		AA0AD06116647BBB00CE5896 /* SDL_gamecontroller.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_gamecontroller.c; sourceTree = "<group>"; };
    4.14  		AA0AD06416647BD400CE5896 /* SDL_gamecontroller.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_gamecontroller.h; sourceTree = "<group>"; };
    4.15 +		AA0F8494178D5F1A00823F9D /* SDL_systls.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_systls.c; sourceTree = "<group>"; };
    4.16  		AA126AD21617C5E6005ABC8F /* SDL_uikitmodes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_uikitmodes.h; sourceTree = "<group>"; };
    4.17  		AA126AD31617C5E6005ABC8F /* SDL_uikitmodes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_uikitmodes.m; sourceTree = "<group>"; };
    4.18  		AA628AD9159369E3005138DD /* SDL_rotate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_rotate.c; sourceTree = "<group>"; };
    4.19 @@ -851,6 +853,7 @@
    4.20  				FD99BA0A0DD52EDC00FB1D6B /* SDL_syssem.c */,
    4.21  				FD99BA0B0DD52EDC00FB1D6B /* SDL_systhread.c */,
    4.22  				FD99BA0C0DD52EDC00FB1D6B /* SDL_systhread_c.h */,
    4.23 +				AA0F8494178D5F1A00823F9D /* SDL_systls.c */,
    4.24  			);
    4.25  			path = pthread;
    4.26  			sourceTree = "<group>";
    4.27 @@ -1189,6 +1192,7 @@
    4.28  				AA704DD7162AA90A0076D1C1 /* SDL_dropevents.c in Sources */,
    4.29  				AABCC3951640643D00AB8930 /* SDL_uikitmessagebox.m in Sources */,
    4.30  				AA0AD06216647BBB00CE5896 /* SDL_gamecontroller.c in Sources */,
    4.31 +				AA0F8495178D5F1A00823F9D /* SDL_systls.c in Sources */,
    4.32  			);
    4.33  			runOnlyForDeploymentPostprocessing = 0;
    4.34  		};
     5.1 --- a/Xcode/SDL/SDL.xcodeproj/project.pbxproj	Tue Jul 09 12:58:54 2013 -0700
     5.2 +++ b/Xcode/SDL/SDL.xcodeproj/project.pbxproj	Wed Jul 10 02:32:04 2013 -0700
     5.3 @@ -398,6 +398,9 @@
     5.4  		A77E6EB4167AB0A90010E40B /* SDL_gamecontroller.h in Headers */ = {isa = PBXBuildFile; fileRef = A77E6EB3167AB0A90010E40B /* SDL_gamecontroller.h */; settings = {ATTRIBUTES = (Public, ); }; };
     5.5  		A77E6EB5167AB0A90010E40B /* SDL_gamecontroller.h in Headers */ = {isa = PBXBuildFile; fileRef = A77E6EB3167AB0A90010E40B /* SDL_gamecontroller.h */; };
     5.6  		AA0AD09D16648D1700CE5896 /* SDL_gamecontroller.c in Sources */ = {isa = PBXBuildFile; fileRef = BBFC088A164C6514003E6A99 /* SDL_gamecontroller.c */; };
     5.7 +		AA0F8491178D5ECC00823F9D /* SDL_systls.c in Sources */ = {isa = PBXBuildFile; fileRef = AA0F8490178D5ECC00823F9D /* SDL_systls.c */; };
     5.8 +		AA0F8492178D5ECC00823F9D /* SDL_systls.c in Sources */ = {isa = PBXBuildFile; fileRef = AA0F8490178D5ECC00823F9D /* SDL_systls.c */; };
     5.9 +		AA0F8493178D5ECC00823F9D /* SDL_systls.c in Sources */ = {isa = PBXBuildFile; fileRef = AA0F8490178D5ECC00823F9D /* SDL_systls.c */; };
    5.10  		AA41F88014B8F1F500993C4F /* SDL_dropevents.c in Sources */ = {isa = PBXBuildFile; fileRef = 566CDE8E148F0AC200C5A9BB /* SDL_dropevents.c */; };
    5.11  		AA628ACA159367B7005138DD /* SDL_rotate.c in Sources */ = {isa = PBXBuildFile; fileRef = AA628AC8159367B7005138DD /* SDL_rotate.c */; };
    5.12  		AA628ACB159367B7005138DD /* SDL_rotate.c in Sources */ = {isa = PBXBuildFile; fileRef = AA628AC8159367B7005138DD /* SDL_rotate.c */; };
    5.13 @@ -984,6 +987,7 @@
    5.14  		566CDE8D148F0AC200C5A9BB /* SDL_dropevents_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_dropevents_c.h; sourceTree = "<group>"; };
    5.15  		566CDE8E148F0AC200C5A9BB /* SDL_dropevents.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_dropevents.c; sourceTree = "<group>"; };
    5.16  		A77E6EB3167AB0A90010E40B /* SDL_gamecontroller.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_gamecontroller.h; sourceTree = "<group>"; };
    5.17 +		AA0F8490178D5ECC00823F9D /* SDL_systls.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_systls.c; sourceTree = "<group>"; };
    5.18  		AA628AC8159367B7005138DD /* SDL_rotate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_rotate.c; sourceTree = "<group>"; };
    5.19  		AA628AC9159367B7005138DD /* SDL_rotate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_rotate.h; sourceTree = "<group>"; };
    5.20  		AA628ACF159367F2005138DD /* SDL_x11xinput2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_x11xinput2.c; sourceTree = "<group>"; };
    5.21 @@ -1462,6 +1466,7 @@
    5.22  				04BDFE8112E6671800899322 /* SDL_syssem.c */,
    5.23  				04BDFE8212E6671800899322 /* SDL_systhread.c */,
    5.24  				04BDFE8312E6671800899322 /* SDL_systhread_c.h */,
    5.25 +				AA0F8490178D5ECC00823F9D /* SDL_systls.c */,
    5.26  			);
    5.27  			path = pthread;
    5.28  			sourceTree = "<group>";
    5.29 @@ -2403,6 +2408,7 @@
    5.30  				AA9E4093163BE51E007A2AD0 /* SDL_x11messagebox.c in Sources */,
    5.31  				AABCC38F164063D200AB8930 /* SDL_cocoamessagebox.m in Sources */,
    5.32  				AA0AD09D16648D1700CE5896 /* SDL_gamecontroller.c in Sources */,
    5.33 +				AA0F8491178D5ECC00823F9D /* SDL_systls.c in Sources */,
    5.34  			);
    5.35  			runOnlyForDeploymentPostprocessing = 0;
    5.36  		};
    5.37 @@ -2519,6 +2525,7 @@
    5.38  				AA628AD2159367F2005138DD /* SDL_x11xinput2.c in Sources */,
    5.39  				AA9E4094163BE51E007A2AD0 /* SDL_x11messagebox.c in Sources */,
    5.40  				AABCC390164063D200AB8930 /* SDL_cocoamessagebox.m in Sources */,
    5.41 +				AA0F8492178D5ECC00823F9D /* SDL_systls.c in Sources */,
    5.42  			);
    5.43  			runOnlyForDeploymentPostprocessing = 0;
    5.44  		};
    5.45 @@ -2635,6 +2642,7 @@
    5.46  				DB31406817554B71006C0E22 /* SDL_x11xinput2.c in Sources */,
    5.47  				DB31406917554B71006C0E22 /* SDL_x11messagebox.c in Sources */,
    5.48  				DB31406A17554B71006C0E22 /* SDL_cocoamessagebox.m in Sources */,
    5.49 +				AA0F8493178D5ECC00823F9D /* SDL_systls.c in Sources */,
    5.50  			);
    5.51  			runOnlyForDeploymentPostprocessing = 0;
    5.52  		};
     6.1 --- a/configure	Tue Jul 09 12:58:54 2013 -0700
     6.2 +++ b/configure	Wed Jul 10 02:32:04 2013 -0700
     6.3 @@ -1511,7 +1511,7 @@
     6.4    --enable-sse            use SSE assembly routines [[default=yes]]
     6.5    --enable-sse2           use SSE2 assembly routines [[default=no]]
     6.6    --enable-altivec        use Altivec assembly routines [[default=yes]]
     6.7 -  --enable-oss            support the OSS audio API [[default=yes]]
     6.8 +  --enable-oss            support the OSS audio API [[default=maybe]]
     6.9    --enable-alsa           support the ALSA audio API [[default=yes]]
    6.10    --disable-alsatest      Do not try to compile and run a test Alsa program
    6.11    --enable-alsa-shared    dynamically load ALSA audio support [[default=yes]]
    6.12 @@ -17535,8 +17535,20 @@
    6.13  if test "${enable_oss+set}" = set; then :
    6.14    enableval=$enable_oss;
    6.15  else
    6.16 -  enable_oss=yes
    6.17 -fi
    6.18 +  enable_oss=maybe
    6.19 +fi
    6.20 +
    6.21 +
    6.22 +    # OpenBSD "has" OSS, but it's not really for app use. They want you to
    6.23 +    #  use sndio instead. So on there, we default to disabled. You can force
    6.24 +    #  it on if you really want, though.
    6.25 +    if test x$enable_oss = xmaybe; then
    6.26 +        enable_oss=yes
    6.27 +        case "$host" in
    6.28 +            *-*-openbsd*)
    6.29 +                enable_oss=no;;
    6.30 +        esac
    6.31 +    fi
    6.32  
    6.33      if test x$enable_audio = xyes -a x$enable_oss = xyes; then
    6.34          { $as_echo "$as_me:${as_lineno-$LINENO}: checking for OSS audio support" >&5
    6.35 @@ -21423,6 +21435,9 @@
    6.36              # We can fake these with semaphores and mutexes if necessary
    6.37              SOURCES="$SOURCES $srcdir/src/thread/pthread/SDL_syscond.c"
    6.38  
    6.39 +            # Thread local storage
    6.40 +            SOURCES="$SOURCES $srcdir/src/thread/pthread/SDL_systls.c"
    6.41 +
    6.42              have_threads=yes
    6.43          fi
    6.44      fi
    6.45 @@ -22206,7 +22221,7 @@
    6.46                  SOURCES="$SOURCES $srcdir/src/audio/sun/*.c"
    6.47                  have_audio=yes
    6.48              ;;
    6.49 -            netbsd|openbsd)
    6.50 +            netbsd)  # Don't use this on OpenBSD, it's busted.
    6.51  
    6.52  $as_echo "#define SDL_AUDIO_DRIVER_BSD 1" >>confdefs.h
    6.53  
    6.54 @@ -22367,9 +22382,7 @@
    6.55  
    6.56  $as_echo "#define SDL_THREAD_WINDOWS 1" >>confdefs.h
    6.57  
    6.58 -            SOURCES="$SOURCES $srcdir/src/thread/windows/SDL_sysmutex.c"
    6.59 -            SOURCES="$SOURCES $srcdir/src/thread/windows/SDL_syssem.c"
    6.60 -            SOURCES="$SOURCES $srcdir/src/thread/windows/SDL_systhread.c"
    6.61 +            SOURCES="$SOURCES $srcdir/src/thread/windows/*.c"
    6.62              SOURCES="$SOURCES $srcdir/src/thread/generic/SDL_syscond.c"
    6.63              have_threads=yes
    6.64          fi
     7.1 --- a/configure.in	Tue Jul 09 12:58:54 2013 -0700
     7.2 +++ b/configure.in	Wed Jul 10 02:32:04 2013 -0700
     7.3 @@ -657,6 +657,7 @@
     7.4          case "$host" in
     7.5              *-*-openbsd*)
     7.6                  enable_oss=no;;
     7.7 +        esac
     7.8      fi
     7.9  
    7.10      if test x$enable_audio = xyes -a x$enable_oss = xyes; then
    7.11 @@ -2019,6 +2020,9 @@
    7.12              # We can fake these with semaphores and mutexes if necessary
    7.13              SOURCES="$SOURCES $srcdir/src/thread/pthread/SDL_syscond.c"
    7.14  
    7.15 +            # Thread local storage
    7.16 +            SOURCES="$SOURCES $srcdir/src/thread/pthread/SDL_systls.c"
    7.17 +
    7.18              have_threads=yes
    7.19          fi
    7.20      fi
    7.21 @@ -2470,9 +2474,7 @@
    7.22          # Set up files for the thread library
    7.23          if test x$enable_threads = xyes; then
    7.24              AC_DEFINE(SDL_THREAD_WINDOWS, 1, [ ])
    7.25 -            SOURCES="$SOURCES $srcdir/src/thread/windows/SDL_sysmutex.c"
    7.26 -            SOURCES="$SOURCES $srcdir/src/thread/windows/SDL_syssem.c"
    7.27 -            SOURCES="$SOURCES $srcdir/src/thread/windows/SDL_systhread.c"
    7.28 +            SOURCES="$SOURCES $srcdir/src/thread/windows/*.c"
    7.29              SOURCES="$SOURCES $srcdir/src/thread/generic/SDL_syscond.c"
    7.30              have_threads=yes
    7.31          fi
     8.1 --- a/include/SDL_thread.h	Tue Jul 09 12:58:54 2013 -0700
     8.2 +++ b/include/SDL_thread.h	Wed Jul 10 02:32:04 2013 -0700
     8.3 @@ -32,6 +32,7 @@
     8.4  #include "SDL_error.h"
     8.5  
     8.6  /* Thread synchronization primitives */
     8.7 +#include "SDL_atomic.h"
     8.8  #include "SDL_mutex.h"
     8.9  
    8.10  #include "begin_code.h"
    8.11 @@ -47,6 +48,9 @@
    8.12  /* The SDL thread ID */
    8.13  typedef unsigned long SDL_threadID;
    8.14  
    8.15 +/* Thread local storage ID */
    8.16 +typedef int SDL_TLSID;
    8.17 +
    8.18  /* The SDL thread priority
    8.19   *
    8.20   * Note: On many systems you require special privileges to set high priority.
    8.21 @@ -166,6 +170,63 @@
    8.22   */
    8.23  extern DECLSPEC void SDLCALL SDL_WaitThread(SDL_Thread * thread, int *status);
    8.24  
    8.25 +/**
    8.26 + *  \brief Create an identifier that is globally visible to all threads but refers to data that is thread-specific.
    8.27 + *
    8.28 + *  \return The newly created thread local storage identifier, or 0 on error
    8.29 + *
    8.30 + *  \code
    8.31 + *  static SDL_SpinLock tls_lock;
    8.32 + *  static SDL_TLSID thread_local_storage;
    8.33 + * 
    8.34 + *  void SetMyThreadData(void *value)
    8.35 + *  {
    8.36 + *      if (!thread_local_storage) {
    8.37 + *          SDL_AtomicLock(&tls_lock);
    8.38 + *          if (!thread_local_storage) {
    8.39 + *              thread_local_storage = SDL_TLSCreate();
    8.40 + *          }
    8.41 + *          SDL_AtomicUnLock(&tls_lock);
    8.42 + *      }
    8.43 + *      SDL_TLSSet(thread_local_storage, value);
    8.44 + *  }
    8.45 + *  
    8.46 + *  void *GetMyThreadData(void)
    8.47 + *  {
    8.48 + *      return SDL_TLSGet(thread_local_storage);
    8.49 + *  }
    8.50 + *  \endcode
    8.51 + *
    8.52 + *  \sa SDL_TLSGet()
    8.53 + *  \sa SDL_TLSSet()
    8.54 + */
    8.55 +extern DECLSPEC SDL_TLSID SDLCALL SDL_TLSCreate();
    8.56 +
    8.57 +/**
    8.58 + *  \brief Get the value associated with a thread local storage ID for the current thread.
    8.59 + *
    8.60 + *  \param id The thread local storage ID
    8.61 + *
    8.62 + *  \return The value associated with the ID for the current thread, or NULL if no value has been set.
    8.63 + *
    8.64 + *  \sa SDL_TLSCreate()
    8.65 + *  \sa SDL_TLSSet()
    8.66 + */
    8.67 +extern DECLSPEC void * SDLCALL SDL_TLSGet(SDL_TLSID id);
    8.68 +
    8.69 +/**
    8.70 + *  \brief Set the value associated with a thread local storage ID for the current thread.
    8.71 + *
    8.72 + *  \param id The thread local storage ID
    8.73 + *  \param value The value to associate with the ID for the current thread
    8.74 + *
    8.75 + *  \return 0 on success, -1 on error
    8.76 + *
    8.77 + *  \sa SDL_TLSCreate()
    8.78 + *  \sa SDL_TLSGet()
    8.79 + */
    8.80 +extern DECLSPEC int SDLCALL SDL_TLSSet(SDL_TLSID id, const void *value);
    8.81 +
    8.82  
    8.83  /* Ends C function definitions when using C++ */
    8.84  #ifdef __cplusplus
     9.1 --- a/src/thread/SDL_thread.c	Tue Jul 09 12:58:54 2013 -0700
     9.2 +++ b/src/thread/SDL_thread.c	Wed Jul 10 02:32:04 2013 -0700
     9.3 @@ -22,158 +22,46 @@
     9.4  
     9.5  /* System independent thread management routines for SDL */
     9.6  
     9.7 -#include "SDL_mutex.h"
     9.8  #include "SDL_thread.h"
     9.9  #include "SDL_thread_c.h"
    9.10  #include "SDL_systhread.h"
    9.11  #include "../SDL_error_c.h"
    9.12  
    9.13 -#define ARRAY_CHUNKSIZE 32
    9.14 -/* The array of threads currently active in the application
    9.15 -   (except the main thread)
    9.16 -   The manipulation of an array here is safer than using a linked list.
    9.17 -*/
    9.18 -static int SDL_maxthreads = 0;
    9.19 -static int SDL_numthreads = 0;
    9.20 -static SDL_Thread **SDL_Threads = NULL;
    9.21 -static SDL_mutex *thread_lock = NULL;
    9.22 -
    9.23 -static int
    9.24 -SDL_ThreadsInit(void)
    9.25 -{
    9.26 -    int retval;
    9.27 -
    9.28 -    retval = 0;
    9.29 -    thread_lock = SDL_CreateMutex();
    9.30 -    if (thread_lock == NULL) {
    9.31 -        retval = -1;
    9.32 -    }
    9.33 -    return (retval);
    9.34 -}
    9.35 -
    9.36 -/* This should never be called...
    9.37 -   If this is called by SDL_Quit(), we don't know whether or not we should
    9.38 -   clean up threads here.  If any threads are still running after this call,
    9.39 -   they will no longer have access to any per-thread data.
    9.40 - */
    9.41 -#if 0
    9.42 -static void
    9.43 -SDL_ThreadsQuit(void)
    9.44 -{
    9.45 -    SDL_mutex *mutex;
    9.46 -
    9.47 -    mutex = thread_lock;
    9.48 -    thread_lock = NULL;
    9.49 -    if (mutex != NULL) {
    9.50 -        SDL_DestroyMutex(mutex);
    9.51 -    }
    9.52 -}
    9.53 -#endif
    9.54 -
    9.55 -/* Routines for manipulating the thread list */
    9.56 -static void
    9.57 -SDL_AddThread(SDL_Thread * thread)
    9.58 -{
    9.59 -    /* WARNING:
    9.60 -       If the very first threads are created simultaneously, then
    9.61 -       there could be a race condition causing memory corruption.
    9.62 -       In practice, this isn't a problem because by definition there
    9.63 -       is only one thread running the first time this is called.
    9.64 -     */
    9.65 -    if (!thread_lock) {
    9.66 -        if (SDL_ThreadsInit() < 0) {
    9.67 -            return;
    9.68 -        }
    9.69 -    }
    9.70 -    SDL_LockMutex(thread_lock);
    9.71 -
    9.72 -    /* Expand the list of threads, if necessary */
    9.73 -#ifdef DEBUG_THREADS
    9.74 -    printf("Adding thread (%d already - %d max)\n",
    9.75 -           SDL_numthreads, SDL_maxthreads);
    9.76 -#endif
    9.77 -    if (SDL_numthreads == SDL_maxthreads) {
    9.78 -        SDL_Thread **threads;
    9.79 -        threads = (SDL_Thread **) SDL_realloc(SDL_Threads,
    9.80 -                                              (SDL_maxthreads +
    9.81 -                                               ARRAY_CHUNKSIZE) *
    9.82 -                                              (sizeof *threads));
    9.83 -        if (threads == NULL) {
    9.84 -            SDL_OutOfMemory();
    9.85 -            goto done;
    9.86 -        }
    9.87 -        SDL_maxthreads += ARRAY_CHUNKSIZE;
    9.88 -        SDL_Threads = threads;
    9.89 -    }
    9.90 -    SDL_Threads[SDL_numthreads++] = thread;
    9.91 -  done:
    9.92 -    SDL_mutexV(thread_lock);
    9.93 -}
    9.94 -
    9.95 -static void
    9.96 -SDL_DelThread(SDL_Thread * thread)
    9.97 -{
    9.98 -    int i;
    9.99 -
   9.100 -    if (!thread_lock) {
   9.101 -        return;
   9.102 -    }
   9.103 -    SDL_LockMutex(thread_lock);
   9.104 -    for (i = 0; i < SDL_numthreads; ++i) {
   9.105 -        if (thread == SDL_Threads[i]) {
   9.106 -            break;
   9.107 -        }
   9.108 -    }
   9.109 -    if (i < SDL_numthreads) {
   9.110 -        if (--SDL_numthreads > 0) {
   9.111 -            while (i < SDL_numthreads) {
   9.112 -                SDL_Threads[i] = SDL_Threads[i + 1];
   9.113 -                ++i;
   9.114 -            }
   9.115 -        } else {
   9.116 -            SDL_maxthreads = 0;
   9.117 -            SDL_free(SDL_Threads);
   9.118 -            SDL_Threads = NULL;
   9.119 -        }
   9.120 -#ifdef DEBUG_THREADS
   9.121 -        printf("Deleting thread (%d left - %d max)\n",
   9.122 -               SDL_numthreads, SDL_maxthreads);
   9.123 -#endif
   9.124 -    }
   9.125 -    SDL_mutexV(thread_lock);
   9.126 -
   9.127 -#if 0   /* There could be memory corruption if another thread is starting */
   9.128 -    if (SDL_Threads == NULL) {
   9.129 -        SDL_ThreadsQuit();
   9.130 -    }
   9.131 -#endif
   9.132 -}
   9.133 -
   9.134 -/* The default (non-thread-safe) global error variable */
   9.135 -static SDL_error SDL_global_error;
   9.136  
   9.137  /* Routine to get the thread-specific error variable */
   9.138  SDL_error *
   9.139  SDL_GetErrBuf(void)
   9.140  {
   9.141 +    static SDL_SpinLock spinlock;
   9.142 +    static SDL_bool tls_being_created;
   9.143 +    static SDL_TLSID tls_errbuf;
   9.144 +    static SDL_error SDL_global_errbuf;
   9.145      SDL_error *errbuf;
   9.146  
   9.147 -    errbuf = &SDL_global_error;
   9.148 -    if (SDL_Threads) {
   9.149 -        int i;
   9.150 -        SDL_threadID this_thread;
   9.151 +    if (!tls_errbuf && !tls_being_created) {
   9.152 +        SDL_AtomicLock(&spinlock);
   9.153 +        if (!tls_errbuf) {
   9.154 +            /* SDL_TLSCreate() could fail and call SDL_SetError() */
   9.155 +            tls_being_created = SDL_TRUE;
   9.156 +            tls_errbuf = SDL_TLSCreate();
   9.157 +            tls_being_created = SDL_FALSE;
   9.158 +        }
   9.159 +        SDL_AtomicUnlock(&spinlock);
   9.160 +    }
   9.161 +    if (!tls_errbuf) {
   9.162 +        return &SDL_global_errbuf;
   9.163 +    }
   9.164  
   9.165 -        this_thread = SDL_ThreadID();
   9.166 -        SDL_LockMutex(thread_lock);
   9.167 -        for (i = 0; i < SDL_numthreads; ++i) {
   9.168 -            if (this_thread == SDL_Threads[i]->threadid) {
   9.169 -                errbuf = &SDL_Threads[i]->errbuf;
   9.170 -                break;
   9.171 -            }
   9.172 +    errbuf = SDL_TLSGet(tls_errbuf);
   9.173 +    if (!errbuf) {
   9.174 +        errbuf = (SDL_error *)SDL_malloc(sizeof(*errbuf));
   9.175 +        if (!errbuf) {
   9.176 +            return &SDL_global_errbuf;
   9.177          }
   9.178 -        SDL_mutexV(thread_lock);
   9.179 +        SDL_zerop(errbuf);
   9.180 +        SDL_TLSSet(tls_errbuf, errbuf);
   9.181      }
   9.182 -    return (errbuf);
   9.183 +    return errbuf;
   9.184  }
   9.185  
   9.186  
   9.187 @@ -264,9 +152,6 @@
   9.188          return (NULL);
   9.189      }
   9.190  
   9.191 -    /* Add the thread to the list of available threads */
   9.192 -    SDL_AddThread(thread);
   9.193 -
   9.194      /* Create the thread and go! */
   9.195  #ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
   9.196      ret = SDL_SYS_CreateThread(thread, args, pfnBeginThread, pfnEndThread);
   9.197 @@ -278,7 +163,6 @@
   9.198          SDL_SemWait(args->wait);
   9.199      } else {
   9.200          /* Oops, failed.  Gotta free everything */
   9.201 -        SDL_DelThread(thread);
   9.202          SDL_free(thread->name);
   9.203          SDL_free(thread);
   9.204          thread = NULL;
   9.205 @@ -323,7 +207,6 @@
   9.206          if (status) {
   9.207              *status = thread->status;
   9.208          }
   9.209 -        SDL_DelThread(thread);
   9.210          SDL_free(thread->name);
   9.211          SDL_free(thread);
   9.212      }
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/src/thread/beos/SDL_systls.c	Wed Jul 10 02:32:04 2013 -0700
    10.3 @@ -0,0 +1,106 @@
    10.4 +/*
    10.5 +  Simple DirectMedia Layer
    10.6 +  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
    10.7 +
    10.8 +  This software is provided 'as-is', without any express or implied
    10.9 +  warranty.  In no event will the authors be held liable for any damages
   10.10 +  arising from the use of this software.
   10.11 +
   10.12 +  Permission is granted to anyone to use this software for any purpose,
   10.13 +  including commercial applications, and to alter it and redistribute it
   10.14 +  freely, subject to the following restrictions:
   10.15 +
   10.16 +  1. The origin of this software must not be misrepresented; you must not
   10.17 +     claim that you wrote the original software. If you use this software
   10.18 +     in a product, an acknowledgment in the product documentation would be
   10.19 +     appreciated but is not required.
   10.20 +  2. Altered source versions must be plainly marked as such, and must not be
   10.21 +     misrepresented as being the original software.
   10.22 +  3. This notice may not be removed or altered from any source distribution.
   10.23 +*/
   10.24 +
   10.25 +#include "SDL_config.h"
   10.26 +#include "SDL_thread.h"
   10.27 +
   10.28 +#if SDL_THREAD_BEOS
   10.29 +
   10.30 +#include <support/TLS.h>
   10.31 +
   10.32 +
   10.33 +#define TLS_ALLOC_CHUNKSIZE 8
   10.34 +
   10.35 +typedef struct {
   10.36 +    int limit;
   10.37 +    void *data[1];
   10.38 +} SDL_TLSData;
   10.39 +
   10.40 +static SDL_SpinLock tls_lock;
   10.41 +static int32 thread_local_storage = B_NO_MEMORY;
   10.42 +static SDL_atomic_t tls_id;
   10.43 +
   10.44 +
   10.45 +SDL_TLSID
   10.46 +SDL_TLSCreate()
   10.47 +{
   10.48 +    if (thread_local_storage == B_NO_MEMORY) {
   10.49 +        SDL_AtomicLock(&tls_lock);
   10.50 +        if (thread_local_storage == B_NO_MEMORY) {
   10.51 +            thread_local_storage = tls_allocate();
   10.52 +            if (thread_local_storage == B_NO_MEMORY) {
   10.53 +                SDL_SetError("tls_allocate() failed");
   10.54 +                SDL_AtomicUnlock(&tls_lock);
   10.55 +                return 0;
   10.56 +            }
   10.57 +        }
   10.58 +        SDL_AtomicUnlock(&tls_lock);
   10.59 +    }
   10.60 +    return SDL_AtomicIncRef(&tls_id)+1;
   10.61 +}
   10.62 +
   10.63 +void *
   10.64 +SDL_TLSGet(SDL_TLSID id)
   10.65 +{
   10.66 +    SDL_TLSData *data;
   10.67 +
   10.68 +    data = (SDL_TLSData *)tls_get(thread_local_storage);
   10.69 +    if (!data || id <= 0 || id > data->limit) {
   10.70 +        return NULL;
   10.71 +    }
   10.72 +    return data->data[id-1];
   10.73 +}
   10.74 +
   10.75 +int
   10.76 +SDL_TLSSet(SDL_TLSID id, const void *value)
   10.77 +{
   10.78 +    SDL_TLSData *data;
   10.79 +
   10.80 +    if (thread_local_storage == B_NO_MEMORY || id <= 0) {
   10.81 +        return SDL_InvalidParamError(id);
   10.82 +    }
   10.83 +
   10.84 +    data = (SDL_TLSData *)tls_get(thread_local_storage);
   10.85 +    if (!data || id > data->limit) {
   10.86 +        int i, oldlimit, newlimit;
   10.87 +
   10.88 +        oldlimit = data ? data->limit : 0;
   10.89 +        newlimit = (id + TLS_ALLOC_CHUNKSIZE);
   10.90 +        data = (SDL_TLSData *)SDL_realloc(data, sizeof(*data)+(newlimit-1)*sizeof(void*));
   10.91 +        if (!data) {
   10.92 +            return SDL_OutOfMemory();
   10.93 +        }
   10.94 +        data->limit = newlimit;
   10.95 +        for (i = oldlimit; i < newlimit; ++i) {
   10.96 +            data->data[i] = NULL;
   10.97 +        }
   10.98 +        if (!tls_set(thread_local_storage, data)) {
   10.99 +            return SDL_SetError("TlsSetValue() failed");
  10.100 +        }
  10.101 +    }
  10.102 +
  10.103 +    data->data[id-1] = SDL_const_cast(void*, value);
  10.104 +    return 0;
  10.105 +}
  10.106 +
  10.107 +#endif /* SDL_THREAD_BEOS */
  10.108 +
  10.109 +/* vi: set ts=4 sw=4 expandtab: */
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/src/thread/generic/SDL_systls.c	Wed Jul 10 02:32:04 2013 -0700
    11.3 @@ -0,0 +1,163 @@
    11.4 +/*
    11.5 +  Simple DirectMedia Layer
    11.6 +  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
    11.7 +
    11.8 +  This software is provided 'as-is', without any express or implied
    11.9 +  warranty.  In no event will the authors be held liable for any damages
   11.10 +  arising from the use of this software.
   11.11 +
   11.12 +  Permission is granted to anyone to use this software for any purpose,
   11.13 +  including commercial applications, and to alter it and redistribute it
   11.14 +  freely, subject to the following restrictions:
   11.15 +
   11.16 +  1. The origin of this software must not be misrepresented; you must not
   11.17 +     claim that you wrote the original software. If you use this software
   11.18 +     in a product, an acknowledgment in the product documentation would be
   11.19 +     appreciated but is not required.
   11.20 +  2. Altered source versions must be plainly marked as such, and must not be
   11.21 +     misrepresented as being the original software.
   11.22 +  3. This notice may not be removed or altered from any source distribution.
   11.23 +*/
   11.24 +
   11.25 +#include "SDL_config.h"
   11.26 +#include "SDL_thread.h"
   11.27 +
   11.28 +/* This is a generic implementation of thread-local storage which doesn't
   11.29 +   require additional OS support.
   11.30 +
   11.31 +   It is not especially efficient and doesn't clean up thread-local storage
   11.32 +   as threads exit.  If there is a real OS that doesn't support thread-local
   11.33 +   storage this implementation should be improved to be production quality.
   11.34 +*/
   11.35 +
   11.36 +#define TLS_ALLOC_CHUNKSIZE 8
   11.37 +
   11.38 +typedef struct {
   11.39 +    int limit;
   11.40 +    void *data[1];
   11.41 +} SDL_TLSData;
   11.42 +
   11.43 +typedef struct SDL_TLSEntry {
   11.44 +    SDL_threadID thread;
   11.45 +    SDL_TLSData *data;
   11.46 +    struct SDL_TLSEntry *next;
   11.47 +} SDL_TLSEntry;
   11.48 +
   11.49 +static SDL_SpinLock tls_lock;
   11.50 +static SDL_mutex *tls_mutex;
   11.51 +static SDL_TLSEntry *thread_local_storage;
   11.52 +static SDL_atomic_t tls_id;
   11.53 +
   11.54 +
   11.55 +static SDL_TLSData *GetTLSData()
   11.56 +{
   11.57 +    SDL_threadID thread = SDL_ThreadID();
   11.58 +    SDL_TLSEntry *entry;
   11.59 +    SDL_TLSData *data = NULL;
   11.60 +
   11.61 +    if (!tls_mutex) {
   11.62 +        SDL_AtomicLock(&tls_lock);
   11.63 +        if (!tls_mutex) {
   11.64 +            tls_mutex = SDL_CreateMutex();
   11.65 +            if (!tls_mutex) {
   11.66 +                SDL_AtomicUnlock(&tls_lock);
   11.67 +                return NULL;
   11.68 +            }
   11.69 +        }
   11.70 +        SDL_AtomicUnlock(&tls_lock);
   11.71 +    }
   11.72 +
   11.73 +    SDL_LockMutex(tls_mutex);
   11.74 +    for (entry = thread_local_storage; entry; entry = entry->next) {
   11.75 +        if (entry->thread == thread) {
   11.76 +            data = entry->data;
   11.77 +            break;
   11.78 +        }
   11.79 +    }
   11.80 +    SDL_UnlockMutex(tls_mutex);
   11.81 +
   11.82 +    return data;
   11.83 +}
   11.84 +
   11.85 +static int SetTLSData(SDL_TLSData *data)
   11.86 +{
   11.87 +    SDL_threadID thread = SDL_ThreadID();
   11.88 +    SDL_TLSEntry *entry;
   11.89 +
   11.90 +    /* GetTLSData() is always called first, so we can assume tls_mutex */
   11.91 +    SDL_LockMutex(tls_mutex);
   11.92 +    for (entry = thread_local_storage; entry; entry = entry->next) {
   11.93 +        if (entry->thread == thread) {
   11.94 +            entry->data = data;
   11.95 +            break;
   11.96 +        }
   11.97 +    }
   11.98 +    if (!entry) {
   11.99 +        entry = (SDL_TLSEntry *)SDL_malloc(sizeof(*entry));
  11.100 +        if (entry) {
  11.101 +            entry->thread = thread;
  11.102 +            entry->data = data;
  11.103 +            entry->next = thread_local_storage;
  11.104 +            thread_local_storage = entry;
  11.105 +        }
  11.106 +    }
  11.107 +    SDL_UnlockMutex(tls_mutex);
  11.108 +
  11.109 +    if (!entry) {
  11.110 +        return SDL_OutOfMemory();
  11.111 +    }
  11.112 +    return 0;
  11.113 +}
  11.114 +
  11.115 +
  11.116 +SDL_TLSID
  11.117 +SDL_TLSCreate()
  11.118 +{
  11.119 +    return SDL_AtomicIncRef(&tls_id)+1;
  11.120 +}
  11.121 +
  11.122 +void *
  11.123 +SDL_TLSGet(SDL_TLSID id)
  11.124 +{
  11.125 +    SDL_TLSData *data;
  11.126 +
  11.127 +    data = GetTLSData();
  11.128 +    if (!data || id <= 0 || id > data->limit) {
  11.129 +        return NULL;
  11.130 +    }
  11.131 +    return data->data[id-1];
  11.132 +}
  11.133 +
  11.134 +int
  11.135 +SDL_TLSSet(SDL_TLSID id, const void *value)
  11.136 +{
  11.137 +    SDL_TLSData *data;
  11.138 +
  11.139 +    if (id <= 0) {
  11.140 +        return SDL_InvalidParamError(id);
  11.141 +    }
  11.142 +
  11.143 +    data = GetTLSData();
  11.144 +    if (!data || id > data->limit) {
  11.145 +        int i, oldlimit, newlimit;
  11.146 +
  11.147 +        oldlimit = data ? data->limit : 0;
  11.148 +        newlimit = (id + TLS_ALLOC_CHUNKSIZE);
  11.149 +        data = (SDL_TLSData *)SDL_realloc(data, sizeof(*data)+(newlimit-1)*sizeof(void*));
  11.150 +        if (!data) {
  11.151 +            return SDL_OutOfMemory();
  11.152 +        }
  11.153 +        data->limit = newlimit;
  11.154 +        for (i = oldlimit; i < newlimit; ++i) {
  11.155 +            data->data[i] = NULL;
  11.156 +        }
  11.157 +        if (SetTLSData(data) != 0) {
  11.158 +            return -1;
  11.159 +        }
  11.160 +    }
  11.161 +
  11.162 +    data->data[id-1] = SDL_const_cast(void*, value);
  11.163 +    return 0;
  11.164 +}
  11.165 +
  11.166 +/* vi: set ts=4 sw=4 expandtab: */
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/src/thread/pthread/SDL_systls.c	Wed Jul 10 02:32:04 2013 -0700
    12.3 @@ -0,0 +1,101 @@
    12.4 +/*
    12.5 +  Simple DirectMedia Layer
    12.6 +  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
    12.7 +
    12.8 +  This software is provided 'as-is', without any express or implied
    12.9 +  warranty.  In no event will the authors be held liable for any damages
   12.10 +  arising from the use of this software.
   12.11 +
   12.12 +  Permission is granted to anyone to use this software for any purpose,
   12.13 +  including commercial applications, and to alter it and redistribute it
   12.14 +  freely, subject to the following restrictions:
   12.15 +
   12.16 +  1. The origin of this software must not be misrepresented; you must not
   12.17 +     claim that you wrote the original software. If you use this software
   12.18 +     in a product, an acknowledgment in the product documentation would be
   12.19 +     appreciated but is not required.
   12.20 +  2. Altered source versions must be plainly marked as such, and must not be
   12.21 +     misrepresented as being the original software.
   12.22 +  3. This notice may not be removed or altered from any source distribution.
   12.23 +*/
   12.24 +
   12.25 +#include "SDL_config.h"
   12.26 +#include "SDL_thread.h"
   12.27 +
   12.28 +#include <pthread.h>
   12.29 +
   12.30 +
   12.31 +#define TLS_ALLOC_CHUNKSIZE 8
   12.32 +
   12.33 +typedef struct {
   12.34 +    int limit;
   12.35 +    void *data[1];
   12.36 +} SDL_TLSData;
   12.37 +
   12.38 +static SDL_SpinLock tls_lock;
   12.39 +static pthread_key_t thread_local_storage;
   12.40 +static SDL_atomic_t tls_id;
   12.41 +
   12.42 +
   12.43 +SDL_TLSID
   12.44 +SDL_TLSCreate()
   12.45 +{
   12.46 +    if (!thread_local_storage) {
   12.47 +        SDL_AtomicLock(&tls_lock);
   12.48 +        if (!thread_local_storage) {
   12.49 +            if (pthread_key_create(&thread_local_storage, NULL) != 0) {
   12.50 +                SDL_SetError("pthread_key_create() failed");
   12.51 +                SDL_AtomicUnlock(&tls_lock);
   12.52 +                return 0;
   12.53 +            }
   12.54 +        }
   12.55 +        SDL_AtomicUnlock(&tls_lock);
   12.56 +    }
   12.57 +    return SDL_AtomicIncRef(&tls_id)+1;
   12.58 +}
   12.59 +
   12.60 +void *
   12.61 +SDL_TLSGet(SDL_TLSID id)
   12.62 +{
   12.63 +    SDL_TLSData *data;
   12.64 +
   12.65 +    data = (SDL_TLSData *)pthread_getspecific(thread_local_storage);
   12.66 +    if (!data || id <= 0 || id > data->limit) {
   12.67 +        return NULL;
   12.68 +    }
   12.69 +    return data->data[id-1];
   12.70 +}
   12.71 +
   12.72 +int
   12.73 +SDL_TLSSet(SDL_TLSID id, const void *value)
   12.74 +{
   12.75 +    SDL_TLSData *data;
   12.76 +
   12.77 +    if (!thread_local_storage || id <= 0) {
   12.78 +        return SDL_InvalidParamError(id);
   12.79 +    }
   12.80 +
   12.81 +    data = (SDL_TLSData *)pthread_getspecific(thread_local_storage);
   12.82 +    if (!data || id > data->limit) {
   12.83 +        int i, oldlimit, newlimit;
   12.84 +
   12.85 +        oldlimit = data ? data->limit : 0;
   12.86 +        newlimit = (id + TLS_ALLOC_CHUNKSIZE);
   12.87 +        data = (SDL_TLSData *)SDL_realloc(data, sizeof(*data)+(newlimit-1)*sizeof(void*));
   12.88 +        if (!data) {
   12.89 +            return SDL_OutOfMemory();
   12.90 +        }
   12.91 +        data->limit = newlimit;
   12.92 +        for (i = oldlimit; i < newlimit; ++i) {
   12.93 +            data->data[i] = NULL;
   12.94 +        }
   12.95 +        if (pthread_setspecific(thread_local_storage, data) != 0) {
   12.96 +            return SDL_SetError("pthread_setspecific() failed");
   12.97 +        }
   12.98 +    }
   12.99 +
  12.100 +    data->data[id-1] = SDL_const_cast(void*, value);
  12.101 +    return 0;
  12.102 +}
  12.103 +
  12.104 +/* vi: set ts=4 sw=4 expandtab: */
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/src/thread/windows/SDL_systls.c	Wed Jul 10 02:32:04 2013 -0700
    13.3 @@ -0,0 +1,106 @@
    13.4 +/*
    13.5 +  Simple DirectMedia Layer
    13.6 +  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
    13.7 +
    13.8 +  This software is provided 'as-is', without any express or implied
    13.9 +  warranty.  In no event will the authors be held liable for any damages
   13.10 +  arising from the use of this software.
   13.11 +
   13.12 +  Permission is granted to anyone to use this software for any purpose,
   13.13 +  including commercial applications, and to alter it and redistribute it
   13.14 +  freely, subject to the following restrictions:
   13.15 +
   13.16 +  1. The origin of this software must not be misrepresented; you must not
   13.17 +     claim that you wrote the original software. If you use this software
   13.18 +     in a product, an acknowledgment in the product documentation would be
   13.19 +     appreciated but is not required.
   13.20 +  2. Altered source versions must be plainly marked as such, and must not be
   13.21 +     misrepresented as being the original software.
   13.22 +  3. This notice may not be removed or altered from any source distribution.
   13.23 +*/
   13.24 +
   13.25 +#include "SDL_config.h"
   13.26 +#include "SDL_thread.h"
   13.27 +
   13.28 +#if SDL_THREAD_WINDOWS
   13.29 +
   13.30 +#include "../../core/windows/SDL_windows.h"
   13.31 +
   13.32 +
   13.33 +#define TLS_ALLOC_CHUNKSIZE 8
   13.34 +
   13.35 +typedef struct {
   13.36 +    int limit;
   13.37 +    void *data[1];
   13.38 +} SDL_TLSData;
   13.39 +
   13.40 +static SDL_SpinLock tls_lock;
   13.41 +static DWORD thread_local_storage = TLS_OUT_OF_INDEXES;
   13.42 +static SDL_atomic_t tls_id;
   13.43 +
   13.44 +
   13.45 +SDL_TLSID
   13.46 +SDL_TLSCreate()
   13.47 +{
   13.48 +    if (thread_local_storage == TLS_OUT_OF_INDEXES) {
   13.49 +        SDL_AtomicLock(&tls_lock);
   13.50 +        if (thread_local_storage == TLS_OUT_OF_INDEXES) {
   13.51 +            thread_local_storage = TlsAlloc();
   13.52 +            if (thread_local_storage == TLS_OUT_OF_INDEXES) {
   13.53 +                SDL_SetError("TlsAlloc() failed");
   13.54 +                SDL_AtomicUnlock(&tls_lock);
   13.55 +                return 0;
   13.56 +            }
   13.57 +        }
   13.58 +        SDL_AtomicUnlock(&tls_lock);
   13.59 +    }
   13.60 +    return SDL_AtomicIncRef(&tls_id)+1;
   13.61 +}
   13.62 +
   13.63 +void *
   13.64 +SDL_TLSGet(SDL_TLSID id)
   13.65 +{
   13.66 +    SDL_TLSData *data;
   13.67 +
   13.68 +    data = (SDL_TLSData *)TlsGetValue(thread_local_storage);
   13.69 +    if (!data || id <= 0 || id > data->limit) {
   13.70 +        return NULL;
   13.71 +    }
   13.72 +    return data->data[id-1];
   13.73 +}
   13.74 +
   13.75 +int
   13.76 +SDL_TLSSet(SDL_TLSID id, const void *value)
   13.77 +{
   13.78 +    SDL_TLSData *data;
   13.79 +
   13.80 +    if (thread_local_storage == TLS_OUT_OF_INDEXES || id <= 0) {
   13.81 +        return SDL_InvalidParamError(id);
   13.82 +    }
   13.83 +
   13.84 +    data = (SDL_TLSData *)TlsGetValue(thread_local_storage);
   13.85 +    if (!data || id > data->limit) {
   13.86 +        int i, oldlimit, newlimit;
   13.87 +
   13.88 +        oldlimit = data ? data->limit : 0;
   13.89 +        newlimit = (id + TLS_ALLOC_CHUNKSIZE);
   13.90 +        data = (SDL_TLSData *)SDL_realloc(data, sizeof(*data)+(newlimit-1)*sizeof(void*));
   13.91 +        if (!data) {
   13.92 +            return SDL_OutOfMemory();
   13.93 +        }
   13.94 +        data->limit = newlimit;
   13.95 +        for (i = oldlimit; i < newlimit; ++i) {
   13.96 +            data->data[i] = NULL;
   13.97 +        }
   13.98 +        if (!TlsSetValue(thread_local_storage, data)) {
   13.99 +            return SDL_SetError("TlsSetValue() failed");
  13.100 +        }
  13.101 +    }
  13.102 +
  13.103 +    data->data[id-1] = SDL_const_cast(void*, value);
  13.104 +    return 0;
  13.105 +}
  13.106 +
  13.107 +#endif /* SDL_THREAD_WINDOWS */
  13.108 +
  13.109 +/* vi: set ts=4 sw=4 expandtab: */
    14.1 --- a/test/testthread.c	Tue Jul 09 12:58:54 2013 -0700
    14.2 +++ b/test/testthread.c	Wed Jul 10 02:32:04 2013 -0700
    14.3 @@ -19,6 +19,7 @@
    14.4  #include "SDL.h"
    14.5  #include "SDL_thread.h"
    14.6  
    14.7 +static SDL_TLSID tls;
    14.8  static int alive = 0;
    14.9  
   14.10  /* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
   14.11 @@ -32,8 +33,9 @@
   14.12  int SDLCALL
   14.13  ThreadFunc(void *data)
   14.14  {
   14.15 -    printf("Started thread %s: My thread id is %lu\n",
   14.16 -           (char *) data, SDL_ThreadID());
   14.17 +    SDL_TLSSet(tls, "baby thread");
   14.18 +    printf("Started thread %s: My thread id is %lu, thread data = %s\n",
   14.19 +           (char *) data, SDL_ThreadID(), (const char *)SDL_TLSGet(tls));
   14.20      while (alive) {
   14.21          printf("Thread '%s' is alive!\n", (char *) data);
   14.22          SDL_Delay(1 * 1000);
   14.23 @@ -62,6 +64,11 @@
   14.24          return (1);
   14.25      }
   14.26  
   14.27 +    tls = SDL_TLSCreate();
   14.28 +    SDL_assert(tls);
   14.29 +    SDL_TLSSet(tls, "main thread");
   14.30 +    printf("Main thread data initially: %s\n", (const char *)SDL_TLSGet(tls));
   14.31 +
   14.32      alive = 1;
   14.33      thread = SDL_CreateThread(ThreadFunc, "One", "#1");
   14.34      if (thread == NULL) {
   14.35 @@ -73,6 +80,8 @@
   14.36      alive = 0;
   14.37      SDL_WaitThread(thread, NULL);
   14.38  
   14.39 +    printf("Main thread data finally: %s\n", (const char *)SDL_TLSGet(tls));
   14.40 +
   14.41      alive = 1;
   14.42      signal(SIGTERM, killed);
   14.43      thread = SDL_CreateThread(ThreadFunc, "Two", "#2");