// Scan.Sr // // July 3 version // Changes from previous version: // 1) qBufRead is an outgoing static // 2) scanstatus outgoing static. It is set to tcScanner // at the beginning of the Sretrty loop. // Last modified October 29, 1979 7:29 PM by Taft get "BRAVO1.dF" get "altofilesys.d" get "bfs.def" get "q.df" get "vm.df" // Incoming procedures external [ CallersFrame; TIMER InitializeCbStorage move errhlta GetCb LengthQ Dequeue DoDiskCommand waitforfd Enqueue ult umax ReadVec ] // Incoming Statics external [ DCread fillInDA DCseekOnly ] // Outgoing Procedures external [ ScanPages EnQBuf fCbWaiting ] // Outgoing Statics external [ scanstatus ] // Local Statics static [ scanstatus tcScanner tcUser cLoops cLoopsNoBuf Dbuf ] // Local Structure // Local Manifests // S C A N P A G E S // let ScanPages(cfa,qBufFree,TcScanProc,bMpPgnDa,maxCRead,qBufRead; numargs na) = valof [ let tqBufRead= vec lQ switchon na into [ case 3: bMpPgnDa = 0 case 4: maxCRead = -1 case 5: qBufRead = tqBufRead case 6: endcase default: errhlta(212) ] let pgnMac = umax(maxCRead,maxCRead+cfa >> CFA.fa.pageNumber) qBufRead >> Q.head = 0; let qBufReading = vec lQ; qBufReading >> Q.head = 0; let scanParams = vec lScp; scanParams >> SCP.fmCaller = CallersFrame() scanParams >> SCP.qBufFree = qBufFree scanParams >> SCP.qBufRead = qBufRead scanParams >> SCP.fa = lv cfa >> CFA.fa scanParams >> SCP.qBufReading = qBufReading scanParams >> SCP.TcScanProc = TcScanProc let zone=vec CBzoneLength let fileId = vec 3 tcScanner = tcNotDone //insert "let" tcUser = tcNotDone //insert "let" cLoops = 0; cLoopsNoBuf = 0 InitializeCbStorage(zone, CBzoneLength, cfa >>CFA.fa.pageNumber, Sretry, true) if bMpPgnDa ne 0 then [ bMpPgnDa! 0 = cfa >> CFA.fa.da zone>>CBZ.DAs=bMpPgnDa-zone>>CBZ.currentPage ] zone>>CBZ.cleanupRoutine=EnQBuf zone>>CBZ.currentNumChars=#1000 zone>>CBZ.currentDA=cfa >> CFA.fa.da zone>>CBZ.errorRoutine=ReQBufs zone>>CBZ.extra=scanParams fileId ! 0 = cfa >> CFA.fp.version; move(lv (cfa >>CFA.fp.serialNumber),fileId+1,2); Sretry: [ // Note that each cb is used twice: to hold the DL for // page i-1, and then to hold the DCB for page i. It isn't // reused until the command for page i is done, and that is // guaranteed to be after the DL for page i-1 is no longer // needed, since everything is done strictly sequentially by // page number. let pgn = zone>>CBZ.currentPage; let da = zone>>CBZ.currentDA let cb=GetCb(zone) let nextCb = 0 let FReturn = fCbWaiting [ cLoops = cLoops+1 scanstatus = tcScanner tcUser = (scanParams >> SCP.TcScanProc)(zone,FReturn) if (tcUser eq tcDone) % (tcUser eq tcAbort) % ((tcScanner eq tcDone) & (tcUser eq tcToYou)) then break if nextCb eq 0 then [ if fCbWaiting(zone) eq false then loop nextCb = GetCb(zone) ] if zone>>CBZ.currentNumChars ne #1000 then [ tcScanner = tcDone FReturn = FNever loop; ] if pgn eq pgnMac then [ test rv zone>>CBZ.queueHead eq 0 ifso [ tcScanner = tcDone FReturn = FNever; ] ifnot nextCb = 0 loop ] let buf = Dequeue(qBufFree) Dbuf= buf //debug static if buf eq 0 then [ FReturn = FBufAvail; cLoopsNoBuf = cLoopsNoBuf+1 loop ] FReturn = fCbWaiting Enqueue(qBufReading,buf) cb>>CB.labelAddress=lv nextCb>>CB.diskAddress DoDiskCommand(cb, buf >> BUF.ca, da, fileId, pgn, DCread) cb=nextCb; nextCb = 0; da = fillInDA; pgn = pgn+1; ] repeat // This is what was here before. It's not safe, since the current cb // (located in this procedure's stack) may still be executing!!! // rv nextDiskCommand = 0 // Here is what we do instead: cut off the chain, then wait for // the current cb to be finished. [ cb = @nextDiskCommand if cb eq 0 then break cb>>CB.nextCommand = 0 ] repeat ] if tcUser eq tcAbort then resultis tcAbort if tcUser eq tcDone then resultis tcByScanProc // else resultis tcByScanPages ] // E N Q B U F // and EnQBuf(cb) be [ if cb >> CB.command eq DCseekOnly then return let zone = cb >> CB.zone; let label = cb>>CB.labelAddress if zone >> CBZ.DAs ne 0 then (zone >> CBZ.DAs) ! (cb >> CB.truePageNumber+1) = label>>DL.next let scanParams = zone >> CBZ.extra let buf = Dequeue(scanParams >> SCP.qBufReading) buf >> BUF.pgn = label >> DL.pageNumber buf >> BUF.numChars = label >> DL.numChars let tq = (buf >> BUF.pgn eq 0) ? scanParams >> SCP.qBufFree,scanParams >> SCP.qBufRead Enqueue(tq,buf) let fa = (zone >> CBZ.extra) >> SCP.fa unless (fa >> FA.pageNumber eq label >> DL.pageNumber) % (fa >> FA.pageNumber+1 eq label >> DL.pageNumber) then errhlta(213) fa >> FA.pageNumber = label >> DL.pageNumber fa >> FA.da = cb >> CB.diskAddress fa >> FA.charPos = label >> DL.numChars zone >> CBZ.currentDA = label >> DL.next ] // F C B W A I T I N G // and fCbWaiting(zone) = (((@(zone >> CBZ.queueHead)) >> CB.status & DSdoneBits) ne 0) // L F I LE // // and LFile(cfa) be // [ let ca1 = vec #400; let ca2 = vec #400; // let buf2 = vec lBuf; buf2 >> BUF.ca = ca2; // let buf1 = vec lBuf; buf1 >> BUF.ca = ca1; // let qBuf = vec lQ // qBuf >> Q.head = 0; // Enqueue(qBuf,buf1); Enqueue(qBuf,buf2) // ScanPages(cfa,qBuf,tcReQ) // ] // R E Q // // and tcReQ(zone,fReturn) = valof // [ let scanParams = zone >> CBZ.extra; // let qBufRead = scanParams >> SCP.qBufRead // until LengthQ(qBufRead) eq 0 do // Enqueue(scanParams >> SCP.qBufFree,Dequeue(qBufRead)) // resultis tcToYou // ] // R E Q B U F S // and ReQBufs(zone) be [ let scanParams = zone >> CBZ.extra; let qSrc = scanParams >> SCP.qBufReading until LengthQ(qSrc) eq 0 do Enqueue(scanParams >> SCP.qBufFree,Dequeue(qSrc)) ] // F B U F A V A I L // and FBufAvail(zone) = (LengthQ((zone >> CBZ.extra) >> SCP.qBufFree) eq 0) ? false,true and FNever(zone) = false