mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
runtime: convert sigqueue to Go
LGTM=rsc R=golang-codereviews, rsc CC=golang-codereviews, khr https://golang.org/cl/132090043
This commit is contained in:
parent
98bebcc90a
commit
651d0cf204
3 changed files with 85 additions and 24 deletions
|
|
@ -781,6 +781,7 @@ extern DebugVars runtime·debug;
|
||||||
extern uintptr runtime·maxstacksize;
|
extern uintptr runtime·maxstacksize;
|
||||||
extern byte* runtime·gcdatamask;
|
extern byte* runtime·gcdatamask;
|
||||||
extern byte* runtime·gcbssmask;
|
extern byte* runtime·gcbssmask;
|
||||||
|
extern Note runtime·signote;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* common functions and data
|
* common functions and data
|
||||||
|
|
|
||||||
|
|
@ -24,22 +24,26 @@
|
||||||
// unnecessary rechecks of sig.mask, but must not lead to missed signals
|
// unnecessary rechecks of sig.mask, but must not lead to missed signals
|
||||||
// nor deadlocks.
|
// nor deadlocks.
|
||||||
|
|
||||||
package runtime
|
|
||||||
#include "runtime.h"
|
#include "runtime.h"
|
||||||
#include "defs_GOOS_GOARCH.h"
|
#include "defs_GOOS_GOARCH.h"
|
||||||
#include "os_GOOS.h"
|
#include "os_GOOS.h"
|
||||||
#include "cgocall.h"
|
#include "cgocall.h"
|
||||||
#include "../../cmd/ld/textflag.h"
|
#include "../../cmd/ld/textflag.h"
|
||||||
|
|
||||||
#pragma textflag NOPTR
|
typedef struct Sig Sig;
|
||||||
static struct {
|
struct Sig {
|
||||||
Note note;
|
|
||||||
uint32 mask[(NSIG+31)/32];
|
uint32 mask[(NSIG+31)/32];
|
||||||
uint32 wanted[(NSIG+31)/32];
|
uint32 wanted[(NSIG+31)/32];
|
||||||
uint32 recv[(NSIG+31)/32];
|
uint32 recv[(NSIG+31)/32];
|
||||||
uint32 state;
|
uint32 state;
|
||||||
bool inuse;
|
bool inuse;
|
||||||
} sig;
|
bool afterwait;
|
||||||
|
};
|
||||||
|
|
||||||
|
#pragma dataflag NOPTR
|
||||||
|
static Sig sig;
|
||||||
|
|
||||||
|
Note runtime·signote;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
HASWAITER = 1,
|
HASWAITER = 1,
|
||||||
|
|
@ -72,7 +76,7 @@ runtime·sigsend(int32 s)
|
||||||
new = HASSIGNAL;
|
new = HASSIGNAL;
|
||||||
if(runtime·cas(&sig.state, old, new)) {
|
if(runtime·cas(&sig.state, old, new)) {
|
||||||
if (old == HASWAITER)
|
if (old == HASWAITER)
|
||||||
runtime·notewakeup(&sig.note);
|
runtime·notewakeup(&runtime·signote);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -84,16 +88,23 @@ runtime·sigsend(int32 s)
|
||||||
|
|
||||||
// Called to receive the next queued signal.
|
// Called to receive the next queued signal.
|
||||||
// Must only be called from a single goroutine at a time.
|
// Must only be called from a single goroutine at a time.
|
||||||
func signal_recv() (m uint32) {
|
void
|
||||||
|
runtime·signal_recv_m(void)
|
||||||
|
{
|
||||||
uint32 i, old, new;
|
uint32 i, old, new;
|
||||||
|
|
||||||
|
if(sig.afterwait) {
|
||||||
|
sig.afterwait = false;
|
||||||
|
goto update;
|
||||||
|
}
|
||||||
for(;;) {
|
for(;;) {
|
||||||
// Serve from local copy if there are bits left.
|
// Serve from local copy if there are bits left.
|
||||||
for(i=0; i<NSIG; i++) {
|
for(i=0; i<NSIG; i++) {
|
||||||
if(sig.recv[i/32]&(1U<<(i&31))) {
|
if(sig.recv[i/32]&(1U<<(i&31))) {
|
||||||
sig.recv[i/32] ^= 1U<<(i&31);
|
sig.recv[i/32] ^= 1U<<(i&31);
|
||||||
m = i;
|
g->m->scalararg[0] = true;
|
||||||
goto done;
|
g->m->scalararg[1] = i;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -108,41 +119,43 @@ func signal_recv() (m uint32) {
|
||||||
new = HASWAITER;
|
new = HASWAITER;
|
||||||
if(runtime·cas(&sig.state, old, new)) {
|
if(runtime·cas(&sig.state, old, new)) {
|
||||||
if (new == HASWAITER) {
|
if (new == HASWAITER) {
|
||||||
runtime·notetsleepg(&sig.note, -1);
|
sig.afterwait = true;
|
||||||
runtime·noteclear(&sig.note);
|
g->m->scalararg[0] = false;
|
||||||
|
g->m->scalararg[1] = 0;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get a new local copy.
|
// Get a new local copy.
|
||||||
|
update:
|
||||||
for(i=0; i<nelem(sig.mask); i++) {
|
for(i=0; i<nelem(sig.mask); i++) {
|
||||||
for(;;) {
|
for(;;) {
|
||||||
m = sig.mask[i];
|
old = sig.mask[i];
|
||||||
if(runtime·cas(&sig.mask[i], m, 0))
|
if(runtime·cas(&sig.mask[i], old, 0))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
sig.recv[i] = m;
|
sig.recv[i] = old;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
done:;
|
|
||||||
// goc requires that we fall off the end of functions
|
|
||||||
// that return values instead of using our own return
|
|
||||||
// statements.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Must only be called from a single goroutine at a time.
|
// Must only be called from a single goroutine at a time.
|
||||||
func signal_enable(s uint32) {
|
void
|
||||||
|
runtime·signal_enable_m(void)
|
||||||
|
{
|
||||||
|
uint32 s;
|
||||||
|
|
||||||
if(!sig.inuse) {
|
if(!sig.inuse) {
|
||||||
// The first call to signal_enable is for us
|
// The first call to signal_enable is for us
|
||||||
// to use for initialization. It does not pass
|
// to use for initialization. It does not pass
|
||||||
// signal information in m.
|
// signal information in m.
|
||||||
sig.inuse = true; // enable reception of signals; cannot disable
|
sig.inuse = true; // enable reception of signals; cannot disable
|
||||||
runtime·noteclear(&sig.note);
|
runtime·noteclear(&runtime·signote);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
s = g->m->scalararg[0];
|
||||||
if(s >= nelem(sig.wanted)*32)
|
if(s >= nelem(sig.wanted)*32)
|
||||||
return;
|
return;
|
||||||
sig.wanted[s/32] |= 1U<<(s&31);
|
sig.wanted[s/32] |= 1U<<(s&31);
|
||||||
|
|
@ -150,7 +163,12 @@ func signal_enable(s uint32) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Must only be called from a single goroutine at a time.
|
// Must only be called from a single goroutine at a time.
|
||||||
func signal_disable(s uint32) {
|
void
|
||||||
|
runtime·signal_disable_m(void)
|
||||||
|
{
|
||||||
|
uint32 s;
|
||||||
|
|
||||||
|
s = g->m->scalararg[0];
|
||||||
if(s >= nelem(sig.wanted)*32)
|
if(s >= nelem(sig.wanted)*32)
|
||||||
return;
|
return;
|
||||||
sig.wanted[s/32] &= ~(1U<<(s&31));
|
sig.wanted[s/32] &= ~(1U<<(s&31));
|
||||||
42
src/pkg/runtime/sigqueue.go
Normal file
42
src/pkg/runtime/sigqueue.go
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
// Copyright 2009 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// This file implements runtime support for signal handling.
|
||||||
|
|
||||||
|
package runtime
|
||||||
|
|
||||||
|
func signal_recv() (m uint32) {
|
||||||
|
for {
|
||||||
|
mp := acquirem()
|
||||||
|
onM(&signal_recv_m)
|
||||||
|
ok := mp.scalararg[0] != 0
|
||||||
|
m = uint32(mp.scalararg[1])
|
||||||
|
releasem(mp)
|
||||||
|
if ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
gonotetsleepg(&signote, -1)
|
||||||
|
gonoteclear(&signote)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func signal_enable(s uint32) {
|
||||||
|
mp := acquirem()
|
||||||
|
mp.scalararg[0] = uint(s)
|
||||||
|
onM(&signal_enable_m)
|
||||||
|
releasem(mp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func signal_disable(s uint32) {
|
||||||
|
mp := acquirem()
|
||||||
|
mp.scalararg[0] = uint(s)
|
||||||
|
onM(&signal_disable_m)
|
||||||
|
releasem(mp)
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
signal_recv_m,
|
||||||
|
signal_enable_m,
|
||||||
|
signal_disable_m mFunction
|
||||||
|
)
|
||||||
Loading…
Add table
Add a link
Reference in a new issue