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
 | 
						mapFn           = vmm.Map
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type markAs bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						markReserved markAs = false
 | 
				
			||||||
 | 
						markFree            = true
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type framePool struct {
 | 
					type framePool struct {
 | 
				
			||||||
	// startFrame is the frame number for the first page in this pool.
 | 
						// startFrame is the frame number for the first page in this pool.
 | 
				
			||||||
	// each free bitmap entry i corresponds to frame (startFrame + i).
 | 
						// each free bitmap entry i corresponds to frame (startFrame + i).
 | 
				
			||||||
@ -145,6 +152,43 @@ func (alloc *BitmapAllocator) setupPoolBitmaps() *kernel.Error {
 | 
				
			|||||||
	return nil
 | 
						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
 | 
					// earlyAllocFrame is a helper that delegates a frame allocation request to the
 | 
				
			||||||
// early allocator instance. This function is passed as an argument to
 | 
					// early allocator instance. This function is passed as an argument to
 | 
				
			||||||
// vmm.SetFrameAllocator instead of earlyAllocator.AllocFrame. The latter
 | 
					// 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) {
 | 
					func TestAllocatorPackageInit(t *testing.T) {
 | 
				
			||||||
	defer func() {
 | 
						defer func() {
 | 
				
			||||||
		mapFn = vmm.Map
 | 
							mapFn = vmm.Map
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user