Files
sqlite3/internal/util/mmap_unix.go

89 lines
1.9 KiB
Go
Raw Normal View History

2024-11-29 15:51:51 +00:00
//go:build unix
package util
import (
"context"
"os"
"unsafe"
"golang.org/x/sys/unix"
2025-11-20 11:35:01 +00:00
"github.com/tetratelabs/wazero/api"
)
2024-04-26 16:25:45 +01:00
type mmapState struct {
regions []*MappedRegion
}
2024-04-11 12:00:17 +01:00
func (s *mmapState) new(ctx context.Context, mod api.Module, size int32) *MappedRegion {
// Find unused region.
for _, r := range s.regions {
if !r.used && r.size == size {
return r
}
}
// Allocate page aligned memmory.
alloc := mod.ExportedFunction("aligned_alloc")
2025-01-21 01:42:57 +00:00
stack := [...]Stk_t{
Stk_t(unix.Getpagesize()),
Stk_t(size),
}
if err := alloc.CallWithStack(ctx, stack[:]); err != nil {
panic(err)
}
if stack[0] == 0 {
panic(OOMErr)
}
// Save the newly allocated region.
2025-01-21 01:42:57 +00:00
ptr := Ptr_t(stack[0])
buf := View(mod, ptr, int64(size))
ret := &MappedRegion{
Ptr: ptr,
size: size,
2024-12-19 14:00:46 +00:00
addr: unsafe.Pointer(&buf[0]),
}
2025-01-21 01:42:57 +00:00
s.regions = append(s.regions, ret)
return ret
}
type MappedRegion struct {
2024-06-25 10:31:11 +01:00
addr unsafe.Pointer
2025-01-21 01:42:57 +00:00
Ptr Ptr_t
2024-04-11 12:00:17 +01:00
size int32
used bool
}
2024-11-05 17:30:10 +00:00
func MapRegion(ctx context.Context, mod api.Module, f *os.File, offset int64, size int32, readOnly bool) (*MappedRegion, error) {
s := ctx.Value(moduleKey{}).(*moduleState)
r := s.new(ctx, mod, size)
2024-11-05 17:30:10 +00:00
err := r.mmap(f, offset, readOnly)
if err != nil {
return nil, err
}
return r, nil
}
func (r *MappedRegion) Unmap() 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.
2024-06-25 10:31:11 +01:00
_, err := unix.MmapPtr(-1, 0, r.addr, uintptr(r.size),
unix.PROT_NONE, unix.MAP_PRIVATE|unix.MAP_FIXED|unix.MAP_ANON)
r.used = err != nil
return err
}
2024-11-05 17:30:10 +00:00
func (r *MappedRegion) mmap(f *os.File, offset int64, readOnly bool) error {
prot := unix.PROT_READ
if !readOnly {
prot |= unix.PROT_WRITE
}
2024-06-25 10:31:11 +01:00
_, err := unix.MmapPtr(int(f.Fd()), offset, r.addr, uintptr(r.size),
prot, unix.MAP_SHARED|unix.MAP_FIXED)
r.used = err == nil
return err
}