diff options
Diffstat (limited to 'src/pkg/runtime/sigqueue.goc')
-rw-r--r-- | src/pkg/runtime/sigqueue.goc | 165 |
1 files changed, 0 insertions, 165 deletions
diff --git a/src/pkg/runtime/sigqueue.goc b/src/pkg/runtime/sigqueue.goc deleted file mode 100644 index e08bf98aa..000000000 --- a/src/pkg/runtime/sigqueue.goc +++ /dev/null @@ -1,165 +0,0 @@ -// 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. -// -// Most synchronization primitives are not available from -// the signal handler (it cannot block, allocate memory, or use locks) -// so the handler communicates with a processing goroutine -// via struct sig, below. -// -// sigsend() is called by the signal handler to queue a new signal. -// signal_recv() is called by the Go program to receive a newly queued signal. -// Synchronization between sigsend() and signal_recv() is based on the sig.state -// variable. It can be in 3 states: 0, HASWAITER and HASSIGNAL. -// HASWAITER means that signal_recv() is blocked on sig.Note and there are no -// new pending signals. -// HASSIGNAL means that sig.mask *may* contain new pending signals, -// signal_recv() can't be blocked in this state. -// 0 means that there are no new pending signals and signal_recv() is not blocked. -// Transitions between states are done atomically with CAS. -// When signal_recv() is unblocked, it resets sig.Note and rechecks sig.mask. -// If several sigsend()'s and signal_recv() execute concurrently, it can lead to -// unnecessary rechecks of sig.mask, but must not lead to missed signals -// nor deadlocks. - -package runtime -#include "runtime.h" -#include "defs_GOOS_GOARCH.h" -#include "os_GOOS.h" -#include "cgocall.h" -#include "../../cmd/ld/textflag.h" - -static struct { - Note; - uint32 mask[(NSIG+31)/32]; - uint32 wanted[(NSIG+31)/32]; - uint32 state; - bool inuse; -} sig; - -enum { - HASWAITER = 1, - HASSIGNAL = 2, -}; - -// Called from sighandler to send a signal back out of the signal handling thread. -bool -runtime·sigsend(int32 s) -{ - uint32 bit, mask, old, new; - - if(!sig.inuse || s < 0 || s >= 32*nelem(sig.wanted) || !(sig.wanted[s/32]&(1U<<(s&31)))) - return false; - bit = 1 << (s&31); - for(;;) { - mask = sig.mask[s/32]; - if(mask & bit) - break; // signal already in queue - if(runtime·cas(&sig.mask[s/32], mask, mask|bit)) { - // Added to queue. - // Only send a wakeup if the receiver needs a kick. - for(;;) { - old = runtime·atomicload(&sig.state); - if(old == HASSIGNAL) - break; - if(old == HASWAITER) - new = 0; - else // if(old == 0) - new = HASSIGNAL; - if(runtime·cas(&sig.state, old, new)) { - if (old == HASWAITER) - runtime·notewakeup(&sig); - break; - } - } - break; - } - } - return true; -} - -// Called to receive the next queued signal. -// Must only be called from a single goroutine at a time. -func signal_recv() (m uint32) { - static uint32 recv[nelem(sig.mask)]; - uint32 i, old, new; - - for(;;) { - // Serve from local copy if there are bits left. - for(i=0; i<NSIG; i++) { - if(recv[i/32]&(1U<<(i&31))) { - recv[i/32] ^= 1U<<(i&31); - m = i; - goto done; - } - } - - // Check and update sig.state. - for(;;) { - old = runtime·atomicload(&sig.state); - if(old == HASWAITER) - runtime·throw("inconsistent state in signal_recv"); - if(old == HASSIGNAL) - new = 0; - else // if(old == 0) - new = HASWAITER; - if(runtime·cas(&sig.state, old, new)) { - if (new == HASWAITER) { - runtime·notetsleepg(&sig, -1); - runtime·noteclear(&sig); - } - break; - } - } - - // Get a new local copy. - for(i=0; i<nelem(sig.mask); i++) { - for(;;) { - m = sig.mask[i]; - if(runtime·cas(&sig.mask[i], m, 0)) - break; - } - recv[i] = m; - } - } - -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. -func signal_enable(s uint32) { - if(!sig.inuse) { - // The first call to signal_enable is for us - // to use for initialization. It does not pass - // signal information in m. - sig.inuse = true; // enable reception of signals; cannot disable - runtime·noteclear(&sig); - return; - } - - if(s >= nelem(sig.wanted)*32) - return; - sig.wanted[s/32] |= 1U<<(s&31); - runtime·sigenable(s); -} - -// Must only be called from a single goroutine at a time. -func signal_disable(s uint32) { - if(s >= nelem(sig.wanted)*32) - return; - sig.wanted[s/32] &= ~(1U<<(s&31)); - runtime·sigdisable(s); -} - -// This runs on a foreign stack, without an m or a g. No stack split. -#pragma textflag NOSPLIT -void -runtime·badsignal(uintptr sig) -{ - runtime·cgocallback((void (*)(void))runtime·sigsend, &sig, sizeof(sig)); -} |