//
// VMEMAUX -- VMEM routines other than page fault handler
// last edited March 14, 1977  2:53 PM
//
// Copyright Xerox Corporation 1979

	get "vmem.d"

external	// entry procedures
[	AddBuffers	// (first, last)
	SnarfBuffer	// (addr/0[, nbufs, align]) -> addr/0
	UnsnarfBuffer	// (addr)
	FlushBuffers	// ()
	IsLocked	// (addr) -> true/false
	VirtualPage	// (corepage) -> vp
]


external	// procedures
[		// O.S.
	DefaultArgs
		// VMEM
	FindFreeBuf
	FlushBufs
	FlushMapStats
	DoLocks
		// user-supplied
	CleanupLocks
]

external	// statics
[		// VMEM
	@HASHMAP
	MapStatProc
	@Bpt; @BptLast
	EMPTYXX
	NAXX
]


let AddBuffers(FIRST, Last) be
for tn = (FIRST+WM) rshift PS to (Last-WM) rshift PS do
[	let TP = Bpt+tn
	if @TP eq NAXX then	// buffer is free
	 [ @TP = EMPTYXX+@Bpt
	   if @Bpt eq 0 then BptLast = tn
	   @Bpt = tn
	   MapStatProc(tn, -2)
	 ]
]

and SnarfBuffer(addr, n, align; numargs na) = valof
[	DefaultArgs(lv na, 1, 1, 0)
	if (addr & WM) ne 0 resultis 0
	CleanupLocks()
	let tn = FindFreeBuf(n, align, addr rshift PS)
	if tn eq 0 resultis 0
	if addr ne 0 then tn = addr rshift PS
	FlushBufs(tn, n, -1)
	for i = tn to tn+n-1 do
	 if Bpt!i ne NAXX then
	 [ MapStatProc(i, -3); Bpt!i = NAXX ]
	resultis tn lshift PS
]

and UnsnarfBuffer(addr) be
[	if (addr & WM) ne 0 return
	AddBuffers(addr, addr+WM)
]

and FlushBuffers() be
[	CleanupLocks()
	FlushMapStats()
	FlushBufs(1, BptSize-1, 0)
]

and IsLocked(addr) = DoLocks(addr, 0, false)

and VirtualPage(cpage) =
	not (HASHMAP+(Bpt+cpage)>>BPT.HASHX*2)>>HM.NKEY