itself before reporting the singal to pm.
#include "debug.h"
#include "kernel.h"
#include "proc.h"
+#include <signal.h>
/* Scheduling and message passing functions. The functions are available to
* other parts of the kernel through lock_...(). The lock temporarily disables
* anywhere in data or stack or gap. It will have to be made more elaborate
* for machines which don't have the gap mapped.
*/
- if (function & CHECK_PTR) {
+ if (function & CHECK_PTR) {
vlo = (vir_bytes) m_ptr >> CLICK_SHIFT;
vhi = ((vir_bytes) m_ptr + MESS_SIZE - 1) >> CLICK_SHIFT;
if (vlo < caller_ptr->p_memmap[D].mem_vir || vlo > vhi ||
/* If the call is to send to a process, i.e., for SEND, SENDREC or NOTIFY,
* verify that the caller is allowed to send to the given destination.
*/
- if (function & CHECK_DST) {
+ if (function & CHECK_DST) {
if (! get_sys_bit(priv(caller_ptr)->s_ipc_to, nr_to_id(src_dst))) {
#if DEBUG_ENABLE_IPC_WARNINGS
kprintf("sys_call: ipc mask denied trap %d from %d to %d\n",
dst_p = _ENDPOINT_P(dst_e);
dst_ptr = proc_addr(dst_p);
+ if (dst_ptr->p_rts_flags & NO_ENDPOINT) return EDSTDIED;
+
/* Check if 'dst' is blocked waiting for this message. The destination's
* SENDING flag may be set when its SENDREC call blocked while sending.
*/
int i, src_id, src_proc_nr, src_p;
if(src_e == ANY) src_p = ANY;
- else okendpt(src_e, &src_p);
+ else
+ {
+ okendpt(src_e, &src_p);
+ if (proc_addr(src_p)->p_rts_flags & NO_ENDPOINT) return ESRCDIED;
+ }
+
/* Check to see if a message from desired source is already available.
* The caller's SENDING flag may be set if SENDREC couldn't send. If it is
#define P_STOP 0x40 /* set when process is being traced */
#define NO_PRIV 0x80 /* keep forked system process from running */
#define NO_PRIORITY 0x100 /* process has been stopped */
+#define NO_ENDPOINT 0x200 /* process cannot send or receive messages */
/* Misc flags */
#define REPLY_PENDING 0x01 /* reply to IPC_REQUEST is pending */
vir_bytes vir_addr, vir_bytes bytes) );
_PROTOTYPE( phys_bytes umap_bios, (struct proc *rp, vir_bytes vir_addr,
vir_bytes bytes) );
+_PROTOTYPE( void clear_endpoint, (struct proc *rc) );
#if (CHIP == INTEL)
* umap_bios: map virtual address in BIOS_SEG to physical
* virtual_copy: copy bytes from one virtual address to another
* get_randomness: accumulate randomness in a buffer
+ * clear_endpoint: remove a process' ability to send and receive messages
*
* Changes:
* Aug 04, 2005 check if system call is allowed (Jorrit N. Herder)
return(OK);
}
+
+/*===========================================================================*
+ * clear_endpoint *
+ *===========================================================================*/
+PUBLIC void clear_endpoint(rc)
+register struct proc *rc; /* slot of process to clean up */
+{
+ register struct proc *rp; /* iterate over process table */
+ register struct proc **xpp; /* iterate over caller queue */
+ int i;
+ int sys_id;
+
+ if(isemptyp(rc)) panic("clear_proc: empty process", proc_nr(rc));
+
+ /* Make sure that the exiting process is no longer scheduled. */
+ if (rc->p_rts_flags == 0) lock_dequeue(rc);
+ rc->p_rts_flags |= NO_ENDPOINT;
+
+ /* If the process happens to be queued trying to send a
+ * message, then it must be removed from the message queues.
+ */
+ if (rc->p_rts_flags & SENDING) {
+ int target_proc;
+
+ okendpt(rc->p_sendto_e, &target_proc);
+ xpp = &proc_addr(target_proc)->p_caller_q; /* destination's queue */
+ while (*xpp != NIL_PROC) { /* check entire queue */
+ if (*xpp == rc) { /* process is on the queue */
+ *xpp = (*xpp)->p_q_link; /* replace by next process */
+#if DEBUG_ENABLE_IPC_WARNINGS
+ kprintf("Proc %d removed from queue at %d\n",
+ proc_nr(rc), rc->p_sendto_e);
+#endif
+ break; /* can only be queued once */
+ }
+ xpp = &(*xpp)->p_q_link; /* proceed to next queued */
+ }
+ rc->p_rts_flags &= ~SENDING;
+ }
+ rc->p_rts_flags &= ~RECEIVING;
+
+ /* Likewise, if another process was sending or receive a message to or from
+ * the exiting process, it must be alerted that process no longer is alive.
+ * Check all processes.
+ */
+ for (rp = BEG_PROC_ADDR; rp < END_PROC_ADDR; rp++) {
+ if(isemptyp(rp))
+ continue;
+
+ /* Unset pending notification bits. */
+ unset_sys_bit(priv(rp)->s_notify_pending, priv(rc)->s_id);
+
+ /* Check if process is receiving from exiting process. */
+ if ((rp->p_rts_flags & RECEIVING) && rp->p_getfrom_e == rc->p_endpoint) {
+ rp->p_reg.retreg = ESRCDIED; /* report source died */
+ rp->p_rts_flags &= ~RECEIVING; /* no longer receiving */
+#if DEBUG_ENABLE_IPC_WARNINGS
+ kprintf("Proc %d receive dead src %d\n", proc_nr(rp), proc_nr(rc));
+#endif
+ if (rp->p_rts_flags == 0) lock_enqueue(rp);/* let process run again */
+ }
+ if ((rp->p_rts_flags & SENDING) && rp->p_sendto_e == rc->p_endpoint) {
+ rp->p_reg.retreg = EDSTDIED; /* report destination died */
+ rp->p_rts_flags &= ~SENDING; /* no longer sending */
+#if DEBUG_ENABLE_IPC_WARNINGS
+ kprintf("Proc %d send dead dst %d\n", proc_nr(rp), proc_nr(rc));
+#endif
+ if (rp->p_rts_flags == 0) lock_enqueue(rp);/* let process run again */
+ }
+ }
+}
+
+
/* Don't clear if already cleared. */
if(isemptyp(rc)) return;
+ /* Remove the process' ability to send and receive messages */
+ clear_endpoint(rc);
+
/* Turn off any alarm timers at the clock. */
reset_timer(&priv(rc)->s_alarm_timer);
rc->p_rts_flags = SLOT_FREE;
if (priv(rc)->s_flags & SYS_PROC) priv(rc)->s_proc_nr = NONE;
- /* If the process being terminated happens to be queued trying to send a
- * message (e.g., the process was killed by a signal, rather than it doing
- * a normal exit), then it must be removed from the message queues.
- */
- if (saved_rts_flags & SENDING) {
- int target_proc;
- okendpt(rc->p_sendto_e, &target_proc);
- xpp = &proc_addr(target_proc)->p_caller_q; /* destination's queue */
- while (*xpp != NIL_PROC) { /* check entire queue */
- if (*xpp == rc) { /* process is on the queue */
- *xpp = (*xpp)->p_q_link; /* replace by next process */
-#if DEBUG_ENABLE_IPC_WARNINGS
- kprintf("Proc %d removed from queue at %d\n",
- proc_nr(rc), rc->p_sendto_e);
-#endif
- break; /* can only be queued once */
- }
- xpp = &(*xpp)->p_q_link; /* proceed to next queued */
- }
- }
-
- /* Likewise, if another process was sending or receive a message to or from
- * the exiting process, it must be alerted that process no longer is alive.
- * Check all processes.
- */
- for (rp = BEG_PROC_ADDR; rp < END_PROC_ADDR; rp++) {
- if(isemptyp(rp))
- continue;
-
- /* Unset pending notification bits. */
- unset_sys_bit(priv(rp)->s_notify_pending, priv(rc)->s_id);
-
- /* Check if process is receiving from exiting process. */
- if ((rp->p_rts_flags & RECEIVING) && rp->p_getfrom_e == rc->p_endpoint) {
- rp->p_reg.retreg = ESRCDIED; /* report source died */
- rp->p_rts_flags &= ~RECEIVING; /* no longer receiving */
-#if DEBUG_ENABLE_IPC_WARNINGS
- kprintf("Proc %d receive dead src %d\n", proc_nr(rp), proc_nr(rc));
-#endif
- if (rp->p_rts_flags == 0) lock_enqueue(rp);/* let process run again */
- }
- if ((rp->p_rts_flags & SENDING) && rp->p_sendto_e == rc->p_endpoint) {
- rp->p_reg.retreg = EDSTDIED; /* report destination died */
- rp->p_rts_flags &= ~SENDING; /* no longer sending */
-#if DEBUG_ENABLE_IPC_WARNINGS
- kprintf("Proc %d send dead dst %d\n", proc_nr(rp), proc_nr(rc));
-#endif
- if (rp->p_rts_flags == 0) lock_enqueue(rp);/* let process run again */
- }
- }
-
/* Clean up virtual memory */
if (rc->p_misc_flags & MF_VM)
vm_map_default(rc);
* are usually blocked on a RECEIVE), they can request the PM to transform
* signals into messages. This is done by the PM with a call to sys_kill().
*/
- proc_nr_t proc_nr;
+ proc_nr_t proc_nr, proc_nr_e;
int sig_nr = m_ptr->SIG_NUMBER;
- if (!isokendpt(m_ptr->SIG_ENDPT, &proc_nr)) return(EINVAL);
+ proc_nr_e= m_ptr->SIG_ENDPT;
+
+ if (proc_nr_e == SELF)
+ proc_nr_e= m_ptr->m_source;
+
+ if (!isokendpt(proc_nr_e, &proc_nr)) return(EINVAL);
+
if (sig_nr > _NSIG) return(EINVAL);
if (iskerneln(proc_nr)) return(EPERM);
/* Set pending signal to be processed by the PM. */
cause_sig(proc_nr, sig_nr);
+ if (sig_nr == SIGKILL)
+ clear_endpoint(proc_addr(proc_nr));
return(OK);
}