148ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com#include "SkTLS.h" 248ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com 37b578928a5705f40cfe051ae1c41c1b2e1df0bddreed@google.com// enable to help debug TLS storage 47b578928a5705f40cfe051ae1c41c1b2e1df0bddreed@google.com//#define SK_TRACE_TLS_LIFETIME 57b578928a5705f40cfe051ae1c41c1b2e1df0bddreed@google.com 67b578928a5705f40cfe051ae1c41c1b2e1df0bddreed@google.com 77b578928a5705f40cfe051ae1c41c1b2e1df0bddreed@google.com#ifdef SK_TRACE_TLS_LIFETIME 87b578928a5705f40cfe051ae1c41c1b2e1df0bddreed@google.com #include "SkThread.h" 97b578928a5705f40cfe051ae1c41c1b2e1df0bddreed@google.com static int32_t gTLSRecCount; 107b578928a5705f40cfe051ae1c41c1b2e1df0bddreed@google.com#endif 117b578928a5705f40cfe051ae1c41c1b2e1df0bddreed@google.com 1248ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.comstruct SkTLSRec { 1348ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com SkTLSRec* fNext; 1448ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com void* fData; 1548ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com SkTLS::CreateProc fCreateProc; 1648ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com SkTLS::DeleteProc fDeleteProc; 1748ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com 187b578928a5705f40cfe051ae1c41c1b2e1df0bddreed@google.com#ifdef SK_TRACE_TLS_LIFETIME 197b578928a5705f40cfe051ae1c41c1b2e1df0bddreed@google.com SkTLSRec() { 207b578928a5705f40cfe051ae1c41c1b2e1df0bddreed@google.com int n = sk_atomic_inc(&gTLSRecCount); 217b578928a5705f40cfe051ae1c41c1b2e1df0bddreed@google.com SkDebugf(" SkTLSRec[%d]\n", n); 227b578928a5705f40cfe051ae1c41c1b2e1df0bddreed@google.com } 237b578928a5705f40cfe051ae1c41c1b2e1df0bddreed@google.com#endif 247b578928a5705f40cfe051ae1c41c1b2e1df0bddreed@google.com 2548ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com ~SkTLSRec() { 2648ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com if (fDeleteProc) { 2748ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com fDeleteProc(fData); 2848ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com } 2948ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com // else we leak fData, or it will be managed by the caller 307b578928a5705f40cfe051ae1c41c1b2e1df0bddreed@google.com 317b578928a5705f40cfe051ae1c41c1b2e1df0bddreed@google.com#ifdef SK_TRACE_TLS_LIFETIME 327b578928a5705f40cfe051ae1c41c1b2e1df0bddreed@google.com int n = sk_atomic_dec(&gTLSRecCount); 337b578928a5705f40cfe051ae1c41c1b2e1df0bddreed@google.com SkDebugf("~SkTLSRec[%d]\n", n - 1); 347b578928a5705f40cfe051ae1c41c1b2e1df0bddreed@google.com#endif 3548ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com } 3648ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com}; 3748ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com 3848ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.comvoid SkTLS::Destructor(void* ptr) { 397b578928a5705f40cfe051ae1c41c1b2e1df0bddreed@google.com#ifdef SK_TRACE_TLS_LIFETIME 407b578928a5705f40cfe051ae1c41c1b2e1df0bddreed@google.com SkDebugf("SkTLS::Destructor(%p)\n", ptr); 417b578928a5705f40cfe051ae1c41c1b2e1df0bddreed@google.com#endif 427b578928a5705f40cfe051ae1c41c1b2e1df0bddreed@google.com 4348ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com SkTLSRec* rec = (SkTLSRec*)ptr; 4448ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com do { 4548ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com SkTLSRec* next = rec->fNext; 4648ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com SkDELETE(rec); 4748ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com rec = next; 4849f085dddff10473b6ebf832a974288300224e60bsalomon } while (rec); 4948ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com} 5048ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com 5148ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.comvoid* SkTLS::Get(CreateProc createProc, DeleteProc deleteProc) { 5248ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com if (NULL == createProc) { 5348ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com return NULL; 5448ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com } 5548ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com 56331e2dc8eb69b093bf012d8dcd1ab652d67fc36breed@google.com void* ptr = SkTLS::PlatformGetSpecific(true); 5748ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com 5848ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com if (ptr) { 5948ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com const SkTLSRec* rec = (const SkTLSRec*)ptr; 6048ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com do { 6148ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com if (rec->fCreateProc == createProc) { 6248ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com SkASSERT(rec->fDeleteProc == deleteProc); 6348ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com return rec->fData; 6448ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com } 6548ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com } while ((rec = rec->fNext) != NULL); 6648ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com // not found, so create a new one 6748ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com } 68fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 6948ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com // add a new head of our change 7048ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com SkTLSRec* rec = new SkTLSRec; 7148ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com rec->fNext = (SkTLSRec*)ptr; 7248ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com 7348ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com SkTLS::PlatformSetSpecific(rec); 7448ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com 7548ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com rec->fData = createProc(); 7648ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com rec->fCreateProc = createProc; 7748ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com rec->fDeleteProc = deleteProc; 7848ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com return rec->fData; 7948ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com} 8048ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com 8148ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.comvoid* SkTLS::Find(CreateProc createProc) { 8248ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com if (NULL == createProc) { 8348ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com return NULL; 8448ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com } 85fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 86331e2dc8eb69b093bf012d8dcd1ab652d67fc36breed@google.com void* ptr = SkTLS::PlatformGetSpecific(false); 8748ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com 8848ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com if (ptr) { 8948ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com const SkTLSRec* rec = (const SkTLSRec*)ptr; 9048ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com do { 9148ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com if (rec->fCreateProc == createProc) { 9248ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com return rec->fData; 9348ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com } 9448ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com } while ((rec = rec->fNext) != NULL); 9548ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com } 9648ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com return NULL; 9748ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com} 9848ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com 9948ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.comvoid SkTLS::Delete(CreateProc createProc) { 10048ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com if (NULL == createProc) { 10148ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com return; 10248ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com } 103fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 104331e2dc8eb69b093bf012d8dcd1ab652d67fc36breed@google.com void* ptr = SkTLS::PlatformGetSpecific(false); 105fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 10648ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com SkTLSRec* curr = (SkTLSRec*)ptr; 10748ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com SkTLSRec* prev = NULL; 10848ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com while (curr) { 10948ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com SkTLSRec* next = curr->fNext; 11048ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com if (curr->fCreateProc == createProc) { 11148ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com if (prev) { 11248ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com prev->fNext = next; 11348ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com } else { 11448ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com // we have a new head of our chain 11548ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com SkTLS::PlatformSetSpecific(next); 11648ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com } 11748ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com SkDELETE(curr); 11848ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com break; 11948ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com } 12048ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com prev = curr; 12148ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com curr = next; 12248ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com } 12348ca7e37ef684dea5271b8d779c1ccc66b9bf275reed@google.com} 124