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