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

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

Powered by Google App Engine
This is Rietveld 408576698