forked from SagerNet/sing-tun
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathstack_go_memory.go
More file actions
113 lines (98 loc) · 2.04 KB
/
Copy pathstack_go_memory.go
File metadata and controls
113 lines (98 loc) · 2.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
package tun
import (
"os"
"github.com/sagernet/sing/common"
"github.com/sagernet/sing/common/buf"
)
var goPageSize = os.Getpagesize()
type goSlabStore interface {
acquire() *goSlab
release(slab *goSlab, discard bool)
purge()
close()
}
type goHeapSlabStore struct{}
func (goHeapSlabStore) acquire() *goSlab {
return (*goSlab)(buf.Get(goSlabSize))
}
func (goHeapSlabStore) release(slab *goSlab, discard bool) {
if discard {
return
}
common.Must(buf.Put(slab[:]))
}
func (goHeapSlabStore) purge() {
}
func (goHeapSlabStore) close() {
}
type goReadSlots struct {
buffers []*buf.Buffer
region []byte
stride int
woken int
}
func (s *goReadSlots) configure(count int, stride int) {
if s.buffers != nil && len(s.buffers) == count && s.stride == stride {
return
}
s.release()
s.buffers = make([]*buf.Buffer, count)
s.stride = stride
}
func (s *goReadSlots) wake(count int) {
if !goArenaEnabled() {
return
}
if s.region == nil {
s.region = goRegionMap(len(s.buffers) * s.stride)
}
if count <= s.woken {
return
}
start := s.woken * s.stride &^ (goPageSize - 1)
end := min((count*s.stride+goPageSize-1)&^(goPageSize-1), len(s.region))
goRegionReuse(s.region[start:end])
s.woken = count
}
func (s *goReadSlots) slot(index int) *buf.Buffer {
if goArenaEnabled() && index >= s.woken {
s.wake(index + 1)
}
buffer := s.buffers[index]
if buffer != nil {
return buffer
}
if goArenaEnabled() {
buffer = buf.With(s.region[index*s.stride : (index+1)*s.stride])
} else {
buffer = buf.NewSize(s.stride)
}
s.buffers[index] = buffer
return buffer
}
func (s *goReadSlots) sleep() {
if !goArenaEnabled() {
buf.ReleaseMulti(s.buffers)
clear(s.buffers)
return
}
if s.woken == 0 {
return
}
end := min((s.woken*s.stride+goPageSize-1)&^(goPageSize-1), len(s.region))
goRegionPark(s.region[:end])
s.woken = 0
}
func (s *goReadSlots) release() {
if goArenaEnabled() {
if s.region != nil {
goRegionUnmap(s.region)
s.region = nil
}
} else {
buf.ReleaseMulti(s.buffers)
}
s.buffers = nil
s.stride = 0
s.woken = 0
}