URL
https://opencores.org/ocsvn/openrisc/openrisc/trunk
Subversion Repositories openrisc
[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [runtime/] [sigqueue.goc] - Rev 747
Compare with Previous | Blame | View Log
// 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 siginit).// 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 runtime#include "config.h"#include "runtime.h"#include "arch.h"#include "malloc.h"#include "defs.h"static struct {Note;uint32 mask;bool inuse;} sig;voidsiginit(void){runtime_noteclear(&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)return false;bit = 1 << s;for(;;) {mask = sig.mask;if(mask & bit)break; // signal already in queueif(runtime_cas(&sig.mask, mask, mask|bit)) {// Added to queue.// Only send a wakeup for the first signal in each round.if(mask == 0)runtime_notewakeup(&sig);break;}}return true;}// Called to receive a bitmask of queued signals.func Sigrecv() (m uint32) {runtime_entersyscall();runtime_notesleep(&sig);runtime_exitsyscall();runtime_noteclear(&sig);for(;;) {m = sig.mask;if(runtime_cas(&sig.mask, m, 0))break;}}func Signame(sig int32) (name String) {const char* s = NULL;char buf[100];#if defined(HAVE_STRSIGNAL)s = strsignal(sig);#endifif (s == NULL) {snprintf(buf, sizeof buf, "signal %d", sig);s = buf;}int32 len = __builtin_strlen(s);unsigned char *data = runtime_mallocgc(len, FlagNoPointers, 0, 0);__builtin_memcpy(data, s, len);name.__data = data;name.__length = len;}func Siginit() {runtime_initsig(SigQueue);sig.inuse = true; // enable reception of signals; cannot disable}
