OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2008, 2010 Apple Inc. All Rights Reserved. | 2 * Copyright (C) 2008, 2010 Apple Inc. All Rights Reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
11 * documentation and/or other materials provided with the distribution. | 11 * documentation and/or other materials provided with the distribution. |
12 * | 12 * |
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY | 13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY |
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR | 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR |
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
24 * | 24 * |
25 */ | 25 */ |
26 | 26 |
27 #include "wtf/WTFThreadData.h" | 27 #include "wtf/WTFThreadData.h" |
28 | 28 |
29 #include "wtf/PtrUtil.h" | |
30 #include "wtf/StackUtil.h" | |
29 #include "wtf/text/AtomicStringTable.h" | 31 #include "wtf/text/AtomicStringTable.h" |
30 #include "wtf/text/TextCodecICU.h" | 32 #include "wtf/text/TextCodecICU.h" |
31 | 33 |
32 namespace WTF { | 34 namespace WTF { |
33 | 35 |
36 uintptr_t WTFThreadData::s_mainThreadStackStart = 0; | |
37 uintptr_t WTFThreadData::s_mainThreadUnderestimatedStackSize = 0; | |
38 uint8_t WTFThreadData::s_mainThreadDataStorage[sizeof(WTFThreadData)]; | |
39 | |
34 ThreadSpecific<WTFThreadData>* WTFThreadData::staticData; | 40 ThreadSpecific<WTFThreadData>* WTFThreadData::staticData; |
35 | 41 |
36 WTFThreadData::WTFThreadData() | 42 WTFThreadData::WTFThreadData(ThreadType type) |
37 : m_atomicStringTable(new AtomicStringTable), | 43 : m_threadId(internal::currentThreadSyscall()) { |
38 m_cachedConverterICU(new ICUConverterWrapper), | 44 // Static globals must be initialized before the AtomicStringTable, but after |
39 m_threadId(internal::currentThreadSyscall()) {} | 45 // |this| is initialized. Note that we call threadStackSize() from |
46 // getUnderestimatedStackSize() on MSVC. | |
47 if (type == MainThread) { | |
48 s_mainThreadStackStart = | |
49 reinterpret_cast<uintptr_t>(WTF::getStackStart()) - sizeof(void*); | |
50 size_t underestimatedStackSize = getUnderestimatedStackSize(); | |
51 if (underestimatedStackSize > sizeof(void*)) { | |
52 s_mainThreadUnderestimatedStackSize = | |
53 underestimatedStackSize - sizeof(void*); | |
54 } | |
haraken
2017/01/16 04:42:30
Can we do this initialization in WTFThreadData::in
Charlie Harrison
2017/01/18 01:49:48
This is all gone.
| |
55 } | |
56 m_atomicStringTable = makeUnique<AtomicStringTable>(); | |
57 m_cachedConverterICU = makeUnique<ICUConverterWrapper>(); | |
58 } | |
40 | 59 |
41 WTFThreadData::~WTFThreadData() {} | 60 WTFThreadData::~WTFThreadData() {} |
42 | 61 |
62 #if OS(WIN) && COMPILER(MSVC) | |
63 size_t WTFThreadData::threadStackSize() { | |
haraken
2017/01/16 04:42:30
I want to put this method in the same file as getU
Charlie Harrison
2017/01/18 01:49:48
Done.
| |
64 if (m_threadStackSize) | |
65 return m_threadStackSize; | |
66 | |
67 // Notice that we cannot use the TIB's StackLimit for the stack end, as it | |
68 // tracks the end of the committed range. We're after the end of the reserved | |
69 // stack area (most of which will be uncommitted, most times.) | |
70 MEMORY_BASIC_INFORMATION stackInfo; | |
71 memset(&stackInfo, 0, sizeof(MEMORY_BASIC_INFORMATION)); | |
72 size_t resultSize = | |
73 VirtualQuery(&stackInfo, &stackInfo, sizeof(MEMORY_BASIC_INFORMATION)); | |
74 DCHECK_GE(resultSize, sizeof(MEMORY_BASIC_INFORMATION)); | |
75 uint8_t* stackEnd = reinterpret_cast<uint8_t*>(stackInfo.AllocationBase); | |
76 | |
77 uint8_t* stackStart = reinterpret_cast<uint8_t*>(WTF::getStackStart()); | |
78 RELEASE_ASSERT(stackStart && stackStart > stackEnd); | |
79 m_threadStackSize = static_cast<size_t>(stackStart - stackEnd); | |
80 // When the third last page of the reserved stack is accessed as a | |
81 // guard page, the second last page will be committed (along with removing | |
82 // the guard bit on the third last) _and_ a stack overflow exception | |
83 // is raised. | |
84 // | |
85 // We have zero interest in running into stack overflow exceptions while | |
86 // marking objects, so simply consider the last three pages + one above | |
87 // as off-limits and adjust the reported stack size accordingly. | |
88 // | |
89 // http://blogs.msdn.com/b/satyem/archive/2012/08/13/thread-s-stack-memory-man agement.aspx | |
90 // explains the details. | |
91 RELEASE_ASSERT(m_threadStackSize > 4 * 0x1000); | |
92 m_threadStackSize -= 4 * 0x1000; | |
93 return m_threadStackSize; | |
94 } | |
95 #endif | |
96 | |
97 void WTFThreadData::initialize() { | |
98 DCHECK(!WTFThreadData::staticData); | |
99 WTFThreadData::staticData = new ThreadSpecific<WTFThreadData>; | |
100 new (s_mainThreadDataStorage) WTFThreadData(MainThread); | |
101 } | |
102 | |
103 WTFThreadData& WTFThreadData::current() { | |
104 #if defined(__GLIBC__) || OS(ANDROID) || OS(FREEBSD) | |
105 return **WTFThreadData::staticData; | |
106 #else | |
107 // TLS lookup is slow. | |
108 if (LIKELY(stackBasedIsMainThread())) | |
109 return mainThreadData(); | |
110 return **WTFThreadData::staticData; | |
111 #endif | |
112 } | |
113 | |
114 bool WTFThreadData::isMainThread() { | |
115 return current() == mainThreadData(); | |
116 } | |
117 | |
118 WTFThreadData& WTFThreadData::mainThreadData() { | |
119 return *(reinterpret_cast<WTFThreadData*>(s_mainThreadDataStorage)); | |
120 } | |
121 | |
122 bool WTFThreadData::stackBasedIsMainThread() { | |
123 uintptr_t dummy; | |
124 uintptr_t addressDiff = | |
125 s_mainThreadStackStart - reinterpret_cast<uintptr_t>(&dummy); | |
126 // This is a fast way to judge if we are in the main thread. | |
127 // If |&dummy| is within |s_mainThreadUnderestimatedStackSize| byte from | |
128 // the stack start of the main thread, we judge that we are in | |
129 // the main thread. | |
130 return addressDiff < s_mainThreadUnderestimatedStackSize; | |
131 } | |
132 | |
133 bool operator==(const WTFThreadData& data1, const WTFThreadData& data2) { | |
134 return data1.threadId() == data2.threadId(); | |
135 } | |
136 | |
43 } // namespace WTF | 137 } // namespace WTF |
OLD | NEW |