//go:build unix

package util

import (
	
	
	

	

	
)

type mmapState struct {
	regions []*MappedRegion
}

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

	// Allocate page aligned memmory.
	 := .ExportedFunction("aligned_alloc")
	 := [...]Stk_t{
		Stk_t(unix.Getpagesize()),
		Stk_t(),
	}
	if  := .CallWithStack(, [:]);  != nil {
		panic()
	}
	if [0] == 0 {
		panic(OOMErr)
	}

	// Save the newly allocated region.
	 := Ptr_t([0])
	 := View(, , 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 ( context.Context,  api.Module,  *os.File,  int64,  int32,  bool) (*MappedRegion, error) {
	 := .Value(moduleKey{}).(*moduleState)
	 := .new(, , )
	 := .mmap(, , )
	if  != nil {
		return nil, 
	}
	return , nil
}

func ( *MappedRegion) () error {
	// We can't munmap the region, otherwise it could be remaped.
	// Instead, convert it to a protected, private, anonymous mapping.
	// If successful, it can be reused for a subsequent mmap.
	,  := unix.MmapPtr(-1, 0, .addr, uintptr(.size),
		unix.PROT_NONE, 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 
}