1ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com#include "SkTLS.h" 2ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com 3b9afafaa9e7dacb1371edc109a4ba7d0d4ce7369reed@google.com// enable to help debug TLS storage 4b9afafaa9e7dacb1371edc109a4ba7d0d4ce7369reed@google.com//#define SK_TRACE_TLS_LIFETIME 5b9afafaa9e7dacb1371edc109a4ba7d0d4ce7369reed@google.com 6b9afafaa9e7dacb1371edc109a4ba7d0d4ce7369reed@google.com 7b9afafaa9e7dacb1371edc109a4ba7d0d4ce7369reed@google.com#ifdef SK_TRACE_TLS_LIFETIME 8b9afafaa9e7dacb1371edc109a4ba7d0d4ce7369reed@google.com #include "SkThread.h" 9b9afafaa9e7dacb1371edc109a4ba7d0d4ce7369reed@google.com static int32_t gTLSRecCount; 10b9afafaa9e7dacb1371edc109a4ba7d0d4ce7369reed@google.com#endif 11b9afafaa9e7dacb1371edc109a4ba7d0d4ce7369reed@google.com 12ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.comstruct SkTLSRec { 13ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com SkTLSRec* fNext; 14ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com void* fData; 15ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com SkTLS::CreateProc fCreateProc; 16ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com SkTLS::DeleteProc fDeleteProc; 17ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com 18b9afafaa9e7dacb1371edc109a4ba7d0d4ce7369reed@google.com#ifdef SK_TRACE_TLS_LIFETIME 19b9afafaa9e7dacb1371edc109a4ba7d0d4ce7369reed@google.com SkTLSRec() { 20b9afafaa9e7dacb1371edc109a4ba7d0d4ce7369reed@google.com int n = sk_atomic_inc(&gTLSRecCount); 21b9afafaa9e7dacb1371edc109a4ba7d0d4ce7369reed@google.com SkDebugf(" SkTLSRec[%d]\n", n); 22b9afafaa9e7dacb1371edc109a4ba7d0d4ce7369reed@google.com } 23b9afafaa9e7dacb1371edc109a4ba7d0d4ce7369reed@google.com#endif 24b9afafaa9e7dacb1371edc109a4ba7d0d4ce7369reed@google.com 25ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com ~SkTLSRec() { 26ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com if (fDeleteProc) { 27ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com fDeleteProc(fData); 28ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com } 29ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com // else we leak fData, or it will be managed by the caller 30b9afafaa9e7dacb1371edc109a4ba7d0d4ce7369reed@google.com 31b9afafaa9e7dacb1371edc109a4ba7d0d4ce7369reed@google.com#ifdef SK_TRACE_TLS_LIFETIME 32b9afafaa9e7dacb1371edc109a4ba7d0d4ce7369reed@google.com int n = sk_atomic_dec(&gTLSRecCount); 33b9afafaa9e7dacb1371edc109a4ba7d0d4ce7369reed@google.com SkDebugf("~SkTLSRec[%d]\n", n - 1); 34b9afafaa9e7dacb1371edc109a4ba7d0d4ce7369reed@google.com#endif 35ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com } 36ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com}; 37ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com 38ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.comvoid SkTLS::Destructor(void* ptr) { 39b9afafaa9e7dacb1371edc109a4ba7d0d4ce7369reed@google.com#ifdef SK_TRACE_TLS_LIFETIME 40b9afafaa9e7dacb1371edc109a4ba7d0d4ce7369reed@google.com SkDebugf("SkTLS::Destructor(%p)\n", ptr); 41b9afafaa9e7dacb1371edc109a4ba7d0d4ce7369reed@google.com#endif 42b9afafaa9e7dacb1371edc109a4ba7d0d4ce7369reed@google.com 43ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com SkTLSRec* rec = (SkTLSRec*)ptr; 44ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com do { 45ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com SkTLSRec* next = rec->fNext; 46ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com SkDELETE(rec); 47ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com rec = next; 48ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com } while (NULL != rec); 49ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com} 50ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com 51ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.comvoid* SkTLS::Get(CreateProc createProc, DeleteProc deleteProc) { 52ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com if (NULL == createProc) { 53ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com return NULL; 54ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com } 55ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com 56be82fae824622779a4682a2598baab62c0027a0dreed@google.com void* ptr = SkTLS::PlatformGetSpecific(true); 57ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com 58ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com if (ptr) { 59ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com const SkTLSRec* rec = (const SkTLSRec*)ptr; 60ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com do { 61ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com if (rec->fCreateProc == createProc) { 62ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com SkASSERT(rec->fDeleteProc == deleteProc); 63ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com return rec->fData; 64ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com } 65ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com } while ((rec = rec->fNext) != NULL); 66ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com // not found, so create a new one 67ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com } 68935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com 69ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com // add a new head of our change 70ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com SkTLSRec* rec = new SkTLSRec; 71ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com rec->fNext = (SkTLSRec*)ptr; 72ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com 73ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com SkTLS::PlatformSetSpecific(rec); 74ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com 75ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com rec->fData = createProc(); 76ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com rec->fCreateProc = createProc; 77ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com rec->fDeleteProc = deleteProc; 78ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com return rec->fData; 79ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com} 80ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com 81ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.comvoid* SkTLS::Find(CreateProc createProc) { 82ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com if (NULL == createProc) { 83ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com return NULL; 84ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com } 85935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com 86be82fae824622779a4682a2598baab62c0027a0dreed@google.com void* ptr = SkTLS::PlatformGetSpecific(false); 87ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com 88ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com if (ptr) { 89ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com const SkTLSRec* rec = (const SkTLSRec*)ptr; 90ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com do { 91ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com if (rec->fCreateProc == createProc) { 92ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com return rec->fData; 93ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com } 94ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com } while ((rec = rec->fNext) != NULL); 95ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com } 96ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com return NULL; 97ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com} 98ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com 99ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.comvoid SkTLS::Delete(CreateProc createProc) { 100ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com if (NULL == createProc) { 101ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com return; 102ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com } 103935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com 104be82fae824622779a4682a2598baab62c0027a0dreed@google.com void* ptr = SkTLS::PlatformGetSpecific(false); 105935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com 106ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com SkTLSRec* curr = (SkTLSRec*)ptr; 107ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com SkTLSRec* prev = NULL; 108ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com while (curr) { 109ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com SkTLSRec* next = curr->fNext; 110ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com if (curr->fCreateProc == createProc) { 111ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com if (prev) { 112ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com prev->fNext = next; 113ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com } else { 114ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com // we have a new head of our chain 115ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com SkTLS::PlatformSetSpecific(next); 116ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com } 117ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com SkDELETE(curr); 118ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com break; 119ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com } 120ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com prev = curr; 121ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com curr = next; 122ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com } 123ee8e50f33723ba46aa1dca5c3257797ec2d09985reed@google.com} 124