• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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