• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved.
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 "ffrt_profiler_socker_client.h"
17 
18 #include "ffrt_profiler_common.h"
19 #include "ffrt_profiler.h"
20 
21 namespace {
22 std::atomic<uint64_t> g_flushCount = 0;
23 std::atomic<bool> g_disableHook = false;
24 constexpr uint32_t FILTER_SIZE = (1 << 10);
25 } // namespace
26 
27 namespace OHOS::Developtools::Profiler {
FfrtProfilerSocketClient(int pid,FfrtProfiler * profiler,void (* disableHookCallback)())28 FfrtProfilerSocketClient::FfrtProfilerSocketClient(int pid, FfrtProfiler* profiler, void (*disableHookCallback)())
29     : pid_(pid), disableHookCallback_(disableHookCallback), profiler_(profiler)
30 {
31     smbFd_ = 0;
32     eventFd_ = 0;
33     unixSocketClient_ = nullptr;
34     serviceName_ = "FfrtProfilerService";
35     Connect(FFRT_PROFILER_UNIX_SOCKET_FULL_PATH);
36 }
37 
~FfrtProfilerSocketClient()38 FfrtProfilerSocketClient::~FfrtProfilerSocketClient()
39 {
40     if (writer_) {
41         writer_->Flush();
42     }
43     unixSocketClient_ = nullptr;
44     writer_ = nullptr;
45 }
46 
Connect(const std::string addrname)47 bool FfrtProfilerSocketClient::Connect(const std::string addrname)
48 {
49     if (unixSocketClient_ != nullptr) {
50         return false;
51     }
52     unixSocketClient_ = std::make_shared<UnixSocketClient>();
53     if (!unixSocketClient_->Connect(addrname, *this)) {
54         unixSocketClient_ = nullptr;
55         return false;
56     }
57 
58     unixSocketClient_->SendHookConfig(reinterpret_cast<uint8_t *>(&pid_), sizeof(pid_));
59     return true;
60 }
61 
ProtocolProc(SocketContext & context,uint32_t pnum,const int8_t * buf,const uint32_t size)62 bool FfrtProfilerSocketClient::ProtocolProc(SocketContext &context, uint32_t pnum, const int8_t *buf,
63     const uint32_t size)
64 {
65     CHECK_TRUE(size == sizeof(FfrtConfig), true, "FfrtProfilerSocketClient config size not match = %u\n", size);
66     FfrtConfig* config = reinterpret_cast<FfrtConfig *>(const_cast<int8_t*>(buf));
67     smbFd_ = context.ReceiveFileDiscriptor();
68     eventFd_ = context.ReceiveFileDiscriptor();
69     PROFILER_LOG_INFO(LOG_CORE, "ffrt profiler client: smbFd: %d, eventFd: %d, shmSize: %d",
70         smbFd_, eventFd_, config->shmSize);
71 
72     flushInterval_ = static_cast<uint32_t>(config->flushCount);
73     block_ = config->block;
74     profiler_->SetClockId(config->clock);
75     PROFILER_LOG_INFO(LOG_CORE, "ffrt profiler client: flushInterval: %d, block: %d, clock: %d",
76         flushInterval_, block_, config->clock);
77 
78     std::string smbName = "ffrtProfilerSmb_" + std::to_string(pid_);
79     writer_ = std::make_shared<FfrtProfilerWriter>(smbName, config->shmSize, smbFd_, eventFd_, config->block);
80     profiler_->SetEnableFlag(true);
81     return true;
82 }
83 
SendFfrtProfilerData(const void * data,size_t size,const void * payload,size_t payloadSize)84 bool FfrtProfilerSocketClient::SendFfrtProfilerData(const void* data, size_t size, const void* payload,
85     size_t payloadSize)
86 {
87     if (writer_ == nullptr || unixSocketClient_ == nullptr || g_disableHook) {
88         return false;
89     } else if (unixSocketClient_->GetClientState() == CLIENT_STAT_THREAD_EXITED) {
90         DisableHook();
91         return false;
92     }
93 
94     if (payloadSize > FILTER_SIZE) {
95         PROFILER_LOG_ERROR(LOG_CORE, "payloadSize exceeds the maximum of %d bytes", FILTER_SIZE);
96         return false;
97     }
98     bool ret = writer_->WriteWithPayloadTimeout(
99         data,
100         size,
101         payload,
102         payloadSize,
103         std::bind(&FfrtProfilerSocketClient::PeerIsConnected, this));
104     if (!ret && block_) {
105         DisableHook();
106         return false;
107     }
108     if (++g_flushCount % flushInterval_ == 0) {
109         writer_->Flush();
110     }
111     return true;
112 }
113 
Flush()114 void FfrtProfilerSocketClient::Flush()
115 {
116     if (writer_ == nullptr || unixSocketClient_ == nullptr) {
117         return;
118     }
119     writer_->Flush();
120 }
121 
DisableHook()122 void FfrtProfilerSocketClient::DisableHook()
123 {
124     bool expected = false;
125     if (g_disableHook.compare_exchange_strong(expected, true, std::memory_order_release, std::memory_order_relaxed)) {
126         PROFILER_LOG_INFO(LOG_CORE, "%s", __func__);
127         if (disableHookCallback_ != nullptr) {
128             disableHookCallback_();
129         }
130     }
131 }
132 
PeerIsConnected()133 bool FfrtProfilerSocketClient::PeerIsConnected()
134 {
135     if (unixSocketClient_ == nullptr) {
136         return false;
137     }
138     return !unixSocketClient_->IsConnected();
139 }
140 }