//go:build unix

package sqlite3_wrap

import (
	
	

	
	
)

type mmapState struct {
	regions []*MappedRegion
}

func ( *Wrapper) ( *os.File,  int64,  int32,  bool) (*MappedRegion, error) {
	 := .newRegion()
	 := .mmap(, , )
	if  != nil {
		return nil, 
	}
	return , nil
}

func ( *Wrapper) ( int32) *MappedRegion {
	// Find unused region.
	for ,  := range .regions {
		if !.used && .size ==  {
			return 
		}
	}

	// Allocate page aligned memmory.
	 := Ptr_t(.Xaligned_alloc(int32(unix.Getpagesize()), ))
	if  == 0 {
		panic(errutil.OOMErr)
	}

	// Save the newly allocated region.
	 := .Bytes(, int64())
	 := &MappedRegion{
		Ptr:  ,
		size: ,
		addr: unsafe.Pointer(&[0]),
	}
	.regions = append(.regions, )
	return 
}

type MappedRegion struct {
	addr unsafe.Pointer
	Ptr  Ptr_t
	size int32
	used bool
}

func ( *MappedRegion) () error {
	// We can't munmap the region, otherwise it could be remaped by the runtime.
	// We shouldn't create a hole, because unaligned reads might fail.
	// Instead remap it readonly, and if successful,
	// it can be reused for a subsequent mmap.
	,  := unix.MmapPtr(-1, 0, .addr, uintptr(.size),
		unix.PROT_READ, unix.MAP_PRIVATE|unix.MAP_FIXED|unix.MAP_ANON)
	.used =  != nil
	return 
}

func ( *MappedRegion) ( *os.File,  int64,  bool) error {
	 := unix.PROT_READ
	if ! {
		 |= unix.PROT_WRITE
	}
	,  := unix.MmapPtr(int(.Fd()), , .addr, uintptr(.size),
		, unix.MAP_SHARED|unix.MAP_FIXED)
	.used =  == nil
	return 
}