summaryrefslogtreecommitdiffstats
path: root/sys/arm
diff options
context:
space:
mode:
authordavidxu <davidxu@FreeBSD.org>2005-10-14 12:43:47 +0000
committerdavidxu <davidxu@FreeBSD.org>2005-10-14 12:43:47 +0000
commit3fbdb3c21524d9d95278ada1d61b4d1e6bee654b (patch)
tree95d82b1a11b0c187223f8ac12f020b19901fa750 /sys/arm
parent6b2407fb7677ef2b8cef5c0925b3fe88a6ec7ca4 (diff)
downloadFreeBSD-src-3fbdb3c21524d9d95278ada1d61b4d1e6bee654b.zip
FreeBSD-src-3fbdb3c21524d9d95278ada1d61b4d1e6bee654b.tar.gz
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and sendsig use discrete parameters, now they uses member fields of ksiginfo_t structure. For sendsig, this change allows us to pass POSIX realtime signal value to user code. 2. Remove cpu_thread_siginfo, it is no longer needed because we now always generate ksiginfo_t data and feed it to libpthread. 3. Add p_sigqueue to proc structure to hold shared signals which were blocked by all threads in the proc. 4. Add td_sigqueue to thread structure to hold all signals delivered to thread. 5. i386 and amd64 now return POSIX standard si_code, other arches will be fixed. 6. In this sigqueue implementation, pending signal set is kept as before, an extra siginfo list holds additional siginfo_t data for signals. kernel code uses psignal() still behavior as before, it won't be failed even under memory pressure, only exception is when deleting a signal, we should call sigqueue_delete to remove signal from sigqueue but not SIGDELSET. Current there is no kernel code will deliver a signal with additional data, so kernel should be as stable as before, a ksiginfo can carry more information, for example, allow signal to be delivered but throw away siginfo data if memory is not enough. SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can not be caught or masked. The sigqueue() syscall allows user code to queue a signal to target process, if resource is unavailable, EAGAIN will be returned as specification said. Just before thread exits, signal queue memory will be freed by sigqueue_flush. Current, all signals are allowed to be queued, not only realtime signals. Earlier patch reviewed by: jhb, deischen Tested on: i386, amd64
Diffstat (limited to 'sys/arm')
-rw-r--r--sys/arm/arm/machdep.c23
-rw-r--r--sys/arm/arm/trap.c10
-rw-r--r--sys/arm/arm/undefined.c21
3 files changed, 32 insertions, 22 deletions
diff --git a/sys/arm/arm/machdep.c b/sys/arm/arm/machdep.c
index 7043a7b..1e9f5b1 100644
--- a/sys/arm/arm/machdep.c
+++ b/sys/arm/arm/machdep.c
@@ -101,11 +101,10 @@ int _min_memcpy_size = 0;
int _min_bzero_size = 0;
void
-sendsig(catcher, sig, mask, code)
+sendsig(catcher, ksi, mask)
sig_t catcher;
- int sig;
+ ksiginfo_t *ksi;
sigset_t *mask;
- u_long code;
{
struct thread *td = curthread;
struct proc *p = td->td_proc;
@@ -113,9 +112,13 @@ sendsig(catcher, sig, mask, code)
struct sigframe *fp, frame;
struct sigacts *psp = td->td_proc->p_sigacts;
int onstack;
+ int sig;
+ int code;
onstack = sigonstack(td->td_frame->tf_usr_sp);
+ sig = ksi->ksi_signo;
+ code = ksi->ksi_code;
if ((td->td_flags & TDP_ALTSTACK) &&
!(onstack) &&
SIGISMEMBER(td->td_proc->p_sigacts->ps_sigonstack, sig)) {
@@ -130,8 +133,7 @@ sendsig(catcher, sig, mask, code)
/* make the stack aligned */
fp = (struct sigframe *)STACKALIGN(fp);
/* Populate the siginfo frame. */
- frame.sf_si.si_signo = sig;
- frame.sf_si.si_code = code;
+ frame.sf_si = ksi->ksi_info;
frame.sf_uc.uc_sigmask = *mask;
frame.sf_uc.uc_link = NULL;
frame.sf_uc.uc_flags = (td->td_pflags & TDP_ALTSTACK )
@@ -436,17 +438,6 @@ exec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings)
}
/*
- * Build siginfo_t for SA thread
- */
-void
-cpu_thread_siginfo(int sig, u_long code, siginfo_t *si)
-{
- bzero(si, sizeof(*si));
- si->si_signo = sig;
- si->si_code = code;
-}
-
-/*
* Get machine context.
*/
int
diff --git a/sys/arm/arm/trap.c b/sys/arm/arm/trap.c
index 8248783..f858af0 100644
--- a/sys/arm/arm/trap.c
+++ b/sys/arm/arm/trap.c
@@ -184,8 +184,12 @@ static const struct data_abort data_aborts[] = {
static __inline void
call_trapsignal(struct thread *td, int sig, u_long code)
{
+ ksiginfo_t ksi;
- trapsignal(td, sig, code);
+ ksiginfo_init_trap(&ksi);
+ ksi.ksi_signo = sig;
+ ksi.ksi_code = (int)code;
+ trapsignal(td, &ksi);
}
static __inline int
@@ -875,7 +879,7 @@ syscall(struct thread *td, trapframe_t *frame, u_int32_t insn)
nap = 4;
break;
default:
- trapsignal(td, SIGILL, 0);
+ call_trapsignal(td, SIGILL, 0);
userret(td, frame, td->td_sticks);
return;
}
@@ -993,7 +997,7 @@ swi_handler(trapframe_t *frame)
* don't take an alignment fault trying to read the opcode.
*/
if (__predict_false(((frame->tf_pc - INSN_SIZE) & 3) != 0)) {
- trapsignal(td, SIGILL, 0);
+ call_trapsignal(td, SIGILL, 0);
userret(td, frame, td->td_sticks);
return;
}
diff --git a/sys/arm/arm/undefined.c b/sys/arm/arm/undefined.c
index 3d7d3cb..94a3ec1 100644
--- a/sys/arm/arm/undefined.c
+++ b/sys/arm/arm/undefined.c
@@ -134,11 +134,17 @@ static int
gdb_trapper(u_int addr, u_int insn, struct trapframe *frame, int code)
{
struct thread *td;
+ ksiginfo_t ksi;
+
td = (curthread == NULL) ? &thread0 : curthread;
if (insn == GDB_BREAKPOINT || insn == GDB5_BREAKPOINT) {
if (code == FAULT_USER) {
- trapsignal(td, SIGTRAP, 0);
+ ksiginfo_init_trap(&ksi);
+ ksi.ksi_signo = SIGTRAP;
+ ksi.ksi_code = TRAP_BRKPT;
+ ksi.ksi_addr = (u_int32_t *)addr;
+ trapsignal(td, &ksi);
return 0;
}
#if 0
@@ -179,6 +185,7 @@ undefinedinstruction(trapframe_t *frame)
#ifdef VERBOSE_ARM32
int s;
#endif
+ ksiginfo_t ksi;
/* Enable interrupts if they were enabled before the exception. */
if (!(frame->tf_spsr & I32_bit))
@@ -200,7 +207,11 @@ undefinedinstruction(trapframe_t *frame)
* don't take an alignment fault trying to read the opcode.
*/
if (__predict_false((fault_pc & 3) != 0)) {
- trapsignal(td, SIGILL, 0);
+ ksiginfo_init_trap(&ksi);
+ ksi.ksi_signo = SIGILL;
+ ksi.ksi_code = ILL_ILLADR;
+ ksi.ksi_addr = (u_int32_t *)(intptr_t) fault_pc;
+ trapsignal(td, &ksi);
userret(td, frame, 0);
return;
}
@@ -256,7 +267,11 @@ undefinedinstruction(trapframe_t *frame)
if (uh == NULL && (fault_code & FAULT_USER)) {
/* Fault has not been handled */
- trapsignal(td, SIGILL, 0);
+ ksiginfo_init_trap(&ksi);
+ ksi.ksi_signo = SIGILL;
+ ksi.ksi_code = ILL_ILLOPC;
+ ksi.ksi_addr = (u_int32_t *)(intptr_t) fault_pc;
+ trapsignal(td, &ksi);
}
if ((fault_code & FAULT_USER) == 0) {
OpenPOWER on IntegriCloud