From 82bcbebce43f0227f506d75a5b764b6847041bae Mon Sep 17 00:00:00 2001 From: Ben Cheng Date: Mon, 1 Oct 2012 10:30:31 -0700 Subject: Initial check-in of gcc 4.7.2. Change-Id: I4a2f5a921c21741a0e18bda986d77e5f1bef0365 --- gcc-4.7/libgo/runtime/sigqueue.goc | 153 +++++++++++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 gcc-4.7/libgo/runtime/sigqueue.goc (limited to 'gcc-4.7/libgo/runtime/sigqueue.goc') diff --git a/gcc-4.7/libgo/runtime/sigqueue.goc b/gcc-4.7/libgo/runtime/sigqueue.goc new file mode 100644 index 000000000..be7c5920c --- /dev/null +++ b/gcc-4.7/libgo/runtime/sigqueue.goc @@ -0,0 +1,153 @@ +// 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 and cannot use locks) +// so the handler communicates with a processing goroutine +// via struct sig, below. +// +// Ownership for sig.Note passes back and forth between +// the signal handler and the signal goroutine in rounds. +// The initial state is that sig.note is cleared (setup by signal_enable). +// At the beginning of each round, mask == 0. +// The round goes through three stages: +// +// (In parallel) +// 1a) One or more signals arrive and are handled +// by sigsend using cas to set bits in sig.mask. +// The handler that changes sig.mask from zero to non-zero +// calls notewakeup(&sig). +// 1b) Sigrecv calls notesleep(&sig) to wait for the wakeup. +// +// 2) Having received the wakeup, sigrecv knows that sigsend +// will not send another wakeup, so it can noteclear(&sig) +// to prepare for the next round. (Sigsend may still be adding +// signals to sig.mask at this point, which is fine.) +// +// 3) Sigrecv uses cas to grab the current sig.mask and zero it, +// triggering the next round. +// +// The signal handler takes ownership of the note by atomically +// changing mask from a zero to non-zero value. It gives up +// ownership by calling notewakeup. The signal goroutine takes +// ownership by returning from notesleep (caused by the notewakeup) +// and gives up ownership by clearing mask. + +package signal +#include "config.h" +#include "runtime.h" +#include "arch.h" +#include "malloc.h" +#include "defs.h" + +static struct { + Note; + uint32 mask[(NSIG+31)/32]; + uint32 wanted[(NSIG+31)/32]; + uint32 kick; + bool inuse; +} sig; + +// Called from sighandler to send a signal back out of the signal handling thread. +bool +__go_sigsend(int32 s) +{ + uint32 bit, mask; + + if(!sig.inuse || s < 0 || (size_t)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. + if(runtime_cas(&sig.kick, 1, 0)) + runtime_notewakeup(&sig); + 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)]; + int32 i, more; + + for(;;) { + // Serve from local copy if there are bits left. + for(i=0; i= nelem(sig.wanted)*32) + return; + sig.wanted[s/32] |= 1U<<(s&31); + runtime_sigenable(s); +} -- cgit v1.2.3