1 /*
2 * Copyright (c) 2020 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 #include "task_manager.h"
16 #include <securec.h>
17 #include <log.h>
18 #include <ohos_errno.h>
19 #include "memory_adapter.h"
20 #include "time_adapter.h"
21 #include "queue_adapter.h"
22 #include "service_impl.h"
23 #include "message_inner.h"
24 #include "samgr_lite_inner.h"
25
26 #undef LOG_TAG
27 #undef LOG_DOMAIN
28 #define LOG_TAG "Samgr"
29 #define LOG_DOMAIN 0xD001800
30
31 #define DONT_WAIT 0
32 static void BeginWork(ServiceImpl *service);
33 static void EndWork(ServiceImpl *service, const Exchange *exchange);
34 static void *TaskEntry(void *);
35 static void ProcRequest(Exchange *exchange, ServiceImpl *serviceImpl);
36 static void ProcDirectRequest(Exchange *exchange);
37 static void ProcResponse(Exchange *exchange);
38 static ServiceImpl *CorrectServiceImpl(Exchange *exchange, ServiceImpl *serviceImpl);
39
SAMGR_CreateFixedTaskPool(const TaskConfig * config,const char * name,uint8 size)40 TaskPool *SAMGR_CreateFixedTaskPool(const TaskConfig *config, const char *name, uint8 size)
41 {
42 if (config == NULL || size == 0 || MAX_TASK_SIZE <= THREAD_Total()) {
43 return NULL;
44 }
45
46 MQueueId queueId = (MQueueId)QUEUE_Create(name, sizeof(Exchange), config->queueSize);
47 if (queueId == NULL) {
48 HILOG_ERROR(HILOG_MODULE_SAMGR, "Create Queue<%s> size:%hu failed!", name, config->queueSize);
49 return NULL;
50 }
51
52 TaskPool *taskPool = (TaskPool *)SAMGR_Malloc(sizeof(TaskPool) + sizeof(ThreadId) * size);
53 if (taskPool == NULL) {
54 HILOG_ERROR(HILOG_MODULE_SAMGR, "Create TaskPool<%s> size:%hu failed!", name, config->queueSize);
55 QUEUE_Destroy(queueId);
56 return NULL;
57 }
58
59 (void)memset_s(taskPool, sizeof(TaskPool) + sizeof(ThreadId) * size, 0,
60 sizeof(TaskPool) + sizeof(ThreadId) * size);
61 taskPool->queueId = queueId;
62 taskPool->stackSize = config->stackSize;
63 taskPool->priority = (uint8)config->priority;
64 taskPool->size = size;
65 taskPool->top = 0;
66 taskPool->ref = 1;
67 return taskPool;
68 }
69
SAMGR_StartTaskPool(TaskPool * pool,const char * name)70 int32 SAMGR_StartTaskPool(TaskPool *pool, const char *name)
71 {
72 if (pool == NULL) {
73 return EC_INVALID;
74 }
75
76 if (pool->top > 0) {
77 return EC_SUCCESS;
78 }
79
80 ThreadAttr attr = {name, pool->stackSize, pool->priority, 0, 0};
81 while (pool->top < pool->size) {
82 register ThreadId threadId = (ThreadId)THREAD_Create(TaskEntry, pool->queueId, &attr);
83 if (threadId == NULL) {
84 HILOG_ERROR(HILOG_MODULE_SAMGR, "Start Task<%s, %hu, %hhu> failed!", name, pool->stackSize, pool->priority);
85 break;
86 }
87 pool->tasks[pool->top] = threadId;
88 ++(pool->top);
89 }
90 return EC_SUCCESS;
91 }
92
SAMGR_ReleaseTaskPool(TaskPool * pool)93 int32 SAMGR_ReleaseTaskPool(TaskPool *pool)
94 {
95 if (pool == NULL) {
96 return EC_INVALID;
97 }
98
99 pool->ref--;
100 if (pool->ref == 0) {
101 Exchange exchange = {0};
102 exchange.type = MSG_EXIT;
103 QUEUE_Put(pool->queueId, &exchange, 0, DONT_WAIT);
104 SAMGR_Free(pool);
105 }
106 return EC_SUCCESS;
107 }
108
SAMGR_ReferenceTaskPool(TaskPool * pool)109 TaskPool *SAMGR_ReferenceTaskPool(TaskPool *pool)
110 {
111 if (pool == NULL) {
112 return NULL;
113 }
114
115 if (pool->ref >= MAX_REF_NUM) {
116 return NULL;
117 }
118
119 pool->ref++;
120 return pool;
121 }
122
TaskEntry(void * argv)123 static void *TaskEntry(void *argv)
124 {
125 ServiceImpl *serviceImpl = NULL;
126 THREAD_SetThreadLocal(argv);
127 while (TRUE) {
128 Exchange exchange;
129 uint32 msgRcvRet = SAMGR_MsgRecv((MQueueId)argv, (uint8 *)&exchange, sizeof(Exchange));
130 if (msgRcvRet != EC_SUCCESS) {
131 continue;
132 }
133
134 if (exchange.type == MSG_EXIT) {
135 SAMGR_FreeMsg(&exchange);
136 break;
137 }
138
139 serviceImpl = CorrectServiceImpl(&exchange, serviceImpl);
140 BeginWork(serviceImpl);
141 ProcResponse(&exchange);
142 ProcDirectRequest(&exchange);
143 ProcRequest(&exchange, serviceImpl);
144 EndWork(serviceImpl, &exchange);
145 SAMGR_FreeMsg(&exchange);
146 }
147 QUEUE_Destroy((MQueueId)argv);
148 return NULL;
149 }
150
ProcRequest(Exchange * exchange,ServiceImpl * serviceImpl)151 static void ProcRequest(Exchange *exchange, ServiceImpl *serviceImpl)
152 {
153 if (serviceImpl == NULL || exchange->type == MSG_ACK || exchange->type == MSG_DIRECT) {
154 return;
155 }
156
157 DEFAULT_MessageHandle(serviceImpl, &(exchange->id), &(exchange->request));
158
159 if (exchange->type == MSG_CON) {
160 SAMGR_SendResponse(&exchange->request, &exchange->response);
161 }
162 }
163
ProcResponse(Exchange * exchange)164 static void ProcResponse(Exchange *exchange)
165 {
166 if (exchange->handler == NULL) {
167 return;
168 }
169
170 if (exchange->type != MSG_ACK) {
171 return;
172 }
173
174 exchange->handler(&exchange->request, &exchange->response);
175 }
176
ProcDirectRequest(Exchange * exchange)177 static void ProcDirectRequest(Exchange *exchange)
178 {
179 if (exchange->handler == NULL) {
180 return;
181 }
182
183 if (exchange->type != MSG_DIRECT) {
184 return;
185 }
186
187 exchange->handler(&exchange->request, &exchange->response);
188 }
189
CorrectServiceImpl(Exchange * exchange,ServiceImpl * serviceImpl)190 static ServiceImpl *CorrectServiceImpl(Exchange *exchange, ServiceImpl *serviceImpl)
191 {
192 if (exchange->type == MSG_ACK) {
193 // The ack message use the last service.
194 return serviceImpl;
195 }
196
197 if (serviceImpl == NULL || serviceImpl->serviceId != exchange->id.serviceId) {
198 serviceImpl = SAMGR_GetServiceByID(exchange->id.serviceId);
199 }
200
201 if (serviceImpl == NULL) {
202 return NULL;
203 }
204
205 return serviceImpl;
206 }
207
SAMGR_GetCurrentQueueID()208 MQueueId SAMGR_GetCurrentQueueID()
209 {
210 return (MQueueId)THREAD_GetThreadLocal();
211 }
212
BeginWork(ServiceImpl * service)213 static void BeginWork(ServiceImpl *service)
214 {
215 if (service == NULL || service->inited != SVC_IDLE) {
216 return;
217 }
218
219 if (service->ops.step == BOOT_SYS_WAIT) {
220 WDT_Start(MSG_PROC_THRESHOLD);
221 }
222
223 service->ops.messages++;
224 service->ops.timestamp = SAMGR_GetProcessTime();
225 service->inited = SVC_BUSY;
226 }
227
EndWork(ServiceImpl * service,const Exchange * exchange)228 static void EndWork(ServiceImpl *service, const Exchange *exchange)
229 {
230 if (service == NULL || service->inited != SVC_BUSY) {
231 return;
232 }
233
234 if (service->ops.step == BOOT_SYS_WAIT) {
235 WDT_Stop();
236 }
237
238 uint32 lastTime = service->ops.timestamp;
239 service->ops.timestamp = (uint32)SAMGR_GetProcessTime();
240 uint32 interval = GET_INTERVAL(lastTime, service->ops.timestamp);
241 if (interval > MSG_PROC_THRESHOLD) {
242 const char *name = service->service->GetName(service->service);
243 HILOG_INFO(HILOG_MODULE_SAMGR, "Message Timeout <service:%s, feature:%d, type:%d, reqId:%d, time:%ums>",
244 name, exchange->id.featureId, exchange->type, exchange->request.msgId, interval);
245 service->ops.abnormal++;
246 }
247 service->inited = SVC_IDLE;
248 }
249