system.c

Go to the documentation of this file.
00001 /* This task handles the interface between the kernel and user-level servers.
00002  * System services can be accessed by doing a system call. System calls are 
00003  * transformed into request messages, which are handled by this task. By 
00004  * convention, a sys_call() is transformed in a SYS_CALL request message that
00005  * is handled in a function named do_call(). 
00006  *
00007  * A private call vector is used to map all system calls to the functions that
00008  * handle them. The actual handler functions are contained in separate files
00009  * to keep this file clean. The call vector is used in the system task's main
00010  * loop to handle all incoming requests.  
00011  *
00012  * In addition to the main sys_task() entry point, which starts the main loop,
00013  * there are several other minor entry points:
00014  *   get_priv:          assign privilege structure to user or system process
00015  *   send_sig:          send a signal directly to a system process
00016  *   cause_sig:         take action to cause a signal to occur via PM
00017  *   umap_local:        map virtual address in LOCAL_SEG to physical 
00018  *   umap_remote:       map virtual address in REMOTE_SEG to physical 
00019  *   umap_bios:         map virtual address in BIOS_SEG to physical 
00020  *   virtual_copy:      copy bytes from one virtual address to another 
00021  *   get_randomness:    accumulate randomness in a buffer
00022  *   clear_endpoint:    remove a process' ability to send and receive messages
00023  *
00024  * Changes:
00025  *   Aug 04, 2005   check if system call is allowed  (Jorrit N. Herder)
00026  *   Jul 20, 2005   send signal to services with message  (Jorrit N. Herder) 
00027  *   Jan 15, 2005   new, generalized virtual copy function  (Jorrit N. Herder)
00028  *   Oct 10, 2004   dispatch system calls from call vector  (Jorrit N. Herder)
00029  *   Sep 30, 2004   source code documentation updated  (Jorrit N. Herder)
00030  */
00031 
00032 #include "debug.h"
00033 #include "kernel.h"
00034 #include "system.h"
00035 #include <stdlib.h>
00036 #include <signal.h>
00037 #include <unistd.h>
00038 #include <sys/sigcontext.h>
00039 #include <minix/endpoint.h>
00040 #if (CHIP == INTEL)
00041 #include <ibm/memory.h>
00042 #include "protect.h"
00043 #endif
00044 
00045 /* Declaration of the call vector that defines the mapping of system calls 
00046  * to handler functions. The vector is initialized in sys_init() with map(), 
00047  * which makes sure the system call numbers are ok. No space is allocated, 
00048  * because the dummy is declared extern. If an illegal call is given, the 
00049  * array size will be negative and this won't compile. 
00050  */
00051 PUBLIC int (*call_vec[NR_SYS_CALLS])(message *m_ptr);
00052 
00053 #define map(call_nr, handler) \
00054     {extern int dummy[NR_SYS_CALLS>(unsigned)(call_nr-KERNEL_CALL) ? 1:-1];} \
00055     call_vec[(call_nr-KERNEL_CALL)] = (handler)  
00056 
00057 FORWARD _PROTOTYPE( void initialize, (void));
00058 
00059 /*===========================================================================*
00060  *                              sys_task                                     *
00061  *===========================================================================*/
00062 PUBLIC void sys_task()
00063 {
00064 /* Main entry point of sys_task.  Get the message and dispatch on type. */
00065   static message m;
00066   register int result;
00067   register struct proc *caller_ptr;
00068   unsigned int call_nr;
00069   int s;
00070 
00071   /* Initialize the system task. */
00072   initialize();
00073 
00074   while (TRUE) {
00075       /* Get work. Block and wait until a request message arrives. */
00076       receive(ANY, &m);                 
00077       call_nr = (unsigned) m.m_type - KERNEL_CALL;      
00078       who_e = m.m_source;
00079       okendpt(who_e, &who_p);
00080       caller_ptr = proc_addr(who_p);
00081 
00082       /* See if the caller made a valid request and try to handle it. */
00083       if (! (priv(caller_ptr)->s_call_mask & (1<<call_nr))) {
00084 #if DEBUG_ENABLE_IPC_WARNINGS
00085           kprintf("SYSTEM: request %d from %d denied.\n", call_nr,m.m_source);
00086 #endif
00087           result = ECALLDENIED;                 /* illegal message type */
00088       } else if (call_nr >= NR_SYS_CALLS) {             /* check call number */
00089 #if DEBUG_ENABLE_IPC_WARNINGS
00090           kprintf("SYSTEM: illegal request %d from %d.\n", call_nr,m.m_source);
00091 #endif
00092           result = EBADREQUEST;                 /* illegal message type */
00093       } 
00094       else {
00095           result = (*call_vec[call_nr])(&m);    /* handle the system call */
00096       }
00097 
00098       /* Send a reply, unless inhibited by a handler function. Use the kernel
00099        * function lock_send() to prevent a system call trap. The destination
00100        * is known to be blocked waiting for a message.
00101        */
00102       if (result != EDONTREPLY) {
00103           m.m_type = result;                    /* report status of call */
00104           if (OK != (s=lock_send(m.m_source, &m))) {
00105               kprintf("SYSTEM, reply to %d failed: %d\n", m.m_source, s);
00106           }
00107       }
00108   }
00109 }
00110 
00111 /*===========================================================================*
00112  *                              initialize                                   *
00113  *===========================================================================*/
00114 PRIVATE void initialize(void)
00115 {
00116   register struct priv *sp;
00117   int i;
00118 
00119   /* Initialize IRQ handler hooks. Mark all hooks available. */
00120   for (i=0; i<NR_IRQ_HOOKS; i++) {
00121       irq_hooks[i].proc_nr_e = NONE;
00122   }
00123 
00124   /* Initialize all alarm timers for all processes. */
00125   for (sp=BEG_PRIV_ADDR; sp < END_PRIV_ADDR; sp++) {
00126     tmr_inittimer(&(sp->s_alarm_timer));
00127   }
00128 
00129   /* Initialize the call vector to a safe default handler. Some system calls 
00130    * may be disabled or nonexistant. Then explicitely map known calls to their
00131    * handler functions. This is done with a macro that gives a compile error
00132    * if an illegal call number is used. The ordering is not important here.
00133    */
00134   for (i=0; i<NR_SYS_CALLS; i++) {
00135       call_vec[i] = do_unused;
00136   }
00137 
00138   /* Process management. */
00139   map(SYS_FORK, do_fork);               /* a process forked a new process */
00140   map(SYS_EXEC, do_exec);               /* update process after execute */
00141   map(SYS_EXIT, do_exit);               /* clean up after process exit */
00142   map(SYS_NICE, do_nice);               /* set scheduling priority */
00143   map(SYS_PRIVCTL, do_privctl);         /* system privileges control */
00144   map(SYS_TRACE, do_trace);             /* request a trace operation */
00145 
00146   /* Signal handling. */
00147   map(SYS_KILL, do_kill);               /* cause a process to be signaled */
00148   map(SYS_GETKSIG, do_getksig);         /* PM checks for pending signals */
00149   map(SYS_ENDKSIG, do_endksig);         /* PM finished processing signal */
00150   map(SYS_SIGSEND, do_sigsend);         /* start POSIX-style signal */
00151   map(SYS_SIGRETURN, do_sigreturn);     /* return from POSIX-style signal */
00152 
00153   /* Device I/O. */
00154   map(SYS_IRQCTL, do_irqctl);           /* interrupt control operations */ 
00155   map(SYS_DEVIO, do_devio);             /* inb, inw, inl, outb, outw, outl */ 
00156   map(SYS_SDEVIO, do_sdevio);           /* phys_insb, _insw, _outsb, _outsw */
00157   map(SYS_VDEVIO, do_vdevio);           /* vector with devio requests */ 
00158   map(SYS_INT86, do_int86);             /* real-mode BIOS calls */ 
00159 
00160   /* Memory management. */
00161   map(SYS_NEWMAP, do_newmap);           /* set up a process memory map */
00162   map(SYS_SEGCTL, do_segctl);           /* add segment and get selector */
00163   map(SYS_MEMSET, do_memset);           /* write char to memory area */
00164   map(SYS_VM_SETBUF, do_vm_setbuf);     /* PM passes buffer for page tables */
00165   map(SYS_VM_MAP, do_vm_map);           /* Map/unmap physical (device) memory */
00166 
00167   /* Copying. */
00168   map(SYS_UMAP, do_umap);               /* map virtual to physical address */
00169   map(SYS_VIRCOPY, do_vircopy);         /* use pure virtual addressing */
00170   map(SYS_PHYSCOPY, do_physcopy);       /* use physical addressing */
00171   map(SYS_VIRVCOPY, do_virvcopy);       /* vector with copy requests */
00172   map(SYS_PHYSVCOPY, do_physvcopy);     /* vector with copy requests */
00173 
00174   /* Clock functionality. */
00175   map(SYS_TIMES, do_times);             /* get uptime and process times */
00176   map(SYS_SETALARM, do_setalarm);       /* schedule a synchronous alarm */
00177 
00178   /* System control. */
00179   map(SYS_ABORT, do_abort);             /* abort MINIX */
00180   map(SYS_GETINFO, do_getinfo);         /* request system information */ 
00181   map(SYS_IOPENABLE, do_iopenable);     /* Enable I/O */
00182 }
00183 
00184 /*===========================================================================*
00185  *                              get_priv                                     *
00186  *===========================================================================*/
00187 PUBLIC int get_priv(rc, proc_type)
00188 register struct proc *rc;               /* new (child) process pointer */
00189 int proc_type;                          /* system or user process flag */
00190 {
00191 /* Get a privilege structure. All user processes share the same privilege 
00192  * structure. System processes get their own privilege structure. 
00193  */
00194   register struct priv *sp;                     /* privilege structure */
00195 
00196   if (proc_type == SYS_PROC) {                  /* find a new slot */
00197       for (sp = BEG_PRIV_ADDR; sp < END_PRIV_ADDR; ++sp) 
00198           if (sp->s_proc_nr == NONE && sp->s_id != USER_PRIV_ID) break; 
00199       if (sp->s_proc_nr != NONE) return(ENOSPC);
00200       rc->p_priv = sp;                          /* assign new slot */
00201       rc->p_priv->s_proc_nr = proc_nr(rc);      /* set association */
00202       rc->p_priv->s_flags = SYS_PROC;           /* mark as privileged */
00203   } else {
00204       rc->p_priv = &priv[USER_PRIV_ID];         /* use shared slot */
00205       rc->p_priv->s_proc_nr = INIT_PROC_NR;     /* set association */
00206       rc->p_priv->s_flags = 0;                  /* no initial flags */
00207   }
00208   return(OK);
00209 }
00210 
00211 /*===========================================================================*
00212  *                              get_randomness                               *
00213  *===========================================================================*/
00214 PUBLIC void get_randomness(source)
00215 int source;
00216 {
00217 /* On machines with the RDTSC (cycle counter read instruction - pentium
00218  * and up), use that for high-resolution raw entropy gathering. Otherwise,
00219  * use the realtime clock (tick resolution).
00220  *
00221  * Unfortunately this test is run-time - we don't want to bother with
00222  * compiling different kernels for different machines.
00223  *
00224  * On machines without RDTSC, we use read_clock().
00225  */
00226   int r_next;
00227   unsigned long tsc_high, tsc_low;
00228 
00229   source %= RANDOM_SOURCES;
00230   r_next= krandom.bin[source].r_next;
00231   if (machine.processor > 486) {
00232       read_tsc(&tsc_high, &tsc_low);
00233       krandom.bin[source].r_buf[r_next] = tsc_low;
00234   } else {
00235       krandom.bin[source].r_buf[r_next] = read_clock();
00236   }
00237   if (krandom.bin[source].r_size < RANDOM_ELEMENTS) {
00238         krandom.bin[source].r_size ++;
00239   }
00240   krandom.bin[source].r_next = (r_next + 1 ) % RANDOM_ELEMENTS;
00241 }
00242 
00243 /*===========================================================================*
00244  *                              send_sig                                     *
00245  *===========================================================================*/
00246 PUBLIC void send_sig(int proc_nr, int sig_nr)
00247 {
00248 /* Notify a system process about a signal. This is straightforward. Simply
00249  * set the signal that is to be delivered in the pending signals map and 
00250  * send a notification with source SYSTEM.
00251  *
00252  * Process number is verified to avoid writing in random places, but we
00253  * don't kprintf() or panic() because that causes send_sig() invocations.
00254  */ 
00255   register struct proc *rp;
00256   static int n;
00257 
00258   if(!isokprocn(proc_nr) || isemptyn(proc_nr))
00259         return;
00260 
00261   rp = proc_addr(proc_nr);
00262   sigaddset(&priv(rp)->s_sig_pending, sig_nr);
00263   lock_notify(SYSTEM, rp->p_endpoint); 
00264 }
00265 
00266 /*===========================================================================*
00267  *                              cause_sig                                    *
00268  *===========================================================================*/
00269 PUBLIC void cause_sig(proc_nr, sig_nr)
00270 int proc_nr;                    /* process to be signalled */
00271 int sig_nr;                     /* signal to be sent, 1 to _NSIG */
00272 {
00273 /* A system process wants to send a signal to a process.  Examples are:
00274  *  - HARDWARE wanting to cause a SIGSEGV after a CPU exception
00275  *  - TTY wanting to cause SIGINT upon getting a DEL
00276  *  - FS wanting to cause SIGPIPE for a broken pipe 
00277  * Signals are handled by sending a message to PM.  This function handles the 
00278  * signals and makes sure the PM gets them by sending a notification. The 
00279  * process being signaled is blocked while PM has not finished all signals 
00280  * for it. 
00281  * Race conditions between calls to this function and the system calls that
00282  * process pending kernel signals cannot exist. Signal related functions are
00283  * only called when a user process causes a CPU exception and from the kernel 
00284  * process level, which runs to completion.
00285  */
00286   register struct proc *rp;
00287 
00288   /* Check if the signal is already pending. Process it otherwise. */
00289   rp = proc_addr(proc_nr);
00290   if (! sigismember(&rp->p_pending, sig_nr)) {
00291       sigaddset(&rp->p_pending, sig_nr);
00292       if (! (rp->p_rts_flags & SIGNALED)) {             /* other pending */
00293           if (rp->p_rts_flags == 0) lock_dequeue(rp);   /* make not ready */
00294           rp->p_rts_flags |= SIGNALED | SIG_PENDING;    /* update flags */
00295           send_sig(PM_PROC_NR, SIGKSIG);
00296       }
00297   }
00298 }
00299 
00300 /*===========================================================================*
00301  *                              umap_bios                                    *
00302  *===========================================================================*/
00303 PUBLIC phys_bytes umap_bios(rp, vir_addr, bytes)
00304 register struct proc *rp;       /* pointer to proc table entry for process */
00305 vir_bytes vir_addr;             /* virtual address in BIOS segment */
00306 vir_bytes bytes;                /* # of bytes to be copied */
00307 {
00308 /* Calculate the physical memory address at the BIOS. Note: currently, BIOS
00309  * address zero (the first BIOS interrupt vector) is not considered, as an 
00310  * error here, but since the physical address will be zero as well, the 
00311  * calling function will think an error occurred. This is not a problem,
00312  * since no one uses the first BIOS interrupt vector.  
00313  */
00314 
00315   /* Check all acceptable ranges. */
00316   if (vir_addr >= BIOS_MEM_BEGIN && vir_addr + bytes <= BIOS_MEM_END)
00317         return (phys_bytes) vir_addr;
00318   else if (vir_addr >= BASE_MEM_TOP && vir_addr + bytes <= UPPER_MEM_END)
00319         return (phys_bytes) vir_addr;
00320 
00321 #if DEAD_CODE   /* brutal fix, if the above is too restrictive */
00322   if (vir_addr >= BIOS_MEM_BEGIN && vir_addr + bytes <= UPPER_MEM_END)
00323         return (phys_bytes) vir_addr;
00324 #endif
00325 
00326   kprintf("Warning, error in umap_bios, virtual address 0x%x\n", vir_addr);
00327   return 0;
00328 }
00329 
00330 /*===========================================================================*
00331  *                              umap_local                                   *
00332  *===========================================================================*/
00333 PUBLIC phys_bytes umap_local(rp, seg, vir_addr, bytes)
00334 register struct proc *rp;       /* pointer to proc table entry for process */
00335 int seg;                        /* T, D, or S segment */
00336 vir_bytes vir_addr;             /* virtual address in bytes within the seg */
00337 vir_bytes bytes;                /* # of bytes to be copied */
00338 {
00339 /* Calculate the physical memory address for a given virtual address. */
00340   vir_clicks vc;                /* the virtual address in clicks */
00341   phys_bytes pa;                /* intermediate variables as phys_bytes */
00342 #if (CHIP == INTEL)
00343   phys_bytes seg_base;
00344 #endif
00345 
00346   /* If 'seg' is D it could really be S and vice versa.  T really means T.
00347    * If the virtual address falls in the gap,  it causes a problem. On the
00348    * 8088 it is probably a legal stack reference, since "stackfaults" are
00349    * not detected by the hardware.  On 8088s, the gap is called S and
00350    * accepted, but on other machines it is called D and rejected.
00351    * The Atari ST behaves like the 8088 in this respect.
00352    */
00353 
00354   if (bytes <= 0) return( (phys_bytes) 0);
00355   if (vir_addr + bytes <= vir_addr) return 0;   /* overflow */
00356   vc = (vir_addr + bytes - 1) >> CLICK_SHIFT;   /* last click of data */
00357 
00358 #if (CHIP == INTEL) || (CHIP == M68000)
00359   if (seg != T)
00360         seg = (vc < rp->p_memmap[D].mem_vir + rp->p_memmap[D].mem_len ? D : S);
00361 #else
00362   if (seg != T)
00363         seg = (vc < rp->p_memmap[S].mem_vir ? D : S);
00364 #endif
00365 
00366   if ((vir_addr>>CLICK_SHIFT) >= rp->p_memmap[seg].mem_vir + 
00367         rp->p_memmap[seg].mem_len) return( (phys_bytes) 0 );
00368 
00369   if (vc >= rp->p_memmap[seg].mem_vir + 
00370         rp->p_memmap[seg].mem_len) return( (phys_bytes) 0 );
00371 
00372 #if (CHIP == INTEL)
00373   seg_base = (phys_bytes) rp->p_memmap[seg].mem_phys;
00374   seg_base = seg_base << CLICK_SHIFT;   /* segment origin in bytes */
00375 #endif
00376   pa = (phys_bytes) vir_addr;
00377 #if (CHIP != M68000)
00378   pa -= rp->p_memmap[seg].mem_vir << CLICK_SHIFT;
00379   return(seg_base + pa);
00380 #endif
00381 #if (CHIP == M68000)
00382   pa -= (phys_bytes)rp->p_memmap[seg].mem_vir << CLICK_SHIFT;
00383   pa += (phys_bytes)rp->p_memmap[seg].mem_phys << CLICK_SHIFT;
00384   return(pa);
00385 #endif
00386 }
00387 
00388 /*===========================================================================*
00389  *                              umap_remote                                  *
00390  *===========================================================================*/
00391 PUBLIC phys_bytes umap_remote(rp, seg, vir_addr, bytes)
00392 register struct proc *rp;       /* pointer to proc table entry for process */
00393 int seg;                        /* index of remote segment */
00394 vir_bytes vir_addr;             /* virtual address in bytes within the seg */
00395 vir_bytes bytes;                /* # of bytes to be copied */
00396 {
00397 /* Calculate the physical memory address for a given virtual address. */
00398   struct far_mem *fm;
00399 
00400   if (bytes <= 0) return( (phys_bytes) 0);
00401   if (seg < 0 || seg >= NR_REMOTE_SEGS) return( (phys_bytes) 0);
00402 
00403   fm = &rp->p_priv->s_farmem[seg];
00404   if (! fm->in_use) return( (phys_bytes) 0);
00405   if (vir_addr + bytes > fm->mem_len) return( (phys_bytes) 0);
00406 
00407   return(fm->mem_phys + (phys_bytes) vir_addr); 
00408 }
00409 
00410 /*===========================================================================*
00411  *                              virtual_copy                                 *
00412  *===========================================================================*/
00413 PUBLIC int virtual_copy(src_addr, dst_addr, bytes)
00414 struct vir_addr *src_addr;      /* source virtual address */
00415 struct vir_addr *dst_addr;      /* destination virtual address */
00416 vir_bytes bytes;                /* # of bytes to copy  */
00417 {
00418 /* Copy bytes from virtual address src_addr to virtual address dst_addr. 
00419  * Virtual addresses can be in ABS, LOCAL_SEG, REMOTE_SEG, or BIOS_SEG.
00420  */
00421   struct vir_addr *vir_addr[2]; /* virtual source and destination address */
00422   phys_bytes phys_addr[2];      /* absolute source and destination */ 
00423   int seg_index;
00424   int i;
00425 
00426   /* Check copy count. */
00427   if (bytes <= 0) return(EDOM);
00428 
00429   /* Do some more checks and map virtual addresses to physical addresses. */
00430   vir_addr[_SRC_] = src_addr;
00431   vir_addr[_DST_] = dst_addr;
00432   for (i=_SRC_; i<=_DST_; i++) {
00433         int proc_nr, type;
00434         struct proc *p;
00435 
00436         type = vir_addr[i]->segment & SEGMENT_TYPE;
00437         if(type != PHYS_SEG && isokendpt(vir_addr[i]->proc_nr_e, &proc_nr))
00438            p = proc_addr(proc_nr);
00439         else
00440            p = NULL;
00441 
00442       /* Get physical address. */
00443       switch(type) {
00444       case LOCAL_SEG:
00445           if(!p) return EDEADSRCDST;
00446           seg_index = vir_addr[i]->segment & SEGMENT_INDEX;
00447           phys_addr[i] = umap_local(p, seg_index, vir_addr[i]->offset, bytes);
00448           break;
00449       case REMOTE_SEG:
00450           if(!p) return EDEADSRCDST;
00451           seg_index = vir_addr[i]->segment & SEGMENT_INDEX;
00452           phys_addr[i] = umap_remote(p, seg_index, vir_addr[i]->offset, bytes);
00453           break;
00454       case BIOS_SEG:
00455           if(!p) return EDEADSRCDST;
00456           phys_addr[i] = umap_bios(p, vir_addr[i]->offset, bytes );
00457           break;
00458       case PHYS_SEG:
00459           phys_addr[i] = vir_addr[i]->offset;
00460           break;
00461       default:
00462           return(EINVAL);
00463       }
00464 
00465       /* Check if mapping succeeded. */
00466       if (phys_addr[i] <= 0 && vir_addr[i]->segment != PHYS_SEG) 
00467           return(EFAULT);
00468   }
00469 
00470   /* Now copy bytes between physical addresseses. */
00471   phys_copy(phys_addr[_SRC_], phys_addr[_DST_], (phys_bytes) bytes);
00472   return(OK);
00473 }
00474 
00475 
00476 /*===========================================================================*
00477  *                               clear_endpoint                              *
00478  *===========================================================================*/
00479 PUBLIC void clear_endpoint(rc)
00480 register struct proc *rc;               /* slot of process to clean up */
00481 {
00482   register struct proc *rp;             /* iterate over process table */
00483   register struct proc **xpp;           /* iterate over caller queue */
00484   int i;
00485   int sys_id;
00486 
00487   if(isemptyp(rc)) panic("clear_proc: empty process", proc_nr(rc));
00488 
00489   /* Make sure that the exiting process is no longer scheduled. */
00490   if (rc->p_rts_flags == 0) lock_dequeue(rc);
00491   rc->p_rts_flags |= NO_ENDPOINT;
00492 
00493   /* If the process happens to be queued trying to send a
00494    * message, then it must be removed from the message queues.
00495    */
00496   if (rc->p_rts_flags & SENDING) {
00497       int target_proc;
00498 
00499       okendpt(rc->p_sendto_e, &target_proc);
00500       xpp = &proc_addr(target_proc)->p_caller_q; /* destination's queue */
00501       while (*xpp != NIL_PROC) {                /* check entire queue */
00502           if (*xpp == rc) {                     /* process is on the queue */
00503               *xpp = (*xpp)->p_q_link;          /* replace by next process */
00504 #if DEBUG_ENABLE_IPC_WARNINGS
00505               kprintf("Proc %d removed from queue at %d\n",
00506                   proc_nr(rc), rc->p_sendto_e);
00507 #endif
00508               break;                            /* can only be queued once */
00509           }
00510           xpp = &(*xpp)->p_q_link;              /* proceed to next queued */
00511       }
00512       rc->p_rts_flags &= ~SENDING;
00513   }
00514   rc->p_rts_flags &= ~RECEIVING;
00515 
00516   /* Likewise, if another process was sending or receive a message to or from 
00517    * the exiting process, it must be alerted that process no longer is alive.
00518    * Check all processes. 
00519    */
00520   for (rp = BEG_PROC_ADDR; rp < END_PROC_ADDR; rp++) {
00521       if(isemptyp(rp))
00522         continue;
00523 
00524       /* Unset pending notification bits. */
00525       unset_sys_bit(priv(rp)->s_notify_pending, priv(rc)->s_id);
00526 
00527       /* Check if process is receiving from exiting process. */
00528       if ((rp->p_rts_flags & RECEIVING) && rp->p_getfrom_e == rc->p_endpoint) {
00529           rp->p_reg.retreg = ESRCDIED;          /* report source died */
00530           rp->p_rts_flags &= ~RECEIVING;        /* no longer receiving */
00531 #if DEBUG_ENABLE_IPC_WARNINGS
00532           kprintf("Proc %d receive dead src %d\n", proc_nr(rp), proc_nr(rc));
00533 #endif
00534           if (rp->p_rts_flags == 0) lock_enqueue(rp);/* let process run again */
00535       } 
00536       if ((rp->p_rts_flags & SENDING) && rp->p_sendto_e == rc->p_endpoint) {
00537           rp->p_reg.retreg = EDSTDIED;          /* report destination died */
00538           rp->p_rts_flags &= ~SENDING;          /* no longer sending */
00539 #if DEBUG_ENABLE_IPC_WARNINGS
00540           kprintf("Proc %d send dead dst %d\n", proc_nr(rp), proc_nr(rc));
00541 #endif
00542           if (rp->p_rts_flags == 0) lock_enqueue(rp);/* let process run again */
00543       } 
00544   }
00545 }
00546 
00547 

Generated on Fri Apr 14 22:56:37 2006 for minix by  doxygen 1.4.6