⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 signal.c

📁 pebble
💻 C
字号:
/* 
 * Copyright 1999, 2000, 2001, 2002 Lucent Technologies Inc.
 * All Rights Reserved.
 * Information Sciences Research Center, Bell Labs.
 *
 * LUCENT TECHNOLOGIES DOES NOT CLAIM MERCHANTABILITY OF THIS SOFTWARE 
 * OR THE SUITABILITY OF THIS SOFTWARE FOR ANY PARTICULAR PURPOSE. The
 * software is provided "as is" without expressed or implied warranty 
 * of any kind.
 *
 * These notices must be retained in any copies of any part of this
 * software.
 *
 */

/*
 * User-level signals manager.
 *
 * The signals manager implements POSIX-like signal services.
 *
 * *** important ***
 * The signals manager must be initialized before any use of signals.
 */

#include <unistd.h>		/* for write */
#include "diag.h"
#include "pebble.h"
#include "mem.h"
#include "synch.h"
#include "signal.h"
#include "nucleus.h"
#include <assert.h>

/* per domain signals information */
typedef struct	{
	Lock lock;
	uint is_initialized;	/* are the condition variables initialized? */
	sigset_t pending;	/* pending signals */
	uint is_suspend;	/* a thread is currently in sigsuspend() */
	Condition sigwait;	/* sigwait() waits here */
	Condition sigsuspend;	/* sigsuspend() waits here */
} DomSignal;

static DomSignal dom_sig[NASID];

const char INVALID_SET[] = "invalid signals set address";
const char INVALID_ASID[] = "invalid protection domain ID";
const char INVALID_SIG[] = "invalid signal number";
const char NOT_INIT[] = "target domain not initialized";


/* initialize the data structures of the current domain */
/* assumption: the dom_signal[] entry is locked */
static void
init_dom(DomSignal *dom_p)
{
	if (dom_p->is_initialized)
		return;

	sigemptyset(&dom_p->pending);
	dom_p->is_suspend = 0;
	cond_init(&dom_p->sigwait);
	cond_init(&dom_p->sigsuspend);
	dom_p->is_initialized = 1;
}


int
sys_kill(Thread *t, int asid, int signo)
{
	DomSignal *dom_p;

	DIAG(SIGNAL_DIAG,
		("sys_kill: t=%p asid=%d signo=%d\n", t, asid, signo));

	if (asid <= 0 || asid >= NASID)
		error(INVALID_ASID);

	if (signo <= 0 || signo > NSIG)
		error(INVALID_SIG);

	dom_p = &dom_sig[asid];
	if (!dom_p->is_initialized)
		error(NOT_INIT);

	mutex_lock(&dom_p->lock);
	sigaddset(&dom_p->pending, signo);
	if (dom_p->is_suspend)
		cond_signal(&dom_p->sigsuspend);
	else
		cond_signal(&dom_p->sigwait);
	mutex_unlock(&dom_p->lock);

	return 0;
}


/*
 * the normal signals handling thread calls sigwait() to get
 * the next few signals.
 */
int
sys_sigwait(int caller_asid, sigset_t *set)
{
	DomSignal *dom_p;

	DIAG(SIGNAL_DIAG,
		("sys_sigwait: caller_asid=%d set=%p\n", caller_asid, set));

	if (caller_asid <= 0 || caller_asid >= NASID)
		error(INVALID_ASID);

	if (set == NULL || param_check((char *)set, sizeof(sigset_t), 1) < 0)
		error(INVALID_SET);

	dom_p = &dom_sig[caller_asid];
	mutex_lock(&dom_p->lock);
	init_dom(dom_p);

	if (cond_wait(&dom_p->sigwait, &dom_p->lock) < 0)
		panic("sys_sigwait: cond_wait failed:");
	*set = dom_p->pending;
	sigemptyset(&dom_p->pending);

	mutex_unlock(&dom_p->lock);
	DIAG(SIGNAL_DIAG, ("sys_sigwait return: set=%08x\n", *set));

	return 0;
}


/*
 * sigsuspend() calls this portal to suspend the calling thread
 * until a signal is received.
 * When this portal is called, all further signals will wake up the
 * thread which waits on sigsusend condition and not the normal
 * signals handling thread.
 * sigsuspend() calls this portal with a NULL signals set to indicate
 * that the calling thread is not suspended any longer, so that further
 * signals will wake up the normal signals handling thread.
 */
int
sys_sigsuspend(int caller_asid, sigset_t *set)
{
	DomSignal *dom_p;

	DIAG(SIGNAL_DIAG,
		("sys_sigsuspend: caller_asid=%d set=%p\n", caller_asid, set));

	if (caller_asid <= 0 || caller_asid >= NASID)
		error(INVALID_ASID);

	if (set != NULL && param_check((char *)set, sizeof(sigset_t), 1) < 0)
		error(INVALID_SET);

	dom_p = &dom_sig[caller_asid];
	mutex_lock(&dom_p->lock);
	init_dom(dom_p);

	if (set == NULL)
		dom_p->is_suspend = 0;
	else	{
		dom_p->is_suspend = 1;
		if (cond_wait(&dom_p->sigsuspend, &dom_p->lock) < 0)
			panic("sys_sigsuspend: cond_wait failed:");
		*set = dom_p->pending;
		sigemptyset(&dom_p->pending);
	}

	mutex_unlock(&dom_p->lock);
	DIAG(SIGNAL_DIAG, ("sys_sigsuspend return: set=%08x\n",
		(set != NULL)? *set : 0));

	return 0;
}


/* signals manager initialization */
int main()
{
	printf("signals manager is active\n");

	/* verify that we are running in user mode with interrupts enabled */
	if (!check_psw(1,1)) {
		DIAG(LOCK_DIAG,
			("signals: invalid processor status: %08lx\n",
			get_psw()));
		task_exit(1);
	}

	if (portal_create(SYS_KILL, "sptiii", 0, (Func) sys_kill, 0) < 0)
		panic("portal_create for kill():");
	if (portal_create(SYS_SIGWAIT, "spaiii", 0, (Func) sys_sigwait, 0) < 0)
		panic("portal_create for sigwait():");
	if (portal_create(SYS_SIGSUSPEND, "spaiii", 0, (Func) sys_sigsuspend, 0)
	    < 0)
		panic("portal_create for sigwait():");

	DIAG(SIGNAL_DIAG, ("before returning to initialization code\n"));

	/*
	 * return to initialization code.
	 * cannot just "return", since the startup code (crt0.S) calls
	 * exit when main routine terminates.
	 */
	call_portal(SYS_RTN_RPC);
	return(1);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -