Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
1 #include "SkTLS.h"
3 // enable to help debug TLS storage
4 //#define SK_TRACE_TLS_LIFETIME
7 #ifdef SK_TRACE_TLS_LIFETIME
8 #include "SkThread.h"
9 static int32_t gTLSRecCount;
10 #endif
12 struct SkTLSRec {
13 SkTLSRec* fNext;
14 void* fData;
15 SkTLS::CreateProc fCreateProc;
16 SkTLS::DeleteProc fDeleteProc;
18 #ifdef SK_TRACE_TLS_LIFETIME
19 SkTLSRec() {
20 int n = sk_atomic_inc(&gTLSRecCount);
21 SkDebugf(" SkTLSRec[%d]\n", n);
22 }
23 #endif
25 ~SkTLSRec() {
26 if (fDeleteProc) {
27 fDeleteProc(fData);
28 }
29 // else we leak fData, or it will be managed by the caller
31 #ifdef SK_TRACE_TLS_LIFETIME
32 int n = sk_atomic_dec(&gTLSRecCount);
33 SkDebugf("~SkTLSRec[%d]\n", n - 1);
34 #endif
35 }
36 };
38 void SkTLS::Destructor(void* ptr) {
39 #ifdef SK_TRACE_TLS_LIFETIME
40 SkDebugf("SkTLS::Destructor(%p)\n", ptr);
41 #endif
43 SkTLSRec* rec = (SkTLSRec*)ptr;
44 do {
45 SkTLSRec* next = rec->fNext;
46 SkDELETE(rec);
47 rec = next;
48 } while (NULL != rec);
49 }
51 void* SkTLS::Get(CreateProc createProc, DeleteProc deleteProc) {
52 if (NULL == createProc) {
53 return NULL;
54 }
56 void* ptr = SkTLS::PlatformGetSpecific(true);
58 if (ptr) {
59 const SkTLSRec* rec = (const SkTLSRec*)ptr;
60 do {
61 if (rec->fCreateProc == createProc) {
62 SkASSERT(rec->fDeleteProc == deleteProc);
63 return rec->fData;
64 }
65 } while ((rec = rec->fNext) != NULL);
66 // not found, so create a new one
67 }
69 // add a new head of our change
70 SkTLSRec* rec = new SkTLSRec;
71 rec->fNext = (SkTLSRec*)ptr;
73 SkTLS::PlatformSetSpecific(rec);
75 rec->fData = createProc();
76 rec->fCreateProc = createProc;
77 rec->fDeleteProc = deleteProc;
78 return rec->fData;
79 }
81 void* SkTLS::Find(CreateProc createProc) {
82 if (NULL == createProc) {
83 return NULL;
84 }
86 void* ptr = SkTLS::PlatformGetSpecific(false);
88 if (ptr) {
89 const SkTLSRec* rec = (const SkTLSRec*)ptr;
90 do {
91 if (rec->fCreateProc == createProc) {
92 return rec->fData;
93 }
94 } while ((rec = rec->fNext) != NULL);
95 }
96 return NULL;
97 }
99 void SkTLS::Delete(CreateProc createProc) {
100 if (NULL == createProc) {
101 return;
102 }
104 void* ptr = SkTLS::PlatformGetSpecific(false);
106 SkTLSRec* curr = (SkTLSRec*)ptr;
107 SkTLSRec* prev = NULL;
108 while (curr) {
109 SkTLSRec* next = curr->fNext;
110 if (curr->fCreateProc == createProc) {
111 if (prev) {
112 prev->fNext = next;
113 } else {
114 // we have a new head of our chain
115 SkTLS::PlatformSetSpecific(next);
116 }
117 SkDELETE(curr);
118 break;
119 }
120 prev = curr;
121 curr = next;
122 }
123 }