1 /* The kernel call that is implemented in this file:
4 * The parameters for this kernel call are:
5 * m2_i1: SIG_ENDPT # process to call signal handler
6 * m2_p1: SIG_CTXT_PTR # pointer to sigcontext structure
7 * m2_i3: SIG_FLAGS # flags for S_SIGRETURN call
11 #include "kernel/system.h"
17 /*===========================================================================*
19 *===========================================================================*/
20 int do_sigsend(struct proc
* caller
, message
* m_ptr
)
22 /* Handle sys_sigsend, POSIX-style signal handling. */
25 register struct proc
*rp
;
26 struct sigcontext sc
, *scp
;
27 struct sigframe fr
, *frp
;
30 if (!isokendpt(m_ptr
->SIG_ENDPT
, &proc_nr
)) return(EINVAL
);
31 if (iskerneln(proc_nr
)) return(EPERM
);
32 rp
= proc_addr(proc_nr
);
34 /* Get the sigmsg structure into our address space. */
35 if((r
=data_copy_vmcheck(caller
, caller
->p_endpoint
,
36 (vir_bytes
) m_ptr
->SIG_CTXT_PTR
, KERNEL
, (vir_bytes
) &smsg
,
37 (phys_bytes
) sizeof(struct sigmsg
))) != OK
)
40 /* Compute the user stack pointer where sigcontext will be stored. */
41 smsg
.sm_stkptr
= arch_get_sp(rp
);
42 scp
= (struct sigcontext
*) smsg
.sm_stkptr
- 1;
44 /* Copy the registers to the sigcontext structure. */
45 memcpy(&sc
.sc_regs
, (char *) &rp
->p_reg
, sizeof(sigregs
));
48 sc
.trap_style
= rp
->p_seg
.p_kern_trap_style
;
50 if(sc
.trap_style
== KTS_NONE
) {
51 printf("do_sigsend: sigsend an unsaved process\n");
55 if(proc_used_fpu(rp
)) {
56 /* save the FPU context before saving it to the sig context */
58 memcpy(&sc
.sc_fpu_state
, rp
->p_seg
.fpu_state
, FPU_XFP_SIZE
);
62 /* Finish the sigcontext initialization. */
63 sc
.sc_mask
= smsg
.sm_mask
;
64 sc
.sc_flags
= rp
->p_misc_flags
& MF_FPU_INITIALIZED
;
66 /* Copy the sigcontext structure to the user's stack. */
67 if((r
=data_copy_vmcheck(caller
, KERNEL
, (vir_bytes
) &sc
, m_ptr
->SIG_ENDPT
,
68 (vir_bytes
) scp
, (vir_bytes
) sizeof(struct sigcontext
))) != OK
)
71 /* Initialize the sigframe structure. */
72 frp
= (struct sigframe
*) scp
- 1;
74 fr
.sf_retadr2
= (void (*)()) rp
->p_reg
.pc
;
75 fr
.sf_fp
= rp
->p_reg
.fp
;
76 rp
->p_reg
.fp
= (reg_t
) &frp
->sf_fp
;
79 fpu_sigcontext(rp
, &fr
, &sc
);
81 fr
.sf_signo
= smsg
.sm_signo
;
82 fr
.sf_retadr
= (void (*)()) smsg
.sm_sigreturn
;
85 /* use the ARM link register to set the return address from the signal
88 rp
->p_reg
.lr
= (reg_t
) fr
.sf_retadr
;
89 if(rp
->p_reg
.lr
& 1) { printf("sigsend: LSB LR makes no sense.\n"); }
91 /* pass signal handler parameters in registers */
92 rp
->p_reg
.retreg
= (reg_t
) fr
.sf_signo
;
93 rp
->p_reg
.r1
= (reg_t
) fr
.sf_code
;
94 rp
->p_reg
.r2
= (reg_t
) fr
.sf_scp
;
95 rp
->p_misc_flags
|= MF_CONTEXT_SET
;
98 /* Copy the sigframe structure to the user's stack. */
99 if((r
=data_copy_vmcheck(caller
, KERNEL
, (vir_bytes
) &fr
,
100 m_ptr
->SIG_ENDPT
, (vir_bytes
) frp
,
101 (vir_bytes
) sizeof(struct sigframe
))) != OK
)
104 /* Reset user registers to execute the signal handler. */
105 rp
->p_reg
.sp
= (reg_t
) frp
;
106 rp
->p_reg
.pc
= (reg_t
) smsg
.sm_sighandler
;
108 /* Signal handler should get clean FPU. */
109 rp
->p_misc_flags
&= ~MF_FPU_INITIALIZED
;
111 if(!RTS_ISSET(rp
, RTS_PROC_STOP
)) {
112 printf("system: warning: sigsend a running process\n");
113 printf("caller stack: ");
114 proc_stacktrace(caller
);
120 #endif /* USE_SIGSEND */