src/thread/pthread/SDL_systls.c
changeset 7393 358696c354a8
parent 7391 a29895dc5e9a
child 8093 b43765095a6f
equal deleted inserted replaced
7392:7e32fcb41b44 7393:358696c354a8
    16      appreciated but is not required.
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    20 */
    21 
       
    22 #include "SDL_config.h"
    21 #include "SDL_config.h"
    23 #include "SDL_thread.h"
    22 #include "SDL_thread.h"
       
    23 #include "../SDL_thread_c.h"
    24 
    24 
    25 #include <pthread.h>
    25 #include <pthread.h>
    26 
    26 
    27 
    27 
    28 #define TLS_ALLOC_CHUNKSIZE 8
    28 #define INVALID_PTHREAD_KEY ((pthread_key_t)-1)
    29 
    29 
    30 typedef struct {
    30 static pthread_key_t thread_local_storage = INVALID_PTHREAD_KEY;
    31     int limit;
    31 static SDL_bool generic_local_storage = SDL_FALSE;
    32     void *data[1];
       
    33 } SDL_TLSData;
       
    34 
    32 
    35 static SDL_SpinLock tls_lock;
    33 SDL_TLSData *
    36 static pthread_key_t thread_local_storage;
    34 SDL_SYS_GetTLSData()
    37 static SDL_atomic_t tls_id;
       
    38 
       
    39 
       
    40 SDL_TLSID
       
    41 SDL_TLSCreate()
       
    42 {
    35 {
    43     if (!thread_local_storage) {
    36     if (thread_local_storage == INVALID_PTHREAD_KEY && !generic_local_storage) {
    44         SDL_AtomicLock(&tls_lock);
    37         static SDL_SpinLock lock;
    45         if (!thread_local_storage) {
    38         SDL_AtomicLock(&lock);
    46             if (pthread_key_create(&thread_local_storage, NULL) != 0) {
    39         if (thread_local_storage == INVALID_PTHREAD_KEY && !generic_local_storage) {
    47                 SDL_SetError("pthread_key_create() failed");
    40             pthread_key_t storage;
    48                 SDL_AtomicUnlock(&tls_lock);
    41             if (pthread_key_create(&storage, NULL) == 0) {
    49                 return 0;
    42                 SDL_MemoryBarrierRelease();
       
    43                 thread_local_storage = storage;
       
    44             } else {
       
    45                 generic_local_storage = SDL_TRUE;
    50             }
    46             }
    51         }
    47         }
    52         SDL_AtomicUnlock(&tls_lock);
    48         SDL_AtomicUnlock(&lock);
    53     }
    49     }
    54     return SDL_AtomicIncRef(&tls_id)+1;
    50     if (generic_local_storage) {
    55 }
    51         return SDL_Generic_GetTLSData();
    56 
       
    57 void *
       
    58 SDL_TLSGet(SDL_TLSID id)
       
    59 {
       
    60     SDL_TLSData *data;
       
    61 
       
    62     data = (SDL_TLSData *)pthread_getspecific(thread_local_storage);
       
    63     if (!data || id <= 0 || id > data->limit) {
       
    64         return NULL;
       
    65     }
    52     }
    66     return data->data[id-1];
    53     SDL_MemoryBarrierAcquire();
       
    54     return (SDL_TLSData *)pthread_getspecific(thread_local_storage);
    67 }
    55 }
    68 
    56 
    69 int
    57 int
    70 SDL_TLSSet(SDL_TLSID id, const void *value)
    58 SDL_SYS_SetTLSData(SDL_TLSData *data)
    71 {
    59 {
    72     SDL_TLSData *data;
    60     if (generic_local_storage) {
    73 
    61         return SDL_Generic_SetTLSData(data);
    74     if (!thread_local_storage || id <= 0) {
       
    75         return SDL_InvalidParamError(id);
       
    76     }
    62     }
    77 
    63     if (pthread_setspecific(thread_local_storage, data) != 0) {
    78     data = (SDL_TLSData *)pthread_getspecific(thread_local_storage);
    64         return SDL_SetError("pthread_setspecific() failed");
    79     if (!data || id > data->limit) {
       
    80         int i, oldlimit, newlimit;
       
    81 
       
    82         oldlimit = data ? data->limit : 0;
       
    83         newlimit = (id + TLS_ALLOC_CHUNKSIZE);
       
    84         data = (SDL_TLSData *)SDL_realloc(data, sizeof(*data)+(newlimit-1)*sizeof(void*));
       
    85         if (!data) {
       
    86             return SDL_OutOfMemory();
       
    87         }
       
    88         data->limit = newlimit;
       
    89         for (i = oldlimit; i < newlimit; ++i) {
       
    90             data->data[i] = NULL;
       
    91         }
       
    92         if (pthread_setspecific(thread_local_storage, data) != 0) {
       
    93             return SDL_SetError("pthread_setspecific() failed");
       
    94         }
       
    95     }
    65     }
    96 
       
    97     data->data[id-1] = SDL_const_cast(void*, value);
       
    98     return 0;
    66     return 0;
    99 }
    67 }
   100 
    68 
   101 /* vi: set ts=4 sw=4 expandtab: */
    69 /* vi: set ts=4 sw=4 expandtab: */