• 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 "ipc_workthread.h"
17 
18 #include <cmath>
19 #include <cstddef>
20 #include <memory>
21 #include <pthread.h>
22 #include <sys/prctl.h>
23 #include <sys/syscall.h>
24 #include <unistd.h>
25 
26 #include "hilog/log_cpp.h"
27 #include "iosfwd"
28 #include "ipc_debug.h"
29 #include "ipc_process_skeleton.h"
30 #include "ipc_thread_skeleton.h"
31 #include "iremote_invoker.h"
32 #include "process_skeleton.h"
33 #include "string"
34 #include "type_traits"
35 #include "unistd.h"
36 
37 namespace OHOS {
38 #ifdef CONFIG_IPC_SINGLE
39 namespace IPC_SINGLE {
40 #endif
41 
42 static constexpr OHOS::HiviewDFX::HiLogLabel LOG_LABEL = { LOG_CORE, LOG_ID_IPC_COMMON, "IPCWorkThread" };
43 
44 struct IPCWorkThreadParam {
45     int proto;
46     int policy;
47     int index;
48 };
49 
IPCWorkThread(std::string threadName)50 IPCWorkThread::IPCWorkThread(std::string threadName) : threadName_(std::move(threadName)) {}
51 
~IPCWorkThread()52 IPCWorkThread::~IPCWorkThread()
53 {
54     StopWorkThread();
55 }
56 
MakeBasicThreadName(int proto,int threadIndex)57 std::string IPCWorkThread::MakeBasicThreadName(int proto, int threadIndex)
58 {
59     if (proto == IRemoteObject::IF_PROT_DATABUS) {
60         return "OS_RPC_" + std::to_string(threadIndex);
61     } else {
62         return "OS_IPC_" + std::to_string(threadIndex);
63     }
64 }
65 
JoinThread(int proto,int policy)66 void IPCWorkThread::JoinThread(int proto, int policy)
67 {
68     IRemoteInvoker *invoker = IPCThreadSkeleton::GetRemoteInvoker(proto);
69     if (invoker == nullptr) {
70         ZLOGE(LOG_LABEL, "invoker is nullptr.");
71         return;
72     }
73     switch (policy) {
74         case SPAWN_PASSIVE:
75             invoker->JoinThread(false);
76             break;
77         case SPAWN_ACTIVE:
78             invoker->JoinThread(true);
79             break;
80         case PROCESS_PASSIVE:
81             invoker->JoinProcessThread(false);
82             break;
83         case PROCESS_ACTIVE:
84             invoker->JoinProcessThread(true);
85             break;
86         default:
87             ZLOGE(LOG_LABEL, "invalid policy:%{public}d", policy);
88             break;
89     }
90 }
91 
ThreadHandler(void * args)92 void *IPCWorkThread::ThreadHandler(void *args)
93 {
94     auto param = (IPCWorkThreadParam *)args;
95     if (param == nullptr) {
96         ZLOGE(LOG_LABEL, "param is nullptr.");
97         return nullptr;
98     }
99 
100     (void)IPCThreadSkeleton::SetThreadType(ThreadType::IPC_THREAD);
101     ProcessSkeleton *process = ProcessSkeleton::GetInstance();
102     if (process == nullptr) {
103         ZLOGE(LOG_LABEL, "get ProcessSkeleton object failed");
104         delete param;
105         return nullptr;
106     }
107 
108     if (process->GetThreadStopFlag()) {
109         ZLOGD(LOG_LABEL, "the stop flag is true, thread start exit");
110         delete param;
111         return nullptr;
112     }
113 
114     IRemoteInvoker *invoker = IPCThreadSkeleton::GetRemoteInvoker(param->proto);
115     std::string basicName = MakeBasicThreadName(param->proto, param->index);
116     std::string threadName = basicName + "_" + std::to_string(syscall(SYS_gettid));
117     int32_t ret = prctl(PR_SET_NAME, threadName.c_str());
118     if (ret != 0) {
119         ZLOGE(LOG_LABEL, "set thread name:%{public}s fail, ret:%{public}d", threadName.c_str(), ret);
120     } else {
121         ZLOGD(LOG_LABEL, "proto:%{public}d policy:%{public}d name:%{public}s invoker:%{public}u", param->proto,
122             param->policy, threadName.c_str(), ProcessSkeleton::ConvertAddr(invoker));
123     }
124     IPCThreadSkeleton::SaveThreadName(threadName);
125 
126     JoinThread(param->proto, param->policy);
127 
128     IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
129     if (current == nullptr) {
130         ZLOGE(LOG_LABEL, "current is nullptr.");
131     } else if (!current->OnThreadTerminated(basicName)) {
132         ZLOGE(LOG_LABEL, "OnThreadTerminated is failed.");
133     }
134     ZLOGI(LOG_LABEL, "exit, proto:%{public}d policy:%{public}d name:%{public}s invoker:%{public}u", param->proto,
135         param->policy, threadName.c_str(), ProcessSkeleton::ConvertAddr(invoker));
136     delete param;
137     return nullptr;
138 }
139 
StopWorkThread()140 void IPCWorkThread::StopWorkThread()
141 {
142     IRemoteInvoker *invoker = IPCThreadSkeleton::GetRemoteInvoker(proto_);
143     if (invoker != nullptr) {
144         invoker->StopWorkThread();
145     }
146 }
147 
Start(int policy,int proto,int threadIndex)148 bool IPCWorkThread::Start(int policy, int proto, int threadIndex)
149 {
150     ProcessSkeleton *process = ProcessSkeleton::GetInstance();
151     if (process == nullptr) {
152         ZLOGE(LOG_LABEL, "get ProcessSkeleton object failed");
153         return false;
154     }
155 
156     if (process->GetThreadStopFlag()) {
157         ZLOGD(LOG_LABEL, "the stop flag is true, can not create other thread");
158         return false;
159     }
160 
161     auto param = new (std::nothrow) IPCWorkThreadParam();
162     if (param == nullptr) {
163         ZLOGE(LOG_LABEL, "create IPCWorkThreadParam failed");
164         return false;
165     }
166 
167     policy_ = policy;
168     proto_ = proto;
169     param->policy = policy;
170     param->proto = proto;
171     param->index = threadIndex;
172     pthread_t threadId;
173 
174     int ret = pthread_create(&threadId, NULL, &IPCWorkThread::ThreadHandler, param);
175     if (ret != 0) {
176         ZLOGE(LOG_LABEL, "create thread failed, ret:%{public}d", ret);
177         delete param;
178         return false;
179     }
180     process->IncreaseThreadCount();
181     ZLOGD(LOG_LABEL, "create thread, policy:%{public}d proto:%{public}d", policy, proto);
182     if (pthread_detach(threadId) != 0) {
183         ZLOGE(LOG_LABEL, "detach error");
184         return false;
185     }
186     return true;
187 }
188 #ifdef CONFIG_IPC_SINGLE
189 } // namespace IPC_SINGLE
190 #endif
191 } // namespace OHOS
192