1 /*
2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3 * Copyright (c) 2020-2023 Huawei Device Co., Ltd. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this list of
9 * conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 * of conditions and the following disclaimer in the documentation and/or other materials
13 * provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16 * to endorse or promote products derived from this software without specific prior written
17 * permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include "stdlib.h"
33 #include "los_config.h"
34 #include "los_exc.h"
35 #include "los_memstat_pri.h"
36 #include "los_sem_pri.h"
37 #include "los_seq_buf.h"
38 #include "los_task_pri.h"
39 #ifdef LOSCFG_SHELL
40 #include "shcmd.h"
41 #include "shell.h"
42 #endif
43 #ifdef LOSCFG_KERNEL_CPUP
44 #include "los_cpup_pri.h"
45 #endif
46 #ifdef LOSCFG_SAVE_EXCINFO
47 #include "los_excinfo_pri.h"
48 #endif
49 #include "los_process_pri.h"
50 #ifdef LOSCFG_FS_VFS
51 #include "fs/file.h"
52 #endif
53 #include "los_sched_pri.h"
54 #include "los_swtmr_pri.h"
55 #include "los_info_pri.h"
56 #ifdef LOSCFG_SCHED_DEBUG
57 #include "los_statistics_pri.h"
58 #endif
59
60 #define OS_PROCESS_MEM_INFO 0x2U
61 #undef SHOW
62 #ifdef LOSCFG_FS_VFS
63 #if defined(LOSCFG_BLACKBOX) && defined(LOSCFG_SAVE_EXCINFO)
64 #define SaveExcInfo(arg, ...) WriteExcInfoToBuf(arg, ##__VA_ARGS__)
65 #else
66 #define SaveExcInfo(arg, ...)
67 #endif
68 #define SHOW(arg...) do { \
69 if (seqBuf != NULL) { \
70 (void)LosBufPrintf((struct SeqBuf *)seqBuf, ##arg); \
71 } else { \
72 PRINTK(arg); \
73 } \
74 SaveExcInfo(arg); \
75 } while (0)
76 #else
77 #define SHOW(arg...) PRINTK(arg)
78 #endif
79
80 #define CPUP_MULT LOS_CPUP_PRECISION_MULT
81
ConvertProcessModeToString(UINT16 mode)82 STATIC UINT8 *ConvertProcessModeToString(UINT16 mode)
83 {
84 if (mode == OS_KERNEL_MODE) {
85 return (UINT8 *)"kernel";
86 } else if (mode == OS_USER_MODE) {
87 return (UINT8 *)"user";
88 }
89
90 return (UINT8 *)"ERROR";
91 }
92
ConvertSchedPolicyToString(UINT16 policy)93 STATIC UINT8 *ConvertSchedPolicyToString(UINT16 policy)
94 {
95 if (policy == LOS_SCHED_RR) {
96 return (UINT8 *)"RR";
97 } else if (policy == LOS_SCHED_FIFO) {
98 return (UINT8 *)"FIFO";
99 } else if (policy == LOS_SCHED_DEADLINE) {
100 return (UINT8 *)"EDF";
101 } else if (policy == LOS_SCHED_IDLE) {
102 return (UINT8 *)"IDLE";
103 }
104
105 return (UINT8 *)"ERROR";
106 }
107
ConvertProcessStatusToString(UINT16 status)108 STATIC UINT8 *ConvertProcessStatusToString(UINT16 status)
109 {
110 if (status & OS_PROCESS_STATUS_ZOMBIES) {
111 return (UINT8 *)"Zombies";
112 } else if (status & OS_PROCESS_STATUS_INIT) {
113 return (UINT8 *)"Init";
114 } else if (status & OS_PROCESS_STATUS_RUNNING) {
115 return (UINT8 *)"Running";
116 } else if (status & OS_PROCESS_STATUS_READY) {
117 return (UINT8 *)"Ready";
118 }
119 return (UINT8 *)"Pending";
120 }
121
ProcessInfoTitle(VOID * seqBuf,UINT16 flag)122 STATIC VOID ProcessInfoTitle(VOID *seqBuf, UINT16 flag)
123 {
124 SHOW("\r\n PID PPID PGID UID Mode Status Policy Priority MTID TTotal");
125 if (flag & OS_PROCESS_INFO_ALL) {
126 #ifdef LOSCFG_KERNEL_VM
127 if (flag & OS_PROCESS_MEM_INFO) {
128 SHOW(" VirtualMem ShareMem PhysicalMem");
129 }
130 #endif
131 #ifdef LOSCFG_KERNEL_CPUP
132 SHOW(" CPUUSE CPUUSE10s CPUUSE1s");
133 #endif /* LOSCFG_KERNEL_CPUP */
134 } else {
135 #ifdef LOSCFG_KERNEL_CPUP
136 SHOW(" CPUUSE10s");
137 #endif /* LOSCFG_KERNEL_CPUP */
138 }
139 SHOW(" PName\n");
140 }
141
ProcessDataShow(const ProcessInfo * processInfo,VOID * seqBuf,UINT16 flag)142 STATIC VOID ProcessDataShow(const ProcessInfo *processInfo, VOID *seqBuf, UINT16 flag)
143 {
144 SHOW("%5u%6u%5d%6d%7s%8s%7s%9u%5u%7u", processInfo->pid, processInfo->ppid, processInfo->pgroupID,
145 processInfo->userID, ConvertProcessModeToString(processInfo->mode),
146 ConvertProcessStatusToString(processInfo->status),
147 ConvertSchedPolicyToString(processInfo->policy), processInfo->basePrio,
148 processInfo->threadGroupID, processInfo->threadNumber);
149
150 if (flag & OS_PROCESS_INFO_ALL) {
151 #ifdef LOSCFG_KERNEL_VM
152 if (flag & OS_PROCESS_MEM_INFO) {
153 SHOW("%#11x%#9x%#12x", processInfo->virtualMem, processInfo->shareMem, processInfo->physicalMem);
154 }
155 #endif
156 #ifdef LOSCFG_KERNEL_CPUP
157 SHOW("%4u.%-2u%7u.%-2u%6u.%-2u ",
158 processInfo->cpupAllsUsage / CPUP_MULT, processInfo->cpupAllsUsage % CPUP_MULT,
159 processInfo->cpup10sUsage / CPUP_MULT, processInfo->cpup10sUsage % CPUP_MULT,
160 processInfo->cpup1sUsage / CPUP_MULT, processInfo->cpup1sUsage % CPUP_MULT);
161 #endif /* LOSCFG_KERNEL_CPUP */
162 } else {
163 #ifdef LOSCFG_KERNEL_CPUP
164 SHOW("%7u.%-2u ", processInfo->cpup10sUsage / CPUP_MULT, processInfo->cpup10sUsage % CPUP_MULT);
165 #endif /* LOSCFG_KERNEL_CPUP */
166 }
167 SHOW("%-32s\n", processInfo->name);
168 }
169
AllProcessDataShow(const ProcessInfo * pcbArray,VOID * seqBuf,UINT16 flag)170 STATIC VOID AllProcessDataShow(const ProcessInfo *pcbArray, VOID *seqBuf, UINT16 flag)
171 {
172 for (UINT32 pid = 1; pid < g_processMaxNum; ++pid) {
173 const ProcessInfo *processInfo = pcbArray + pid;
174 if (processInfo->status & OS_PROCESS_FLAG_UNUSED) {
175 continue;
176 }
177 ProcessDataShow(processInfo, seqBuf, flag);
178 }
179 }
180
ProcessInfoShow(const ProcessInfo * pcbArray,VOID * seqBuf,UINT16 flag)181 STATIC VOID ProcessInfoShow(const ProcessInfo *pcbArray, VOID *seqBuf, UINT16 flag)
182 {
183 #ifdef LOSCFG_KERNEL_CPUP
184 UINT32 pid = OS_KERNEL_IDLE_PROCESS_ID;
185 UINT32 sysUsage = LOS_CPUP_PRECISION - pcbArray[pid].cpup10sUsage;
186 SHOW("\n allCpu(%%): %4u.%02u sys, %4u.%02u idle\n", sysUsage / CPUP_MULT, sysUsage % CPUP_MULT,
187 pcbArray[pid].cpup10sUsage / CPUP_MULT, pcbArray[pid].cpup10sUsage % CPUP_MULT);
188 #endif
189
190 ProcessInfoTitle(seqBuf, flag);
191 AllProcessDataShow(pcbArray, seqBuf, flag);
192 }
193
ConvertTaskStatusToString(UINT16 taskStatus)194 STATIC UINT8 *ConvertTaskStatusToString(UINT16 taskStatus)
195 {
196 if (taskStatus & OS_TASK_STATUS_INIT) {
197 return (UINT8 *)"Init";
198 } else if (taskStatus & OS_TASK_STATUS_RUNNING) {
199 return (UINT8 *)"Running";
200 } else if (taskStatus & OS_TASK_STATUS_READY) {
201 return (UINT8 *)"Ready";
202 } else if (taskStatus & OS_TASK_STATUS_FROZEN) {
203 return (UINT8 *)"Frozen";
204 } else if (taskStatus & OS_TASK_STATUS_SUSPENDED) {
205 return (UINT8 *)"Suspended";
206 } else if (taskStatus & OS_TASK_STATUS_DELAY) {
207 return (UINT8 *)"Delay";
208 } else if (taskStatus & OS_TASK_STATUS_PEND_TIME) {
209 return (UINT8 *)"PendTime";
210 } else if (taskStatus & OS_TASK_STATUS_PENDING) {
211 return (UINT8 *)"Pending";
212 } else if (taskStatus & OS_TASK_STATUS_EXIT) {
213 return (UINT8 *)"Exit";
214 }
215
216 return (UINT8 *)"Invalid";
217 }
218
219 #ifdef LOSCFG_SHELL_CMD_DEBUG
220 #define OS_PEND_REASON_MAX_LEN 20
221
CheckTaskWaitFlag(const TaskInfo * taskInfo,UINTPTR * lockID)222 STATIC CHAR *CheckTaskWaitFlag(const TaskInfo *taskInfo, UINTPTR *lockID)
223 {
224 *lockID = taskInfo->waitID;
225 switch (taskInfo->waitFlag) {
226 case OS_TASK_WAIT_PROCESS:
227 return "Child";
228 case OS_TASK_WAIT_GID:
229 return "PGroup";
230 case OS_TASK_WAIT_ANYPROCESS:
231 return "AnyChild";
232 case OS_TASK_WAIT_SEM:
233 return "Semaphore";
234 case OS_TASK_WAIT_QUEUE:
235 return "Queue";
236 case OS_TASK_WAIT_JOIN:
237 return "Join";
238 case OS_TASK_WAIT_SIGNAL:
239 return "Signal";
240 case OS_TASK_WAIT_LITEIPC:
241 return "LiteIPC";
242 case OS_TASK_WAIT_MUTEX:
243 return "Mutex";
244 case OS_TASK_WAIT_EVENT:
245 return "Event";
246 case OS_TASK_WAIT_FUTEX:
247 return "Futex";
248 case OS_TASK_WAIT_COMPLETE:
249 return "Complete";
250 default:
251 break;
252 }
253
254 return NULL;
255 }
256
TaskPendingReasonInfoGet(const TaskInfo * taskInfo,CHAR * pendReason,UINT32 maxLen,UINTPTR * lockID)257 STATIC VOID TaskPendingReasonInfoGet(const TaskInfo *taskInfo, CHAR *pendReason, UINT32 maxLen, UINTPTR *lockID)
258 {
259 CHAR *reason = NULL;
260
261 if (!(taskInfo->status & OS_TASK_STATUS_PENDING)) {
262 reason = (CHAR *)ConvertTaskStatusToString(taskInfo->status);
263 goto EXIT;
264 }
265
266 reason = CheckTaskWaitFlag(taskInfo, lockID);
267 if (reason == NULL) {
268 reason = "Others";
269 }
270
271 if (taskInfo->taskMux != NULL) {
272 *lockID = (UINTPTR)taskInfo->taskMux;
273 LosTaskCB *owner = ((LosMux *)taskInfo->taskMux)->owner;
274 if (owner != NULL) {
275 if (snprintf_s(pendReason, maxLen, maxLen - 1, "Mutex-%u", owner->taskID) == EOK) {
276 return;
277 }
278 }
279 }
280
281 EXIT:
282 if (strcpy_s(pendReason, maxLen, reason) != EOK) {
283 PRINT_ERR("Get pend reason copy failed !\n");
284 }
285 }
286 #endif
287
TaskInfoTitle(VOID * seqBuf,UINT16 flag)288 STATIC VOID TaskInfoTitle(VOID *seqBuf, UINT16 flag)
289 {
290 SHOW("\r\n TID PID");
291 #ifdef LOSCFG_KERNEL_SMP
292 SHOW(" Affi CPU");
293 #endif
294 SHOW(" Status Policy Priority StackSize WaterLine");
295 if (flag & OS_PROCESS_INFO_ALL) {
296 #ifdef LOSCFG_KERNEL_CPUP
297 SHOW(" CPUUSE CPUUSE10s CPUUSE1s");
298 #endif /* LOSCFG_KERNEL_CPUP */
299 #ifdef LOSCFG_SHELL_CMD_DEBUG
300 SHOW(" StackPoint TopOfStack PendReason LockID");
301 #endif
302 } else {
303 #ifdef LOSCFG_KERNEL_CPUP
304 SHOW(" CPUUSE10s ");
305 #endif /* LOSCFG_KERNEL_CPUP */
306 }
307 SHOW(" TaskName\n");
308 }
309
TaskInfoDataShow(const TaskInfo * taskInfo,VOID * seqBuf,UINT16 flag)310 STATIC VOID TaskInfoDataShow(const TaskInfo *taskInfo, VOID *seqBuf, UINT16 flag)
311 {
312 #ifdef LOSCFG_SHELL_CMD_DEBUG
313 UINTPTR lockID = 0;
314 CHAR pendReason[OS_PEND_REASON_MAX_LEN] = { 0 };
315 #endif
316 SHOW(" %4u%5u", taskInfo->tid, taskInfo->pid);
317
318 #ifdef LOSCFG_KERNEL_SMP
319 SHOW("%#5x%4d ", taskInfo->cpuAffiMask, (INT16)(taskInfo->currCpu));
320 #endif
321 SHOW("%9s%7s%9u%#10x%#10x", ConvertTaskStatusToString(taskInfo->status),
322 ConvertSchedPolicyToString(taskInfo->policy), taskInfo->priority, taskInfo->stackSize, taskInfo->waterLine);
323 if (flag & OS_PROCESS_INFO_ALL) {
324 #ifdef LOSCFG_KERNEL_CPUP
325 SHOW("%4u.%-2u%7u.%-2u%6u.%-2u ", taskInfo->cpupAllsUsage / CPUP_MULT, taskInfo->cpupAllsUsage % CPUP_MULT,
326 taskInfo->cpup10sUsage / CPUP_MULT, taskInfo->cpup10sUsage % CPUP_MULT,
327 taskInfo->cpup1sUsage / CPUP_MULT, taskInfo->cpup1sUsage % CPUP_MULT);
328 #endif /* LOSCFG_KERNEL_CPUP */
329 #ifdef LOSCFG_SHELL_CMD_DEBUG
330 TaskPendingReasonInfoGet(taskInfo, pendReason, OS_PEND_REASON_MAX_LEN, &lockID);
331 SHOW("%#12x%#12x%11s%#11x", taskInfo->stackPoint, taskInfo->topOfStack, pendReason, lockID);
332 #endif
333 } else {
334 #ifdef LOSCFG_KERNEL_CPUP
335 SHOW("%8u.%-2u ", taskInfo->cpup10sUsage / CPUP_MULT, taskInfo->cpup10sUsage % CPUP_MULT);
336 #endif /* LOSCFG_KERNEL_CPUP */
337 }
338 SHOW(" %-32s\n", taskInfo->name);
339 }
340
ProcessTaskInfoDataShow(const ProcessThreadInfo * allTaskInfo,VOID * seqBuf,UINT16 flag)341 STATIC VOID ProcessTaskInfoDataShow(const ProcessThreadInfo *allTaskInfo, VOID *seqBuf, UINT16 flag)
342 {
343 for (UINT32 index = 0; index < allTaskInfo->threadCount; index++) {
344 const TaskInfo *taskInfo = &allTaskInfo->taskInfo[index];
345 TaskInfoDataShow(taskInfo, seqBuf, flag);
346 }
347 }
348
TaskInfoData(const ProcessThreadInfo * allTaskInfo,VOID * seqBuf,UINT16 flag)349 STATIC VOID TaskInfoData(const ProcessThreadInfo *allTaskInfo, VOID *seqBuf, UINT16 flag)
350 {
351 ProcessInfoTitle(seqBuf, flag);
352 ProcessDataShow(&allTaskInfo->processInfo, seqBuf, flag);
353 TaskInfoTitle(seqBuf, flag);
354 ProcessTaskInfoDataShow(allTaskInfo, seqBuf, flag);
355 }
356
OsShellCmdTskInfoGet(UINT32 processID,VOID * seqBuf,UINT16 flag)357 LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdTskInfoGet(UINT32 processID, VOID *seqBuf, UINT16 flag)
358 {
359 UINT32 size;
360
361 if (processID == OS_ALL_TASK_MASK) {
362 size = sizeof(ProcessInfo) * g_processMaxNum;
363 ProcessInfo *pcbArray = (ProcessInfo *)LOS_MemAlloc(m_aucSysMem1, size);
364 if (pcbArray == NULL) {
365 PRINT_ERR("Memory is not enough to save task info!\n");
366 return LOS_NOK;
367 }
368 (VOID)memset_s(pcbArray, size, 0, size);
369 OsGetAllProcessInfo(pcbArray);
370 ProcessInfoShow((const ProcessInfo *)pcbArray, seqBuf, flag);
371 (VOID)LOS_MemFree(m_aucSysMem1, pcbArray);
372 return LOS_OK;
373 }
374
375 ProcessThreadInfo *threadInfo = (ProcessThreadInfo *)LOS_MemAlloc(m_aucSysMem1, sizeof(ProcessThreadInfo));
376 if (threadInfo == NULL) {
377 return LOS_NOK;
378 }
379 (VOID)memset_s(threadInfo, sizeof(ProcessThreadInfo), 0, sizeof(ProcessThreadInfo));
380
381 if (OsGetProcessThreadInfo(processID, threadInfo) != LOS_OK) {
382 (VOID)LOS_MemFree(m_aucSysMem1, threadInfo);
383 return LOS_NOK;
384 }
385
386 TaskInfoData(threadInfo, seqBuf, flag);
387 (VOID)LOS_MemFree(m_aucSysMem1, threadInfo);
388 return LOS_OK;
389 }
390
OsShellCmdDumpTask(INT32 argc,const CHAR ** argv)391 LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdDumpTask(INT32 argc, const CHAR **argv)
392 {
393 INT32 processID = OS_ALL_TASK_MASK;
394 UINT32 flag = 0;
395 #ifdef LOSCFG_KERNEL_VM
396 flag |= OS_PROCESS_MEM_INFO;
397 #endif
398
399 if (argc == 0) {
400 return OsShellCmdTskInfoGet((UINT32)processID, NULL, flag);
401 }
402
403 if (argc >= 3) { /* 3: The task shell name restricts the parameters */
404 goto TASK_HELP;
405 }
406
407 if ((argc == 1) && (strcmp("-a", argv[0]) == 0)) {
408 flag |= OS_PROCESS_INFO_ALL;
409 } else if ((argc == 2) && (strcmp("-p", argv[0]) == 0)) { /* 2: Two parameters */
410 flag |= OS_PROCESS_INFO_ALL;
411 processID = atoi(argv[1]);
412 #ifdef LOSCFG_SCHED_DEBUG
413 #ifdef LOSCFG_SCHED_TICK_DEBUG
414 } else if (strcmp("-i", argv[0]) == 0) {
415 if (!OsShellShowTickResponse()) {
416 return LOS_OK;
417 }
418 goto TASK_HELP;
419 #endif
420 #ifdef LOSCFG_SCHED_HPF_DEBUG
421 } else if (strcmp("-t", argv[0]) == 0) {
422 if (!OsShellShowSchedStatistics()) {
423 return LOS_OK;
424 }
425 goto TASK_HELP;
426 #endif
427 #ifdef LOSCFG_SCHED_EDF_DEBUG
428 } else if (strcmp("-e", argv[0]) == 0) {
429 if (!OsShellShowEdfSchedStatistics()) {
430 return LOS_OK;
431 }
432 goto TASK_HELP;
433 #endif
434 #endif
435 } else {
436 goto TASK_HELP;
437 }
438
439 return OsShellCmdTskInfoGet((UINT32)processID, NULL, flag);
440
441 TASK_HELP:
442 PRINTK("Unknown option: %s\n", argv[0]);
443 PRINTK("Usage:\n");
444 PRINTK(" task --- Basic information about all created processes.\n");
445 PRINTK(" task -a --- Complete information about all created processes.\n");
446 PRINTK(" task -p [pid] --- Complete information about specifies processes and its task.\n");
447 return LOS_NOK;
448 }
449
450 #ifdef LOSCFG_SHELL
451 SHELLCMD_ENTRY(task_shellcmd, CMD_TYPE_EX, "task", 1, (CmdCallBackFunc)OsShellCmdDumpTask);
452 #endif
453
454