// // Copyright 2014 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // // tls.h: Simple cross-platform interface for thread local storage. #ifndef COMMON_TLS_H_ #define COMMON_TLS_H_ #include "common/angleutils.h" #include "common/platform.h" #if defined(ANGLE_PLATFORM_POSIX) # include # include # include #elif defined(ANGLE_PLATFORM_WINDOWS) # include #endif namespace gl { class Context; } namespace angle { #ifdef ANGLE_PLATFORM_WINDOWS // TLS does not exist for Windows Store and needs to be emulated # ifdef ANGLE_ENABLE_WINDOWS_UWP # ifndef TLS_OUT_OF_INDEXES # define TLS_OUT_OF_INDEXES static_cast(0xFFFFFFFF) # endif # ifndef CREATE_SUSPENDED # define CREATE_SUSPENDED 0x00000004 # endif # endif typedef DWORD TLSIndex; # define TLS_INVALID_INDEX (TLS_OUT_OF_INDEXES) #elif defined(ANGLE_PLATFORM_POSIX) typedef pthread_key_t TLSIndex; # define TLS_INVALID_INDEX (static_cast(-1)) #else # error Unsupported platform. #endif #if defined(ANGLE_PLATFORM_ANDROID) // TLS_SLOT_OPENGL and TLS_SLOT_OPENGL_API aren't used by bionic itself, but allow the graphics code // to access TLS directly rather than using the pthread API. // // Choose the TLS_SLOT_OPENGL TLS slot with the value that matches value in the header file in // bionic(tls_defines.h). Note that this slot cannot be used when the GLES backend of is in use. # if defined(__arm__) || defined(__aarch64__) constexpr size_t kAndroidOpenGLTlsSlot = 3; # elif defined(__i386__) || defined(__x86_64__) constexpr size_t kAndroidOpenGLTlsSlot = 3; # elif defined(__riscv) constexpr int kAndroidOpenGLTlsSlot = -5; # else # error Unsupported platform. # endif // The following ASM variant provides a much more performant store/retrieve interface // compared to those provided by the pthread library. These have been derived from code // in the bionic module of Android -> // https://cs.android.com/android/platform/superproject/+/master:bionic/libc/platform/bionic/tls.h;l=30 # if defined(__aarch64__) # define ANGLE_ANDROID_GET_GL_TLS() \ ({ \ void **__val; \ __asm__("mrs %0, tpidr_el0" : "=r"(__val)); \ __val; \ }) # elif defined(__arm__) # define ANGLE_ANDROID_GET_GL_TLS() \ ({ \ void **__val; \ __asm__("mrc p15, 0, %0, c13, c0, 3" : "=r"(__val)); \ __val; \ }) # elif defined(__mips__) // On mips32r1, this goes via a kernel illegal instruction trap that's // optimized for v1 # define ANGLE_ANDROID_GET_GL_TLS() \ ({ \ register void **__val asm("v1"); \ __asm__( \ ".set push\n" \ ".set mips32r2\n" \ "rdhwr %0,$29\n" \ ".set pop\n" \ : "=r"(__val)); \ __val; \ }) # elif defined(__i386__) # define ANGLE_ANDROID_GET_GL_TLS() \ ({ \ void **__val; \ __asm__("movl %%gs:0, %0" : "=r"(__val)); \ __val; \ }) # elif defined(__x86_64__) # define ANGLE_ANDROID_GET_GL_TLS() \ ({ \ void **__val; \ __asm__("mov %%fs:0, %0" : "=r"(__val)); \ __val; \ }) # elif defined(__riscv) # define ANGLE_ANDROID_GET_GL_TLS() \ ({ \ void **__val; \ __asm__("mv %0, tp" : "=r"(__val)); \ __val; \ }) # else # error unsupported architecture # endif #endif // ANGLE_PLATFORM_ANDROID using PthreadKeyDestructor = void (*)(void *); TLSIndex CreateTLSIndex(PthreadKeyDestructor destructor); bool DestroyTLSIndex(TLSIndex index); bool SetTLSValue(TLSIndex index, void *value); void *GetTLSValue(TLSIndex index); } // namespace angle #endif // COMMON_TLS_H_