2 Copyright © 1995-2010, The AROS Development Team. All rights reserved.
5 Desc: Basic functions for resource tracking
10 #define ENABLE_RT 0 /* no RT inside this file */
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>
22 #include <proto/dos.h>
23 #include <proto/intuition.h>
24 #include <proto/alib.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 /*****************************************************************************
49 Begin initialization of resource tracking.
68 24-12-95 digulla created
70 ******************************************************************************/
74 if ((rtd
= GetRTData ()))
76 D(bug ("RT_Init() called twice %p\n", rtd
) );
80 if (!(rtd
= AllocMem (sizeof (RTData
), MEMF_ANY
)) )
82 D(bug ("RT_Init(): No memory\n") );
88 rtd
->rtd_Version
= RT_VERSION
;
89 rtd
->rtd_StackPtr
= STACKDEPTH
;
92 /*****************************************************************************
103 End initialization of resource tracking.
122 24-12-95 digulla created
124 ******************************************************************************/
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"
144 /*****************************************************************************
155 Stops the resource tracking. All resources which are still allocated
156 are printed and then released.
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,
178 24-12-95 digulla created
180 ******************************************************************************/
186 if (!(rtd
= GetRTData ()) )
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
);
203 /*****************************************************************************
214 Stops the resource tracking. All resources which are still allocated
215 are printed and then released.
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,
237 24-12-95 digulla created
239 ******************************************************************************/
243 if (!(rtd
= GetRTData ()) )
246 FreeMem (rtd
, sizeof (RTData
));
251 /*****************************************************************************
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,
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
293 24-12-95 digulla created
295 ******************************************************************************/
303 if (!(rtd
= GetRTData ()) )
306 if (!(rtnew
= AllocMem (GetRTSize(rtt
), MEMF_ANY
)) )
308 D(bug ("RT_IntAdd: Out of memory\n") );
316 va_start (args
, line
);
320 ret
= (*GetRTAllocFunc(rtt
))
332 AddTail ((struct List
*)&rtd
->rtd_ResHash
[rtt
][CALCHASH(HASH_BASE(rtnew
))]
333 ,(struct Node
*)rtnew
338 FreeMem (rtnew
, GetRTSize(rtt
));
344 /*****************************************************************************
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
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
384 24-12-95 digulla created
386 ******************************************************************************/
392 if (!(rtd
= GetRTData ()) )
395 if (!(rtnew
= AllocMem (GetRTSize(rtt
), MEMF_ANY
|MEMF_CLEAR
)) )
397 D(bug("RT_IntAdd: Out of memory\n"));
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
);
410 AddTail ((struct List
*)&rtd
->rtd_ResHash
[rtt
][CALCHASH(HASH_BASE(rtnew
))]
411 , (struct Node
*)rtnew
416 /*****************************************************************************
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
436 RTT_ALLOCMEM: APTR memPtr,
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
451 All strings must be static.
462 24-12-95 digulla created
464 ******************************************************************************/
471 if (!(rtd
= GetRTData ()) )
476 if (GetRTCheckFunc(rtt
))
478 ret
= (*(GetRTCheckFunc(rtt
)))
490 ret
= (*(GetRTSearchFunc(rtt
)))
498 if (ret
!= RT_SEARCH_FOUND
)
500 ret
= (*(GetRTShowError(rtt
)))
519 /*****************************************************************************
533 Stops tracing of a resource. The arguments after
534 line depend on the type of resource to be traced.
537 rtt - Type of the resource
538 file - The file RT_IntAdd was called it
539 line - The line of the file
545 All strings must be static.
556 24-12-95 digulla created
558 ******************************************************************************/
565 if (!(rtd
= GetRTData ()) )
568 va_start (args
, line
);
570 ret
= (*(GetRTSearchFunc(rtt
)))
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
));
587 ret
= (*(GetRTShowError(rtt
)))
606 /*****************************************************************************
614 const char * 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.
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
631 All strings must be static.
642 24-12-95 digulla created
644 ******************************************************************************/
648 if (!(rtd
= GetRTData ()) )
651 if (rtd
->rtd_StackPtr
== 0)
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
;
662 /*****************************************************************************
673 Tells the RT that a the function has been left.
692 24-12-95 digulla created
694 ******************************************************************************/
698 if (!(rtd
= GetRTData ()) )
701 if (rtd
->rtd_StackPtr
== STACKDEPTH
)
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
++;
712 /*****************************************************************************
723 Prints the contents of the callstack stored in the node.
726 node - The node with the callstack to be printed
742 24-12-95 digulla created
744 ******************************************************************************/
750 if (!(rtd
= GetRTData ()) )
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
763 /*****************************************************************************
768 void RT_ShowRTStack (
774 Prints the contents of the callstack built by RT_Enter() and
794 24-12-95 digulla created
796 ******************************************************************************/
801 if (!(rtd
= GetRTData ()) )
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
, ...)
822 (void)(*GetRTShowError(rtt
))(rtd
, rtt
, n
, ptr
, i
, file
, line
, ap
);
827 /*****************************************************************************
832 void RT_FreeResource (
840 Free a resource after the task that allocated it, died. Also
841 print a nasty message about this.
844 rt - The node with the resource to be freed.
858 Don't free the node or remove it from the list. This is done
862 24-12-95 digulla created
864 ******************************************************************************/
866 if (!rtd
&& !(rtd
= GetRTData ()))
869 if (!(rtnode
->Flags
& RTNF_DONT_FREE
) )
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 /**************************************
895 **************************************/
897 BOOL
CheckPtr (APTR ptr
, ULONG flags
)
901 (!ptr
&& !(flags
& NULL_PTR
))
902 || (((IPTR
)ptr
& 3) && (flags
& ALIGNED_PTR
))
912 BOOL
CheckArea (APTR ptr
, ULONG size
, ULONG flags
)
917 || !CheckPtr (ptr
+size
-1, flags
)
924 IPTR
RT_Search (RTData
* rtd
, int rtt
, RTNode
** rtptr
, va_list args
)
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
;