Skip to content

Commit bdaf77a

Browse files
committed
Custom Windows allocator.
1 parent 323bd6e commit bdaf77a

File tree

8 files changed

+112
-17
lines changed

8 files changed

+112
-17
lines changed

gormlite/go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,6 @@ require (
1111
github.com/jinzhu/inflection v1.0.0 // indirect
1212
github.com/jinzhu/now v1.1.5 // indirect
1313
github.com/ncruces/julianday v1.0.0 // indirect
14-
github.com/tetratelabs/wazero v1.7.1 // indirect
14+
github.com/tetratelabs/wazero v1.7.2 // indirect
1515
golang.org/x/sys v0.20.0 // indirect
1616
)

gormlite/go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ github.com/ncruces/go-sqlite3 v0.15.0 h1:C+SIrcYsAIR5GUYWmCnif6x81n6BS9y75vYcQyn
66
github.com/ncruces/go-sqlite3 v0.15.0/go.mod h1:kHHYmFmK4G2VFFoIovEg9BEQ8BP+D81y4ESHXnzJV/w=
77
github.com/ncruces/julianday v1.0.0 h1:fH0OKwa7NWvniGQtxdJRxAgkBMolni2BjDHaWTxqt7M=
88
github.com/ncruces/julianday v1.0.0/go.mod h1:Dusn2KvZrrovOMJuOt0TNXL6tB7U2E8kvza5fFc9G7g=
9-
github.com/tetratelabs/wazero v1.7.1 h1:QtSfd6KLc41DIMpDYlJdoMc6k7QTN246DM2+n2Y/Dx8=
10-
github.com/tetratelabs/wazero v1.7.1/go.mod h1:ytl6Zuh20R/eROuyDaGPkp82O9C/DJfXAwJfQ3X6/7Y=
9+
github.com/tetratelabs/wazero v1.7.2 h1:1+z5nXJNwMLPAWaTePFi49SSTL0IMx/i3Fg8Yc25GDc=
10+
github.com/tetratelabs/wazero v1.7.2/go.mod h1:ytl6Zuh20R/eROuyDaGPkp82O9C/DJfXAwJfQ3X6/7Y=
1111
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
1212
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
1313
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=

internal/util/alloc_other.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
//go:build !(unix || windows) || sqlite3_nosys
2+
3+
package util
4+
5+
import "context"
6+
7+
func withAllocator(ctx context.Context) context.Context {
8+
return ctx
9+
}

internal/util/alloc.go renamed to internal/util/alloc_unix.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,22 @@
33
package util
44

55
import (
6+
"context"
67
"math"
78

89
"github.com/tetratelabs/wazero/experimental"
910
"golang.org/x/sys/unix"
1011
)
1112

12-
func mmappedAllocator(cap, max uint64) experimental.LinearMemory {
13+
func withAllocator(ctx context.Context) context.Context {
14+
if math.MaxInt != math.MaxInt64 {
15+
return ctx
16+
}
17+
return experimental.WithMemoryAllocator(ctx,
18+
experimental.MemoryAllocatorFunc(newAllocator))
19+
}
20+
21+
func newAllocator(cap, max uint64) experimental.LinearMemory {
1322
// Round up to the page size.
1423
rnd := uint64(unix.Getpagesize() - 1)
1524
max = (max + rnd) &^ rnd

internal/util/alloc_windows.go

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
//go:build !sqlite3_nosys
2+
3+
package util
4+
5+
import (
6+
"context"
7+
"math"
8+
"reflect"
9+
"unsafe"
10+
11+
"github.com/tetratelabs/wazero/experimental"
12+
"golang.org/x/sys/windows"
13+
)
14+
15+
func withAllocator(ctx context.Context) context.Context {
16+
if math.MaxInt != math.MaxInt64 {
17+
return ctx
18+
}
19+
return experimental.WithMemoryAllocator(ctx,
20+
experimental.MemoryAllocatorFunc(newAllocator))
21+
}
22+
23+
func newAllocator(cap, max uint64) experimental.LinearMemory {
24+
// Round up to the page size.
25+
rnd := uint64(windows.Getpagesize() - 1)
26+
max = (max + rnd) &^ rnd
27+
cap = (cap + rnd) &^ rnd
28+
29+
if max > math.MaxInt {
30+
// This ensures int(max) overflows to a negative value,
31+
// and unix.Mmap returns EINVAL.
32+
max = math.MaxUint64
33+
}
34+
// Reserve max bytes of address space, to ensure we won't need to move it.
35+
// A protected, private, anonymous mapping should not commit memory.
36+
r, err := windows.VirtualAlloc(0, uintptr(max), windows.MEM_RESERVE, windows.PAGE_READWRITE)
37+
if err != nil {
38+
panic(err)
39+
}
40+
// Commit the initial cap bytes of memory.
41+
_, err = windows.VirtualAlloc(r, uintptr(cap), windows.MEM_COMMIT, windows.PAGE_READWRITE)
42+
if err != nil {
43+
windows.VirtualFree(r, 0, windows.MEM_RELEASE)
44+
panic(err)
45+
}
46+
mem := virtualMemory{addr: r}
47+
// SliceHeader, although deprecated, avoids a go vet warning.
48+
sh := (*reflect.SliceHeader)(unsafe.Pointer(&mem.buf))
49+
sh.Len = int(cap) // Not a bug.
50+
sh.Cap = int(max) // Not a bug.
51+
sh.Data = r
52+
return &mem
53+
}
54+
55+
// The slice covers the entire mmapped memory:
56+
// - len(buf) is the already committed memory,
57+
// - cap(buf) is the reserved address space.
58+
type virtualMemory struct {
59+
buf []byte
60+
addr uintptr
61+
}
62+
63+
func (m *virtualMemory) Reallocate(size uint64) []byte {
64+
if com := uint64(len(m.buf)); com < size {
65+
// Round up to the page size.
66+
rnd := uint64(windows.Getpagesize() - 1)
67+
new := (size + rnd) &^ rnd
68+
69+
// Commit additional memory up to new bytes.
70+
_, err := windows.VirtualAlloc(m.addr, uintptr(new), windows.MEM_COMMIT, windows.PAGE_READWRITE)
71+
if err != nil {
72+
panic(err)
73+
}
74+
75+
// Update committed memory.
76+
m.buf = m.buf[:new]
77+
}
78+
// Limit returned capacity because bytes beyond
79+
// len(m.buf) have not yet been committed.
80+
return m.buf[:size:len(m.buf)]
81+
}
82+
83+
func (m *virtualMemory) Free() {
84+
err := windows.VirtualFree(m.addr, 0, windows.MEM_RELEASE)
85+
if err != nil {
86+
panic(err)
87+
}
88+
m.addr = 0
89+
}

internal/util/mmap.go

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,9 @@ import (
88
"unsafe"
99

1010
"github.com/tetratelabs/wazero/api"
11-
"github.com/tetratelabs/wazero/experimental"
1211
"golang.org/x/sys/unix"
1312
)
1413

15-
func withMmappedAllocator(ctx context.Context) context.Context {
16-
return experimental.WithMemoryAllocator(ctx,
17-
experimental.MemoryAllocatorFunc(mmappedAllocator))
18-
}
19-
2014
type mmapState struct {
2115
regions []*MappedRegion
2216
}

internal/util/mmap_other.go

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,4 @@
22

33
package util
44

5-
import "context"
6-
75
type mmapState struct{}
8-
9-
func withMmappedAllocator(ctx context.Context) context.Context {
10-
return ctx
11-
}

internal/util/module.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ type moduleState struct {
1414

1515
func NewContext(ctx context.Context) context.Context {
1616
state := new(moduleState)
17-
ctx = withMmappedAllocator(ctx)
17+
ctx = withAllocator(ctx)
1818
ctx = experimental.WithCloseNotifier(ctx, state)
1919
ctx = context.WithValue(ctx, moduleKey{}, state)
2020
return ctx

0 commit comments

Comments
 (0)