OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #ifndef VM_OS_THREAD_H_ | 5 #ifndef VM_OS_THREAD_H_ |
6 #define VM_OS_THREAD_H_ | 6 #define VM_OS_THREAD_H_ |
7 | 7 |
8 #include "platform/globals.h" | 8 #include "platform/globals.h" |
| 9 #include "vm/allocation.h" |
9 #include "vm/globals.h" | 10 #include "vm/globals.h" |
10 | 11 |
11 // Declare the OS-specific types ahead of defining the generic classes. | 12 // Declare the OS-specific types ahead of defining the generic classes. |
12 #if defined(TARGET_OS_ANDROID) | 13 #if defined(TARGET_OS_ANDROID) |
13 #include "vm/os_thread_android.h" | 14 #include "vm/os_thread_android.h" |
14 #elif defined(TARGET_OS_LINUX) | 15 #elif defined(TARGET_OS_LINUX) |
15 #include "vm/os_thread_linux.h" | 16 #include "vm/os_thread_linux.h" |
16 #elif defined(TARGET_OS_MACOS) | 17 #elif defined(TARGET_OS_MACOS) |
17 #include "vm/os_thread_macos.h" | 18 #include "vm/os_thread_macos.h" |
18 #elif defined(TARGET_OS_WINDOWS) | 19 #elif defined(TARGET_OS_WINDOWS) |
19 #include "vm/os_thread_win.h" | 20 #include "vm/os_thread_win.h" |
20 #else | 21 #else |
21 #error Unknown target os. | 22 #error Unknown target os. |
22 #endif | 23 #endif |
23 | 24 |
24 namespace dart { | 25 namespace dart { |
25 | 26 |
| 27 // Forward declarations. |
| 28 class Log; |
| 29 class Mutex; |
| 30 class Thread; |
| 31 class TimelineEventBlock; |
| 32 |
| 33 class BaseThread { |
| 34 public: |
| 35 bool is_os_thread() const { return is_os_thread_; } |
| 36 |
| 37 private: |
| 38 explicit BaseThread(bool is_os_thread) : is_os_thread_(is_os_thread) {} |
| 39 ~BaseThread() {} |
| 40 |
| 41 bool is_os_thread_; |
| 42 |
| 43 friend class Thread; |
| 44 friend class OSThread; |
| 45 |
| 46 DISALLOW_IMPLICIT_CONSTRUCTORS(BaseThread); |
| 47 }; |
| 48 |
| 49 |
26 // Low-level operations on OS platform threads. | 50 // Low-level operations on OS platform threads. |
27 // TODO(koda): Move to runtime/platform. | 51 class OSThread : public BaseThread { |
28 class OSThread { | |
29 public: | 52 public: |
30 static ThreadLocalKey kUnsetThreadLocalKey; | 53 OSThread(); |
31 static ThreadId kInvalidThreadId; | 54 ~OSThread(); |
32 static ThreadJoinId kInvalidThreadJoinId; | 55 |
| 56 ThreadId id() const { |
| 57 ASSERT(id_ != OSThread::kInvalidThreadId); |
| 58 return id_; |
| 59 } |
| 60 |
| 61 ThreadId join_id() const { |
| 62 ASSERT(join_id_ != OSThread::kInvalidThreadJoinId); |
| 63 return join_id_; |
| 64 } |
| 65 |
| 66 ThreadId trace_id() const { |
| 67 ASSERT(trace_id_ != OSThread::kInvalidThreadJoinId); |
| 68 return trace_id_; |
| 69 } |
| 70 |
| 71 const char* name() const { |
| 72 return name_; |
| 73 } |
| 74 |
| 75 void set_name(const char* name) { |
| 76 ASSERT(OSThread::Current() == this); |
| 77 ASSERT(name_ == NULL); |
| 78 name_ = name; |
| 79 } |
| 80 |
| 81 Mutex* timeline_block_lock() const { |
| 82 return timeline_block_lock_; |
| 83 } |
| 84 |
| 85 // Only safe to access when holding |timeline_block_lock_|. |
| 86 TimelineEventBlock* timeline_block() const { |
| 87 return timeline_block_; |
| 88 } |
| 89 |
| 90 // Only safe to access when holding |timeline_block_lock_|. |
| 91 void set_timeline_block(TimelineEventBlock* block) { |
| 92 timeline_block_ = block; |
| 93 } |
| 94 |
| 95 Log* log() const { return log_; } |
| 96 |
| 97 uword stack_base() const { return stack_base_; } |
| 98 void set_stack_base(uword stack_base) { stack_base_ = stack_base; } |
| 99 |
| 100 // Retrieve the stack address bounds for profiler. |
| 101 bool GetProfilerStackBounds(uword* lower, uword* upper) const { |
| 102 uword stack_upper = stack_base_; |
| 103 if (stack_upper == 0) { |
| 104 return false; |
| 105 } |
| 106 uword stack_lower = stack_upper - GetSpecifiedStackSize(); |
| 107 *lower = stack_lower; |
| 108 *upper = stack_upper; |
| 109 return true; |
| 110 } |
| 111 |
| 112 // Used to temporarily disable or enable thread interrupts. |
| 113 void DisableThreadInterrupts(); |
| 114 void EnableThreadInterrupts(); |
| 115 bool ThreadInterruptsEnabled(); |
| 116 |
| 117 // The currently executing thread, or NULL if not yet initialized. |
| 118 static OSThread* Current() { |
| 119 BaseThread* thread = GetCurrentTLS(); |
| 120 OSThread* os_thread = NULL; |
| 121 if (thread != NULL) { |
| 122 if (thread->is_os_thread()) { |
| 123 os_thread = reinterpret_cast<OSThread*>(thread); |
| 124 } else { |
| 125 Thread* vm_thread = reinterpret_cast<Thread*>(thread); |
| 126 os_thread = GetOSThreadFromThread(vm_thread); |
| 127 } |
| 128 } |
| 129 return os_thread; |
| 130 } |
| 131 static void SetCurrent(OSThread* current); |
| 132 |
| 133 // TODO(5411455): Use flag to override default value and Validate the |
| 134 // stack size by querying OS. |
| 135 static uword GetSpecifiedStackSize() { |
| 136 ASSERT(OSThread::kStackSizeBuffer < OSThread::GetMaxStackSize()); |
| 137 uword stack_size = OSThread::GetMaxStackSize() - OSThread::kStackSizeBuffer; |
| 138 return stack_size; |
| 139 } |
| 140 static BaseThread* GetCurrentTLS() { |
| 141 return reinterpret_cast<BaseThread*>(OSThread::GetThreadLocal(thread_key_)); |
| 142 } |
| 143 static void SetCurrentTLS(uword value) { |
| 144 SetThreadLocal(thread_key_, value); |
| 145 } |
33 | 146 |
34 typedef void (*ThreadStartFunction) (uword parameter); | 147 typedef void (*ThreadStartFunction) (uword parameter); |
35 typedef void (*ThreadDestructor) (void* parameter); | 148 typedef void (*ThreadDestructor) (void* parameter); |
36 | 149 |
37 // Start a thread running the specified function. Returns 0 if the | 150 // Start a thread running the specified function. Returns 0 if the |
38 // thread started successfuly and a system specific error code if | 151 // thread started successfuly and a system specific error code if |
39 // the thread failed to start. | 152 // the thread failed to start. |
40 static int Start(ThreadStartFunction function, uword parameters); | 153 static int Start( |
| 154 const char* name, ThreadStartFunction function, uword parameter); |
41 | 155 |
42 static ThreadLocalKey CreateThreadLocal(ThreadDestructor destructor = NULL); | 156 static ThreadLocalKey CreateThreadLocal(ThreadDestructor destructor = NULL); |
43 static void DeleteThreadLocal(ThreadLocalKey key); | 157 static void DeleteThreadLocal(ThreadLocalKey key); |
44 static uword GetThreadLocal(ThreadLocalKey key) { | 158 static uword GetThreadLocal(ThreadLocalKey key) { |
45 return ThreadInlineImpl::GetThreadLocal(key); | 159 return ThreadInlineImpl::GetThreadLocal(key); |
46 } | 160 } |
| 161 static ThreadId GetCurrentThreadId(); |
47 static void SetThreadLocal(ThreadLocalKey key, uword value); | 162 static void SetThreadLocal(ThreadLocalKey key, uword value); |
48 static intptr_t GetMaxStackSize(); | 163 static intptr_t GetMaxStackSize(); |
49 static ThreadId GetCurrentThreadId(); | |
50 static ThreadId GetCurrentThreadTraceId(); | |
51 static intptr_t CurrentCurrentThreadIdAsIntPtr() { | |
52 return ThreadIdToIntPtr(GetCurrentThreadId()); | |
53 } | |
54 static ThreadJoinId GetCurrentThreadJoinId(); | |
55 static void Join(ThreadJoinId id); | 164 static void Join(ThreadJoinId id); |
56 static intptr_t ThreadIdToIntPtr(ThreadId id); | 165 static intptr_t ThreadIdToIntPtr(ThreadId id); |
57 static ThreadId ThreadIdFromIntPtr(intptr_t id); | 166 static ThreadId ThreadIdFromIntPtr(intptr_t id); |
58 static bool Compare(ThreadId a, ThreadId b); | 167 static bool Compare(ThreadId a, ThreadId b); |
59 static void GetThreadCpuUsage(ThreadId thread_id, int64_t* cpu_usage); | 168 static void GetThreadCpuUsage(ThreadId thread_id, int64_t* cpu_usage); |
| 169 |
| 170 // Called at VM startup and shutdown. |
| 171 static void InitOnce(); |
| 172 |
| 173 static bool IsThreadInList(ThreadId join_id); |
| 174 |
| 175 static const intptr_t kStackSizeBuffer = (4 * KB * kWordSize); |
| 176 |
| 177 static ThreadLocalKey kUnsetThreadLocalKey; |
| 178 static ThreadId kInvalidThreadId; |
| 179 static ThreadJoinId kInvalidThreadJoinId; |
| 180 |
| 181 private: |
| 182 // These methods should not be used in a generic way and hence |
| 183 // are private, they have been added to solve the problem of |
| 184 // accessing the VM thread structure from an OSThread object |
| 185 // in the windows thread interrupter which is used for profiling. |
| 186 // We could eliminate this requirement if the windows thread interrupter |
| 187 // is implemented differently. |
| 188 Thread* thread() const { return thread_; } |
| 189 void set_thread(Thread* value) { |
| 190 thread_ = value; |
| 191 } |
| 192 |
| 193 static void Cleanup(); |
| 194 static ThreadId GetCurrentThreadTraceId(); |
| 195 static ThreadJoinId GetCurrentThreadJoinId(); |
| 196 static OSThread* GetOSThreadFromThread(Thread* thread); |
| 197 static void AddThreadToList(OSThread* thread); |
| 198 static void RemoveThreadFromList(OSThread* thread); |
| 199 |
| 200 static ThreadLocalKey thread_key_; |
| 201 |
| 202 const ThreadId id_; |
| 203 const ThreadId join_id_; |
| 204 const ThreadId trace_id_; // Used to interface with tracing tools. |
| 205 const char* name_; // A name for this thread. |
| 206 |
| 207 Mutex* timeline_block_lock_; |
| 208 TimelineEventBlock* timeline_block_; |
| 209 |
| 210 // All |Thread|s are registered in the thread list. |
| 211 OSThread* thread_list_next_; |
| 212 |
| 213 uintptr_t thread_interrupt_disabled_; |
| 214 Log* log_; |
| 215 uword stack_base_; |
| 216 Thread* thread_; |
| 217 |
| 218 static OSThread* thread_list_head_; |
| 219 static Mutex* thread_list_lock_; |
| 220 |
| 221 friend class OSThreadIterator; |
| 222 friend class ThreadInterrupterWin; |
| 223 friend class ThreadRegistry; |
60 }; | 224 }; |
61 | 225 |
62 | 226 |
| 227 // Note that this takes the thread list lock, prohibiting threads from coming |
| 228 // on- or off-line. |
| 229 class OSThreadIterator : public ValueObject { |
| 230 public: |
| 231 OSThreadIterator(); |
| 232 ~OSThreadIterator(); |
| 233 |
| 234 // Returns false when there are no more threads left. |
| 235 bool HasNext() const; |
| 236 |
| 237 // Returns the current thread and moves forward. |
| 238 OSThread* Next(); |
| 239 |
| 240 private: |
| 241 OSThread* next_; |
| 242 }; |
| 243 |
| 244 |
63 class Mutex { | 245 class Mutex { |
64 public: | 246 public: |
65 Mutex(); | 247 Mutex(); |
66 ~Mutex(); | 248 ~Mutex(); |
67 | 249 |
68 void Lock(); | 250 void Lock(); |
69 bool TryLock(); | 251 bool TryLock(); |
70 void Unlock(); | 252 void Unlock(); |
71 | 253 |
72 #if defined(DEBUG) | 254 #if defined(DEBUG) |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
131 #endif // defined(DEBUG) | 313 #endif // defined(DEBUG) |
132 | 314 |
133 DISALLOW_COPY_AND_ASSIGN(Monitor); | 315 DISALLOW_COPY_AND_ASSIGN(Monitor); |
134 }; | 316 }; |
135 | 317 |
136 | 318 |
137 } // namespace dart | 319 } // namespace dart |
138 | 320 |
139 | 321 |
140 #endif // VM_OS_THREAD_H_ | 322 #endif // VM_OS_THREAD_H_ |
OLD | NEW |