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

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: code-review-comments 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 if (Timeline::recorder() != NULL) {
42 Timeline::recorder()->FinishBlock(timeline_block_);
43 }
44 timeline_block_ = NULL;
45 delete timeline_block_lock_;
46 }
47
48
49 void OSThread::DisableThreadInterrupts() {
50 ASSERT(OSThread::Current() == this);
51 AtomicOperations::FetchAndIncrement(&thread_interrupt_disabled_);
52 }
53
54
55 void OSThread::EnableThreadInterrupts() {
56 ASSERT(OSThread::Current() == this);
57 uintptr_t old =
58 AtomicOperations::FetchAndDecrement(&thread_interrupt_disabled_);
59 if (old == 1) {
60 // We just decremented from 1 to 0.
61 // Make sure the thread interrupter is awake.
62 ThreadInterrupter::WakeUp();
63 }
64 if (old == 0) {
65 // We just decremented from 0, this means we've got a mismatched pair
66 // of calls to EnableThreadInterrupts and DisableThreadInterrupts.
67 FATAL("Invalid call to OSThread::EnableThreadInterrupts()");
68 }
69 }
70
71
72 bool OSThread::ThreadInterruptsEnabled() {
73 return AtomicOperations::LoadRelaxed(&thread_interrupt_disabled_) == 0;
74 }
75
76
77 static void DeleteThread(void* thread) {
78 delete reinterpret_cast<OSThread*>(thread);
79 }
80
81
82 void OSThread::InitOnce() {
83 // Allocate the global OSThread lock.
84 ASSERT(thread_list_lock_ == NULL);
85 thread_list_lock_ = new Mutex();
86 ASSERT(thread_list_lock_ != NULL);
87
88 // Create the thread local key.
89 ASSERT(thread_key_ == kUnsetThreadLocalKey);
90 thread_key_ = CreateThreadLocal(DeleteThread);
91 ASSERT(thread_key_ != kUnsetThreadLocalKey);
92
93 // Create a new OSThread strcture and set it as the TLS.
94 OSThread* os_thread = new OSThread();
95 OSThread::SetCurrent(os_thread);
96 os_thread->set_name("Dart_Initialize");
97 }
98
99
100 void OSThread::Cleanup() {
101 if (thread_list_lock_ != NULL) {
102 // Delete the thread local key.
103 ASSERT(thread_key_ != kUnsetThreadLocalKey);
104 DeleteThreadLocal(thread_key_);
105 thread_key_ = kUnsetThreadLocalKey;
106
107 // Delete the global OSThread lock.
108 ASSERT(thread_list_lock_ != NULL);
109 delete thread_list_lock_;
110 thread_list_lock_ = NULL;
111 }
112 }
113
114
115 bool OSThread::IsThreadInList(ThreadId join_id) {
116 if (join_id == OSThread::kInvalidThreadJoinId) {
117 return false;
118 }
119 OSThreadIterator it;
120 while (it.HasNext()) {
121 ASSERT(OSThread::thread_list_lock_->IsOwnedByCurrentThread());
122 OSThread* t = it.Next();
123 // An address test is not sufficient because the allocator may recycle
124 // the address for another Thread. Test against the thread's join id.
125 if (t->join_id() == join_id) {
126 return true;
127 }
128 }
129 return false;
130 }
131
132
133 OSThread* OSThread::GetOSThreadFromThread(Thread* thread) {
134 ASSERT(thread->os_thread() != NULL);
135 return thread->os_thread();
136 }
137
138
139 void OSThread::AddThreadToList(OSThread* thread) {
140 ASSERT(thread != NULL);
141 ASSERT(thread_list_lock_ != NULL);
142 MutexLocker ml(thread_list_lock_);
143
144 ASSERT(thread->thread_list_next_ == NULL);
145
146 #if defined(DEBUG)
147 {
148 // Ensure that we aren't already in the list.
149 OSThread* current = thread_list_head_;
150 while (current != NULL) {
151 ASSERT(current != thread);
152 current = current->thread_list_next_;
153 }
154 }
155 #endif
156
157 // Insert at head of list.
158 thread->thread_list_next_ = thread_list_head_;
159 thread_list_head_ = thread;
160 }
161
162
163 void OSThread::RemoveThreadFromList(OSThread* thread) {
164 {
165 ASSERT(thread != NULL);
166 ASSERT(thread_list_lock_ != NULL);
167 MutexLocker ml(thread_list_lock_);
168 OSThread* current = thread_list_head_;
169 OSThread* previous = NULL;
170
171 // Scan across list and remove |thread|.
172 while (current != NULL) {
173 if (current == thread) {
174 // We found |thread|, remove from list.
175 if (previous == NULL) {
176 thread_list_head_ = thread->thread_list_next_;
177 } else {
178 previous->thread_list_next_ = current->thread_list_next_;
179 }
180 thread->thread_list_next_ = NULL;
181 break;
182 }
183 previous = current;
184 current = current->thread_list_next_;
185 }
186 }
187 // Check if this is the last thread. The last thread does a cleanup
188 // which removes the thread local key and the associated mutex.
189 if (thread_list_head_ == NULL) {
190 Cleanup();
191 }
192 }
193
194
195 void OSThread::SetCurrent(OSThread* current) {
196 OSThread::SetThreadLocal(thread_key_, reinterpret_cast<uword>(current));
197 }
198
199
200 OSThreadIterator::OSThreadIterator() {
201 ASSERT(OSThread::thread_list_lock_ != NULL);
202 // Lock the thread list while iterating.
203 OSThread::thread_list_lock_->Lock();
204 next_ = OSThread::thread_list_head_;
205 }
206
207
208 OSThreadIterator::~OSThreadIterator() {
209 ASSERT(OSThread::thread_list_lock_ != NULL);
210 // Unlock the thread list when done.
211 OSThread::thread_list_lock_->Unlock();
212 }
213
214
215 bool OSThreadIterator::HasNext() const {
216 ASSERT(OSThread::thread_list_lock_ != NULL);
217 ASSERT(OSThread::thread_list_lock_->IsOwnedByCurrentThread());
218 return next_ != NULL;
219 }
220
221
222 OSThread* OSThreadIterator::Next() {
223 ASSERT(OSThread::thread_list_lock_ != NULL);
224 ASSERT(OSThread::thread_list_lock_->IsOwnedByCurrentThread());
225 OSThread* current = next_;
226 next_ = next_->thread_list_next_;
227 return current;
228 }
229
230 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698