src/thread/pthread/SDL_systls.c
changeset 7393 358696c354a8
parent 7391 a29895dc5e9a
child 8093 b43765095a6f
     1.1 --- a/src/thread/pthread/SDL_systls.c	Wed Jul 10 02:37:57 2013 -0700
     1.2 +++ b/src/thread/pthread/SDL_systls.c	Wed Jul 10 18:31:17 2013 -0700
     1.3 @@ -18,83 +18,51 @@
     1.4       misrepresented as being the original software.
     1.5    3. This notice may not be removed or altered from any source distribution.
     1.6  */
     1.7 -
     1.8  #include "SDL_config.h"
     1.9  #include "SDL_thread.h"
    1.10 +#include "../SDL_thread_c.h"
    1.11  
    1.12  #include <pthread.h>
    1.13  
    1.14  
    1.15 -#define TLS_ALLOC_CHUNKSIZE 8
    1.16 +#define INVALID_PTHREAD_KEY ((pthread_key_t)-1)
    1.17  
    1.18 -typedef struct {
    1.19 -    int limit;
    1.20 -    void *data[1];
    1.21 -} SDL_TLSData;
    1.22 +static pthread_key_t thread_local_storage = INVALID_PTHREAD_KEY;
    1.23 +static SDL_bool generic_local_storage = SDL_FALSE;
    1.24  
    1.25 -static SDL_SpinLock tls_lock;
    1.26 -static pthread_key_t thread_local_storage;
    1.27 -static SDL_atomic_t tls_id;
    1.28 -
    1.29 -
    1.30 -SDL_TLSID
    1.31 -SDL_TLSCreate()
    1.32 +SDL_TLSData *
    1.33 +SDL_SYS_GetTLSData()
    1.34  {
    1.35 -    if (!thread_local_storage) {
    1.36 -        SDL_AtomicLock(&tls_lock);
    1.37 -        if (!thread_local_storage) {
    1.38 -            if (pthread_key_create(&thread_local_storage, NULL) != 0) {
    1.39 -                SDL_SetError("pthread_key_create() failed");
    1.40 -                SDL_AtomicUnlock(&tls_lock);
    1.41 -                return 0;
    1.42 +    if (thread_local_storage == INVALID_PTHREAD_KEY && !generic_local_storage) {
    1.43 +        static SDL_SpinLock lock;
    1.44 +        SDL_AtomicLock(&lock);
    1.45 +        if (thread_local_storage == INVALID_PTHREAD_KEY && !generic_local_storage) {
    1.46 +            pthread_key_t storage;
    1.47 +            if (pthread_key_create(&storage, NULL) == 0) {
    1.48 +                SDL_MemoryBarrierRelease();
    1.49 +                thread_local_storage = storage;
    1.50 +            } else {
    1.51 +                generic_local_storage = SDL_TRUE;
    1.52              }
    1.53          }
    1.54 -        SDL_AtomicUnlock(&tls_lock);
    1.55 +        SDL_AtomicUnlock(&lock);
    1.56      }
    1.57 -    return SDL_AtomicIncRef(&tls_id)+1;
    1.58 -}
    1.59 -
    1.60 -void *
    1.61 -SDL_TLSGet(SDL_TLSID id)
    1.62 -{
    1.63 -    SDL_TLSData *data;
    1.64 -
    1.65 -    data = (SDL_TLSData *)pthread_getspecific(thread_local_storage);
    1.66 -    if (!data || id <= 0 || id > data->limit) {
    1.67 -        return NULL;
    1.68 +    if (generic_local_storage) {
    1.69 +        return SDL_Generic_GetTLSData();
    1.70      }
    1.71 -    return data->data[id-1];
    1.72 +    SDL_MemoryBarrierAcquire();
    1.73 +    return (SDL_TLSData *)pthread_getspecific(thread_local_storage);
    1.74  }
    1.75  
    1.76  int
    1.77 -SDL_TLSSet(SDL_TLSID id, const void *value)
    1.78 +SDL_SYS_SetTLSData(SDL_TLSData *data)
    1.79  {
    1.80 -    SDL_TLSData *data;
    1.81 -
    1.82 -    if (!thread_local_storage || id <= 0) {
    1.83 -        return SDL_InvalidParamError(id);
    1.84 +    if (generic_local_storage) {
    1.85 +        return SDL_Generic_SetTLSData(data);
    1.86      }
    1.87 -
    1.88 -    data = (SDL_TLSData *)pthread_getspecific(thread_local_storage);
    1.89 -    if (!data || id > data->limit) {
    1.90 -        int i, oldlimit, newlimit;
    1.91 -
    1.92 -        oldlimit = data ? data->limit : 0;
    1.93 -        newlimit = (id + TLS_ALLOC_CHUNKSIZE);
    1.94 -        data = (SDL_TLSData *)SDL_realloc(data, sizeof(*data)+(newlimit-1)*sizeof(void*));
    1.95 -        if (!data) {
    1.96 -            return SDL_OutOfMemory();
    1.97 -        }
    1.98 -        data->limit = newlimit;
    1.99 -        for (i = oldlimit; i < newlimit; ++i) {
   1.100 -            data->data[i] = NULL;
   1.101 -        }
   1.102 -        if (pthread_setspecific(thread_local_storage, data) != 0) {
   1.103 -            return SDL_SetError("pthread_setspecific() failed");
   1.104 -        }
   1.105 +    if (pthread_setspecific(thread_local_storage, data) != 0) {
   1.106 +        return SDL_SetError("pthread_setspecific() failed");
   1.107      }
   1.108 -
   1.109 -    data->data[id-1] = SDL_const_cast(void*, value);
   1.110      return 0;
   1.111  }
   1.112