Changeset 40208 in webkit for trunk/JavaScriptCore/runtime
- Timestamp:
- Jan 23, 2009, 7:03:25 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/runtime/JSLock.cpp
r38528 r40208 120 120 } 121 121 122 // This is fairly nasty. We allow multiple threads to run on the same 123 // context, and we do not require any locking semantics in doing so - 124 // clients of the API may simply use the context from multiple threads 125 // concurently, and assume this will work. In order to make this work, 126 // We lock the context when a thread enters, and unlock it when it leaves. 127 // However we do not only unlock when the thread returns from its 128 // entry point (evaluate script or call function), we also unlock the 129 // context if the thread leaves JSC by making a call out to an external 130 // function through a callback. 131 // 132 // All threads using the context share the same JS stack (the RegisterFile). 133 // Whenever a thread calls into JSC it starts using the RegisterFile from the 134 // previous 'high water mark' - the maximum point the stack has ever grown to 135 // (returned by RegisterFile::end()). So if a first thread calls out to a 136 // callback, and a second thread enters JSC, then also exits by calling out 137 // to a callback, we can be left with stackframes from both threads in the 138 // RegisterFile. As such, a problem may occur should the first thread's 139 // callback complete first, and attempt to return to JSC. Were we to allow 140 // this to happen, and were its stack to grow further, then it may potentially 141 // write over the second thread's call frames. 142 // 143 // In avoid JS stack corruption we enforce a policy of only ever allowing two 144 // threads to use a JS context concurrently, and only allowing the second of 145 // these threads to execute until it has completed and fully returned from its 146 // outermost call into JSC. We enforce this policy using 'lockDropDepth'. The 147 // first time a thread exits it will call DropAllLocks - which will do as expected 148 // and drop locks allowing another thread to enter. Should another thread, or the 149 // same thread again, enter JSC (through evaluate script or call function), and exit 150 // again through a callback, then the locks will not be dropped when DropAllLocks 151 // is called (since lockDropDepth is non-zero). Since this thread is still holding 152 // the locks, only it will re able to re-enter JSC (either be returning from the 153 // callback, or by re-entering through another call to evaulate script or call 154 // function). 155 // 156 // This policy is slightly more restricive than it needs to be for correctness - 157 // we could validly allow futher entries into JSC from other threads, we only 158 // need ensure that callbacks return in the reverse chronological order of the 159 // order in which they were made - though implementing the less restrictive policy 160 // would likely increase complexity and overhead. 161 // 162 static unsigned lockDropDepth = 0; 163 122 164 JSLock::DropAllLocks::DropAllLocks(ExecState* exec) 123 165 : m_lockingForReal(exec->globalData().isSharedInstance) 124 166 { 125 167 pthread_once(&createJSLockCountOnce, createJSLockCount); 168 169 if (lockDropDepth++) { 170 m_lockCount = 0; 171 return; 172 } 126 173 127 174 m_lockCount = JSLock::lockCount(); … … 135 182 pthread_once(&createJSLockCountOnce, createJSLockCount); 136 183 184 if (lockDropDepth++) { 185 m_lockCount = 0; 186 return; 187 } 188 137 189 // It is necessary to drop even "unreal" locks, because having a non-zero lock count 138 190 // will prevent a real lock from being taken. … … 147 199 for (intptr_t i = 0; i < m_lockCount; i++) 148 200 JSLock::lock(m_lockingForReal); 201 202 --lockDropDepth; 149 203 } 150 204
Note:
See TracChangeset
for help on using the changeset viewer.