]> Cypherpunks.ru repositories - gostls13.git/blob - src/runtime/mgc0.go
[dev.garbage] all: merge dev.cc into dev.garbage
[gostls13.git] / src / runtime / mgc0.go
1 // Copyright 2012 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package runtime
6
7 import "unsafe"
8
9 // Called from C. Returns the Go type *m.
10 func gc_m_ptr(ret *interface{}) {
11         *ret = (*m)(nil)
12 }
13
14 // Called from C. Returns the Go type *g.
15 func gc_g_ptr(ret *interface{}) {
16         *ret = (*g)(nil)
17 }
18
19 // Called from C. Returns the Go type *itab.
20 func gc_itab_ptr(ret *interface{}) {
21         *ret = (*itab)(nil)
22 }
23
24 func gc_unixnanotime(now *int64) {
25         sec, nsec := timenow()
26         *now = sec*1e9 + int64(nsec)
27 }
28
29 func freeOSMemory() {
30         gogc(2) // force GC and do eager sweep
31         systemstack(scavenge_m)
32 }
33
34 var poolcleanup func()
35
36 func registerPoolCleanup(f func()) {
37         poolcleanup = f
38 }
39
40 func clearpools() {
41         // clear sync.Pools
42         if poolcleanup != nil {
43                 poolcleanup()
44         }
45
46         for _, p := range &allp {
47                 if p == nil {
48                         break
49                 }
50                 // clear tinyalloc pool
51                 if c := p.mcache; c != nil {
52                         c.tiny = nil
53                         c.tinysize = 0
54                         c.sudogcache = nil
55                 }
56                 // clear defer pools
57                 for i := range p.deferpool {
58                         p.deferpool[i] = nil
59                 }
60         }
61 }
62
63 func bgsweep() {
64         sweep.g = getg()
65         getg().issystem = true
66         for {
67                 for gosweepone() != ^uintptr(0) {
68                         sweep.nbgsweep++
69                         Gosched()
70                 }
71                 lock(&gclock)
72                 if !gosweepdone() {
73                         // This can happen if a GC runs between
74                         // gosweepone returning ^0 above
75                         // and the lock being acquired.
76                         unlock(&gclock)
77                         continue
78                 }
79                 sweep.parked = true
80                 goparkunlock(&gclock, "GC sweep wait")
81         }
82 }
83
84 const (
85         _PoisonGC    = 0xf969696969696969 & (1<<(8*ptrSize) - 1)
86         _PoisonStack = 0x6868686868686868 & (1<<(8*ptrSize) - 1)
87 )
88
89 // NOTE: Really dst *unsafe.Pointer, src unsafe.Pointer,
90 // but if we do that, Go inserts a write barrier on *dst = src.
91 //go:nosplit
92 func writebarrierptr(dst *uintptr, src uintptr) {
93         *dst = src
94         writebarrierptr_nostore(dst, src)
95 }
96
97 // Like writebarrierptr, but the store has already been applied.
98 // Do not reapply.
99 //go:nosplit
100 func writebarrierptr_nostore(dst *uintptr, src uintptr) {
101         if getg() == nil { // very low-level startup
102                 return
103         }
104
105         if src != 0 && (src < _PageSize || src == _PoisonGC || src == _PoisonStack) {
106                 systemstack(func() { gothrow("bad pointer in write barrier") })
107         }
108
109         mp := acquirem()
110         if mp.inwb || mp.dying > 0 {
111                 releasem(mp)
112                 return
113         }
114         mp.inwb = true
115         systemstack(func() {
116                 gcmarkwb_m(dst, src)
117         })
118         mp.inwb = false
119         releasem(mp)
120 }
121
122 //go:nosplit
123 func writebarrierstring(dst *[2]uintptr, src [2]uintptr) {
124         writebarrierptr(&dst[0], src[0])
125         dst[1] = src[1]
126 }
127
128 //go:nosplit
129 func writebarrierslice(dst *[3]uintptr, src [3]uintptr) {
130         writebarrierptr(&dst[0], src[0])
131         dst[1] = src[1]
132         dst[2] = src[2]
133 }
134
135 //go:nosplit
136 func writebarrieriface(dst *[2]uintptr, src [2]uintptr) {
137         writebarrierptr(&dst[0], src[0])
138         writebarrierptr(&dst[1], src[1])
139 }
140
141 //go:generate go run wbfat_gen.go -- wbfat.go
142 //
143 // The above line generates multiword write barriers for
144 // all the combinations of ptr+scalar up to four words.
145 // The implementations are written to wbfat.go.
146
147 //go:nosplit
148 func writebarrierfat(typ *_type, dst, src unsafe.Pointer) {
149         mask := loadPtrMask(typ)
150         nptr := typ.size / ptrSize
151         for i := uintptr(0); i < nptr; i += 2 {
152                 bits := mask[i/2]
153                 if (bits>>2)&_BitsMask == _BitsPointer {
154                         writebarrierptr((*uintptr)(dst), *(*uintptr)(src))
155                 } else {
156                         *(*uintptr)(dst) = *(*uintptr)(src)
157                 }
158                 dst = add(dst, ptrSize)
159                 src = add(src, ptrSize)
160                 if i+1 == nptr {
161                         break
162                 }
163                 bits >>= 4
164                 if (bits>>2)&_BitsMask == _BitsPointer {
165                         writebarrierptr((*uintptr)(dst), *(*uintptr)(src))
166                 } else {
167                         *(*uintptr)(dst) = *(*uintptr)(src)
168                 }
169                 dst = add(dst, ptrSize)
170                 src = add(src, ptrSize)
171         }
172 }
173
174 //go:nosplit
175 func writebarriercopy(typ *_type, dst, src slice) int {
176         n := dst.len
177         if n > src.len {
178                 n = src.len
179         }
180         if n == 0 {
181                 return 0
182         }
183         dstp := unsafe.Pointer(dst.array)
184         srcp := unsafe.Pointer(src.array)
185
186         if uintptr(srcp) < uintptr(dstp) && uintptr(srcp)+uintptr(n)*typ.size > uintptr(dstp) {
187                 // Overlap with src before dst.
188                 // Copy backward, being careful not to move dstp/srcp
189                 // out of the array they point into.
190                 dstp = add(dstp, uintptr(n-1)*typ.size)
191                 srcp = add(srcp, uintptr(n-1)*typ.size)
192                 i := uint(0)
193                 for {
194                         writebarrierfat(typ, dstp, srcp)
195                         if i++; i >= n {
196                                 break
197                         }
198                         dstp = add(dstp, -typ.size)
199                         srcp = add(srcp, -typ.size)
200                 }
201         } else {
202                 // Copy forward, being careful not to move dstp/srcp
203                 // out of the array they point into.
204                 i := uint(0)
205                 for {
206                         writebarrierfat(typ, dstp, srcp)
207                         if i++; i >= n {
208                                 break
209                         }
210                         dstp = add(dstp, typ.size)
211                         srcp = add(srcp, typ.size)
212                 }
213         }
214         return int(n)
215 }