mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2024-12-28 01:29:20 +00:00
4325cdcc78
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included. The Tools directory, containing mostly junk, is also excluded.
239 lines
6.0 KiB
C
239 lines
6.0 KiB
C
/*
|
|
File: Sleep.c
|
|
|
|
Contains: Routines which facilitate sleeping processes.
|
|
|
|
Written by: Erich Ringewald
|
|
|
|
Copyright: © 1986-1992 by Apple Computer, Inc., all rights reserved.
|
|
|
|
Change History (most recent first):
|
|
|
|
<5> 3/23/92 JSM OSEvents.h is obsolete, use Events.h.
|
|
<4> 3/16/92 YK (for TSM) In clkint, If a physical event is not for the front
|
|
app, donÕt switch to the front app.
|
|
<2> 11/27/90 DFH Removed unneeded parameter from cpu_resched.
|
|
<0> 3/13/86 ELR New Today.
|
|
|
|
*/
|
|
|
|
#include <types.h>
|
|
#include <memory.h>
|
|
#include <osutils.h>
|
|
#include <files.h>
|
|
#include <quickdraw.h>
|
|
#include <windows.h>
|
|
#include <menus.h>
|
|
#include <events.h>
|
|
#include <resources.h>
|
|
#include <retrace.h>
|
|
#include <segload.h>
|
|
|
|
#include "Glue.h"
|
|
#include "Lomem.h"
|
|
#include "Data.h"
|
|
#include "SysMisc.h"
|
|
#include "Puppet.h"
|
|
|
|
/* Some function prototypes that should be in (yet another) header file */
|
|
void RemoveFromStateList(PEntryPtr, PEntryPtr *);
|
|
void CancelSleep(PEntryPtr);
|
|
Boolean OSEventAvailForFront(short, EventRecord *);
|
|
|
|
/* Function prototypes internal to this file */
|
|
void RoustSleepers(void);
|
|
void PutOnSleepQueue(PEntryPtr, unsigned long);
|
|
void RoustSleepers(void);
|
|
|
|
/* PutOnSleepQueue. Put the specified process on the sleep queue with the designated
|
|
* sleep time.
|
|
*/
|
|
void
|
|
PutOnSleepQueue(PEntryPtr pProc, unsigned long sleepTime)
|
|
{
|
|
register PEntryPtr pPrev, pNext;
|
|
unsigned long thenTicks;
|
|
|
|
if (sleepTime == 0)
|
|
return;
|
|
|
|
/* Figure out time to wakeup. Pin overflow to highest TICKS value. */
|
|
thenTicks = TICKS + sleepTime;
|
|
if (thenTicks < sleepTime)
|
|
thenTicks = MAXVALUE;
|
|
|
|
/* reflect process state in PEntry */
|
|
pProc->p_state = PRSLEEPING;
|
|
pProc->p_wakeuptime = thenTicks;
|
|
|
|
/* Place process in the (ordered) sleep state list */
|
|
pPrev = nil;
|
|
pNext = pSleepingStateList;
|
|
while (pNext != nil)
|
|
{
|
|
unsigned long tempTicks;
|
|
|
|
if ( ((tempTicks = pNext->p_wakeuptime) != 0) && (tempTicks > thenTicks) )
|
|
break;
|
|
pPrev = pNext;
|
|
pNext = pNext->p_NextProcessInState;
|
|
}
|
|
|
|
/* Have insertion point. Fix up newcomer's links, then insert. */
|
|
assert((pProc != pPrev) && (pProc != pNext));
|
|
pProc->p_PrevProcessInState = pPrev;
|
|
pProc->p_NextProcessInState = pNext;
|
|
|
|
if (pPrev == nil)
|
|
pSleepingStateList = pProc;
|
|
else
|
|
pPrev->p_NextProcessInState = pProc;
|
|
|
|
if (pNext != nil)
|
|
pNext->p_PrevProcessInState = pProc;
|
|
}
|
|
|
|
/* SleepProcess. put the calling process to sleep. Call resched to arrange for
|
|
* another process to use the processor.
|
|
*/
|
|
pascal void
|
|
c_SleepProcess(u_long napTime)
|
|
{
|
|
PEntryPtr pCurr;
|
|
u_long olda5;
|
|
|
|
olda5 = ProcessMgrA5SimpleSetup();
|
|
|
|
/* can't sleep if not running */
|
|
pCurr = pCurrentProcess;
|
|
if ( (pCurr->p_state != PRRUN) &&
|
|
(pCurr->p_state != PRBACKRUN) )
|
|
{
|
|
A5SimpleRestore(olda5);
|
|
return;
|
|
}
|
|
|
|
/* can't sleep if coercing */
|
|
if (coercionState != CS_DONE)
|
|
{
|
|
A5SimpleRestore(olda5);
|
|
return;
|
|
}
|
|
|
|
PutOnSleepQueue(pCurr, napTime);
|
|
|
|
/* offer up the machine */
|
|
cpu_resched();
|
|
|
|
A5SimpleRestore(olda5);
|
|
}
|
|
|
|
/* clkint. This routine simulates processing on a clock interrupt. This is silly,
|
|
* and for now we call this thing from the idle loop.
|
|
*/
|
|
void
|
|
clkint(void)
|
|
{
|
|
EventRecord evtRec;
|
|
unsigned long olda5;
|
|
|
|
olda5 = ProcessMgrA5SimpleSetup();
|
|
|
|
/* See if anyone's time is up */
|
|
RoustSleepers();
|
|
|
|
/* Get frontmost app going if there's a physical event queued */
|
|
assert(coercionState == CS_DONE);
|
|
if ( (pFrontProcess->p_state == PRSLEEPING) && OSEventAvailForFront(pFrontProcess->p_eventmask, &evtRec) )
|
|
CancelSleep(pFrontProcess);
|
|
|
|
A5Restore(olda5);
|
|
}
|
|
|
|
/* PushOnStateList. Links process into head of given state list */
|
|
void
|
|
PushOnStateList(register PEntryPtr pProc, PEntryPtr *ppList)
|
|
{
|
|
PEntryPtr pFirstProc;
|
|
|
|
pFirstProc = *ppList;
|
|
pProc->p_NextProcessInState = pFirstProc;
|
|
pProc->p_PrevProcessInState = nil;
|
|
pFirstProc->p_PrevProcessInState = pProc;
|
|
*ppList = pProc;
|
|
}
|
|
|
|
/* RemoveFromStateList. Unlinks process from given state list */
|
|
void
|
|
RemoveFromStateList(register PEntryPtr pProc, PEntryPtr *ppList)
|
|
{
|
|
PEntryPtr pOtherProc;
|
|
|
|
if ((pOtherProc = pProc->p_PrevProcessInState) != nil)
|
|
pOtherProc->p_NextProcessInState = pProc->p_NextProcessInState;
|
|
else
|
|
*ppList = pProc->p_NextProcessInState;
|
|
|
|
if ((pOtherProc = pProc->p_NextProcessInState) != nil)
|
|
pOtherProc->p_PrevProcessInState = pProc->p_PrevProcessInState;
|
|
|
|
pProc->p_PrevProcessInState = nil;
|
|
pProc->p_NextProcessInState = nil;
|
|
}
|
|
|
|
/* RoustSleepers. This fellow is called by the 'clock interrupt'. It dequeues all
|
|
* members that have expired. The queue is ordered by p_wakeuptime, so normally
|
|
* we go no farther than a PEntry that should not be woken. The exception to this,
|
|
* of course, is when napOver == true, since that means that there are processes
|
|
* that are to be woken up prematurely (their p_wakeuptime == 0).
|
|
* NOTE: We turn interrupts off to protect this critical region against interference
|
|
* from WakeupProcess calls by interrupt routines.
|
|
*/
|
|
void
|
|
RoustSleepers(void)
|
|
{
|
|
register PEntryPtr pProc, pNextProc;
|
|
short ps;
|
|
|
|
ps = disable();
|
|
pProc = pSleepingStateList;
|
|
while (pProc != nil)
|
|
{
|
|
/* must get this now, since RemoveFromStateList() changes it */
|
|
pNextProc = pProc->p_NextProcessInState;
|
|
|
|
/* see if this guy should wake up now */
|
|
if (pProc->p_wakeuptime <= (unsigned long) TICKS)
|
|
{
|
|
RemoveFromStateList(pProc, &pSleepingStateList);
|
|
pProc->p_state = PRREADY;
|
|
}
|
|
else if (napOver == false)
|
|
break;
|
|
|
|
/* move on */
|
|
pProc = pNextProc;
|
|
}
|
|
|
|
napOver = false;
|
|
spl(ps);
|
|
}
|
|
|
|
/* CancelSleep. Ensures that pProc gets out of its current event call. */
|
|
void
|
|
CancelSleep(PEntryPtr pProc)
|
|
{
|
|
/* make sure the process is awake */
|
|
if (pProc->p_state == PRSLEEPING)
|
|
{
|
|
RemoveFromStateList(pProc, &pSleepingStateList);
|
|
pProc->p_state = PRREADY;
|
|
}
|
|
|
|
/* make sure the process stays awake. A zeroed p_wakeuptime means that the app
|
|
* will not go to sleep on the way out of its current event call. We must do this
|
|
* even if app is not asleep to begin with.
|
|
*/
|
|
pProc->p_wakeuptime = 0;
|
|
}
|