// IfsVMemFileSwap.bcpl -- VMem access to IFS files -- swappable // Copyright Xerox Corporation 1979, 1981 // Last modified November 17, 1981 9:19 PM by Taft get "Ifs.decl" get "IfsVMem.decl" get "IfsFiles.decl" get "Disks.d" get "IfsDirs.decl" external [ // outgoing procedures OpenVFile; OpenVFileFromFP; CloseVFile; MarkDirtyVFiles // incoming procedures VFileDOPAGEIO; VFilePageType; VFileWritePage VFilePageGroupBase; VFilePageGroupAlign; VFilePageGroupSize LookupIFSFile; DestroyFD; IFSError; ReadCalendar InitFmap; AllocateVMem; FreeVMem; PurgeVMem; Lock; Unlock DefaultArgs; SysAllocateZero; FreePointer; Noop // outgoing statics vFileVMI // incoming statics sysZone; primaryIFS; vmdt ] static vFileVMI = 0 manifest ecInitFmap = 37 structure FVMI: [ @VMI lock @Lock // lock for open/close of VFiles timer word ] manifest lenFVMI = size FVMI/16 //---------------------------------------------------------------------------- let OpenVFile(name, pages, lenFileMap, writeFileMap, fs; numargs na) = valof //---------------------------------------------------------------------------- // Initiates VMEM access to an existing file given its IFS name. // See OpenVFileFromFP (below) for details on other arguments. // Returns zero if the file cannot be opened. // Note: at the moment, this procedure does NOT lock the file. [ DefaultArgs(lv na, -1, 0, 0, 0, primaryIFS) let fd = LookupIFSFile(name, lcVHighest, 0, fs) if fd eq 0 resultis 0 let fp = lv fd>>FD.dr>>DR.fp let vmd = OpenVFileFromFP(fp, fs>>IFS.lpdt↑(fp>>IFP.unit), pages, lenFileMap, writeFileMap) DestroyFD(fd) resultis vmd ] //---------------------------------------------------------------------------- and OpenVFileFromFP(fp, disk, pages, lenFileMap, writeFileMap; numargs na) = valof //---------------------------------------------------------------------------- // Initiates VMEM access to a file given its FP. // Pages is max number of file pages that will be accessible (default 1000). // lenFileMap is the length to allocate for the ISF file map (minimum ~25, // default 50). Page 1 of the file is used to store the file map if // writeFileMap is true (default false). // Returns a VMD to be passed to VFileReadPage and VFileWritePage. [ DefaultArgs(lv na, -2, 1000, 50, false) if vFileVMI eq 0 then [ vFileVMI = SysAllocateZero(lenFVMI) vFileVMI>>VMI.DOPAGEIO = VFileDOPAGEIO vFileVMI>>VMI.CleanupLocks = Noop vFileVMI>>VMI.PageType = VFilePageType vFileVMI>>VMI.PageGroupBase = VFilePageGroupBase vFileVMI>>VMI.PageGroupAlign = VFilePageGroupAlign vFileVMI>>VMI.PageGroupSize = VFilePageGroupSize vFileVMI>>VMI.type = vmiTypeVFile ] Lock(lv vFileVMI>>FVMI.lock, true) let vmd = SysAllocateZero(lenFVMD) vmd>>FVMD.fileMap = SysAllocateZero(lenFileMap) vmd>>FVMD.logVPagesPerDiskPage = disk>>DSK.lnPageSize-logVMPageLength vmd>>FVMD.logPageGroupSize = vmd>>FVMD.logVPagesPerDiskPage AllocateVMem(vmd, vFileVMI, pages lshift vmd>>FVMD.logVPagesPerDiskPage) unless InitFmap(vmd>>FVMD.fileMap, lenFileMap, fp, writeFileMap, 0, sysZone, disk) do IFSError(ecInitFmap) Unlock(lv vFileVMI>>FVMI.lock) resultis vmd ] //---------------------------------------------------------------------------- and CloseVFile(vmd) be //---------------------------------------------------------------------------- [ PurgeVMem(vmd) Lock(lv vFileVMI>>FVMI.lock, true) MarkVFileIfDirty(vmd) FreeVMem(vmd) FreePointer(lv vmd>>FVMD.fileMap, lv vmd) Unlock(lv vFileVMI>>FVMI.lock) ] //---------------------------------------------------------------------------- and MarkDirtyVFiles() be //---------------------------------------------------------------------------- // called every 15 seconds to update the write dates of open VFiles that have // been dirtied. [ vFileVMI>>FVMI.timer = (vFileVMI>>FVMI.timer+1) rem 60 if vFileVMI>>FVMI.timer ne 0 return // do this only every 15 minutes Lock(lv vFileVMI>>FVMI.lock) // "manual" for-loop so VMDT.length is evaluated on every iteration let i = 1 while i le vmdt>>VMDT.length do [ let vmd = vmdt>>VMDT.vmd↑i if vmd>>VMD.vmi>>VMI.type eq vmiTypeVFile then MarkVFileIfDirty(vmd) i = i+1 ] Unlock(lv vFileVMI>>FVMI.lock) ] //---------------------------------------------------------------------------- and MarkVFileIfDirty(vmd) be //---------------------------------------------------------------------------- if vmd>>FVMD.dirty then [ let ld = VFileWritePage(vmd, 0) ReadCalendar(lv ld>>ILD.created) ReadCalendar(lv ld>>ILD.written) // this works because writing the leader page doesn't count as dirtying vmd>>FVMD.dirty = false ]