Hint added.
[AROS.git] / workbench / c / StackSnoop.c
blobf82097ead7a0bb10510d1f2e30d42a8e5aba8f82
1 /*
2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc:
6 Lang: English
7 */
9 /******************************************************************************
12 NAME
14 StackSnoop
16 SYNOPSIS
18 (N/A)
20 LOCATION
24 FUNCTION
26 Prints a list of tasks with their stack usage.
28 INPUTS
30 RESULT
32 NOTES
34 EXAMPLE
36 BUGS
38 SEE ALSO
40 INTERNALS
42 HISTORY
44 ******************************************************************************/
46 #include <exec/exec.h>
47 #include <exec/execbase.h>
48 #include <exec/tasks.h>
49 #include <exec/rawfmt.h>
50 #include <dos/dos.h>
51 #include <proto/exec.h>
52 #include <proto/dos.h>
53 #include <proto/debug.h>
54 #include <proto/alib.h>
56 #include <string.h>
58 #define ARG_TEMPLATE "TASK/K,DEBUG/S"
60 #define ARG_TASK 0
61 #define ARG_DEBUG 1
62 #define NUM_ARGS 2
64 static struct RDArgs *MyArgs;
65 static IPTR Args[NUM_ARGS];
66 static char s[256];
68 static UBYTE outbuffer[20000];
69 static LONG outbuffer_size;
71 static void Cleanup(char *msg)
73 if (msg)
74 Printf("stacksnoop: %s\n",msg);
76 if (MyArgs) FreeArgs(MyArgs);
79 static ULONG GetArguments(void)
81 if (!(MyArgs = ReadArgs(ARG_TEMPLATE,Args,0)))
83 Fault(IoErr(),0,s,255);
84 Cleanup(s);
85 return RETURN_WARN;
87 return 0;
90 static int out (const UBYTE * fmt, ...)
92 va_list ap;
93 int result;
95 va_start (ap, fmt);
97 VNewRawDoFmt(fmt, RAWFMTFUNC_STRING, &outbuffer[outbuffer_size], ap);
98 result = strlen(&outbuffer[outbuffer_size]);
100 if (Args[ARG_DEBUG])
101 KPutStr(&outbuffer[outbuffer_size]);
103 outbuffer_size += result;
105 va_end (ap);
107 return result;
111 static void CheckTaskStack(struct Task *task)
113 UBYTE *startcheck, *endcheck;
114 LONG stacksize, stackinc, unusedstack = 0;
116 stacksize = (LONG)( ((UBYTE *)task->tc_SPUpper) - ((UBYTE *)task->tc_SPLower) );
118 #if AROS_STACK_GROWS_DOWNWARDS
119 startcheck = (UBYTE *)task->tc_SPLower;
120 endcheck = ((UBYTE *)task->tc_SPUpper) - 1;
121 stackinc = 1;
122 #else
123 startcheck = ((UBYTE *)task->tc_SPUpper) - 1;
124 endcheck = (UBYTE *)task->tc_SPLower;
125 stackinc = -1;
126 #endif
128 for(; startcheck != endcheck; startcheck += stackinc)
130 if (*startcheck != 0xE1) break;
131 unusedstack++;
134 out("Task %x (%25s) Stack Size =%6d, Left =%6d, Used %s%6d%s\n",
135 task,
136 task->tc_Node.ln_Name ?
137 (const char *)task->tc_Node.ln_Name : "<NONAME>",
138 stacksize,
139 unusedstack,
140 ((stacksize - unusedstack) < stacksize) ? "=" : ">",
141 stacksize - unusedstack,
142 (unusedstack < 512) ? ": Needs more stack!!!!!!!!!" : "");
145 static void Action(void)
147 struct Task *task;
148 WORD i;
150 Disable();
152 out("\n------------------------------------------------------------------------------\n\n");
154 task = (struct Task *)SysBase->TaskReady.lh_Head;
155 for(i = 0; i < 2;i++)
157 while(task->tc_Node.ln_Succ)
159 CheckTaskStack(task);
161 task = (struct Task *)task->tc_Node.ln_Succ;
162 } /* while(task->tc_Node.ln_Succ) */
164 task = (struct Task *)SysBase->TaskWait.lh_Head;
166 } /* for(i = 0; i < 2;i++) */
167 out("\n");
168 CheckTaskStack(FindTask(NULL));
169 out("\n------------------------------------------------------------------------------\n\n");
171 Enable();
173 PutStr(outbuffer);
176 ULONG __nocommandline = 1;
178 int main(void)
180 int rc;
182 rc = GetArguments();
183 if (rc)
184 return rc;
186 Action();
187 Cleanup(0);
188 return 0;