mirror of
				https://github.com/taigrr/gopher-os
				synced 2025-01-18 04:43:13 -08:00 
			
		
		
		
	Support looking up pools by frame and flagging bitmap entries as
reserved/free
This commit is contained in:
		
							parent
							
								
									bc44151c93
								
							
						
					
					
						commit
						8b22862784
					
				@ -22,6 +22,13 @@ var (
 | 
			
		||||
	mapFn           = vmm.Map
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type markAs bool
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	markReserved markAs = false
 | 
			
		||||
	markFree            = true
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type framePool struct {
 | 
			
		||||
	// startFrame is the frame number for the first page in this pool.
 | 
			
		||||
	// each free bitmap entry i corresponds to frame (startFrame + i).
 | 
			
		||||
@ -145,6 +152,43 @@ func (alloc *BitmapAllocator) setupPoolBitmaps() *kernel.Error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// markFrame updates the reservation flag for the bitmap entry that corresponds
 | 
			
		||||
// to the supplied frame.
 | 
			
		||||
func (alloc *BitmapAllocator) markFrame(poolIndex int, frame pmm.Frame, flag markAs) {
 | 
			
		||||
	if poolIndex < 0 || frame > alloc.pools[poolIndex].endFrame {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// The offset in the block is given by: frame % 64. As the bitmap uses a
 | 
			
		||||
	// big-ending representation we need to set the bit at index: 63 - offset
 | 
			
		||||
	relFrame := frame - alloc.pools[poolIndex].startFrame
 | 
			
		||||
	block := relFrame >> 6
 | 
			
		||||
	mask := uint64(1 << (63 - (relFrame - block<<6)))
 | 
			
		||||
	switch flag {
 | 
			
		||||
	case markFree:
 | 
			
		||||
		alloc.pools[poolIndex].freeBitmap[block] &^= mask
 | 
			
		||||
		alloc.pools[poolIndex].freeCount++
 | 
			
		||||
		alloc.reservedPages--
 | 
			
		||||
	case markReserved:
 | 
			
		||||
		alloc.pools[poolIndex].freeBitmap[block] |= mask
 | 
			
		||||
		alloc.pools[poolIndex].freeCount--
 | 
			
		||||
		alloc.reservedPages++
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// poolForFrame returns the index of the pool that contains frame or -1 if
 | 
			
		||||
// the frame is not contained in any of the available memory pools (e.g it
 | 
			
		||||
// points to a reserved memory region).
 | 
			
		||||
func (alloc *BitmapAllocator) poolForFrame(frame pmm.Frame) int {
 | 
			
		||||
	for poolIndex, pool := range alloc.pools {
 | 
			
		||||
		if frame >= pool.startFrame && frame <= pool.endFrame {
 | 
			
		||||
			return poolIndex
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return -1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// earlyAllocFrame is a helper that delegates a frame allocation request to the
 | 
			
		||||
// early allocator instance. This function is passed as an argument to
 | 
			
		||||
// vmm.SetFrameAllocator instead of earlyAllocator.AllocFrame. The latter
 | 
			
		||||
 | 
			
		||||
@ -130,6 +130,93 @@ func TestSetupPoolBitmapsErrors(t *testing.T) {
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestBitmapAllocatorMarkFrame(t *testing.T) {
 | 
			
		||||
	var alloc = BitmapAllocator{
 | 
			
		||||
		pools: []framePool{
 | 
			
		||||
			{
 | 
			
		||||
				startFrame: pmm.Frame(0),
 | 
			
		||||
				endFrame:   pmm.Frame(127),
 | 
			
		||||
				freeCount:  128,
 | 
			
		||||
				freeBitmap: make([]uint64, 2),
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		totalPages: 128,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	lastFrame := pmm.Frame(alloc.totalPages)
 | 
			
		||||
	for frame := pmm.Frame(0); frame < lastFrame; frame++ {
 | 
			
		||||
		alloc.markFrame(0, frame, markReserved)
 | 
			
		||||
 | 
			
		||||
		block := uint64(frame / 64)
 | 
			
		||||
		blockOffset := uint64(frame % 64)
 | 
			
		||||
		bitIndex := (63 - blockOffset)
 | 
			
		||||
		bitMask := uint64(1 << bitIndex)
 | 
			
		||||
 | 
			
		||||
		if alloc.pools[0].freeBitmap[block]&bitMask != bitMask {
 | 
			
		||||
			t.Errorf("[frame %d] expected block[%d], bit %d to be set", frame, block, bitIndex)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		alloc.markFrame(0, frame, markFree)
 | 
			
		||||
 | 
			
		||||
		if alloc.pools[0].freeBitmap[block]&bitMask != 0 {
 | 
			
		||||
			t.Errorf("[frame %d] expected block[%d], bit %d to be unset", frame, block, bitIndex)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Calling markFrame with a frame not part of the pool should be a no-op
 | 
			
		||||
	alloc.markFrame(0, pmm.Frame(0xbadf00d), markReserved)
 | 
			
		||||
	for blockIndex, block := range alloc.pools[0].freeBitmap {
 | 
			
		||||
		if block != 0 {
 | 
			
		||||
			t.Errorf("expected all blocks to be set to 0; block %d is set to %d", blockIndex, block)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Calling markFrame with a negative pool index should be a no-op
 | 
			
		||||
	alloc.markFrame(-1, pmm.Frame(0), markReserved)
 | 
			
		||||
	for blockIndex, block := range alloc.pools[0].freeBitmap {
 | 
			
		||||
		if block != 0 {
 | 
			
		||||
			t.Errorf("expected all blocks to be set to 0; block %d is set to %d", blockIndex, block)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestBitmapAllocatorPoolForFrame(t *testing.T) {
 | 
			
		||||
	var alloc = BitmapAllocator{
 | 
			
		||||
		pools: []framePool{
 | 
			
		||||
			{
 | 
			
		||||
				startFrame: pmm.Frame(0),
 | 
			
		||||
				endFrame:   pmm.Frame(63),
 | 
			
		||||
				freeCount:  64,
 | 
			
		||||
				freeBitmap: make([]uint64, 1),
 | 
			
		||||
			},
 | 
			
		||||
			{
 | 
			
		||||
				startFrame: pmm.Frame(128),
 | 
			
		||||
				endFrame:   pmm.Frame(191),
 | 
			
		||||
				freeCount:  64,
 | 
			
		||||
				freeBitmap: make([]uint64, 1),
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		totalPages: 128,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	specs := []struct {
 | 
			
		||||
		frame    pmm.Frame
 | 
			
		||||
		expIndex int
 | 
			
		||||
	}{
 | 
			
		||||
		{pmm.Frame(0), 0},
 | 
			
		||||
		{pmm.Frame(63), 0},
 | 
			
		||||
		{pmm.Frame(64), -1},
 | 
			
		||||
		{pmm.Frame(128), 1},
 | 
			
		||||
		{pmm.Frame(192), -1},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for specIndex, spec := range specs {
 | 
			
		||||
		if got := alloc.poolForFrame(spec.frame); got != spec.expIndex {
 | 
			
		||||
			t.Errorf("[spec %d] expected to get pool index %d; got %d", specIndex, spec.expIndex, got)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestAllocatorPackageInit(t *testing.T) {
 | 
			
		||||
	defer func() {
 | 
			
		||||
		mapFn = vmm.Map
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user