📄 signal.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 + -