use m4_normalize on the output strings to remove trailing spaces/tabs and consolidate...
[AROS.git] / workbench / c / TaskList.c
blob063cd578d40d17974ace158d0505915873f47577
1 /*
2 Copyright © 1995-2017, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc:
6 Lang: english
7 */
9 /******************************************************************************
12 NAME
14 TaskList
16 SYNOPSIS
18 (N/A)
20 LOCATION
24 FUNCTION
26 Prints a list of all tasks.
28 INPUTS
30 RESULT
32 NOTES
34 EXAMPLE
36 BUGS
38 SEE ALSO
40 INTERNALS
42 HISTORY
44 ******************************************************************************/
46 int __nocommandline;
48 #include <exec/memory.h>
49 #include <exec/tasks.h>
50 #include <exec/execbase.h>
51 #include <proto/exec.h>
52 #include <proto/timer.h>
53 #include <aros/debug.h>
54 #include <devices/timer.h>
55 #include <dos/dosextens.h>
56 #include <proto/dos.h>
57 #include <proto/task.h>
59 #include <resources/task.h>
61 const TEXT version[] = "$VER: TaskList 42.2 (21.01.2017)\n";
63 APTR TaskResBase = NULL;
64 ULONG eclock;
66 struct task
68 struct Node node;
69 APTR address;
70 WORD state;
71 IPTR stacksize;
72 IPTR stackused;
73 struct timeval cputime;
74 ULONG cpuusage;
77 static int addtask(struct List *tasks, struct Task *task)
79 struct task *t;
80 STRPTR s1,s2, e = NULL;
81 #if defined(__AROS__)
82 struct TagItem QueryTaskTags[] =
84 {TaskTag_CPUTime , 0 },
85 {TaskTag_CPUUsage , 0 },
86 {TAG_DONE , 0 }
88 #endif
90 if (task->tc_Node.ln_Type == NT_PROCESS && ((struct Process *)task)->pr_CLI)
92 struct CommandLineInterface *cli = BADDR(((struct Process *)task)->pr_CLI);
94 if (cli->cli_CommandName)
95 s1 = AROS_BSTR_ADDR(cli->cli_CommandName);
96 else
97 s1 = task->tc_Node.ln_Name;
99 else
100 s1 = task->tc_Node.ln_Name;
102 if (s1 == NULL)
103 t = AllocVec(sizeof(struct task), MEMF_CLEAR|MEMF_PUBLIC);
104 else
106 t = AllocVec(sizeof(struct task) + strlen(s1) + 1, MEMF_CLEAR|MEMF_PUBLIC);
107 e = (STRPTR)&t[1] + strlen(s1);
110 if (!t)
111 return 0;
113 #if defined(__AROS__)
114 QueryTaskTags[0].ti_Data = (IPTR)&t->cputime;
115 QueryTaskTags[1].ti_Data = (IPTR)&t->cpuusage;
116 QueryTaskTagList(task, QueryTaskTags);
117 #endif
119 t->address = task;
120 if (task->tc_Node.ln_Type == NT_PROCESS && ((struct Process *)task)->pr_CLI)
121 t->node.ln_Type = -1;
122 else
123 t->node.ln_Type = task->tc_Node.ln_Type;
124 t->node.ln_Pri = task->tc_Node.ln_Pri;
125 t->state = task->tc_State;
126 t->stacksize = (STRPTR)task->tc_SPUpper - (STRPTR)task->tc_SPLower;
127 #if AROS_STACK_GROWS_DOWNWARDS
128 t->stackused = (STRPTR)task->tc_SPUpper - SP_OFFSET - (STRPTR)task->tc_SPReg;
129 #else
130 t->stackused = (STRPTR)task->tc_SPReg - SP_OFFSET - (STRPTR)task->tc_SPLower;
131 #endif
132 if (task->tc_State == TS_RUN)
134 /* The tc_SPReg for the actual process is invalid
135 if it had no context switch yet */
136 t->stackused = 0;
139 if (s1 != NULL)
141 s2 = s1;
143 while (*s2++)
146 while (s2 > s1)
147 *--e=*--s2;
149 t->node.ln_Name = e;
152 AddTail(tasks, &t->node);
154 return 1;
157 static int fillbuffer(struct List *tasks)
159 struct Task *task;
161 #if !defined(__AROS__)
162 Disable();
164 if (!addtask(task, FindTask(NULL)))
166 Enable();
167 return RETURN_FAIL;
169 for (task = (struct Task *)SysBase->TaskReady.lh_Head;
170 task->tc_Node.ln_Succ != NULL;
171 task = (struct Task *)task->tc_Node.ln_Succ)
173 if (!addtask(tasks, task))
175 Enable();
176 return RETURN_FAIL;
179 for (task = (struct Task *)SysBase->TaskWait.lh_Head;
180 task->tc_Node.ln_Succ != NULL;
181 task = (struct Task *)task->tc_Node.ln_Succ)
183 if (!addtask(tasks, task))
185 Enable();
186 return RETURN_FAIL;
189 Enable();
190 #else
191 struct TaskList *taskList;
193 taskList = LockTaskList(LTF_ALL);
194 while ((task = NextTaskEntry(taskList, LTF_ALL)) != NULL)
196 if (!addtask(tasks, task))
198 break;
201 UnLockTaskList(taskList, LTF_ALL);
202 #endif
204 return RETURN_OK;
207 int main(void)
209 struct task *currentTask, *tmpTask;
210 struct List tasks;
211 int retval;
213 #if defined(__AROS__)
214 TaskResBase = OpenResource("task.resource");
215 if (!TaskResBase) {
216 PutStr("Can't open task.resource\n");
217 return RETURN_FAIL;
219 #endif
221 NEWLIST(&tasks);
223 retval = fillbuffer(&tasks);
225 if (!IsListEmpty(&tasks))
227 #if (__WORDSIZE == 64)
228 PutStr(" Address Type Pri State CPU Time CPU Usage Stack Used Name\n");
229 #else
230 PutStr(" Address Type Pri State CPU Time CPU Usage Stack Used Name\n");
231 #endif
232 ForeachNodeSafe(&tasks, currentTask, tmpTask)
234 IPTR time;
235 IPTR usec;
236 ULONG usage = ((currentTask->cpuusage >> 16) * 10000) >> 16;
238 Remove((struct Node *)currentTask);
240 time = currentTask->cputime.tv_secs;
241 /* Dunno why I need the mask on tv_usec, but sometimes high bits leak from somewhere into this code. gcc issue? */
242 usec = (((currentTask->cputime.tv_usec & 0xfffff) + 5000) / 10000);
243 #if (__WORDSIZE == 64)
244 Printf("0x%012.ix %8s %4id %7s %3id:%02id:%02id.%02id %3id.%02id%% %9id %9id %s\n",
245 #else
246 Printf("0x%08.ix %8s %4id %7s %3id:%02id:%02id.%02id %3id.%02id%% %9id %9id %s\n",
247 #endif
248 currentTask->address,
249 (currentTask->node.ln_Type == NT_TASK) ? "task" :
250 (currentTask->node.ln_Type == NT_PROCESS) ? "process" : "CLI",
251 (SIPTR)currentTask->node.ln_Pri,
252 (currentTask->state == TS_RUN) ? "running" :
253 (currentTask->state == TS_READY) ? "ready" : "waiting",
254 (IPTR)(time / 60 / 60), (IPTR)((time / 60) % 60), (IPTR)(time % 60), usec,
255 (IPTR)usage / 100, (IPTR)usage % 100,
256 currentTask->stacksize, currentTask->stackused,
257 (currentTask->node.ln_Name != NULL) ? currentTask->node.ln_Name : "(null)");
259 FreeVec(currentTask);
262 return retval;