home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 28 / amigaformatcd28.iso / -seriously_amiga- / programming / other / blowup / source / patches.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-27  |  5.4 KB  |  209 lines

  1. /*
  2.  * $Id: patches.c 1.3 1998/04/18 15:45:06 olsen Exp olsen $
  3.  *
  4.  * :ts=4
  5.  *
  6.  * Blowup -- Catches and displays task errors
  7.  *
  8.  * Written by Olaf `Olsen' Barthel <olsen@sourcery.han.de>
  9.  * Public Domain
  10.  */
  11.  
  12. #ifndef _GLOBAL_H
  13. #include "global.h"
  14. #endif    /* _GLOBAL_H */
  15.  
  16. /******************************************************************************/
  17.  
  18. /* library vector offset from amiga.lib */
  19. extern ULONG FAR LVOAddTask;
  20.  
  21. /******************************************************************************/
  22.  
  23. typedef APTR (* ASM ADDTASKFUNC)(REG(a1) struct Task *        task,
  24.                                  REG(a2) APTR                initialPC,
  25.                                  REG(a3) APTR                finalPC,
  26.                                  REG(a6) struct Library *    sysBase);
  27.  
  28. STATIC ADDTASKFUNC OldAddTask;
  29.  
  30. /******************************************************************************/
  31.  
  32. STATIC APTR    TaskTrapHandler;    /* the default system task trap handler */
  33. STATIC APTR    ProcessTrapHandler;    /* the default system process trap handler */
  34.  
  35. /******************************************************************************/
  36.  
  37. /* this is in traphandler.asm */
  38. extern VOID TrapHandler(VOID);
  39.  
  40. /******************************************************************************/
  41.  
  42. STATIC VOID
  43. FixTaskTrapHandler(struct Task * tc)
  44. {
  45.     /* patch a task only if its trap handler matches the system default */
  46.     if(tc->tc_Node.ln_Type == NT_TASK && (tc->tc_TrapCode == TaskTrapHandler || tc->tc_TrapCode == NULL))
  47.     {
  48.         tc->tc_TrapCode = (APTR)TrapHandler;
  49.     }
  50.  
  51.     /* patch a process only if its trap handler matches the system default */
  52.     if(tc->tc_Node.ln_Type == NT_PROCESS && tc->tc_TrapCode == ProcessTrapHandler)
  53.     {
  54.         tc->tc_TrapCode = (APTR)TrapHandler;
  55.     }
  56. }
  57.  
  58. /******************************************************************************/
  59.  
  60. STATIC VOID
  61. FixAllTaskTrapHandlers(VOID)
  62. {
  63.     struct Node * node;
  64.  
  65.     /* this patches all tasks and processes in the system to use our
  66.      * custom trap handler code
  67.      */
  68.  
  69.     Forbid();
  70.  
  71.     FixTaskTrapHandler((struct Task *)FindTask(NULL));
  72.  
  73.     for(node = SysBase->TaskReady.lh_Head ;
  74.         node->ln_Succ != NULL ;
  75.         node = node->ln_Succ)
  76.     {
  77.         FixTaskTrapHandler((struct Task *)node);
  78.     }
  79.  
  80.     for(node = SysBase->TaskWait.lh_Head ;
  81.         node->ln_Succ != NULL ;
  82.         node = node->ln_Succ)
  83.     {
  84.         FixTaskTrapHandler((struct Task *)node);
  85.     }
  86.  
  87.     Permit();
  88. }
  89.  
  90. /******************************************************************************/
  91.  
  92. STATIC VOID
  93. ResetTaskTrapHandler(struct Task * tc)
  94. {
  95.     /* reset the trap handler only if we have a task and it has
  96.      * our custom trap handler installed; unknown trap code
  97.      * will not be replaced
  98.      */
  99.     if(tc->tc_Node.ln_Type == NT_TASK && tc->tc_TrapCode == (APTR)TrapHandler)
  100.     {
  101.         tc->tc_TrapCode = TaskTrapHandler;
  102.     }
  103.  
  104.     /* reset the trap handler only if we have a process and it has
  105.      * our custom trap handler installed; unknown trap code
  106.      * will not be replaced
  107.      */
  108.     if(tc->tc_Node.ln_Type == NT_PROCESS && tc->tc_TrapCode == (APTR)TrapHandler)
  109.     {
  110.         tc->tc_TrapCode = ProcessTrapHandler;
  111.     }
  112. }
  113.  
  114. STATIC VOID
  115. ResetAllTaskTrapHandlers(VOID)
  116. {
  117.     struct Node * node;
  118.  
  119.     /* this patches all tasks and processes in the system to use the
  120.      * system default trap handler code
  121.      */
  122.  
  123.     Forbid();
  124.  
  125.     ResetTaskTrapHandler((struct Task *)FindTask(NULL));
  126.  
  127.     for(node = SysBase->TaskReady.lh_Head ;
  128.         node->ln_Succ != NULL ;
  129.         node = node->ln_Succ)
  130.     {
  131.         ResetTaskTrapHandler((struct Task *)node);
  132.     }
  133.  
  134.     for(node = SysBase->TaskWait.lh_Head ;
  135.         node->ln_Succ != NULL ;
  136.         node = node->ln_Succ)
  137.     {
  138.         ResetTaskTrapHandler((struct Task *)node);
  139.     }
  140.  
  141.     Permit();
  142. }
  143.  
  144. /******************************************************************************/
  145.  
  146. STATIC APTR ASM
  147. NewAddTask(
  148.     REG(a1) struct Task *        task,
  149.     REG(a2) APTR                initialPC,
  150.     REG(a3) APTR                finalPC,
  151.     REG(a6) struct Library *    sysBase)
  152. {
  153.     /* fix up the trap handler code */
  154.     FixTaskTrapHandler(task);
  155.  
  156.     /* and proceed to call the original operating system routine */
  157.     return((*OldAddTask)(task,initialPC,finalPC,sysBase));
  158. }
  159.  
  160. /******************************************************************************/
  161.  
  162. VOID
  163. AddPatches(VOID)
  164. {
  165.     Forbid();
  166.  
  167.     /* The trap handler code is different for plain tasks and for
  168.      * processes; the default task trap handler will end straight
  169.      * in a dead-end alert whereas the process trap handler will
  170.      * show the familiar "Software error -- finish ALL disk activity..."
  171.      * requester, or at least attempt to do so. We have to take care of
  172.      * both cases. The default task trap handler comes from SysBase,
  173.      * whereas there is no absolutely safe way to obtain the default
  174.      * process trap handler; we try to do away with the current
  175.      * process' trap handler and hope that it will work.
  176.      */
  177.  
  178.     TaskTrapHandler        = SysBase->TaskTrapCode;
  179.     ProcessTrapHandler    = ((struct Task *)FindTask(NULL))->tc_TrapCode;
  180.  
  181.     /* patch AddTask() so new tasks will automatically be fitted with
  182.      * the new trap handler
  183.      */
  184.     OldAddTask = (ADDTASKFUNC)SetFunction((struct Library *)SysBase,(LONG)&LVOAddTask,(ULONG (*)())NewAddTask);
  185.  
  186.     /* finally, patch all running tasks to use the new trap handler */
  187.     FixAllTaskTrapHandlers();
  188.  
  189.     Permit();
  190. }
  191.  
  192. /******************************************************************************/
  193.  
  194. VOID
  195. RemovePatches(VOID)
  196. {
  197.     Forbid();
  198.  
  199.     /* reset the AddTask() patch; note: may not be safe as other programs may
  200.      * have redirected the vector
  201.      */
  202.     SetFunction((struct Library *)SysBase,(LONG)&LVOAddTask,(ULONG (*)())OldAddTask);
  203.  
  204.     /* finally, reset all running task/process trap handlers */
  205.     ResetAllTaskTrapHandlers();
  206.  
  207.     Permit();
  208. }
  209.