Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(412)

Side by Side Diff: src/pkg/runtime/sigqueue.goc

Issue 160200044: [dev.power64] code review 160200044: build: merge default into dev.power64 (Closed)
Patch Set: diff -r be0c14f62257b42485019e9e1db23cf40d2e249f https://code.google.com/p/go Created 10 years, 4 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/pkg/runtime/sigqueue.go ('k') | src/pkg/runtime/slice.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2009 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 // This file implements runtime support for signal handling.
6 //
7 // Most synchronization primitives are not available from
8 // the signal handler (it cannot block, allocate memory, or use locks)
9 // so the handler communicates with a processing goroutine
10 // via struct sig, below.
11 //
12 // sigsend() is called by the signal handler to queue a new signal.
13 // signal_recv() is called by the Go program to receive a newly queued signal.
14 // Synchronization between sigsend() and signal_recv() is based on the sig.state
15 // variable. It can be in 3 states: 0, HASWAITER and HASSIGNAL.
16 // HASWAITER means that signal_recv() is blocked on sig.Note and there are no
17 // new pending signals.
18 // HASSIGNAL means that sig.mask *may* contain new pending signals,
19 // signal_recv() can't be blocked in this state.
20 // 0 means that there are no new pending signals and signal_recv() is not blocke d.
21 // Transitions between states are done atomically with CAS.
22 // When signal_recv() is unblocked, it resets sig.Note and rechecks sig.mask.
23 // If several sigsend()'s and signal_recv() execute concurrently, it can lead to
24 // unnecessary rechecks of sig.mask, but must not lead to missed signals
25 // nor deadlocks.
26
27 package runtime
28 #include "runtime.h"
29 #include "defs_GOOS_GOARCH.h"
30 #include "os_GOOS.h"
31 #include "cgocall.h"
32 #include "../../cmd/ld/textflag.h"
33
34 #pragma textflag NOPTR
35 static struct {
36 Note;
37 uint32 mask[(NSIG+31)/32];
38 uint32 wanted[(NSIG+31)/32];
39 uint32 recv[(NSIG+31)/32];
40 uint32 state;
41 bool inuse;
42 } sig;
43
44 enum {
45 HASWAITER = 1,
46 HASSIGNAL = 2,
47 };
48
49 // Called from sighandler to send a signal back out of the signal handling threa d.
50 bool
51 runtime·sigsend(int32 s)
52 {
53 uint32 bit, mask, old, new;
54
55 if(!sig.inuse || s < 0 || s >= 32*nelem(sig.wanted) || !(sig.wanted[s/32 ]&(1U<<(s&31))))
56 return false;
57 bit = 1 << (s&31);
58 for(;;) {
59 mask = sig.mask[s/32];
60 if(mask & bit)
61 break; // signal already in queue
62 if(runtime·cas(&sig.mask[s/32], mask, mask|bit)) {
63 // Added to queue.
64 // Only send a wakeup if the receiver needs a kick.
65 for(;;) {
66 old = runtime·atomicload(&sig.state);
67 if(old == HASSIGNAL)
68 break;
69 if(old == HASWAITER)
70 new = 0;
71 else // if(old == 0)
72 new = HASSIGNAL;
73 if(runtime·cas(&sig.state, old, new)) {
74 if (old == HASWAITER)
75 runtime·notewakeup(&sig);
76 break;
77 }
78 }
79 break;
80 }
81 }
82 return true;
83 }
84
85 // Called to receive the next queued signal.
86 // Must only be called from a single goroutine at a time.
87 func signal_recv() (m uint32) {
88 uint32 i, old, new;
89 ········
90 for(;;) {
91 // Serve from local copy if there are bits left.
92 for(i=0; i<NSIG; i++) {
93 if(sig.recv[i/32]&(1U<<(i&31))) {
94 sig.recv[i/32] ^= 1U<<(i&31);
95 m = i;
96 goto done;
97 }
98 }
99
100 // Check and update sig.state.
101 for(;;) {
102 old = runtime·atomicload(&sig.state);
103 if(old == HASWAITER)
104 runtime·throw("inconsistent state in signal_recv ");
105 if(old == HASSIGNAL)
106 new = 0;
107 else // if(old == 0)
108 new = HASWAITER;
109 if(runtime·cas(&sig.state, old, new)) {
110 if (new == HASWAITER) {
111 runtime·notetsleepg(&sig, -1);
112 runtime·noteclear(&sig);
113 }
114 break;
115 }
116 }
117
118 // Get a new local copy.
119 for(i=0; i<nelem(sig.mask); i++) {
120 for(;;) {
121 m = sig.mask[i];
122 if(runtime·cas(&sig.mask[i], m, 0))
123 break;
124 }
125 sig.recv[i] = m;
126 }
127 }
128
129 done:;
130 // goc requires that we fall off the end of functions
131 // that return values instead of using our own return
132 // statements.
133 }
134
135 // Must only be called from a single goroutine at a time.
136 func signal_enable(s uint32) {
137 if(!sig.inuse) {
138 // The first call to signal_enable is for us
139 // to use for initialization. It does not pass
140 // signal information in m.
141 sig.inuse = true; // enable reception of signals; cannot d isable
142 runtime·noteclear(&sig);
143 return;
144 }
145 ········
146 if(s >= nelem(sig.wanted)*32)
147 return;
148 sig.wanted[s/32] |= 1U<<(s&31);
149 runtime·sigenable(s);
150 }
151
152 // Must only be called from a single goroutine at a time.
153 func signal_disable(s uint32) {
154 if(s >= nelem(sig.wanted)*32)
155 return;
156 sig.wanted[s/32] &= ~(1U<<(s&31));
157 runtime·sigdisable(s);
158 }
159
160 // This runs on a foreign stack, without an m or a g. No stack split.
161 #pragma textflag NOSPLIT
162 void
163 runtime·badsignal(uintptr sig)
164 {
165 runtime·cgocallback((void (*)(void))runtime·sigsend, &sig, sizeof(sig));
166 }
OLDNEW
« no previous file with comments | « src/pkg/runtime/sigqueue.go ('k') | src/pkg/runtime/slice.go » ('j') | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b