tclMacInterupt.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:7k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /* 
  2.  * tclMacInterupt.c --
  3.  *
  4.  * This file contains routines that deal with the Macintosh's low level
  5.  * time manager.  This code provides a better resolution timer than what
  6.  * can be provided by WaitNextEvent.  
  7.  *
  8.  * Copyright (c) 1996 Sun Microsystems, Inc.
  9.  *
  10.  * See the file "license.terms" for information on usage and redistribution
  11.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  12.  *
  13.  * RCS: @(#) $Id: tclMacInterupt.c,v 1.2 1998/09/14 18:40:05 stanton Exp $
  14.  */
  15. #include "tclInt.h"
  16. #include "tclMacInt.h"
  17. #include <LowMem.h>
  18. #include <Processes.h>
  19. #include <Timer.h>
  20. /*
  21.  * Data structure for timer tasks.
  22.  */
  23. typedef struct TMInfo {
  24.     TMTask tmTask;
  25.     ProcessSerialNumber psn;
  26.     Point  lastPoint;
  27.     Point  newPoint;
  28.     long  currentA5;
  29.     long  ourA5;
  30.     int installed;
  31. } TMInfo;
  32. /*
  33.  * Globals used within this file.
  34.  */
  35.  
  36. static TimerUPP sleepTimerProc = NULL;
  37. static int interuptsInited = false;
  38. static ProcessSerialNumber applicationPSN;
  39. #define MAX_TIMER_ARRAY_SIZE 16
  40. static TMInfo timerInfoArray[MAX_TIMER_ARRAY_SIZE];
  41. static int topTimerElement = 0;
  42. /*
  43.  * Prototypes for procedures that are referenced only in this file:
  44.  */
  45. #if !GENERATINGCFM
  46. static TMInfo *  GetTMInfo(void) ONEWORDINLINE(0x2E89); /* MOVE.L A1,(SP) */
  47. #endif
  48. static void SleepTimerProc _ANSI_ARGS_((void));
  49. static pascal void CleanUpExitProc _ANSI_ARGS_((void));
  50. static void InitInteruptSystem _ANSI_ARGS_((void));
  51. /*
  52.  *----------------------------------------------------------------------
  53.  *
  54.  * InitInteruptSystem --
  55.  *
  56.  * Does various initialization for the functions used in this 
  57.  * file.  Sets up Universial Pricedure Pointers, installs a trap
  58.  * patch for ExitToShell, etc.
  59.  *
  60.  * Results:
  61.  * None.
  62.  *
  63.  * Side effects:
  64.  * Various initialization.
  65.  *
  66.  *----------------------------------------------------------------------
  67.  */
  68. void
  69. InitInteruptSystem()
  70. {
  71.     int i;
  72.     
  73.     sleepTimerProc = NewTimerProc(SleepTimerProc);
  74.     GetCurrentProcess(&applicationPSN);
  75.     for (i = 0; i < MAX_TIMER_ARRAY_SIZE; i++) {
  76. timerInfoArray[i].installed = false;
  77.     }
  78.     
  79.     /*
  80.      * Install the ExitToShell patch.  We use this patch instead
  81.      * of the Tcl exit mechanism because we need to ensure that
  82.      * these routines are cleaned up even if we crash or are forced
  83.      * to quit.  There are some circumstances when the Tcl exit
  84.      * handlers may not fire.
  85.      */
  86.      
  87.     TclMacInstallExitToShellPatch(CleanUpExitProc);
  88.     interuptsInited = true;
  89. }
  90. /*
  91.  *----------------------------------------------------------------------
  92.  *
  93.  * TclMacStartTimer --
  94.  *
  95.  * Install a Time Manager task to wake our process up in the
  96.  * future.  The process should get a NULL event after ms 
  97.  * milliseconds.
  98.  *
  99.  * Results:
  100.  * None.
  101.  *
  102.  * Side effects:
  103.  * Schedules our process to wake up.
  104.  *
  105.  *----------------------------------------------------------------------
  106.  */
  107. void *
  108. TclMacStartTimer(
  109.     long ms) /* Milliseconds. */
  110. {
  111.     TMInfo *timerInfoPtr;
  112.     
  113.     if (!interuptsInited) {
  114. InitInteruptSystem();
  115.     }
  116.     
  117.     /*
  118.      * Obtain a pointer for the timer.  We only allocate up
  119.      * to MAX_TIMER_ARRAY_SIZE timers.  If we are past that
  120.      * max we return NULL.
  121.      */
  122.     if (topTimerElement < MAX_TIMER_ARRAY_SIZE) {
  123. timerInfoPtr = &timerInfoArray[topTimerElement];
  124. topTimerElement++;
  125.     } else {
  126. return NULL;
  127.     }
  128.     
  129.     /*
  130.      * Install timer to wake process in ms milliseconds.
  131.      */
  132.     timerInfoPtr->tmTask.tmAddr = sleepTimerProc;
  133.     timerInfoPtr->tmTask.tmWakeUp = 0;
  134.     timerInfoPtr->tmTask.tmReserved = 0;
  135.     timerInfoPtr->psn = applicationPSN;
  136.     timerInfoPtr->installed = true;
  137.     InsTime((QElemPtr) timerInfoPtr);
  138.     PrimeTime((QElemPtr) timerInfoPtr, (long) ms);
  139.     return (void *) timerInfoPtr;
  140. }
  141. /*
  142.  *----------------------------------------------------------------------
  143.  *
  144.  * TclMacRemoveTimer --
  145.  *
  146.  * Remove the timer event from the Time Manager.
  147.  *
  148.  * Results:
  149.  * None.
  150.  *
  151.  * Side effects:
  152.  * A scheduled timer would be removed.
  153.  *
  154.  *----------------------------------------------------------------------
  155.  */
  156. void
  157. TclMacRemoveTimer(
  158.     void * timerToken) /* Token got from start timer. */
  159. {
  160.     TMInfo *timerInfoPtr = (TMInfo *) timerToken;
  161.     
  162.     if (timerInfoPtr == NULL) {
  163. return;
  164.     }
  165.     
  166.     RmvTime((QElemPtr) timerInfoPtr);
  167.     timerInfoPtr->installed = false;
  168.     topTimerElement--;
  169. }
  170. /*
  171.  *----------------------------------------------------------------------
  172.  *
  173.  * TclMacTimerExpired --
  174.  *
  175.  * Check to see if the installed timer has expired.
  176.  *
  177.  * Results:
  178.  * True if timer has expired, false otherwise.
  179.  *
  180.  * Side effects:
  181.  * None.
  182.  *
  183.  *----------------------------------------------------------------------
  184.  */
  185. int
  186. TclMacTimerExpired(
  187.     void * timerToken) /* Our token again. */
  188. {
  189.     TMInfo *timerInfoPtr = (TMInfo *) timerToken;
  190.     
  191.     if ((timerInfoPtr == NULL) || 
  192. !(timerInfoPtr->tmTask.qType & kTMTaskActive)) {
  193. return true;
  194.     } else {
  195. return false;
  196.     }
  197. }
  198. /*
  199.  *----------------------------------------------------------------------
  200.  *
  201.  * SleepTimerProc --
  202.  *
  203.  * Time proc is called by the is a callback routine placed in the 
  204.  * system by Tcl_Sleep.  The routine is called at interupt time
  205.  * and threrfor can not move or allocate memory.  This call will
  206.  * schedule our process to wake up the next time the process gets
  207.  * around to consider running it.
  208.  *
  209.  * Results:
  210.  * None.
  211.  *
  212.  * Side effects:
  213.  * Schedules our process to wake up.
  214.  *
  215.  *----------------------------------------------------------------------
  216.  */
  217. static void
  218. SleepTimerProc()
  219. {
  220.     /*
  221.      * In CFM code we can access our code directly.  In 68k code that
  222.      * isn't based on CFM we must do a glorious hack.  The function 
  223.      * GetTMInfo is an inline assembler call that moves the pointer 
  224.      * at A1 to the top of the stack.  The Time Manager keeps the TMTask
  225.      * info record there before calling this call back.  In order for
  226.      * this to work the infoPtr argument must be the *last* item on the
  227.      * stack.  If we "piggyback" our data to the TMTask info record we 
  228.      * can get access to the information we need.  While this is really 
  229.      * ugly - it's the way Apple recomends it be done - go figure...
  230.      */
  231.     
  232. #if GENERATINGCFM
  233.     WakeUpProcess(&applicationPSN);
  234. #else
  235.     TMInfo * infoPtr;
  236.     
  237.     infoPtr = GetTMInfo();
  238.     WakeUpProcess(&infoPtr->psn);
  239. #endif
  240. }
  241. /*
  242.  *----------------------------------------------------------------------
  243.  *
  244.  * CleanUpExitProc --
  245.  *
  246.  * This procedure is invoked as an exit handler when ExitToShell
  247.  * is called.  It removes the system level timer handler if it 
  248.  * is installed.  This must be called or the Mac OS will more than 
  249.  * likely crash.
  250.  *
  251.  * Results:
  252.  * None.
  253.  *
  254.  * Side effects:
  255.  * None.
  256.  *
  257.  *----------------------------------------------------------------------
  258.  */
  259. static pascal void
  260. CleanUpExitProc()
  261. {
  262.     int i;
  263.     
  264.     for (i = 0; i < MAX_TIMER_ARRAY_SIZE; i++) {
  265. if (timerInfoArray[i].installed) {
  266.     RmvTime((QElemPtr) &timerInfoArray[i]);
  267.     timerInfoArray[i].installed = false;
  268. }
  269.     }
  270. }