2018-23-01 Paul Thomas <pault@gcc.gnu.org>
[official-gcc.git] / libgo / go / runtime / mgc_gccgo.go
blob107a70a789887aafd02fb8ab991fd2355898e1b6
1 // Copyright 2016 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.
5 // gccgo-specific support for GC.
7 package runtime
9 import (
10 "runtime/internal/sys"
11 "unsafe"
14 // gcRoot is a single GC root: a variable plus a ptrmask.
15 type gcRoot struct {
16 decl unsafe.Pointer // Pointer to variable.
17 size uintptr // Size of variable.
18 ptrdata uintptr // Length of gcdata.
19 gcdata *uint8 // Pointer mask.
22 // gcRootList is the set of GC roots for a package.
23 // The next field is used to put this all into a linked list.
24 // count gives the real length of the array.
25 type gcRootList struct {
26 next *gcRootList
27 count int
28 roots [1 << 26]gcRoot
31 // roots is the list of GC roots for the program.
32 // The compiler keeps this variable itself off the list.
33 var gcRoots *gcRootList
35 // registerGCRoots is called by compiler-generated code.
36 //go:linkname registerGCRoots runtime.registerGCRoots
38 // registerGCRoots is called by init functions to register the GC
39 // roots for a package. The init functions are run sequentially at
40 // the start of the program, so no locking is needed.
41 func registerGCRoots(r *gcRootList) {
42 r.next = gcRoots
43 gcRoots = r
46 // checkPreempt is called when the preempt field in the running G is true.
47 // It preempts the goroutine if it is safe to do so.
48 // If preemptscan is true, this scans the stack for the garbage collector
49 // and carries on.
50 func checkPreempt() {
51 gp := getg()
52 if !gp.preempt || gp != gp.m.curg || gp.m.locks != 0 || gp.m.mallocing != 0 || gp.m.preemptoff != "" {
53 return
56 // Synchronize with scang.
57 gp.scanningself = true
58 casgstatus(gp, _Grunning, _Gwaiting)
59 if gp.preemptscan {
60 for !castogscanstatus(gp, _Gwaiting, _Gscanwaiting) {
61 // Likely to be racing with the GC as
62 // it sees a _Gwaiting and does the
63 // stack scan. If so, gcworkdone will
64 // be set and gcphasework will simply
65 // return.
67 if !gp.gcscandone {
68 mp := acquirem()
69 gcw := &gp.m.p.ptr().gcw
70 scanstack(gp, gcw)
71 if gcBlackenPromptly {
72 gcw.dispose()
74 releasem(mp)
75 gp.gcscandone = true
77 gp.preemptscan = false
78 gp.preempt = false
79 casfrom_Gscanstatus(gp, _Gscanwaiting, _Gwaiting)
80 // This clears gcscanvalid.
81 casgstatus(gp, _Gwaiting, _Grunning)
82 gp.scanningself = false
83 return
86 // Act like goroutine called runtime.Gosched.
87 casgstatus(gp, _Gwaiting, _Grunning)
88 gp.scanningself = false
89 mcall(gopreempt_m)
92 // gcWriteBarrier implements a write barrier. This is implemented in
93 // assembly in the gc library, but there is no special advantage to
94 // doing so with gccgo.
95 //go:nosplit
96 //go:nowritebarrier
97 func gcWriteBarrier(dst *uintptr, src uintptr) {
98 buf := &getg().m.p.ptr().wbBuf
99 next := buf.next
100 np := next + 2*sys.PtrSize
101 buf.next = np
102 *(*uintptr)(unsafe.Pointer(next)) = src
103 *(*uintptr)(unsafe.Pointer(next + sys.PtrSize)) = *dst
104 if np >= buf.end {
105 wbBufFlush(dst, src)
107 *dst = src