/* Routine to get the thread-specific error variable */
SDL_error *
SDL_GetErrBuf(void)
{
    static SDL_SpinLock tls_lock;
    static SDL_bool tls_being_created;
    static SDL_TLSID tls_errbuf;
    static SDL_error SDL_global_errbuf;
    const SDL_error *ALLOCATION_IN_PROGRESS = (SDL_error *)-1;
    SDL_error *errbuf;

    /* tls_being_created is there simply to prevent recursion if SDL_TLSCreate() fails.
       It also means it's possible for another thread to also use SDL_global_errbuf,
       but that's very unlikely and hopefully won't cause issues.
     */
    if (!tls_errbuf && !tls_being_created) {
        SDL_AtomicLock(&tls_lock);
        if (!tls_errbuf) {
            SDL_TLSID slot;
            tls_being_created = SDL_TRUE;
            slot = SDL_TLSCreate();
            tls_being_created = SDL_FALSE;
            SDL_MemoryBarrierRelease();
            tls_errbuf = slot;
        }
        SDL_AtomicUnlock(&tls_lock);
    }
    if (!tls_errbuf) {
        return &SDL_global_errbuf;
    }

    SDL_MemoryBarrierAcquire();
    errbuf = (SDL_error *)SDL_TLSGet(tls_errbuf);
    if (errbuf == ALLOCATION_IN_PROGRESS) {
        return &SDL_global_errbuf;
    }
    if (!errbuf) {
        /* Mark that we're in the middle of allocating our buffer */
        SDL_TLSSet(tls_errbuf, ALLOCATION_IN_PROGRESS, NULL);
        errbuf = (SDL_error *)SDL_malloc(sizeof(*errbuf));
        if (!errbuf) {
            SDL_TLSSet(tls_errbuf, NULL, NULL);
            return &SDL_global_errbuf;
        }
        SDL_zerop(errbuf);
        SDL_TLSSet(tls_errbuf, errbuf, SDL_free);
    }
    return errbuf;
}
SDL_TLSData *
SDL_Generic_GetTLSData()
{
    SDL_threadID thread = SDL_ThreadID();
    SDL_TLSEntry *entry;
    SDL_TLSData *storage = NULL;

#if !SDL_THREADS_DISABLED
    if (!SDL_generic_TLS_mutex) {
        static SDL_SpinLock tls_lock;
        SDL_AtomicLock(&tls_lock);
        if (!SDL_generic_TLS_mutex) {
            SDL_mutex *mutex = SDL_CreateMutex();
            SDL_MemoryBarrierRelease();
            SDL_generic_TLS_mutex = mutex;
            if (!SDL_generic_TLS_mutex) {
                SDL_AtomicUnlock(&tls_lock);
                return NULL;
            }
        }
        SDL_AtomicUnlock(&tls_lock);
    }
#endif /* SDL_THREADS_DISABLED */

    SDL_MemoryBarrierAcquire();
    SDL_LockMutex(SDL_generic_TLS_mutex);
    for (entry = SDL_generic_TLS; entry; entry = entry->next) {
        if (entry->thread == thread) {
            storage = entry->storage;
            break;
        }
    }
#if !SDL_THREADS_DISABLED
    SDL_UnlockMutex(SDL_generic_TLS_mutex);
#endif

    return storage;
}
Example #3
0
SDL_TLSData *
SDL_SYS_GetTLSData()
{
    if (thread_local_storage == TLS_OUT_OF_INDEXES && !generic_local_storage) {
        static SDL_SpinLock lock;
        SDL_AtomicLock(&lock);
        if (thread_local_storage == TLS_OUT_OF_INDEXES && !generic_local_storage) {
            DWORD storage = TlsAlloc();
            if (storage != TLS_OUT_OF_INDEXES) {
                SDL_MemoryBarrierRelease();
                thread_local_storage = storage;
            } else {
                generic_local_storage = SDL_TRUE;
            }
        }
        SDL_AtomicUnlock(&lock);
    }
    if (generic_local_storage) {
        return SDL_Generic_GetTLSData();
    }
    SDL_MemoryBarrierAcquire();
    return (SDL_TLSData *)TlsGetValue(thread_local_storage);
}
Example #4
0
SDL_TLSData *
SDL_SYS_GetTLSData()
{
    if (thread_local_storage == INVALID_PTHREAD_KEY && !generic_local_storage) {
        static SDL_SpinLock lock;
        SDL_AtomicLock(&lock);
        if (thread_local_storage == INVALID_PTHREAD_KEY && !generic_local_storage) {
            pthread_key_t storage;
            if (pthread_key_create(&storage, NULL) == 0) {
                SDL_MemoryBarrierRelease();
                thread_local_storage = storage;
            } else {
                generic_local_storage = SDL_TRUE;
            }
        }
        SDL_AtomicUnlock(&lock);
    }
    if (generic_local_storage) {
        return SDL_Generic_GetTLSData();
    }
    SDL_MemoryBarrierAcquire();
    return (SDL_TLSData *)pthread_getspecific(thread_local_storage);
}