2 Copyright © 1995-2017, The AROS Development Team. All rights reserved.
9 /******************************************************************************
26 Prints a list of all tasks.
44 ******************************************************************************/
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
;
73 struct timeval cputime
;
77 static int addtask(struct List
*tasks
, struct Task
*task
)
80 STRPTR s1
,s2
, e
= NULL
;
82 struct TagItem QueryTaskTags
[] =
84 {TaskTag_CPUTime
, 0 },
85 {TaskTag_CPUUsage
, 0 },
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
);
97 s1
= task
->tc_Node
.ln_Name
;
100 s1
= task
->tc_Node
.ln_Name
;
103 t
= AllocVec(sizeof(struct task
), MEMF_CLEAR
|MEMF_PUBLIC
);
106 t
= AllocVec(sizeof(struct task
) + strlen(s1
) + 1, MEMF_CLEAR
|MEMF_PUBLIC
);
107 e
= (STRPTR
)&t
[1] + strlen(s1
);
113 #if defined(__AROS__)
114 QueryTaskTags
[0].ti_Data
= (IPTR
)&t
->cputime
;
115 QueryTaskTags
[1].ti_Data
= (IPTR
)&t
->cpuusage
;
116 QueryTaskTagList(task
, QueryTaskTags
);
120 if (task
->tc_Node
.ln_Type
== NT_PROCESS
&& ((struct Process
*)task
)->pr_CLI
)
121 t
->node
.ln_Type
= -1;
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
;
130 t
->stackused
= (STRPTR
)task
->tc_SPReg
- SP_OFFSET
- (STRPTR
)task
->tc_SPLower
;
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 */
152 AddTail(tasks
, &t
->node
);
157 static int fillbuffer(struct List
*tasks
)
161 #if !defined(__AROS__)
164 if (!addtask(task
, FindTask(NULL
)))
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
))
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
))
191 struct TaskList
*taskList
;
193 taskList
= LockTaskList(LTF_ALL
);
194 while ((task
= NextTaskEntry(taskList
, LTF_ALL
)) != NULL
)
196 if (!addtask(tasks
, task
))
201 UnLockTaskList(taskList
, LTF_ALL
);
209 struct task
*currentTask
, *tmpTask
;
213 #if defined(__AROS__)
214 TaskResBase
= OpenResource("task.resource");
216 PutStr("Can't open task.resource\n");
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");
230 PutStr(" Address Type Pri State CPU Time CPU Usage Stack Used Name\n");
232 ForeachNodeSafe(&tasks
, currentTask
, tmpTask
)
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",
246 Printf("0x%08.ix %8s %4id %7s %3id:%02id:%02id.%02id %3id.%02id%% %9id %9id %s\n",
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
);