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

Unified Diff: runtime/platform/thread_win.cc

Issue 25909002: Sampling profiler (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/platform/thread_win.h ('k') | runtime/vm/dart.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/platform/thread_win.cc
diff --git a/runtime/platform/thread_win.cc b/runtime/platform/thread_win.cc
index e8be678cb6d0a1563aa38995f136ea9821cd4c91..d3712d299677cd600627b26835e0936528df5b3e 100644
--- a/runtime/platform/thread_win.cc
+++ b/runtime/platform/thread_win.cc
@@ -39,12 +39,24 @@ static unsigned int __stdcall ThreadEntry(void* data_ptr) {
uword parameter = data->parameter();
delete data;
+ ASSERT(ThreadInlineImpl::thread_id_key != Thread::kUnsetThreadLocalKey);
+
+ ThreadId thread_id = ThreadInlineImpl::CreateThreadId();
+ // Set thread ID in TLS.
+ Thread::SetThreadLocal(ThreadInlineImpl::thread_id_key,
+ reinterpret_cast<DWORD>(thread_id));
+ MonitorData::GetMonitorWaitDataForThread();
+
// Call the supplied thread start function handing it its parameters.
function(parameter);
// Clean up the monitor wait data for this thread.
MonitorWaitData::ThreadExit();
+ // Clear thread ID in TLS.
+ Thread::SetThreadLocal(ThreadInlineImpl::thread_id_key, NULL);
+ ThreadInlineImpl::DestroyThreadId(thread_id);
+
return 0;
}
@@ -65,6 +77,27 @@ int Thread::Start(ThreadStartFunction function, uword parameter) {
}
+ThreadId ThreadInlineImpl::CreateThreadId() {
+ // Create an ID for this thread that can be shared with other threads.
+ HANDLE thread_id = OpenThread(THREAD_GET_CONTEXT |
+ THREAD_SUSPEND_RESUME |
+ THREAD_QUERY_INFORMATION,
+ false,
+ GetCurrentThreadId());
+ ASSERT(thread_id != NULL);
+ return thread_id;
+}
+
+
+void ThreadInlineImpl::DestroyThreadId(ThreadId thread_id) {
+ ASSERT(thread_id != NULL);
+ // Destroy thread ID.
+ CloseHandle(thread_id);
+}
+
+
+ThreadLocalKey ThreadInlineImpl::thread_id_key = Thread::kUnsetThreadLocalKey;
+
ThreadLocalKey Thread::kUnsetThreadLocalKey = TLS_OUT_OF_INDEXES;
@@ -92,6 +125,44 @@ intptr_t Thread::GetMaxStackSize() {
}
+ThreadId Thread::GetCurrentThreadId() {
+ ThreadId id = reinterpret_cast<ThreadId>(
+ Thread::GetThreadLocal(ThreadInlineImpl::thread_id_key));
+ ASSERT(id != NULL);
+ return id;
+}
+
+
+void Thread::GetThreadCpuUsage(ThreadId thread_id, int64_t* cpu_usage) {
+ static const int64_t kTimeEpoc = 116444736000000000LL;
+ static const int64_t kTimeScaler = 10; // 100 ns to us.
+ // Although win32 uses 64-bit integers for representing timestamps,
+ // these are packed into a FILETIME structure. The FILETIME
+ // structure is just a struct representing a 64-bit integer. The
+ // TimeStamp union allows access to both a FILETIME and an integer
+ // representation of the timestamp. The Windows timestamp is in
+ // 100-nanosecond intervals since January 1, 1601.
+ union TimeStamp {
+ FILETIME ft_;
+ int64_t t_;
+ };
+ ASSERT(cpu_usage != NULL);
+ TimeStamp created;
+ TimeStamp exited;
+ TimeStamp kernel;
+ TimeStamp user;
+ BOOL result = GetThreadTimes(thread_id,
+ &created.ft_,
+ &exited.ft_,
+ &kernel.ft_,
+ &user.ft_);
+ if (!result) {
+ FATAL1("GetThreadCpuUsage failed %d\n", GetLastError());
+ }
+ *cpu_usage = (user.t_ - kTimeEpoc) / kTimeScaler;
+}
+
+
void Thread::SetThreadLocal(ThreadLocalKey key, uword value) {
ASSERT(key != kUnsetThreadLocalKey);
BOOL result = TlsSetValue(key, reinterpret_cast<void*>(value));
@@ -241,6 +312,8 @@ void MonitorData::SignalAndRemoveFirstWaiter() {
} else {
waiters_head_ = waiters_head_->next_;
}
+ // Clear next.
+ first->next_ = NULL;
// Signal event.
BOOL result = SetEvent(first->event_);
if (result == 0) {
@@ -259,11 +332,16 @@ void MonitorData::SignalAndRemoveAllWaiters() {
waiters_head_ = waiters_tail_ = NULL;
// Iterate and signal all events.
while (current != NULL) {
+ // Copy next.
+ MonitorWaitData* next = current->next_;
+ // Clear next.
+ current->next_ = NULL;
+ // Signal event.
BOOL result = SetEvent(current->event_);
if (result == 0) {
FATAL1("Failed to set event for NotifyAll %d", GetLastError());
}
- current = current->next_;
+ current = next;
}
LeaveCriticalSection(&waiters_cs_);
}
@@ -272,11 +350,8 @@ void MonitorData::SignalAndRemoveAllWaiters() {
MonitorWaitData* MonitorData::GetMonitorWaitDataForThread() {
// Ensure that the thread local key for monitor wait data objects is
// initialized.
- EnterCriticalSection(&waiters_cs_);
- if (MonitorWaitData::monitor_wait_data_key_ == Thread::kUnsetThreadLocalKey) {
- MonitorWaitData::monitor_wait_data_key_ = Thread::CreateThreadLocal();
- }
- LeaveCriticalSection(&waiters_cs_);
+ ASSERT(MonitorWaitData::monitor_wait_data_key_ !=
+ Thread::kUnsetThreadLocalKey);
// Get the MonitorWaitData object containing the event for this
// thread from thread local storage. Create it if it does not exist.
@@ -300,7 +375,7 @@ Monitor::WaitResult Monitor::Wait(int64_t millis) {
Monitor::WaitResult retval = kNotified;
// Get the wait data object containing the event to wait for.
- MonitorWaitData* wait_data = data_.GetMonitorWaitDataForThread();
+ MonitorWaitData* wait_data = MonitorData::GetMonitorWaitDataForThread();
// Start waiting by adding the MonitorWaitData to the list of
// waiters.
@@ -338,6 +413,19 @@ Monitor::WaitResult Monitor::Wait(int64_t millis) {
}
+Monitor::WaitResult Monitor::WaitMicros(int64_t micros) {
+ // TODO(johnmccutchan): Investigate sub-millisecond sleep times on Windows.
+ int64_t millis = micros / kMicrosecondsPerMillisecond;
+ if ((millis * kMicrosecondsPerMillisecond) < micros) {
+ // We've been asked to sleep for a fraction of a millisecond,
+ // this isn't supported on Windows. Bumps milliseconds up by one
+ // so that we never return too early. We likely return late though.
+ millis += 1;
+ }
+ return Wait(millis);
+}
+
+
void Monitor::Notify() {
data_.SignalAndRemoveFirstWaiter();
}
« no previous file with comments | « runtime/platform/thread_win.h ('k') | runtime/vm/dart.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698