• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 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 "native_async_work.h"
17 
18 #ifdef ENABLE_HITRACE
19 #include "hitrace/trace.h"
20 #include "hitrace_meter.h"
21 #include "parameter.h"
22 #include <securec.h>
23 #endif
24 #ifdef ENABLE_CONTAINER_SCOPE
25 #include "core/common/container_scope.h"
26 #endif
27 
28 #include "napi/native_api.h"
29 #include "native_engine.h"
30 #include "utils/log.h"
31 
32 #ifdef ENABLE_CONTAINER_SCOPE
33 using OHOS::Ace::ContainerScope;
34 #endif
35 
36 #ifdef ENABLE_HITRACE
37 bool g_napiTraceIdEnabled = false;
38 bool g_ParamUpdated = false;
39 constexpr size_t TRACE_BUFFER_SIZE = 120;
40 constexpr size_t TRACEID_PARAM_SIZE = 10;
41 #endif
42 
NativeAsyncWork(NativeEngine * engine,NativeAsyncExecuteCallback execute,NativeAsyncCompleteCallback complete,const std::string & asyncResourceName,void * data)43 NativeAsyncWork::NativeAsyncWork(NativeEngine* engine,
44                                  NativeAsyncExecuteCallback execute,
45                                  NativeAsyncCompleteCallback complete,
46                                  const std::string &asyncResourceName,
47                                  void* data)
48     : work_({ 0 }), engine_(engine), execute_(execute), complete_(complete), data_(data)
49 {
50     work_.data = this;
51     (void)asyncResourceName;
52 #ifdef ENABLE_HITRACE
53     if (!g_ParamUpdated) {
54         char napiTraceIdEnabled[TRACEID_PARAM_SIZE] = {0};
55         int ret = GetParameter("persist.hiviewdfx.napitraceid.enabled", "false",
56             napiTraceIdEnabled, sizeof(napiTraceIdEnabled));
57         if (ret > 0 && strcmp(napiTraceIdEnabled, "true") == 0) {
58             g_napiTraceIdEnabled = true;
59         }
60         g_ParamUpdated = true;
61     }
62     bool createdTraceId = false;
63     traceId_ = std::make_unique<OHOS::HiviewDFX::HiTraceId>(OHOS::HiviewDFX::HiTraceChain::GetId());
64     if (g_napiTraceIdEnabled && (!traceId_ || !traceId_->IsValid())) {
65         traceId_ = std::make_unique<OHOS::HiviewDFX::HiTraceId>(
66             OHOS::HiviewDFX::HiTraceChain::Begin("New NativeAsyncWork", 0));
67         createdTraceId = true;
68     }
69     char traceStr[TRACE_BUFFER_SIZE] = {0};
70     if (sprintf_s(traceStr, sizeof(traceStr),
71         "name:%s, traceid:0x%x", asyncResourceName.c_str(), traceId_->GetChainId()) < 0) {
72         HILOG_ERROR("Get traceStr fail");
73     }
74     traceDescription_ = traceStr;
75     if (createdTraceId) {
76         OHOS::HiviewDFX::HiTraceChain::ClearId();
77     }
78 #endif
79 #ifdef ENABLE_CONTAINER_SCOPE
80     containerScopeId_ = ContainerScope::CurrentId();
81 #endif
82 }
83 
84 NativeAsyncWork::~NativeAsyncWork() = default;
85 
Queue()86 bool NativeAsyncWork::Queue()
87 {
88     uv_loop_t* loop = engine_->GetUVLoop();
89     if (loop == nullptr) {
90         HILOG_ERROR("Get loop failed");
91         return false;
92     }
93     engine_->IncreaseWaitingRequestCounter();
94 #ifdef ENABLE_HITRACE
95     StartTrace(HITRACE_TAG_ACE, "Napi queue, " + this->GetTraceDescription());
96 #endif
97     int status = uv_queue_work(loop, &work_, AsyncWorkCallback, AsyncAfterWorkCallback);
98 #ifdef ENABLE_HITRACE
99     FinishTrace(HITRACE_TAG_ACE);
100 #endif
101     if (status != 0) {
102         HILOG_ERROR("uv_queue_work failed");
103         return false;
104     }
105     return true;
106 }
107 
QueueWithQos(napi_qos_t qos)108 bool NativeAsyncWork::QueueWithQos(napi_qos_t qos)
109 {
110     uv_loop_t* loop = engine_->GetUVLoop();
111     if (loop == nullptr) {
112         HILOG_ERROR("Get loop failed");
113         return false;
114     }
115     engine_->IncreaseWaitingRequestCounter();
116 #ifdef ENABLE_HITRACE
117     StartTrace(HITRACE_TAG_ACE, "Napi queueWithQos, " + this->GetTraceDescription());
118 #endif
119     int status = uv_queue_work_with_qos(loop, &work_, AsyncWorkCallback, AsyncAfterWorkCallback, uv_qos_t(qos));
120 #ifdef ENABLE_HITRACE
121     FinishTrace(HITRACE_TAG_ACE);
122 #endif
123     if (status != 0) {
124         HILOG_ERROR("uv_queue_work_with_qos failed");
125         return false;
126     }
127     return true;
128 }
129 
Cancel()130 bool NativeAsyncWork::Cancel()
131 {
132     int status = uv_cancel((uv_req_t*)&work_);
133     if (status != 0) {
134         HILOG_ERROR("uv_cancel failed");
135         return false;
136     }
137     return true;
138 }
139 
AsyncWorkCallback(uv_work_t * req)140 void NativeAsyncWork::AsyncWorkCallback(uv_work_t* req)
141 {
142     if (req == nullptr) {
143         HILOG_ERROR("req is nullptr");
144         return;
145     }
146 
147     auto that = reinterpret_cast<NativeAsyncWork*>(req->data);
148 
149 #ifdef ENABLE_CONTAINER_SCOPE
150     ContainerScope containerScope(that->containerScopeId_);
151 #endif
152 #ifdef ENABLE_HITRACE
153     StartTrace(HITRACE_TAG_ACE, "Napi execute, " + that->GetTraceDescription());
154     if (that->traceId_ && that->traceId_->IsValid()) {
155         OHOS::HiviewDFX::HiTraceChain::SetId(*(that->traceId_.get()));
156         that->execute_(that->engine_, that->data_);
157         FinishTrace(HITRACE_TAG_ACE);
158         OHOS::HiviewDFX::HiTraceChain::ClearId();
159         return;
160     }
161 #endif
162     that->execute_(that->engine_, that->data_);
163 #ifdef ENABLE_HITRACE
164     FinishTrace(HITRACE_TAG_ACE);
165 #endif
166 }
167 
AsyncAfterWorkCallback(uv_work_t * req,int status)168 void NativeAsyncWork::AsyncAfterWorkCallback(uv_work_t* req, int status)
169 {
170     if (req == nullptr) {
171         HILOG_ERROR("req is nullptr");
172         return;
173     }
174 
175     auto that = reinterpret_cast<NativeAsyncWork*>(req->data);
176 
177     NativeScopeManager* scopeManager = that->engine_->GetScopeManager();
178     that->engine_->DecreaseWaitingRequestCounter();
179     if (scopeManager == nullptr) {
180         HILOG_ERROR("Get scope manager failed");
181         return;
182     }
183 
184     NativeScope* scope = scopeManager->Open();
185     if (scope == nullptr) {
186         HILOG_ERROR("Open scope failed");
187         return;
188     }
189 
190     napi_status nstatus = napi_generic_failure;
191     switch (status) {
192         case 0:
193             nstatus = napi_ok;
194             break;
195         case (int)UV_EINVAL:
196             nstatus = napi_invalid_arg;
197             break;
198         case (int)UV_ECANCELED:
199             nstatus = napi_cancelled;
200             break;
201         default:
202             nstatus = napi_generic_failure;
203     }
204 #ifdef ENABLE_CONTAINER_SCOPE
205     ContainerScope containerScope(that->containerScopeId_);
206 #endif
207 #ifdef ENABLE_HITRACE
208     StartTrace(HITRACE_TAG_ACE, "Napi complete, " + that->GetTraceDescription());
209     if (that->traceId_ && that->traceId_->IsValid()) {
210         OHOS::HiviewDFX::HiTraceChain::SetId(*(that->traceId_.get()));
211         that->complete_(that->engine_, nstatus, that->data_);
212         FinishTrace(HITRACE_TAG_ACE);
213         OHOS::HiviewDFX::HiTraceChain::ClearId();
214         scopeManager->Close(scope);
215         return;
216     }
217 #endif
218     that->complete_(that->engine_, nstatus, that->data_);
219 #ifdef ENABLE_HITRACE
220     FinishTrace(HITRACE_TAG_ACE);
221 #endif
222     scopeManager->Close(scope);
223 }
224 
GetTraceDescription()225 std::string NativeAsyncWork::GetTraceDescription()
226 {
227     return traceDescription_;
228 }
229