2 Copyright © 1995-2009, The AROS Development Team. All rights reserved.
6 This include file can be included several times!
9 #ifndef CLIB_AROSSUPPORT_PROTOS_H
10 # include <proto/arossupport.h>
13 # include <proto/exec.h> /* For FindTask() */
16 # include <exec/tasks.h>
19 # include <exec/alerts.h>
38 /* Remove all macros. They get new values each time this file is
52 /* Macros for "stair debugging" */
64 # ifndef SDEBUG_INDENT
65 # define SDEBUG_INDENT 2
68 /* This is some new macros for making debug output more readable,
69 ** by indenting for each functioncall made.
70 ** Usage: Call the SDInit() macro before anything else in your main().
71 ** Start the functions you want to debug with EnterFunc(bug("something"))
72 ** and ALWAYS match these with a Returnxxxx type macro
73 ** at the end of the func.
74 ** Inside the func you can use the normal D(bug()) macro.
76 ** To enable the macros, just add a #define SDEBUG 1
80 #define EnterFunc(x) do { \
81 struct Task *sd_task = FindTask(NULL); \
82 int sd_spaceswritten; \
83 for (sd_spaceswritten = 0; sd_spaceswritten < (ULONG)sd_task->tc_UserData; sd_spaceswritten ++) kprintf(" "); \
84 ((ULONG)sd_task->tc_UserData) += SDEBUG_INDENT; } while(0); \
88 /* User macro. Add into start of your main() routine */
90 do { FindTask(NULL)->tc_UserData = NULL; } while(0)
94 # define Indent do { \
95 struct Task *sd_task = FindTask(NULL); \
96 int sd_spaceswritten; \
97 for (sd_spaceswritten = 0; sd_spaceswritten < (ULONG)sd_task->tc_UserData; sd_spaceswritten ++) kprintf(" "); } while(0)
100 #define ExitFunc do { \
101 struct Task *sd_task = FindTask(NULL); \
102 int sd_spaceswritten; \
103 ((ULONG)sd_task->tc_UserData) -= SDEBUG_INDENT; \
104 for (sd_spaceswritten = 0; sd_spaceswritten < (ULONG)sd_task->tc_UserData; sd_spaceswritten ++) kprintf(" "); } while(0)
110 # define EnterFunc(x...) D(x)
117 /* Sanity check macros
120 * Do nothing if the expression <x> evalutates to a
121 * non-zero value, output a debug message otherwise.
123 * ASSERT_VALID_PTR(x)
124 * Checks that the expression <x> points to a valid memory location, and
125 * outputs a debug message otherwise. A NULL pointer is considered INVALID.
127 * ASSERT_VALID_PTR_OR_NULL(x)
128 * Checks that the expression <x> points to a valid memory location or that
129 * it is NULL, and outputs a debug message otherwise. A NULL pointer is
132 * ASSERT_VALID_TASK(t)
133 * Checks that the pointer <t> points to a valid Task
134 * structure and outputs a debug message otherwise.
136 * ASSERT_VALID_PROCESS(p)
137 * Checks that the pointer <p> points to a valid Process
138 * structure and outputs a debug message otherwise.
141 * Do nothing if the expression <x> evalutates to a
142 * non-zero value, output a debug message, and cause an
143 * Alert() otherwise. This should only be used in kernel code.
149 #undef ASSERT_VALID_PTR
150 #undef ASSERT_VALID_PTR_OR_NULL
151 #undef ASSERT_VALID_TASK
152 #undef ASSERT_VALID_PROCESS
156 #define DBPRINTF kprintf
158 /* The trick with THIS_FILE allows us to reuse the same static string
159 * instead of allocating a new copy for each invocation of these macros.
161 #define THIS_FILE __FILE__
163 #define ASSERT(x) do { \
165 ( DBPRINTF("\x07%s:%ld: assertion failed: %s\n", \
166 THIS_FILE, __LINE__, #x) ); \
169 #define ASSERT_VALID_PTR(x) do { \
170 (((IPTR)(x) > 1024) && \
171 TypeOfMem((APTR)(x))) ? 0 : \
172 ( DBPRINTF("\x07%s, %ld: bad pointer: %s = $%lx\n", \
173 THIS_FILE, __LINE__, #x, (APTR)(x)) ); \
176 #define ASSERT_VALID_PTR_OR_NULL(x) do { \
177 ((((APTR)(x)) == NULL) || \
178 (((IPTR)(x) > 1024) && TypeOfMem((APTR)(x)))) ? 0 : \
179 ( DBPRINTF("\x07%s:%ld: bad pointer: %s = $%lx\n", \
180 THIS_FILE, __LINE__, #x, (APTR)(x)) ); \
183 #define ASSERT_VALID_TASK(t) do { \
184 ASSERT_VALID_PTR(t); \
185 ASSERT((((t)->tc_Node.ln_Type == NT_TASK) || \
186 (t)->tc_Node.ln_Type == NT_PROCESS)); \
189 #define ASSERT_VALID_PROCESS(p) do { \
190 ASSERT_VALID_PTR(p); \
191 ASSERT((p)->pr_Task.tc_Node.ln_Type == NT_PROCESS); \
194 #define KASSERT(x) do { \
196 ( DBPRINTF("\x07%s:%ld: assertion failed: %s\n", \
197 THIS_FILE, __LINE__, #x), Alert(AG_BadParm) ); \
203 # define ASSERT_VALID_PTR(x)
204 # define ASSERT_VALID_PTR_OR_NULL(x)
205 # define ASSERT_VALID_TASK(t)
206 # define ASSERT_VALID_PROCESS(p)
212 /* Memory munging macros
215 /* MUNGWALL_SIZE must be a multiple of MEMCHUNK_TOTAL, otherwise for example
216 rom/exec/allocate complains, because the return value (memory pointer) of
217 AllocMem would not be a multiple of MEMCHUNK_TOTAL anymore.
219 See rom/exec/allocmem and rom/exec/freemem for more info.
221 The "32 *" probably makes sure that you get a multiple of MEMCHUNK_TOTAL on
222 every machine, because on 32 bit machines MEMCHUNK_TOTAL will be 8 and
223 on 64 bit machines it will be 16, and it would even work on 128 bit machines
224 because I guess there MEMCHUNK_TOTAL will be 32 */
226 #define MUNGWALL_SIZE (32 * 1)
228 #define MUNGWALLHEADER_SIZE 32
230 #if AROS_SIZEOFULONG == 4
231 # define MEMFILL_FREE 0xDEADBEEFL
232 # define MEMFILL_ALLOC 0xC0DEDBADL
233 # define MEMFILL_WALL 0xABADC0DEL
234 #elif AROS_SIZEOFULONG == 8
235 # define MEMFILL_FREE 0xDEADBEEFDEADBEEFL
236 # define MEMFILL_ALLOC 0xC0DEDBADC0DEDBADL
237 # define MEMFILL_WALL 0xABADC0DEABADC0DEL
239 # error sizeof ULONG is neither 4 nor 8 in this architecture
245 /* Fill the memory block pointed by <ptr> of size <size> with <fill>
247 # define MUNGE_BLOCK(ptr, fill, size) do { \
248 ULONG *__p = (ULONG *)(ptr); \
249 ULONG __s = (size) / sizeof(ULONG); \
250 while (__s--) *__p++ = (fill); \
253 /* Build a wall over the memory block <ptr> of size <size> with <fill> bricks.
255 # define BUILD_WALL(ptr, fill, size) do { \
256 memset((ptr), (fill), (size)); \
259 /* Check the integrity of the wall <ptr> of size <size> bytes containing <fill>.
261 # define CHECK_WALL(ptr, fill, size) do { \
262 UBYTE *__p = (UBYTE *)(ptr); \
263 size_t __s = (size); \
268 struct Task *__t = FindTask(NULL); \
269 kprintf("\x07" "Broken wall detected at %s:%d at 0x%x, " \
270 "Task: 0x%x, Name: %s\n", \
271 __FUNCTION__, __LINE__, \
272 __p, __t, __t->tc_Node.ln_Name);\
278 # define MungWallCheck() AvailMem(MEMF_CLEAR)
281 # define MUNGE_BLOCK(ptr, size, fill)
282 # define CHECK_WALL(ptr, fill, size)
283 # define MungWallCheck()
289 # define D(x...) Indent x
294 # define DB2(x...) /* eps */
297 /* return-macros. NOTE: I make a copy of the value in __aros_val, because
298 the return-value might have side effects (like return x++;). */
299 # define ReturnVoid(name) { ExitFunc kprintf ("Exit " name "()\n"); return; }
300 # define ReturnPtr(name,type,val) { type __aros_val = (type)val; \
301 ExitFunc kprintf ("Exit " name "=%08lx\n", \
302 (ULONG)__aros_val); return __aros_val; }
303 # define ReturnStr(name,type,val) { type __aros_val = (type)val; \
304 ExitFunc kprintf ("Exit " name "=\"%s\"\n", \
305 __aros_val); return __aros_val; }
306 # define ReturnInt(name,type,val) { type __aros_val = (type)val; \
307 ExitFunc kprintf ("Exit " name "=%ld\n", \
308 (ULONG)__aros_val); return __aros_val; }
309 # define ReturnXInt(name,type,val) { type __aros_val = (type)val; \
310 ExitFunc kprintf ("Exit " name "=%lx\n", \
311 (ULONG)__aros_val); return __aros_val; }
312 # define ReturnFloat(name,type,val) { type __aros_val = (type)val; \
313 ExitFunc kprintf ("Exit " name "=%g\n", \
314 (ULONG)__aros_val); return __aros_val; }
315 # define ReturnSpecial(name,type,val,fmt) { type __aros_val = (type)val; \
316 ExitFunc kprintf ("Exit " name "=" fmt "\n", \
317 (ULONG)__aros_val); return __aros_val; }
318 # define ReturnBool(name,val) { BOOL __aros_val = (val != 0); \
319 ExitFunc kprintf ("Exit " name "=%s\n", \
320 __aros_val ? "TRUE" : "FALSE"); \
323 # define D(x...) /* eps */
324 # define DB2(x...) /* eps */
326 # define ReturnVoid(name) return
327 # define ReturnPtr(name,type,val) return val
328 # define ReturnStr(name,type,val) return val
329 # define ReturnInt(name,type,val) return val
330 # define ReturnXInt(name,type,val) return val
331 # define ReturnFloat(name,type,val) return val
332 # define ReturnSpecial(name,type,val,fmt) return val
333 # define ReturnBool(name,val) return val
339 I don't want to care about word length here because ULONG is a part of IPTR and
340 ULONG test will do here on 64-bit machines too.
342 TODO: This doesn't work for 'Reversed' stack (growing upwards). If someone will ever
343 work on such an architecture (SPARC ???) he'll have to fix it.
345 #define CHECK_STACK \
347 struct Task *me = FindTask(NULL); \
349 ULONG *stktop = me->tc_SPLower; \
351 if (stktop && (*stktop != 0xE1E1E1E1)) \
352 bug("STACK OVERFLOW in %s, line %d\n", __FILE__, __LINE__); \
362 #define rbug(main,sub,lvl,fmt,args...) \
363 rkprintf (DBG_MAINSYSTEM_ ## main, \
364 DBG_ ## main ## _SUBSYSTEM_ ## sub, \
367 /* Debugging constants. These should be defined outside and this
368 part should be generated. */
369 #define DBG_MAINSYSTEM_INTUITION "intuition"
370 #define DBG_INTUITION_SUBSYSTEM_INPUTHANDLER "inputhandler"
372 #define AROS_FUNCTION_NOT_IMPLEMENTED(library) \
373 kprintf("The function %s/%s() is not implemented.\n", (library), __FUNCTION__)
375 #define AROS_METHOD_NOT_IMPLEMENTED(CLASS, name) \
376 kprintf("The method %s::%s() is not implemented.\n", (CLASS), (name))
378 #define aros_print_not_implemented(name) \
379 kprintf("The function %s() is not implemented.\n", (name))
381 #define ALIVE kprintf("%s - %s line %d\n",__FILE__,__FUNCTION__,__LINE__);
383 #endif /* AROS_DEBUG_H */