OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2013, 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 "platform/globals.h" |
| 6 #if defined(TARGET_OS_MACOS) |
| 7 |
| 8 #include "vm/isolate.h" |
| 9 #include "vm/json_stream.h" |
| 10 #include "vm/profiler.h" |
| 11 #include "vm/signal_handler.h" |
| 12 |
| 13 namespace dart { |
| 14 |
| 15 DECLARE_FLAG(bool, profile); |
| 16 |
| 17 static void CollectSample(IsolateProfilerData* profiler_data, |
| 18 uintptr_t pc, |
| 19 uintptr_t fp, |
| 20 uintptr_t sp, |
| 21 uintptr_t stack_lower, |
| 22 uintptr_t stack_upper) { |
| 23 SampleBuffer* sample_buffer = profiler_data->sample_buffer(); |
| 24 Sample* sample = sample_buffer->ReserveSample(); |
| 25 ASSERT(sample != NULL); |
| 26 sample->timestamp = OS::GetCurrentTimeMicros(); |
| 27 // TODO(johnmccutchan): Make real use of vm_tags and runtime_tags. |
| 28 // Issue # 14777 |
| 29 sample->vm_tags = Sample::kExecuting; |
| 30 sample->runtime_tags = 0; |
| 31 int64_t cpu_usage; |
| 32 Thread::GetThreadCpuUsage(profiler_data->thread_id(), &cpu_usage); |
| 33 sample->cpu_usage = profiler_data->ComputeDeltaAndSetCpuUsage(cpu_usage); |
| 34 ProfilerSampleStackWalker stackWalker(sample, stack_lower, stack_upper, |
| 35 pc, fp, sp); |
| 36 stackWalker.walk(); |
| 37 } |
| 38 |
| 39 |
| 40 static void ProfileSignalAction(int signal, siginfo_t* info, void* context_) { |
| 41 if (signal != SIGPROF) { |
| 42 return; |
| 43 } |
| 44 ucontext_t* context = reinterpret_cast<ucontext_t*>(context_); |
| 45 mcontext_t mcontext = context->uc_mcontext; |
| 46 Isolate* isolate = Isolate::Current(); |
| 47 if (isolate == NULL) { |
| 48 return; |
| 49 } |
| 50 // Thread owns no profiler locks at this point. |
| 51 { |
| 52 // Thread owns isolate profiler data mutex. |
| 53 ScopedMutex profiler_data_lock(isolate->profiler_data_mutex()); |
| 54 IsolateProfilerData* profiler_data = isolate->profiler_data(); |
| 55 if (profiler_data == NULL) { |
| 56 return; |
| 57 } |
| 58 |
| 59 uintptr_t stack_lower = 0; |
| 60 uintptr_t stack_upper = 0; |
| 61 isolate->GetStackBounds(&stack_lower, &stack_upper); |
| 62 uintptr_t PC = SignalHandler::GetProgramCounter(mcontext); |
| 63 uintptr_t FP = SignalHandler::GetFramePointer(mcontext); |
| 64 uintptr_t SP = SignalHandler::GetStackPointer(mcontext); |
| 65 |
| 66 stack_lower = SignalHandler::GetStackPointer(mcontext); |
| 67 int64_t sample_time = OS::GetCurrentTimeMicros(); |
| 68 profiler_data->SampledAt(sample_time); |
| 69 CollectSample(profiler_data, PC, FP, SP, stack_lower, stack_upper); |
| 70 } |
| 71 // Thread owns no profiler locks at this point. |
| 72 // This call will acquire both ProfilerManager::monitor and the |
| 73 // isolate's profiler data mutex. |
| 74 ProfilerManager::ScheduleIsolate(isolate); |
| 75 } |
| 76 |
| 77 |
| 78 int64_t ProfilerManager::SampleAndRescheduleIsolates(int64_t current_time) { |
| 79 if (isolates_size_ == 0) { |
| 80 return 0; |
| 81 } |
| 82 static const int64_t max_time = 0x7fffffffffffffffLL; |
| 83 int64_t lowest = max_time; |
| 84 intptr_t i = 0; |
| 85 while (i < isolates_size_) { |
| 86 Isolate* isolate = isolates_[i]; |
| 87 ScopedMutex isolate_lock(isolate->profiler_data_mutex()); |
| 88 IsolateProfilerData* profiler_data = isolate->profiler_data(); |
| 89 ASSERT(profiler_data != NULL); |
| 90 if (profiler_data->ShouldSample(current_time)) { |
| 91 pthread_kill(profiler_data->thread_id(), SIGPROF); |
| 92 RemoveIsolate(i); |
| 93 // Remove moves the last element into i, do not increment i. |
| 94 continue; |
| 95 } |
| 96 if (profiler_data->CanExpire()) { |
| 97 int64_t isolate_time_left = |
| 98 profiler_data->TimeUntilExpiration(current_time); |
| 99 if (isolate_time_left < 0) { |
| 100 continue; |
| 101 } |
| 102 if (isolate_time_left < lowest) { |
| 103 lowest = isolate_time_left; |
| 104 } |
| 105 } |
| 106 i++; |
| 107 } |
| 108 if (isolates_size_ == 0) { |
| 109 return 0; |
| 110 } |
| 111 if (lowest == max_time) { |
| 112 return 0; |
| 113 } |
| 114 ASSERT(lowest != max_time); |
| 115 ASSERT(lowest > 0); |
| 116 return lowest; |
| 117 } |
| 118 |
| 119 |
| 120 void ProfilerManager::ThreadMain(uword parameters) { |
| 121 ASSERT(initialized_); |
| 122 ASSERT(FLAG_profile); |
| 123 SignalHandler::Install(ProfileSignalAction); |
| 124 ScopedMonitor lock(monitor_); |
| 125 while (!shutdown_) { |
| 126 int64_t current_time = OS::GetCurrentTimeMicros(); |
| 127 int64_t next_sample = SampleAndRescheduleIsolates(current_time); |
| 128 lock.WaitMicros(next_sample); |
| 129 } |
| 130 } |
| 131 |
| 132 |
| 133 } // namespace dart |
| 134 |
| 135 #endif // defined(TARGET_OS_MACOS) |
OLD | NEW |