Last active
November 27, 2022 00:11
-
-
Save rakslice/f2329427874e38edc649f4b24bd7328c to your computer and use it in GitHub Desktop.
Classic Mac System 7 and later time manager InsTime/RmvTime stress test
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
A program for testing InsTime/RmvTime cycles during timer events | |
Reading list: | |
- Inside Macintosh: Processes, Ch. 3 Time Manager, Using the Time Manager | |
To use, in THINK C 5.x | |
1. Create a THINK C 5.x project called "time manager stress test" | |
2. Add (Source -> Add...) this .c file | |
3. Add Mactraps (from Think C::Mac Libraries) | |
4. Add ANSI-small (from Think C::C Libraries) | |
5. Using ResEdit, create a new resource file in the same location as the project called "time manager stress test.rsrc" | |
6. Add a WIND resource with the default ID 128 and save it. | |
7. In THINK C, Project -> Run or Project -> Build Application... | |
*/ | |
#include <Timer.h> | |
#include <stdio.h> | |
#define malloc NewPtr | |
#define free DisposePtr | |
#define APP_NEW(obj_type) ((obj_type *) NewPtr(sizeof(obj_type))) | |
#define SYS_NEW(obj_type) ((obj_type *) NewPtrSys(sizeof(obj_type))) | |
#define START_DELAY 1000 // ms | |
#define STEP_DELAY 0 // ms | |
long int i; | |
typedef void (*BetterTimerProcPtr)(TMTask * self); | |
struct TMTaskWithA5World { | |
TMTask tmTask; | |
long int a5World; | |
BetterTimerProcPtr innerTimerFunc; | |
}; | |
pascal struct TMTaskWithA5World * GetTMInfo() | |
= {0x2E89}; // MOVE.L A1,(SP) | |
pascal void handleOuterTimer() { | |
int oldA5World; | |
struct TMTaskWithA5World * task; | |
task = GetTMInfo(); | |
oldA5World = SetA5(task->a5World); | |
task->innerTimerFunc((TMTask *) task); | |
SetA5(oldA5World); | |
} | |
TMTask * createTMTask(BetterTimerProcPtr func) { | |
struct TMTaskWithA5World * task; | |
task = SYS_NEW(struct TMTaskWithA5World); | |
if (task) { | |
task->tmTask.tmAddr = &handleOuterTimer; | |
task->tmTask.tmCount = 0; | |
task->tmTask.tmWakeUp = 0; | |
task->tmTask.tmReserved = 0; | |
task->a5World = SetCurrentA5(); | |
task->innerTimerFunc = func; | |
} | |
return (TMTask *) task; | |
} | |
void handleFirstTimer(TMTask * self) { | |
i++; | |
PrimeTime(self, STEP_DELAY); | |
} | |
void handleSecondTimer(TMTask * self) { | |
} | |
int main(void) { | |
TMTask *firstTask, *secondTask; | |
WindowPtr theWindow; | |
char buf[512]; | |
int prevI; | |
BetterTimerProcPtr firstTimerHandler, secondTimerHandler; | |
InitGraf(&thePort); | |
InitFonts(); | |
InitWindows(); | |
firstTask = createTMTask(&handleFirstTimer); | |
secondTask = createTMTask(&handleSecondTimer); | |
theWindow = GetNewWindow(128, 0L, (WindowPtr)-1L); | |
SetPort(theWindow); | |
if (firstTask) { | |
InsTime(firstTask); | |
PrimeTime(firstTask, START_DELAY); | |
} | |
i = 0; | |
prevI = -1; | |
while(!Button()) { | |
if (i != prevI) { | |
prevI = i; | |
EraseRect(&theWindow->portRect); | |
MoveTo(30,50); | |
DrawString("\p- Continuous InsTime RmvTime cycles on a task in the foreground"); | |
MoveTo(30,75); | |
sprintf(buf, " - Runs of a separate task from the Time Manager (count: %ld)", i); | |
buf[0] = strlen(buf) - 1; | |
DrawString(buf); | |
MoveTo(30,100); | |
DrawString("\pClick to close"); | |
} | |
if (secondTask) { | |
InsTime(secondTask); | |
RmvTime(secondTask); | |
} | |
} | |
if (firstTask) { | |
RmvTime(firstTask); | |
free(firstTask); | |
} | |
if (secondTask) | |
free(secondTask); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I created this to more easily reproduce a multithreading locking bug in Basilisk II / SheepShaver