Added option to build for amiga-m68k
[AROS.git] / compiler / arossupport / rt.c
blob537b9285e5287ff3c2a2688e45d6d99794e179fe
1 /*
2 Copyright © 1995-2010, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Basic functions for resource tracking
6 Lang: english
7 */
8 #include "rt.h"
9 #if 0
10 #define ENABLE_RT 0 /* no RT inside this file */
11 #define RT_INTERNAL 1
12 #include <aros/rt.h>
14 #include <exec/lists.h>
15 #include <aros/system.h>
16 #include <exec/tasks.h>
17 #include <exec/ports.h>
18 #include <exec/execbase.h>
19 #include <stdarg.h>
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <proto/dos.h>
23 #include <proto/intuition.h>
24 #include <proto/alib.h>
25 #include "etask.h"
26 #endif
27 #include <string.h>
28 #include <exec/memory.h>
29 #include <proto/arossupport.h>
30 #include <proto/exec.h>
32 /* iaint: Use the debugging macros from now on. */
33 #include <aros/debug.h>
35 RTData * intRTD = NULL; /* Internal pointer in case no ETask is available */
36 RTDesc const * RT_Resources[RTT_MAX];
38 /*****************************************************************************
40 NAME */
41 #include <aros/rt.h>
43 void RT_IntInitB (
45 /* SYNOPSIS */
46 void)
48 /* FUNCTION
49 Begin initialization of resource tracking.
51 INPUTS
52 none
54 RESULT
55 none
57 NOTES
59 EXAMPLE
61 BUGS
63 SEE ALSO
65 INTERNALS
67 HISTORY
68 24-12-95 digulla created
70 ******************************************************************************/
72 RTData * rtd;
74 if ((rtd = GetRTData ()))
76 D(bug ("RT_Init() called twice %p\n", rtd) );
77 return;
80 if (!(rtd = AllocMem (sizeof (RTData), MEMF_ANY)) )
82 D(bug ("RT_Init(): No memory\n") );
83 return;
86 SetRTData (rtd);
88 rtd->rtd_Version = RT_VERSION;
89 rtd->rtd_StackPtr = STACKDEPTH;
90 } /* RT_IntInitB */
92 /*****************************************************************************
94 NAME */
95 #include <aros/rt.h>
97 void RT_IntInitE (
99 /* SYNOPSIS */
100 void)
102 /* FUNCTION
103 End initialization of resource tracking.
105 INPUTS
106 none
108 RESULT
109 none
111 NOTES
113 EXAMPLE
115 BUGS
117 SEE ALSO
119 INTERNALS
121 HISTORY
122 24-12-95 digulla created
124 ******************************************************************************/
126 RTData * rtd;
127 int t, i;
129 rtd = GetRTData ();
131 for (t=0; t<RTT_MAX; t++)
133 for (i=0; i<HASH_SIZE; i++)
135 NEWLIST(&rtd->rtd_ResHash[t][i]);
139 D(bug ("RT_Init(): RT up and kicking in %s mode\n"
140 , intRTD ? "internal" : "ETask"
141 ) );
142 } /* RT_IntInitE */
144 /*****************************************************************************
146 NAME */
147 #include <aros/rt.h>
149 void RT_IntExitB (
151 /* SYNOPSIS */
152 void)
154 /* FUNCTION
155 Stops the resource tracking. All resources which are still allocated
156 are printed and then released.
158 INPUTS
159 none
161 RESULT
162 none
164 NOTES
166 EXAMPLE
168 BUGS
170 SEE ALSO
172 INTERNALS
173 Free the resources from back to front. This allows to sort the
174 resources (ie. windows on a screen are closed before the screen,
175 etc).
177 HISTORY
178 24-12-95 digulla created
180 ******************************************************************************/
182 RTData * rtd;
183 RTNode * rt, * next;
184 int t, i;
186 if (!(rtd = GetRTData ()) )
187 return;
189 for (t=RTT_MAX-1; t>=0; t--)
191 for (i=0; i<HASH_SIZE; i++)
193 for (next=(RTNode *)GetHead(&rtd->rtd_ResHash[t][i]); (rt=next); )
195 next = (RTNode *)GetSucc (rt);
197 RT_FreeResource (rtd, t, rt);
201 } /* RT_IntExitB */
203 /*****************************************************************************
205 NAME */
206 #include <aros/rt.h>
208 void RT_IntExitE (
210 /* SYNOPSIS */
211 void)
213 /* FUNCTION
214 Stops the resource tracking. All resources which are still allocated
215 are printed and then released.
217 INPUTS
218 none
220 RESULT
221 none
223 NOTES
225 EXAMPLE
227 BUGS
229 SEE ALSO
231 INTERNALS
232 Free the resources from back to front. This allows to sort the
233 resources (ie. windows on a screen are closed before the screen,
234 etc).
236 HISTORY
237 24-12-95 digulla created
239 ******************************************************************************/
241 RTData * rtd;
243 if (!(rtd = GetRTData ()) )
244 return;
246 FreeMem (rtd, sizeof (RTData));
248 SetRTData (NULL);
249 } /* RT_IntExitE */
251 /*****************************************************************************
253 NAME */
254 #include <aros/rt.h>
256 IPTR RT_IntAdd (
258 /* SYNOPSIS */
259 int rtt,
260 const char * file,
261 int line,
262 ...)
264 /* FUNCTION
265 Adds a resource to be tracked. The arguments after
266 line depend on the type of resource to be traced:
268 RTT_ALLOCMEM: APTR memPtr,
269 ULONG size)
271 INPUTS
272 rtt - Type of the resource
273 file - The file RT_IntAdd was called it
274 line - The line of the file
275 task - The task to be added
276 memPtr - Pointer to a piece of memory to be tracked
277 size - The size of the memory beginning at memPtr
279 RESULT
280 none
282 NOTES
284 EXAMPLE
286 BUGS
288 SEE ALSO
290 INTERNALS
292 HISTORY
293 24-12-95 digulla created
295 ******************************************************************************/
297 RTData * rtd;
298 IPTR ret;
299 va_list args;
300 RTNode * rtnew;
301 BOOL success;
303 if (!(rtd = GetRTData ()) )
304 return FALSE;
306 if (!(rtnew = AllocMem (GetRTSize(rtt), MEMF_ANY)) )
308 D(bug ("RT_IntAdd: Out of memory\n") );
309 return FALSE;
312 rtnew->File = file;
313 rtnew->Line = line;
314 rtnew->Flags = 0;
316 va_start (args, line);
318 success = FALSE;
320 ret = (*GetRTAllocFunc(rtt))
322 rtd,
323 rtnew,
324 args,
325 &success
328 va_end (args);
330 if (success)
332 AddTail ((struct List *)&rtd->rtd_ResHash[rtt][CALCHASH(HASH_BASE(rtnew))]
333 ,(struct Node *)rtnew
336 else
338 FreeMem (rtnew, GetRTSize(rtt));
341 return ret;
342 } /* RT_IntAdd */
344 /*****************************************************************************
346 NAME */
347 #include <aros/rt.h>
349 void RT_IntTrack (
351 /* SYNOPSIS */
352 int rtt,
353 const char * file,
354 int line,
355 APTR res,
356 ...)
358 /* FUNCTION
359 Adds a resource to be tracked. The arguments after
360 line depend on the type of resource to be traced.
361 The resource is marked as "must not be freed by the
362 user".
364 INPUTS
365 rtt - Type of the resource
366 file - The file RT_IntAdd was called it
367 line - The line of the file
368 res - Pointer to the resouce
370 RESULT
371 none
373 NOTES
375 EXAMPLE
377 BUGS
379 SEE ALSO
381 INTERNALS
383 HISTORY
384 24-12-95 digulla created
386 ******************************************************************************/
388 RTData * rtd;
389 va_list args;
390 Resource * rtnew;
392 if (!(rtd = GetRTData ()) )
393 return;
395 if (!(rtnew = AllocMem (GetRTSize(rtt), MEMF_ANY|MEMF_CLEAR)) )
397 D(bug("RT_IntAdd: Out of memory\n"));
399 else
401 rtnew->Node.File = file;
402 rtnew->Node.Line = line;
403 rtnew->Node.Flags = RTNF_DONT_FREE;
404 rtnew->Resource = res;
406 va_start (args, res);
408 va_end (args);
410 AddTail ((struct List *)&rtd->rtd_ResHash[rtt][CALCHASH(HASH_BASE(rtnew))]
411 , (struct Node *)rtnew
414 } /* RT_IntTrack */
416 /*****************************************************************************
418 NAME */
419 #include <aros/rt.h>
421 IPTR RT_IntCheck (
423 /* SYNOPSIS */
424 int rtt,
425 const char * file,
426 int line,
427 int op,
428 ...)
430 /* FUNCTION
431 Checks a resource. Will print an error if the resource is not found
432 or has already been freed or if the type of the resource doesn't
433 match. The arguments after line depend on the type of resource to
434 be traced:
436 RTT_ALLOCMEM: APTR memPtr,
437 ULONG size)
439 INPUTS
440 rtt - Type of the resource
441 file - The file RT_IntCheck was called it
442 line - The line of the file
443 task - The task to be added
444 memPtr - Pointer to a piece of memory to be tracked
445 size - The size of the memory beginning at memPtr
447 RESULT
448 none
450 NOTES
451 All strings must be static.
453 EXAMPLE
455 BUGS
457 SEE ALSO
459 INTERNALS
461 HISTORY
462 24-12-95 digulla created
464 ******************************************************************************/
466 RTData * rtd;
467 RTNode * rt;
468 va_list args;
469 IPTR ret;
471 if (!(rtd = GetRTData ()) )
472 return FALSE;
474 va_start (args, op);
476 if (GetRTCheckFunc(rtt))
478 ret = (*(GetRTCheckFunc(rtt)))
480 rtd,
481 rtt,
482 file,
483 line,
485 args
488 else
490 ret = (*(GetRTSearchFunc(rtt)))
492 rtd,
493 rtt,
494 &rt,
495 args
498 if (ret != RT_SEARCH_FOUND)
500 ret = (*(GetRTShowError(rtt)))
502 rtd,
503 rtt,
505 ret,
506 RT_CHECK,
507 file,
508 line,
509 args
514 va_end (args);
516 return ret;
517 } /* RT_IntCheck */
519 /*****************************************************************************
521 NAME */
522 #include <aros/rt.h>
524 IPTR RT_IntFree (
526 /* SYNOPSIS */
527 int rtt,
528 const char * file,
529 int line,
530 ...)
532 /* FUNCTION
533 Stops tracing of a resource. The arguments after
534 line depend on the type of resource to be traced.
536 INPUTS
537 rtt - Type of the resource
538 file - The file RT_IntAdd was called it
539 line - The line of the file
541 RESULT
542 none
544 NOTES
545 All strings must be static.
547 EXAMPLE
549 BUGS
551 SEE ALSO
553 INTERNALS
555 HISTORY
556 24-12-95 digulla created
558 ******************************************************************************/
560 RTData * rtd;
561 IPTR ret;
562 va_list args;
563 RTNode * rt;
565 if (!(rtd = GetRTData ()) )
566 return FALSE;
568 va_start (args, line);
570 ret = (*(GetRTSearchFunc(rtt)))
572 rtd,
573 rtt,
574 &rt,
575 args
578 if (ret == RT_SEARCH_FOUND && rt && !(rt->Flags & RTNF_DONT_FREE))
580 ret = (*(GetRTFreeFunc(rtt))) (rtd, rt);
582 Remove ((struct Node *)rt);
583 FreeMem (rt, GetRTSize(rtt));
585 else
587 ret = (*(GetRTShowError(rtt)))
589 rtd,
590 rtt,
592 ret,
593 RT_FREE,
594 file,
595 line,
596 args
600 va_end (args);
602 return ret;
603 } /* RT_IntFree */
606 /*****************************************************************************
608 NAME */
609 #include <aros/rt.h>
611 void RT_IntEnter (
613 /* SYNOPSIS */
614 const char * function,
615 const char * file,
616 int line)
618 /* FUNCTION
619 Tells the RT that a new function is about to be entered. This is used
620 to make it easier to track an error.
622 INPUTS
623 function - name of the function to be entered
624 file - file with the call of the function
625 line - Line-number of the call
627 RESULT
628 none
630 NOTES
631 All strings must be static.
633 EXAMPLE
635 BUGS
637 SEE ALSO
639 INTERNALS
641 HISTORY
642 24-12-95 digulla created
644 ******************************************************************************/
646 RTData * rtd;
648 if (!(rtd = GetRTData ()) )
649 return;
651 if (rtd->rtd_StackPtr == 0)
652 return;
654 -- rtd->rtd_StackPtr;
656 rtd->rtd_CallStack[rtd->rtd_StackPtr].Function = function;
657 rtd->rtd_CallStack[rtd->rtd_StackPtr].File = file;
658 rtd->rtd_CallStack[rtd->rtd_StackPtr].Line = line;
659 } /* RT_IntEnter */
662 /*****************************************************************************
664 NAME */
665 #include <aros/rt.h>
667 void RT_IntLeave (
669 /* SYNOPSIS */
670 void)
672 /* FUNCTION
673 Tells the RT that a the function has been left.
675 INPUTS
676 none
678 RESULT
679 none
681 NOTES
683 EXAMPLE
685 BUGS
687 SEE ALSO
689 INTERNALS
691 HISTORY
692 24-12-95 digulla created
694 ******************************************************************************/
696 RTData * rtd;
698 if (!(rtd = GetRTData ()) )
699 return;
701 if (rtd->rtd_StackPtr == STACKDEPTH)
702 return;
704 rtd->rtd_CallStack[rtd->rtd_StackPtr].Function = NULL;
705 rtd->rtd_CallStack[rtd->rtd_StackPtr].File = NULL;
706 rtd->rtd_CallStack[rtd->rtd_StackPtr].Line = 0;
708 rtd->rtd_StackPtr ++;
709 } /* RT_IntLeave */
712 /*****************************************************************************
714 NAME */
715 #include <aros/rt.h>
717 void RT_ShowStack (
719 /* SYNOPSIS */
720 RTNode * node)
722 /* FUNCTION
723 Prints the contents of the callstack stored in the node.
725 INPUTS
726 node - The node with the callstack to be printed
728 RESULT
729 none
731 NOTES
733 EXAMPLE
735 BUGS
737 SEE ALSO
739 INTERNALS
741 HISTORY
742 24-12-95 digulla created
744 ******************************************************************************/
746 #if 0
747 RTData * rtd;
748 int t;
750 if (!(rtd = GetRTData ()) )
751 return;
753 for (t=0; t<KEEPDEPTH && node->Stack[t].Function; t++)
754 D(bug((" %s (%s:%d)\n"
755 , node->Stack[t].Function
756 , node->Stack[t].File
757 , node->Stack[t].Line
759 #endif
760 } /* RT_ShowStack */
763 /*****************************************************************************
765 NAME */
766 #include <aros/rt.h>
768 void RT_ShowRTStack (
770 /* SYNOPSIS */
771 void)
773 /* FUNCTION
774 Prints the contents of the callstack built by RT_Enter() and
775 RT_Leave().
777 INPUTS
778 none
780 RESULT
781 none
783 NOTES
785 EXAMPLE
787 BUGS
789 SEE ALSO
791 INTERNALS
793 HISTORY
794 24-12-95 digulla created
796 ******************************************************************************/
798 RTData * rtd;
799 int t;
801 if (!(rtd = GetRTData ()) )
802 return;
804 for (t=0; t<=rtd->rtd_StackPtr; t++)
806 D(bug(" %s (%s:%d)\n"
807 , rtd->rtd_CallStack[t].Function
808 , rtd->rtd_CallStack[t].File
809 , rtd->rtd_CallStack[t].Line
812 } /* RT_ShowRTStack */
814 /* To safely pass an empty va_list, we need to use
815 * the following wrapper.
817 static inline void GetRTShowError_ap(RTData * rtd, int rtt, RTNode *n, IPTR ptr, int i, const char * file, ULONG line, ...)
819 va_list ap;
820 va_start(ap, line);
822 (void)(*GetRTShowError(rtt))(rtd, rtt, n, ptr, i, file, line, ap);
824 va_end(ap);
827 /*****************************************************************************
829 NAME */
830 #include <aros/rt.h>
832 void RT_FreeResource (
834 /* SYNOPSIS */
835 RTData * rtd,
836 int rtt,
837 RTNode * rtnode)
839 /* FUNCTION
840 Free a resource after the task that allocated it, died. Also
841 print a nasty message about this.
843 INPUTS
844 rt - The node with the resource to be freed.
846 RESULT
847 none
849 NOTES
851 EXAMPLE
853 BUGS
855 SEE ALSO
857 INTERNALS
858 Don't free the node or remove it from the list. This is done
859 elsewhere.
861 HISTORY
862 24-12-95 digulla created
864 ******************************************************************************/
866 if (!rtd && !(rtd = GetRTData ()))
867 return;
869 if (!(rtnode->Flags & RTNF_DONT_FREE) )
871 /* Print an error */
872 GetRTShowError_ap(
873 rtd,
874 rtt,
875 rtnode,
876 0UL,
877 RT_EXIT,
878 NULL,
882 /* free the resource */
883 (void) (*(GetRTFreeFunc(rtt))) (rtd, rtnode);
886 /* Remove resource from list and free it */
887 Remove ((struct Node *)rtnode);
888 FreeMem (rtnode, GetRTSize(rtt));
890 } /* RT_FreeResource */
893 /**************************************
894 Utility functions
895 **************************************/
897 BOOL CheckPtr (APTR ptr, ULONG flags)
901 (!ptr && !(flags & NULL_PTR))
902 || (((IPTR)ptr & 3) && (flags & ALIGNED_PTR))
905 return FALSE;
909 return TRUE;
910 } /* CheckPtr */
912 BOOL CheckArea (APTR ptr, ULONG size, ULONG flags)
916 (size & 0x8000000)
917 || !CheckPtr (ptr+size-1, flags)
919 return FALSE;
921 return TRUE;
922 } /* CheckArea */
924 IPTR RT_Search (RTData * rtd, int rtt, RTNode ** rtptr, va_list args)
926 Resource * rt;
927 APTR * res;
929 res = va_arg (args, APTR);
931 ForeachNode (&rtd->rtd_ResHash[rtt][CALCHASH(res)], rt)
933 if (rt->Resource == res)
935 *rtptr = (RTNode *)rt;
937 return RT_SEARCH_FOUND;
941 return RT_SEARCH_NOT_FOUND;
942 } /* RT_Search */