src/thread/SDL_thread.c
changeset 7391 a29895dc5e9a
parent 7191 75360622e65f
child 7393 358696c354a8
     1.1 --- a/src/thread/SDL_thread.c	Tue Jul 09 12:58:54 2013 -0700
     1.2 +++ b/src/thread/SDL_thread.c	Wed Jul 10 02:32:04 2013 -0700
     1.3 @@ -22,158 +22,46 @@
     1.4  
     1.5  /* System independent thread management routines for SDL */
     1.6  
     1.7 -#include "SDL_mutex.h"
     1.8  #include "SDL_thread.h"
     1.9  #include "SDL_thread_c.h"
    1.10  #include "SDL_systhread.h"
    1.11  #include "../SDL_error_c.h"
    1.12  
    1.13 -#define ARRAY_CHUNKSIZE 32
    1.14 -/* The array of threads currently active in the application
    1.15 -   (except the main thread)
    1.16 -   The manipulation of an array here is safer than using a linked list.
    1.17 -*/
    1.18 -static int SDL_maxthreads = 0;
    1.19 -static int SDL_numthreads = 0;
    1.20 -static SDL_Thread **SDL_Threads = NULL;
    1.21 -static SDL_mutex *thread_lock = NULL;
    1.22 -
    1.23 -static int
    1.24 -SDL_ThreadsInit(void)
    1.25 -{
    1.26 -    int retval;
    1.27 -
    1.28 -    retval = 0;
    1.29 -    thread_lock = SDL_CreateMutex();
    1.30 -    if (thread_lock == NULL) {
    1.31 -        retval = -1;
    1.32 -    }
    1.33 -    return (retval);
    1.34 -}
    1.35 -
    1.36 -/* This should never be called...
    1.37 -   If this is called by SDL_Quit(), we don't know whether or not we should
    1.38 -   clean up threads here.  If any threads are still running after this call,
    1.39 -   they will no longer have access to any per-thread data.
    1.40 - */
    1.41 -#if 0
    1.42 -static void
    1.43 -SDL_ThreadsQuit(void)
    1.44 -{
    1.45 -    SDL_mutex *mutex;
    1.46 -
    1.47 -    mutex = thread_lock;
    1.48 -    thread_lock = NULL;
    1.49 -    if (mutex != NULL) {
    1.50 -        SDL_DestroyMutex(mutex);
    1.51 -    }
    1.52 -}
    1.53 -#endif
    1.54 -
    1.55 -/* Routines for manipulating the thread list */
    1.56 -static void
    1.57 -SDL_AddThread(SDL_Thread * thread)
    1.58 -{
    1.59 -    /* WARNING:
    1.60 -       If the very first threads are created simultaneously, then
    1.61 -       there could be a race condition causing memory corruption.
    1.62 -       In practice, this isn't a problem because by definition there
    1.63 -       is only one thread running the first time this is called.
    1.64 -     */
    1.65 -    if (!thread_lock) {
    1.66 -        if (SDL_ThreadsInit() < 0) {
    1.67 -            return;
    1.68 -        }
    1.69 -    }
    1.70 -    SDL_LockMutex(thread_lock);
    1.71 -
    1.72 -    /* Expand the list of threads, if necessary */
    1.73 -#ifdef DEBUG_THREADS
    1.74 -    printf("Adding thread (%d already - %d max)\n",
    1.75 -           SDL_numthreads, SDL_maxthreads);
    1.76 -#endif
    1.77 -    if (SDL_numthreads == SDL_maxthreads) {
    1.78 -        SDL_Thread **threads;
    1.79 -        threads = (SDL_Thread **) SDL_realloc(SDL_Threads,
    1.80 -                                              (SDL_maxthreads +
    1.81 -                                               ARRAY_CHUNKSIZE) *
    1.82 -                                              (sizeof *threads));
    1.83 -        if (threads == NULL) {
    1.84 -            SDL_OutOfMemory();
    1.85 -            goto done;
    1.86 -        }
    1.87 -        SDL_maxthreads += ARRAY_CHUNKSIZE;
    1.88 -        SDL_Threads = threads;
    1.89 -    }
    1.90 -    SDL_Threads[SDL_numthreads++] = thread;
    1.91 -  done:
    1.92 -    SDL_mutexV(thread_lock);
    1.93 -}
    1.94 -
    1.95 -static void
    1.96 -SDL_DelThread(SDL_Thread * thread)
    1.97 -{
    1.98 -    int i;
    1.99 -
   1.100 -    if (!thread_lock) {
   1.101 -        return;
   1.102 -    }
   1.103 -    SDL_LockMutex(thread_lock);
   1.104 -    for (i = 0; i < SDL_numthreads; ++i) {
   1.105 -        if (thread == SDL_Threads[i]) {
   1.106 -            break;
   1.107 -        }
   1.108 -    }
   1.109 -    if (i < SDL_numthreads) {
   1.110 -        if (--SDL_numthreads > 0) {
   1.111 -            while (i < SDL_numthreads) {
   1.112 -                SDL_Threads[i] = SDL_Threads[i + 1];
   1.113 -                ++i;
   1.114 -            }
   1.115 -        } else {
   1.116 -            SDL_maxthreads = 0;
   1.117 -            SDL_free(SDL_Threads);
   1.118 -            SDL_Threads = NULL;
   1.119 -        }
   1.120 -#ifdef DEBUG_THREADS
   1.121 -        printf("Deleting thread (%d left - %d max)\n",
   1.122 -               SDL_numthreads, SDL_maxthreads);
   1.123 -#endif
   1.124 -    }
   1.125 -    SDL_mutexV(thread_lock);
   1.126 -
   1.127 -#if 0   /* There could be memory corruption if another thread is starting */
   1.128 -    if (SDL_Threads == NULL) {
   1.129 -        SDL_ThreadsQuit();
   1.130 -    }
   1.131 -#endif
   1.132 -}
   1.133 -
   1.134 -/* The default (non-thread-safe) global error variable */
   1.135 -static SDL_error SDL_global_error;
   1.136  
   1.137  /* Routine to get the thread-specific error variable */
   1.138  SDL_error *
   1.139  SDL_GetErrBuf(void)
   1.140  {
   1.141 +    static SDL_SpinLock spinlock;
   1.142 +    static SDL_bool tls_being_created;
   1.143 +    static SDL_TLSID tls_errbuf;
   1.144 +    static SDL_error SDL_global_errbuf;
   1.145      SDL_error *errbuf;
   1.146  
   1.147 -    errbuf = &SDL_global_error;
   1.148 -    if (SDL_Threads) {
   1.149 -        int i;
   1.150 -        SDL_threadID this_thread;
   1.151 +    if (!tls_errbuf && !tls_being_created) {
   1.152 +        SDL_AtomicLock(&spinlock);
   1.153 +        if (!tls_errbuf) {
   1.154 +            /* SDL_TLSCreate() could fail and call SDL_SetError() */
   1.155 +            tls_being_created = SDL_TRUE;
   1.156 +            tls_errbuf = SDL_TLSCreate();
   1.157 +            tls_being_created = SDL_FALSE;
   1.158 +        }
   1.159 +        SDL_AtomicUnlock(&spinlock);
   1.160 +    }
   1.161 +    if (!tls_errbuf) {
   1.162 +        return &SDL_global_errbuf;
   1.163 +    }
   1.164  
   1.165 -        this_thread = SDL_ThreadID();
   1.166 -        SDL_LockMutex(thread_lock);
   1.167 -        for (i = 0; i < SDL_numthreads; ++i) {
   1.168 -            if (this_thread == SDL_Threads[i]->threadid) {
   1.169 -                errbuf = &SDL_Threads[i]->errbuf;
   1.170 -                break;
   1.171 -            }
   1.172 +    errbuf = SDL_TLSGet(tls_errbuf);
   1.173 +    if (!errbuf) {
   1.174 +        errbuf = (SDL_error *)SDL_malloc(sizeof(*errbuf));
   1.175 +        if (!errbuf) {
   1.176 +            return &SDL_global_errbuf;
   1.177          }
   1.178 -        SDL_mutexV(thread_lock);
   1.179 +        SDL_zerop(errbuf);
   1.180 +        SDL_TLSSet(tls_errbuf, errbuf);
   1.181      }
   1.182 -    return (errbuf);
   1.183 +    return errbuf;
   1.184  }
   1.185  
   1.186  
   1.187 @@ -264,9 +152,6 @@
   1.188          return (NULL);
   1.189      }
   1.190  
   1.191 -    /* Add the thread to the list of available threads */
   1.192 -    SDL_AddThread(thread);
   1.193 -
   1.194      /* Create the thread and go! */
   1.195  #ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
   1.196      ret = SDL_SYS_CreateThread(thread, args, pfnBeginThread, pfnEndThread);
   1.197 @@ -278,7 +163,6 @@
   1.198          SDL_SemWait(args->wait);
   1.199      } else {
   1.200          /* Oops, failed.  Gotta free everything */
   1.201 -        SDL_DelThread(thread);
   1.202          SDL_free(thread->name);
   1.203          SDL_free(thread);
   1.204          thread = NULL;
   1.205 @@ -323,7 +207,6 @@
   1.206          if (status) {
   1.207              *status = thread->status;
   1.208          }
   1.209 -        SDL_DelThread(thread);
   1.210          SDL_free(thread->name);
   1.211          SDL_free(thread);
   1.212      }