1/*
2 * Copyright (C) 2008 Apple Inc. All Rights Reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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.
24 *
25 */
26
27#ifndef WTFThreadData_h
28#define WTFThreadData_h
29
30#include <wtf/HashMap.h>
31#include <wtf/HashSet.h>
32#include <wtf/Noncopyable.h>
33#include <wtf/StackBounds.h>
34#include <wtf/StackStats.h>
35#include <wtf/text/StringHash.h>
36
37#if OS(DARWIN)
38#if defined(__has_include) && __has_include(<System/pthread_machdep.h>)
39#include <System/pthread_machdep.h>
40#endif
41#endif
42
43#if defined(__PTK_FRAMEWORK_JAVASCRIPTCORE_KEY1)
44#define WTF_USE_PTHREAD_GETSPECIFIC_DIRECT 1
45#endif
46
47#if !USE(PTHREAD_GETSPECIFIC_DIRECT)
48#include <wtf/ThreadSpecific.h>
49#include <wtf/Threading.h>
50#endif
51
52namespace WTF {
53
54class AtomicStringTable;
55
56typedef void (*AtomicStringTableDestructor)(AtomicStringTable*);
57
58class WTFThreadData {
59    WTF_MAKE_NONCOPYABLE(WTFThreadData);
60public:
61    WTF_EXPORT_PRIVATE WTFThreadData();
62    WTF_EXPORT_PRIVATE ~WTFThreadData();
63
64    AtomicStringTable* atomicStringTable()
65    {
66        return m_currentAtomicStringTable;
67    }
68
69    AtomicStringTable* setCurrentAtomicStringTable(AtomicStringTable* atomicStringTable)
70    {
71        AtomicStringTable* oldAtomicStringTable = m_currentAtomicStringTable;
72        m_currentAtomicStringTable = atomicStringTable;
73        return oldAtomicStringTable;
74    }
75
76    void resetCurrentAtomicStringTable()
77    {
78        m_currentAtomicStringTable = m_defaultAtomicStringTable;
79    }
80
81    const StackBounds& stack()
82    {
83        // We need to always get a fresh StackBounds from the OS due to how fibers work.
84        // See https://bugs.webkit.org/show_bug.cgi?id=102411
85#if OS(WINDOWS)
86        m_stackBounds = StackBounds::currentThreadStackBounds();
87#endif
88        return m_stackBounds;
89    }
90
91#if ENABLE(STACK_STATS)
92    StackStats::PerThreadStats& stackStats()
93    {
94        return m_stackStats;
95    }
96#endif
97
98    void* savedStackPointerAtVMEntry()
99    {
100        return m_savedStackPointerAtVMEntry;
101    }
102
103    void setSavedStackPointerAtVMEntry(void* stackPointerAtVMEntry)
104    {
105        m_savedStackPointerAtVMEntry = stackPointerAtVMEntry;
106    }
107
108    void* savedLastStackTop()
109    {
110        return m_savedLastStackTop;
111    }
112
113    void setSavedLastStackTop(void* lastStackTop)
114    {
115        m_savedLastStackTop = lastStackTop;
116    }
117
118    void* m_apiData;
119
120private:
121    AtomicStringTable* m_currentAtomicStringTable;
122    AtomicStringTable* m_defaultAtomicStringTable;
123    AtomicStringTableDestructor m_atomicStringTableDestructor;
124
125    StackBounds m_stackBounds;
126#if ENABLE(STACK_STATS)
127    StackStats::PerThreadStats m_stackStats;
128#endif
129    void* m_savedStackPointerAtVMEntry;
130    void* m_savedLastStackTop;
131
132#if USE(PTHREAD_GETSPECIFIC_DIRECT)
133    static const pthread_key_t directKey = __PTK_FRAMEWORK_JAVASCRIPTCORE_KEY1;
134    WTF_EXPORT_PRIVATE static WTFThreadData& createAndRegisterForGetspecificDirect();
135#else
136    static WTF_EXPORTDATA ThreadSpecific<WTFThreadData>* staticData;
137#endif
138
139    friend WTFThreadData& wtfThreadData();
140    friend class AtomicStringTable;
141};
142
143inline WTFThreadData& wtfThreadData()
144{
145    // WRT WebCore:
146    //    WTFThreadData is used on main thread before it could possibly be used
147    //    on secondary ones, so there is no need for synchronization here.
148    // WRT JavaScriptCore:
149    //    wtfThreadData() is initially called from initializeThreading(), ensuring
150    //    this is initially called in a pthread_once locked context.
151#if !USE(PTHREAD_GETSPECIFIC_DIRECT)
152    if (!WTFThreadData::staticData)
153        WTFThreadData::staticData = new ThreadSpecific<WTFThreadData>;
154    return **WTFThreadData::staticData;
155#else
156    if (WTFThreadData* data = static_cast<WTFThreadData*>(_pthread_getspecific_direct(WTFThreadData::directKey)))
157        return *data;
158    return WTFThreadData::createAndRegisterForGetspecificDirect();
159#endif
160}
161
162} // namespace WTF
163
164using WTF::WTFThreadData;
165using WTF::wtfThreadData;
166using WTF::AtomicStringTable;
167
168#endif // WTFThreadData_h
169