//
// OVERLAYS.BCPL - Bcpl overlay package
// last edited September 16, 1976 6:19 PM
//
get "overlays.d"
get "altofilesys.d"
get "disks.d"
external // procedures used
[ // O.S.
SetBlock
ActOnDiskPages
Usc
Dvec
CallSwat
// User-supplied
UserReadOverlay
]
external // statics used
[ sysDisk
]
external // procedures defined
[ LockPendingCode // ()
FindOverlayFromPn // (pn) -> od
GeneratePresentOverlays // (proc(od))
@OverlayFaultProc
DeclareOverlayPresent // (od, core)
OverlayFirstPn // (od) -> pn
OverlayNpages // (od) -> npages
OverlayDiskAddr // (od) -> da
OverlayCoreAddr // (od) -> core
ReadOverlay // (pn, core, npages)
ReleaseOverlay // (od, doIt) -> ok
]
external // statics defined
[ @OverlayNumber
OverlayFaults
FirstOD
LastOD
OverlayFp
]
static
[ @OverlayNumber = 0
OverlayFaults
FirstOD
LastOD
OverlayFp
MinOverlayLoc = -1
]
let LockPendingCode(dummy) be
[ for od = FirstOD by ODsize to LastOD do od>>OD.onstack = 0
let frame = (lv dummy)!-4
while Usc(@frame, frame) gr 0 do
[ let pc = frame!1
if Usc(pc, MinOverlayLoc) ge 0 then // O.S. or overlay
for od = FirstOD by ODsize to LastOD do
if (od>>OD.core ne 0) & ((pc-od>>OD.core) rshift 8 ls (od+ODsize)>>OD.firstPn-od>>OD.firstPn) then
od>>OD.onstack = 1
frame = @frame
]
]
and FindOverlayFromPn(pn) = valof
[ let fpn = FirstOD>>OD.firstPn
for od = FirstOD by ODsize to LastOD do
[ let npn = (od+ODsize)>>OD.firstPn
if (pn ls npn) & (pn ge fpn) resultis od
fpn = npn
]
CallSwat("FindOD failed")
]
and GeneratePresentOverlays(proc) be
for od = FirstOD by ODsize to LastOD do
if od>>OD.core ne 0 then proc(od)
and OverlayFaultProc(ac0, ac1, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil) = valof
[ // *** Critical code began at JSR to missing procedure
let ovn = OverlayNumber
OverlayNumber = 0
// *** End critical code
let od = LastOD-ovn*ODsize
DeclareOverlayPresent(od, UserReadOverlay(od))
// Check to make sure overlay is now present
let callerframe = (lv ac0)!-4
let callerpc1 = callerframe!1
let callins = callerpc1!-1
let disp = (callins±)-(callinsÈ)
let dif = (selecton (callins𫓸) into
[ case #64400: callerpc1!(disp-1) // JSRII
case #65000: callerframe!disp // JSRIS
case #6000: callinsŹ // JSR @
default: lv OverlayFaults // no good
])!0-OverlayFaults
if (dif ge 0) & (dif le (LastOD-FirstOD)/ODsize) then
CallSwat("Bad overlay call")
// Re-execute call
callerframe!1 = callerpc1-2
resultis table[ #1401 ](ac0, ac1) // load up ACs and exit
]
and DeclareOverlayPresent(od, base) be
[ if Usc(base, MinOverlayLoc) ls 0 then MinOverlayLoc = base
let p = base+#21+base!1
let plim = p+2*p!-1
while p ne plim do
[ @(p!0) = base+#20+p!1
p = p+2
]
od>>OD.core = base
]
and OverlayFirstPn(od) = od>>OD.firstPn
and OverlayNpages(od) = (od+ODsize)>>OD.firstPn-od>>OD.firstPn
and OverlayDiskAddr(od) = od>>OD.da
and OverlayCoreAddr(od) = od>>OD.core
and ReadOverlay(pn, core, np) be
[ let DAs, CAs = np, np
Dvec(ReadOverlay, lv DAs, lv CAs)
for i = 0 to np-1 do CAs!i = core + i lshift 8
SetBlock(DAs, fillInDA, np+1)
DAs!0 = FindOverlayFromPn(pn)>>OD.da
ActOnDiskPages(sysDisk, CAs-pn, DAs-pn, OverlayFp, pn, pn+np-1, DCreadD)
]
and ReleaseOverlay(od, flag) = valof
[ if od>>OD.onstack ne 0 resultis false
unless flag resultis true
let faultaddr = OverlayFaults+(od-FirstOD)/ODsize
let base = od>>OD.core
let p = base+#21+base!1
let plim = p+2*p!-1
while p ls plim do
[ @(p!0) = faultaddr
p = p+2
]
od>>OD.core = 0
resultis true
]