📄 tclmacinterupt.c
字号:
/* * tclMacInterupt.c -- * * This file contains routines that deal with the Macintosh's low level * time manager. This code provides a better resolution timer than what * can be provided by WaitNextEvent. * * Copyright (c) 1996 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * SCCS: @(#) tclMacInterupt.c 1.16 96/12/12 19:22:01 */#include "tclInt.h"#include "tclMacInt.h"#include <LowMem.h>#include <Processes.h>#include <Timer.h>/* * Data structure for timer tasks. */typedef struct TMInfo { TMTask tmTask; ProcessSerialNumber psn; Point lastPoint; Point newPoint; long currentA5; long ourA5; int installed;} TMInfo;/* * Globals used within this file. */ static TimerUPP sleepTimerProc = NULL;static int interuptsInited = false;static ProcessSerialNumber applicationPSN;#define MAX_TIMER_ARRAY_SIZE 16static TMInfo timerInfoArray[MAX_TIMER_ARRAY_SIZE];static int topTimerElement = 0;/* * Prototypes for procedures that are referenced only in this file: */#if !GENERATINGCFMstatic TMInfo * GetTMInfo(void) ONEWORDINLINE(0x2E89); /* MOVE.L A1,(SP) */#endifstatic void SleepTimerProc _ANSI_ARGS_((void));static pascal void CleanUpExitProc _ANSI_ARGS_((void));static void InitInteruptSystem _ANSI_ARGS_((void));/* *---------------------------------------------------------------------- * * InitInteruptSystem -- * * Does various initialization for the functions used in this * file. Sets up Universial Pricedure Pointers, installs a trap * patch for ExitToShell, etc. * * Results: * None. * * Side effects: * Various initialization. * *---------------------------------------------------------------------- */voidInitInteruptSystem(){ int i; sleepTimerProc = NewTimerProc(SleepTimerProc); GetCurrentProcess(&applicationPSN); for (i = 0; i < MAX_TIMER_ARRAY_SIZE; i++) { timerInfoArray[i].installed = false; } /* * Install the ExitToShell patch. We use this patch instead * of the Tcl exit mechanism because we need to ensure that * these routines are cleaned up even if we crash or are forced * to quit. There are some circumstances when the Tcl exit * handlers may not fire. */ TclMacInstallExitToShellPatch(CleanUpExitProc); interuptsInited = true;}/* *---------------------------------------------------------------------- * * TclMacStartTimer -- * * Install a Time Manager task to wake our process up in the * future. The process should get a NULL event after ms * milliseconds. * * Results: * None. * * Side effects: * Schedules our process to wake up. * *---------------------------------------------------------------------- */void *TclMacStartTimer( long ms) /* Milliseconds. */{ TMInfo *timerInfoPtr; if (!interuptsInited) { InitInteruptSystem(); } /* * Obtain a pointer for the timer. We only allocate up * to MAX_TIMER_ARRAY_SIZE timers. If we are past that * max we return NULL. */ if (topTimerElement < MAX_TIMER_ARRAY_SIZE) { timerInfoPtr = &timerInfoArray[topTimerElement]; topTimerElement++; } else { return NULL; } /* * Install timer to wake process in ms milliseconds. */ timerInfoPtr->tmTask.tmAddr = sleepTimerProc; timerInfoPtr->tmTask.tmWakeUp = 0; timerInfoPtr->tmTask.tmReserved = 0; timerInfoPtr->psn = applicationPSN; timerInfoPtr->installed = true; InsTime((QElemPtr) timerInfoPtr); PrimeTime((QElemPtr) timerInfoPtr, (long) ms); return (void *) timerInfoPtr;}/* *---------------------------------------------------------------------- * * TclMacRemoveTimer -- * * Remove the timer event from the Time Manager. * * Results: * None. * * Side effects: * A scheduled timer would be removed. * *---------------------------------------------------------------------- */voidTclMacRemoveTimer( void * timerToken) /* Token got from start timer. */{ TMInfo *timerInfoPtr = (TMInfo *) timerToken; if (timerInfoPtr == NULL) { return; } RmvTime((QElemPtr) timerInfoPtr); timerInfoPtr->installed = false; topTimerElement--;}/* *---------------------------------------------------------------------- * * TclMacTimerExpired -- * * Check to see if the installed timer has expired. * * Results: * True if timer has expired, false otherwise. * * Side effects: * None. * *---------------------------------------------------------------------- */intTclMacTimerExpired( void * timerToken) /* Our token again. */{ TMInfo *timerInfoPtr = (TMInfo *) timerToken; if ((timerInfoPtr == NULL) || !(timerInfoPtr->tmTask.qType & kTMTaskActive)) { return true; } else { return false; }}/* *---------------------------------------------------------------------- * * SleepTimerProc -- * * Time proc is called by the is a callback routine placed in the * system by Tcl_Sleep. The routine is called at interupt time * and threrfor can not move or allocate memory. This call will * schedule our process to wake up the next time the process gets * around to consider running it. * * Results: * None. * * Side effects: * Schedules our process to wake up. * *---------------------------------------------------------------------- */static voidSleepTimerProc(){ /* * In CFM code we can access our code directly. In 68k code that * isn't based on CFM we must do a glorious hack. The function * GetTMInfo is an inline assembler call that moves the pointer * at A1 to the top of the stack. The Time Manager keeps the TMTask * info record there before calling this call back. In order for * this to work the infoPtr argument must be the *last* item on the * stack. If we "piggyback" our data to the TMTask info record we * can get access to the information we need. While this is really * ugly - it's the way Apple recomends it be done - go figure... */ #if GENERATINGCFM WakeUpProcess(&applicationPSN);#else TMInfo * infoPtr; infoPtr = GetTMInfo(); WakeUpProcess(&infoPtr->psn);#endif}/* *---------------------------------------------------------------------- * * CleanUpExitProc -- * * This procedure is invoked as an exit handler when ExitToShell * is called. It removes the system level timer handler if it * is installed. This must be called or the Mac OS will more than * likely crash. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */static pascal voidCleanUpExitProc(){ int i; for (i = 0; i < MAX_TIMER_ARRAY_SIZE; i++) { if (timerInfoArray[i].installed) { RmvTime((QElemPtr) &timerInfoArray[i]); timerInfoArray[i].installed = false; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -