annotate libgo/runtime/stack.c @ 111:04ced10e8804

gcc 7
author kono
date Fri, 27 Oct 2017 22:46:09 +0900
parents
children 84e7813d76e9
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 // Copyright 2009 The Go Authors. All rights reserved.
kono
parents:
diff changeset
2 // Use of this source code is governed by a BSD-style
kono
parents:
diff changeset
3 // license that can be found in the LICENSE file.
kono
parents:
diff changeset
4
kono
parents:
diff changeset
5 // Stack scanning code for the garbage collector.
kono
parents:
diff changeset
6
kono
parents:
diff changeset
7 #include "runtime.h"
kono
parents:
diff changeset
8
kono
parents:
diff changeset
9 #ifdef USING_SPLIT_STACK
kono
parents:
diff changeset
10
kono
parents:
diff changeset
11 extern void * __splitstack_find (void *, void *, size_t *, void **, void **,
kono
parents:
diff changeset
12 void **);
kono
parents:
diff changeset
13
kono
parents:
diff changeset
14 extern void * __splitstack_find_context (void *context[10], size_t *, void **,
kono
parents:
diff changeset
15 void **, void **);
kono
parents:
diff changeset
16
kono
parents:
diff changeset
17 #endif
kono
parents:
diff changeset
18
kono
parents:
diff changeset
19 // Calling unwind_init in doscanstack only works if it does not do a
kono
parents:
diff changeset
20 // tail call to doscanstack1.
kono
parents:
diff changeset
21 #pragma GCC optimize ("-fno-optimize-sibling-calls")
kono
parents:
diff changeset
22
kono
parents:
diff changeset
23 extern void scanstackblock(void *addr, uintptr size, void *gcw)
kono
parents:
diff changeset
24 __asm__("runtime.scanstackblock");
kono
parents:
diff changeset
25
kono
parents:
diff changeset
26 void doscanstack(G*, void*)
kono
parents:
diff changeset
27 __asm__("runtime.doscanstack");
kono
parents:
diff changeset
28
kono
parents:
diff changeset
29 static void doscanstack1(G*, void*)
kono
parents:
diff changeset
30 __attribute__ ((noinline));
kono
parents:
diff changeset
31
kono
parents:
diff changeset
32 // Scan gp's stack, passing stack chunks to scanstackblock.
kono
parents:
diff changeset
33 void doscanstack(G *gp, void* gcw) {
kono
parents:
diff changeset
34 // Save registers on the stack, so that if we are scanning our
kono
parents:
diff changeset
35 // own stack we will see them.
kono
parents:
diff changeset
36 __builtin_unwind_init();
kono
parents:
diff changeset
37
kono
parents:
diff changeset
38 doscanstack1(gp, gcw);
kono
parents:
diff changeset
39 }
kono
parents:
diff changeset
40
kono
parents:
diff changeset
41 // Scan gp's stack after saving registers.
kono
parents:
diff changeset
42 static void doscanstack1(G *gp, void *gcw) {
kono
parents:
diff changeset
43 #ifdef USING_SPLIT_STACK
kono
parents:
diff changeset
44 void* sp;
kono
parents:
diff changeset
45 size_t spsize;
kono
parents:
diff changeset
46 void* next_segment;
kono
parents:
diff changeset
47 void* next_sp;
kono
parents:
diff changeset
48 void* initial_sp;
kono
parents:
diff changeset
49
kono
parents:
diff changeset
50 if (gp == runtime_g()) {
kono
parents:
diff changeset
51 // Scanning our own stack.
kono
parents:
diff changeset
52 sp = __splitstack_find(nil, nil, &spsize, &next_segment,
kono
parents:
diff changeset
53 &next_sp, &initial_sp);
kono
parents:
diff changeset
54 } else {
kono
parents:
diff changeset
55 // Scanning another goroutine's stack.
kono
parents:
diff changeset
56 // The goroutine is usually asleep (the world is stopped).
kono
parents:
diff changeset
57
kono
parents:
diff changeset
58 // The exception is that if the goroutine is about to enter or might
kono
parents:
diff changeset
59 // have just exited a system call, it may be executing code such
kono
parents:
diff changeset
60 // as schedlock and may have needed to start a new stack segment.
kono
parents:
diff changeset
61 // Use the stack segment and stack pointer at the time of
kono
parents:
diff changeset
62 // the system call instead, since that won't change underfoot.
kono
parents:
diff changeset
63 if(gp->gcstack != 0) {
kono
parents:
diff changeset
64 sp = (void*)(gp->gcstack);
kono
parents:
diff changeset
65 spsize = gp->gcstacksize;
kono
parents:
diff changeset
66 next_segment = (void*)(gp->gcnextsegment);
kono
parents:
diff changeset
67 next_sp = (void*)(gp->gcnextsp);
kono
parents:
diff changeset
68 initial_sp = (void*)(gp->gcinitialsp);
kono
parents:
diff changeset
69 } else {
kono
parents:
diff changeset
70 sp = __splitstack_find_context((void**)(&gp->stackcontext[0]),
kono
parents:
diff changeset
71 &spsize, &next_segment,
kono
parents:
diff changeset
72 &next_sp, &initial_sp);
kono
parents:
diff changeset
73 }
kono
parents:
diff changeset
74 }
kono
parents:
diff changeset
75 if(sp != nil) {
kono
parents:
diff changeset
76 scanstackblock(sp, (uintptr)(spsize), gcw);
kono
parents:
diff changeset
77 while((sp = __splitstack_find(next_segment, next_sp,
kono
parents:
diff changeset
78 &spsize, &next_segment,
kono
parents:
diff changeset
79 &next_sp, &initial_sp)) != nil)
kono
parents:
diff changeset
80 scanstackblock(sp, (uintptr)(spsize), gcw);
kono
parents:
diff changeset
81 }
kono
parents:
diff changeset
82 #else
kono
parents:
diff changeset
83 byte* bottom;
kono
parents:
diff changeset
84 byte* top;
kono
parents:
diff changeset
85
kono
parents:
diff changeset
86 if(gp == runtime_g()) {
kono
parents:
diff changeset
87 // Scanning our own stack.
kono
parents:
diff changeset
88 bottom = (byte*)&gp;
kono
parents:
diff changeset
89 } else {
kono
parents:
diff changeset
90 // Scanning another goroutine's stack.
kono
parents:
diff changeset
91 // The goroutine is usually asleep (the world is stopped).
kono
parents:
diff changeset
92 bottom = (void*)gp->gcnextsp;
kono
parents:
diff changeset
93 if(bottom == nil)
kono
parents:
diff changeset
94 return;
kono
parents:
diff changeset
95 }
kono
parents:
diff changeset
96 top = (byte*)(void*)(gp->gcinitialsp) + gp->gcstacksize;
kono
parents:
diff changeset
97 if(top > bottom)
kono
parents:
diff changeset
98 scanstackblock(bottom, (uintptr)(top - bottom), gcw);
kono
parents:
diff changeset
99 else
kono
parents:
diff changeset
100 scanstackblock(top, (uintptr)(bottom - top), gcw);
kono
parents:
diff changeset
101 #endif
kono
parents:
diff changeset
102 }