1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "ecmascript/dfx/cpu_profiler/sampling_processor.h"
17
18 #include <csignal>
19 #include <pthread.h>
20 #include <sys/time.h>
21 #include <unistd.h>
22
23 #include "ecmascript/base/config.h"
24 #include "ecmascript/dfx/cpu_profiler/cpu_profiler.h"
25 #include "ecmascript/dfx/cpu_profiler/samples_record.h"
26 #include "ecmascript/ecma_vm.h"
27 #include "ecmascript/log_wrapper.h"
28
29 namespace panda::ecmascript {
30 const int USEC_PER_SEC = 1000 * 1000;
31 const int NSEC_PER_USEC = 1000;
SamplingProcessor(int32_t id,SamplesRecord * generator,int interval)32 SamplingProcessor::SamplingProcessor(int32_t id, SamplesRecord *generator, int interval) : Task(id)
33 {
34 generator_ = generator;
35 interval_ = static_cast<uint32_t>(interval);
36 pid_ = pthread_self();
37 }
~SamplingProcessor()38 SamplingProcessor::~SamplingProcessor() {}
39
Run(uint32_t threadIndex)40 bool SamplingProcessor::Run([[maybe_unused]] uint32_t threadIndex)
41 {
42 pthread_t tid = pthread_self();
43 pthread_setname_np(tid, "SamplingThread");
44 uint64_t startTime = GetMicrosecondsTimeStamp();
45 uint64_t endTime = startTime;
46 generator_->SetThreadStartTime(startTime);
47 while (generator_->GetIsStart()) {
48 if (pthread_kill(pid_, SIGPROF) != 0) {
49 LOG(ERROR, RUNTIME) << "pthread_kill signal failed";
50 return false;
51 }
52 if (generator_->SemWait(0) != 0) {
53 LOG_ECMA(ERROR) << "sem_[0] wait failed";
54 return false;
55 }
56 startTime = GetMicrosecondsTimeStamp();
57 int64_t ts = static_cast<int64_t>(interval_) - static_cast<int64_t>(startTime - endTime);
58 endTime = startTime;
59 if (ts > 0) {
60 usleep(ts);
61 endTime = GetMicrosecondsTimeStamp();
62 }
63 if (generator_->GetMethodNodeCount() + generator_->GetframeStackLength() >= MAX_NODE_COUNT) {
64 break;
65 }
66 if (generator_->samplesQueue_->IsEmpty()) {
67 generator_->AddRootSample();
68 } else {
69 while (!generator_->samplesQueue_->IsEmpty()) {
70 FrameStackAndInfo *frame = generator_->samplesQueue_->PopFrame();
71 generator_->AddSample(frame);
72 }
73 }
74 generator_->SetIsBreakSampleFlag(false);
75 }
76 generator_->SetThreadStopTime();
77 pthread_setname_np(tid, "GC_WorkerThread");
78 if (generator_->SemPost(1) != 0) {
79 LOG_ECMA(ERROR) << "sem_[1] post failed";
80 return false;
81 }
82 return true;
83 }
84
GetMicrosecondsTimeStamp()85 uint64_t SamplingProcessor::GetMicrosecondsTimeStamp()
86 {
87 struct timespec time;
88 clock_gettime(CLOCK_MONOTONIC, &time);
89 return time.tv_sec * USEC_PER_SEC + time.tv_nsec / NSEC_PER_USEC;
90 }
91 } // namespace panda::ecmascript
92