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

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 current threads TLS, should result in the global OSThread
103 // list to become empty.
104 OSThread* thread = OSThread::Current();
105 ASSERT(thread != NULL);
106 OSThread::SetCurrent(NULL);
107
zra 2015/11/16 20:12:28 Does thread need to be deleted? After that, I thi
siva 2015/11/17 20:52:25 As discussed offline moved the deletion of TLS to
108 // Delete the thread local key.
109 ASSERT(thread_key_ != kUnsetThreadLocalKey);
110 DeleteThreadLocal(thread_key_);
111 thread_key_ = kUnsetThreadLocalKey;
112
113 // Delete the global OSThread lock.
114 ASSERT(thread_list_lock_ != NULL);
115 delete thread_list_lock_;
116 thread_list_lock_ = NULL;
117 }
118 }
119
120
121 bool OSThread::IsThreadInList(ThreadId join_id) {
122 if (join_id == OSThread::kInvalidThreadJoinId) {
123 return false;
124 }
125 OSThreadIterator it;
126 while (it.HasNext()) {
127 ASSERT(OSThread::thread_list_lock_->IsOwnedByCurrentThread());
128 OSThread* t = it.Next();
129 // An address test is not sufficient because the allocator may recycle
130 // the address for another Thread. Test against the thread's join id.
131 if (t->join_id() == join_id) {
132 return true;
133 }
134 }
135 return false;
136 }
137
138
139 OSThread* OSThread::GetOSThreadFromThread(Thread* thread) {
140 ASSERT(thread->os_thread() != NULL);
141 return thread->os_thread();
142 }
143
144
145 void OSThread::AddThreadToList(OSThread* thread) {
146 ASSERT(thread != NULL);
147 ASSERT(thread_list_lock_ != NULL);
148 MutexLocker ml(thread_list_lock_);
149
150 ASSERT(thread->thread_list_next_ == NULL);
151
152 #if defined(DEBUG)
153 {
154 // Ensure that we aren't already in the list.
155 OSThread* current = thread_list_head_;
156 while (current != NULL) {
157 ASSERT(current != thread);
158 current = current->thread_list_next_;
159 }
160 }
161 #endif
162
163 // Insert at head of list.
164 thread->thread_list_next_ = thread_list_head_;
165 thread_list_head_ = thread;
166 }
167
168
169 void OSThread::RemoveThreadFromList(OSThread* thread) {
170 ASSERT(thread != NULL);
171 ASSERT(thread_list_lock_ != NULL);
172 MutexLocker ml(thread_list_lock_);
173 OSThread* current = thread_list_head_;
174 OSThread* previous = NULL;
175
176 // Scan across list and remove |thread|.
177 while (current != NULL) {
178 if (current == thread) {
179 // We found |thread|, remove from list.
180 if (previous == NULL) {
181 thread_list_head_ = thread->thread_list_next_;
182 } else {
183 previous->thread_list_next_ = current->thread_list_next_;
184 }
185 thread->thread_list_next_ = NULL;
186 return;
187 }
188 previous = current;
189 current = current->thread_list_next_;
190 }
191 UNREACHABLE();
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