Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(367)

Side by Side Diff: runtime/vm/os_thread.cc

Issue 1439483003: - Add an OSThread structure which is the generic TLS structure for all C++ (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: tweak-comment Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
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.
4
5 #include "vm/os_thread.h"
6
7 #include "vm/atomic.h"
8 #include "vm/lockers.h"
9 #include "vm/log.h"
10 #include "vm/thread_interrupter.h"
11
12 namespace dart {
13
14 // The single thread local key which stores all the thread local data
15 // for a thread.
16 ThreadLocalKey OSThread::thread_key_ = OSThread::kUnsetThreadLocalKey;
17 OSThread* OSThread::thread_list_head_ = NULL;
18 Mutex* OSThread::thread_list_lock_ = NULL;
19
20
21 OSThread::OSThread() :
22 BaseThread(true),
23 id_(OSThread::GetCurrentThreadId()),
24 join_id_(OSThread::GetCurrentThreadJoinId()),
25 trace_id_(OSThread::GetCurrentThreadTraceId()),
26 name_(NULL),
27 timeline_block_lock_(new Mutex()),
28 timeline_block_(NULL),
29 thread_list_next_(NULL),
30 thread_interrupt_disabled_(1), // Thread interrupts disabled by default.
31 log_(new class Log()),
32 stack_base_(0) {
33 AddThreadToList(this);
34 }
35
36
37 OSThread::~OSThread() {
38 RemoveThreadFromList(this);
39 delete log_;
40 log_ = NULL;
41 ASSERT(Timeline::recorder() != NULL);
Cutch 2015/11/14 00:31:56 Replace the ASSERT with: if (Timeline::recorder()
siva 2015/11/14 01:38:26 Done.
42 Timeline::recorder()->FinishBlock(timeline_block_);
43 timeline_block_ = NULL;
44 delete timeline_block_lock_;
45 }
46
47
48 void OSThread::DisableThreadInterrupts() {
49 ASSERT(OSThread::Current() == this);
50 AtomicOperations::FetchAndIncrement(&thread_interrupt_disabled_);
51 }
52
53
54 void OSThread::EnableThreadInterrupts() {
55 ASSERT(OSThread::Current() == this);
56 uintptr_t old =
57 AtomicOperations::FetchAndDecrement(&thread_interrupt_disabled_);
58 if (old == 1) {
59 // We just decremented from 1 to 0.
60 // Make sure the thread interrupter is awake.
61 ThreadInterrupter::WakeUp();
62 }
63 if (old == 0) {
64 // We just decremented from 0, this means we've got a mismatched pair
65 // of calls to EnableThreadInterrupts and DisableThreadInterrupts.
66 FATAL("Invalid call to Thread::EnableThreadInterrupts()");
Cutch 2015/11/14 00:31:56 s/Thread/OSThread
siva 2015/11/14 01:38:26 Done.
67 }
68 }
69
70
71 bool OSThread::ThreadInterruptsEnabled() {
72 return AtomicOperations::LoadRelaxed(&thread_interrupt_disabled_) == 0;
73 }
74
75
76 static void DeleteThread(void* thread) {
77 delete reinterpret_cast<OSThread*>(thread);
78 }
79
80
81 void OSThread::InitOnce() {
82 // Allocate the global OSThread lock.
83 ASSERT(thread_list_lock_ == NULL);
84 thread_list_lock_ = new Mutex();
85 ASSERT(thread_list_lock_ != NULL);
86
87 // Create the thread local key.
88 ASSERT(thread_key_ == kUnsetThreadLocalKey);
89 thread_key_ = CreateThreadLocal(DeleteThread);
90 ASSERT(thread_key_ != kUnsetThreadLocalKey);
91
92 // Create a new OSThread strcture and set it as the TLS.
93 OSThread* os_thread = new OSThread();
94 OSThread::SetCurrent(os_thread);
95 os_thread->set_name("Dart_Initialize");
96 }
97
98
99 void OSThread::Cleanup() {
100 if (thread_list_lock_ != NULL) {
101 // Delete the current threads TLS, should result in the global OSThread
102 // list to become empty.
103 OSThread* thread = OSThread::Current();
104 ASSERT(thread != NULL);
105 OSThread::SetCurrent(NULL);
106
107 // Delete the thread local key.
108 ASSERT(thread_key_ != kUnsetThreadLocalKey);
109 DeleteThreadLocal(thread_key_);
110 thread_key_ = kUnsetThreadLocalKey;
111
112 // Delete the global OSThread lock.
113 ASSERT(thread_list_lock_ != NULL);
114 delete thread_list_lock_;
115 thread_list_lock_ = NULL;
116 }
117 }
118
119
120 bool OSThread::IsThreadInList(ThreadId join_id) {
121 if (join_id == OSThread::kInvalidThreadJoinId) {
122 return false;
123 }
124 OSThreadIterator it;
125 while (it.HasNext()) {
126 ASSERT(OSThread::thread_list_lock_->IsOwnedByCurrentThread());
127 OSThread* t = it.Next();
128 // An address test is not sufficient because the allocator may recycle
129 // the address for another Thread. Test against the thread's join id.
130 if (t->join_id() == join_id) {
131 return true;
132 }
133 }
134 return false;
135 }
136
137
138 OSThread* OSThread::GetOSThreadFromThread(Thread* thread) {
139 ASSERT(thread->os_thread() != NULL);
140 return thread->os_thread();
141 }
142
143
144 void OSThread::AddThreadToList(OSThread* thread) {
145 ASSERT(thread != NULL);
146 ASSERT(thread_list_lock_ != NULL);
147 MutexLocker ml(thread_list_lock_);
148
149 ASSERT(thread->thread_list_next_ == NULL);
150
151 #if defined(DEBUG)
152 {
153 // Ensure that we aren't already in the list.
154 OSThread* current = thread_list_head_;
155 while (current != NULL) {
156 ASSERT(current != thread);
157 current = current->thread_list_next_;
158 }
159 }
160 #endif
161
162 // Insert at head of list.
163 thread->thread_list_next_ = thread_list_head_;
164 thread_list_head_ = thread;
165 }
166
167
168 void OSThread::RemoveThreadFromList(OSThread* thread) {
169 ASSERT(thread != NULL);
170 ASSERT(thread_list_lock_ != NULL);
171 MutexLocker ml(thread_list_lock_);
172 OSThread* current = thread_list_head_;
173 OSThread* previous = NULL;
174
175 // Scan across list and remove |thread|.
176 while (current != NULL) {
177 if (current == thread) {
178 // We found |thread|, remove from list.
179 if (previous == NULL) {
180 thread_list_head_ = thread->thread_list_next_;
181 } else {
182 previous->thread_list_next_ = current->thread_list_next_;
183 }
184 thread->thread_list_next_ = NULL;
185 return;
186 }
187 previous = current;
188 current = current->thread_list_next_;
189 }
190 UNREACHABLE();
191 }
192
193
194 void OSThread::SetCurrent(OSThread* current) {
195 OSThread::SetThreadLocal(thread_key_, reinterpret_cast<uword>(current));
196 }
197
198
199 OSThreadIterator::OSThreadIterator() {
200 ASSERT(OSThread::thread_list_lock_ != NULL);
201 // Lock the thread list while iterating.
202 OSThread::thread_list_lock_->Lock();
203 next_ = OSThread::thread_list_head_;
204 }
205
206
207 OSThreadIterator::~OSThreadIterator() {
208 ASSERT(OSThread::thread_list_lock_ != NULL);
209 // Unlock the thread list when done.
210 OSThread::thread_list_lock_->Unlock();
211 }
212
213
214 bool OSThreadIterator::HasNext() const {
215 ASSERT(OSThread::thread_list_lock_ != NULL);
216 ASSERT(OSThread::thread_list_lock_->IsOwnedByCurrentThread());
217 return next_ != NULL;
218 }
219
220
221 OSThread* OSThreadIterator::Next() {
222 ASSERT(OSThread::thread_list_lock_ != NULL);
223 ASSERT(OSThread::thread_list_lock_->IsOwnedByCurrentThread());
224 OSThread* current = next_;
225 next_ = next_->thread_list_next_;
226 return current;
227 }
228
229 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698