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