Files
sqlite3/internal/util/alloc_unix.go

81 lines
2.0 KiB
Go
Raw Normal View History

2024-05-06 11:45:40 +01:00
//go:build unix && !sqlite3_nosys
package util
import (
2024-05-17 16:42:43 +01:00
"context"
"math"
"github.com/tetratelabs/wazero/experimental"
"golang.org/x/sys/unix"
)
2024-05-17 16:42:43 +01:00
func withAllocator(ctx context.Context) context.Context {
if math.MaxInt != math.MaxInt64 {
return ctx
}
return experimental.WithMemoryAllocator(ctx,
experimental.MemoryAllocatorFunc(newAllocator))
}
func newAllocator(cap, max uint64) experimental.LinearMemory {
// Round up to the page size.
rnd := uint64(unix.Getpagesize() - 1)
max = (max + rnd) &^ rnd
cap = (cap + rnd) &^ rnd
if max > math.MaxInt {
// This ensures int(max) overflows to a negative value,
// and unix.Mmap returns EINVAL.
max = math.MaxUint64
}
// Reserve max bytes of address space, to ensure we won't need to move it.
// A protected, private, anonymous mapping should not commit memory.
b, err := unix.Mmap(-1, 0, int(max), unix.PROT_NONE, unix.MAP_PRIVATE|unix.MAP_ANON)
if err != nil {
panic(err)
}
// Commit the initial cap bytes of memory.
err = unix.Mprotect(b[:cap], unix.PROT_READ|unix.PROT_WRITE)
if err != nil {
unix.Munmap(b)
panic(err)
}
2024-04-15 23:01:20 +01:00
return &mmappedMemory{buf: b[:cap]}
}
// The slice covers the entire mmapped memory:
// - len(buf) is the already committed memory,
2024-04-15 23:01:20 +01:00
// - cap(buf) is the reserved address space.
type mmappedMemory struct {
buf []byte
}
2024-04-15 23:01:20 +01:00
func (m *mmappedMemory) Reallocate(size uint64) []byte {
if com := uint64(len(m.buf)); com < size {
// Round up to the page size.
rnd := uint64(unix.Getpagesize() - 1)
new := (size + rnd) &^ rnd
// Commit additional memory up to new bytes.
err := unix.Mprotect(m.buf[com:new], unix.PROT_READ|unix.PROT_WRITE)
if err != nil {
panic(err)
}
2024-04-16 02:52:37 +01:00
// Update committed memory.
m.buf = m.buf[:new]
}
2024-04-15 23:01:20 +01:00
// Limit returned capacity because bytes beyond
// len(m.buf) have not yet been committed.
return m.buf[:size:len(m.buf)]
}
2024-04-15 23:01:20 +01:00
func (m *mmappedMemory) Free() {
err := unix.Munmap(m.buf[:cap(m.buf)])
if err != nil {
panic(err)
}
m.buf = nil
}