Plan 9 from Bell Labs’s /usr/web/sources/contrib/cinap_lenrek/old/linuxemu.old/syssig.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


#include <u.h>
#include <libc.h>
#include <ureg.h>
#include "linuxsys.h"
#include "linux.h"

SYSCALL(sys_kill)
{
	int pid;
	int sig;
	pid = (int)ARG1;
	sig = (int)ARG2;
	RETURN(_kill(pid, sig));
}

struct sigaction
{
	void *handler;
	ulong flags;
	void *restorer;
	uchar mask;
};

static void
uv2sigset(uchar *set, int setsize, uvlong mask)
{
	int i;
	for(i=0; i<setsize; i++){
		if(i < sizeof(uvlong)){
			set[i] = ((mask >> (i*8)) & 0xff);
		} else {
			set[i] = 0;
		}
	}
}

static uvlong
sigset2uv(uchar *set, int setsize)
{
	uvlong r;
	int i;
	r = 0LL;
	if(setsize > sizeof(uvlong))
		setsize = sizeof(uvlong);
	for(i=0; i<setsize; i++)
		r |= (uvlong)set[i] << (i*8);
	return r;
}

enum
{
	SIG_BLOCK		= 0,
	SIG_UNBLOCK		= 1,
	SIG_SETMASK		= 2,
};

SYSCALL(sys_rt_sigprocmask)
{
	int how;
	uchar *act;
	uchar *oact;
	int setsize;

	uvlong x;

	how = (int)ARG1;
	act = (uchar*)ARG2;
	oact = (uchar*)ARG3;
	setsize = (int)ARG4;

	DPRINT("rt_sigprocmask(%d, 0x%p, 0x%p, %d)...", how, act, oact, setsize);
	if(oact)
		uv2sigset(oact, setsize, threadp->ss.blocked);
	if(act){
		x = sigset2uv(act, setsize);
	} else {
		RETURN(0);
	}
	x &= ~(1LL<<(SIGKILL-1));
	x &= ~(1LL <<(SIGSTOP-1));
	switch(how){
	default:
		RETURN(-EINVAL);
	case SIG_BLOCK:
		threadp->ss.blocked |= x;
		break;
	case SIG_UNBLOCK:
		threadp->ss.blocked &= ~x;
		break;
	case SIG_SETMASK:
		threadp->ss.blocked = x;
		break;
	}
	RETURN(0);
}

static void
printsigstate(char *s)
{
	uvlong pending;
	uvlong blocked;

	blocked = threadp->ss.blocked;
	pending = sigpending(&threadp->ss);

	fprint(2, "[%d] [%s] sigstate: pending: 0x%llux, blocked 0x%llux, ready 0x%llux\n",
		threadp->pid, s, pending, blocked, pending & ~blocked);
}

SYSCALL(sys_rt_sigsuspend)
{
	uvlong x;
	uvlong t;
	uchar *sm;
	int setsize;

	sm = (uchar*)ARG1;
	setsize = (int)ARG2;

	DPRINT("rt_sigsuspend(0x%p, %d)...",sm, setsize);
//	printsigstate("before sigsuspend");
	t = threadp->ss.blocked;
	x = sigset2uv(sm, setsize);
	x &= ~(1LL<<(SIGKILL-1));
	x &= ~(1LL <<(SIGSTOP-1));
	threadp->ss.blocked = x;
	while(!(sigpending(&threadp->ss) & ~x)){
//		printsigstate("sigsuspend sleep");
		sleep(10000);
//		printsigstate("sigsuspend wakeup");
	}
//	printsigstate("sigsuspend break");
	sigenable(&threadp->ss);

	sigdisable(&threadp->ss);
	threadp->ss.blocked = t;
//	printsigstate("after sigsuspend");
	RETURN(-EINTR);
}

SYSCALL(sys_rt_sigaction)
{
	int sig;
	struct sigaction *act;
	struct sigaction *oact;
	int setsize;

	sig = (int)ARG1;
	act = (struct sigaction*)ARG2;
	oact = (struct sigaction*)ARG3;
	setsize = (int)ARG4;

	DPRINT("rt_sigaction(%d, 0x%p, 0x%p, %d)...", sig, act, oact, setsize);
	if(act && act->flags & (SA_SIGINFO | SA_ONSTACK)){
		fprint(2, "[%d] rt_sigaction: unsopprted signalflags %lux\n", threadp->tid, act->flags);
		RETURN(-EINVAL);
	}
	if(oact){
		oact->handler = threadp->ss.action[sig-1].handler;
		oact->flags = threadp->ss.action[sig-1].flags;
		oact->restorer = 0;
		uv2sigset(&oact->mask, setsize, threadp->ss.action[sig-1].blocked);
	}
	if(act){
		threadp->ss.action[sig-1].handler = (void*)act->handler;
		threadp->ss.action[sig-1].flags = act->flags;
		threadp->ss.action[sig-1].blocked = sigset2uv(&act->mask, setsize);
	}
	RETURN(0);
}

SYSCALL(sys_rt_sigpending)
{
	uchar *set;
	int setsize;

	set = (uchar*)ARG1;
	setsize = (int)ARG2;

	DPRINT("rt_sigpending(0x%p, %d)...", set, setsize);
	uv2sigset(set, setsize, sigpending(&threadp->ss));
	RETURN(0);
}


Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to [email protected].