173 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			173 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* The kernel call implemented in this file:
 | |
|  *   m_type:	SYS_UPDATE
 | |
|  *
 | |
|  * The parameters for this kernel call are:
 | |
|  *    m2_i1:	SYS_UPD_SRC_ENDPT 	(source process endpoint)
 | |
|  *    m2_i2:	SYS_UPD_DST_ENDPT	(destination process endpoint)
 | |
|  */
 | |
| 
 | |
| #include "kernel/system.h"
 | |
| #include "kernel/ipc.h"
 | |
| #include <string.h>
 | |
| 
 | |
| #if USE_UPDATE
 | |
| 
 | |
| #define DEBUG 0
 | |
| 
 | |
| #define proc_is_updatable(p) \
 | |
|     (RTS_ISSET(p, RTS_NO_PRIV) || RTS_ISSET(p, RTS_SIG_PENDING) \
 | |
|     || (RTS_ISSET(p, RTS_RECEIVING) && !RTS_ISSET(p, RTS_SENDING)))
 | |
| 
 | |
| FORWARD _PROTOTYPE(void adjust_proc_slot, (struct proc *rp,
 | |
|     struct proc *from_rp));
 | |
| FORWARD _PROTOTYPE(void adjust_priv_slot, (struct priv *privp,
 | |
|     struct priv *from_privp));
 | |
| FORWARD _PROTOTYPE(void swap_proc_slot_pointer, (struct proc **rpp,
 | |
|     struct proc *src_rp, struct proc *dst_rp));
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *				do_update				     *
 | |
|  *===========================================================================*/
 | |
| PUBLIC int do_update(struct proc * caller, message * m_ptr)
 | |
| {
 | |
| /* Handle sys_update(). Update a process into another by swapping their process
 | |
|  * slots.
 | |
|  */
 | |
|   endpoint_t src_e, dst_e;
 | |
|   int src_p, dst_p;
 | |
|   struct proc *src_rp, *dst_rp;
 | |
|   struct priv *src_privp, *dst_privp;
 | |
|   struct proc orig_src_proc;
 | |
|   struct proc orig_dst_proc;
 | |
|   struct priv orig_src_priv;
 | |
|   struct priv orig_dst_priv;
 | |
|   int i;
 | |
| 
 | |
|   /* Lookup slots for source and destination process. */
 | |
|   src_e = m_ptr->SYS_UPD_SRC_ENDPT;
 | |
|   if(!isokendpt(src_e, &src_p)) {
 | |
|       return EINVAL;
 | |
|   }
 | |
|   src_rp = proc_addr(src_p);
 | |
|   src_privp = priv(src_rp);
 | |
|   if(!(src_privp->s_flags & SYS_PROC)) {
 | |
|       return EPERM;
 | |
|   }
 | |
| 
 | |
|   dst_e = m_ptr->SYS_UPD_DST_ENDPT;
 | |
|   if(!isokendpt(dst_e, &dst_p)) {
 | |
|       return EINVAL;
 | |
|   }
 | |
|   dst_rp = proc_addr(dst_p);
 | |
|   dst_privp = priv(dst_rp);
 | |
|   if(!(dst_privp->s_flags & SYS_PROC)) {
 | |
|       return EPERM;
 | |
|   }
 | |
| 
 | |
|   /* Check if processes are updatable. */
 | |
|   if(!proc_is_updatable(src_rp) || !proc_is_updatable(dst_rp)) {
 | |
|       return EBUSY;
 | |
|   }
 | |
| 
 | |
| #if DEBUG
 | |
|   printf("do_update: updating %d (%s, %d, %d) into %d (%s, %d, %d)\n",
 | |
|       src_rp->p_endpoint, src_rp->p_name, src_rp->p_nr, priv(src_rp)->s_proc_nr,
 | |
|       dst_rp->p_endpoint, dst_rp->p_name, dst_rp->p_nr, priv(dst_rp)->s_proc_nr);
 | |
| 
 | |
|   proc_stacktrace(src_rp);
 | |
|   proc_stacktrace(dst_rp);
 | |
|   printf("do_update: curr ptproc %d\n", get_cpulocal_var(ptproc)->p_endpoint);
 | |
| #endif
 | |
| 
 | |
|   /* Let destination inherit the target mask from source. */
 | |
|   for (i=0; i < NR_SYS_PROCS; i++) {
 | |
|       if (get_sys_bit(priv(src_rp)->s_ipc_to, i)) {
 | |
|           set_sendto_bit(dst_rp, i);
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   /* Save existing data. */
 | |
|   orig_src_proc = *src_rp;
 | |
|   orig_src_priv = *(priv(src_rp));
 | |
|   orig_dst_proc = *dst_rp;
 | |
|   orig_dst_priv = *(priv(dst_rp));
 | |
| 
 | |
|   /* Swap slots. */
 | |
|   *src_rp = orig_dst_proc;
 | |
|   *src_privp = orig_dst_priv;
 | |
|   *dst_rp = orig_src_proc;
 | |
|   *dst_privp = orig_src_priv;
 | |
| 
 | |
|   /* Adjust process slots. */
 | |
|   adjust_proc_slot(src_rp, &orig_src_proc);
 | |
|   adjust_proc_slot(dst_rp, &orig_dst_proc);
 | |
| 
 | |
|   /* Adjust privilege slots. */
 | |
|   adjust_priv_slot(priv(src_rp), &orig_src_priv);
 | |
|   adjust_priv_slot(priv(dst_rp), &orig_dst_priv);
 | |
| 
 | |
|   /* Swap global process slot addresses. */
 | |
|   swap_proc_slot_pointer(get_cpulocal_var_ptr(ptproc), src_rp, dst_rp);
 | |
| 
 | |
|   /* Fix segments. */
 | |
|   alloc_segments(src_rp);
 | |
|   alloc_segments(dst_rp);
 | |
|   prot_init();
 | |
| 
 | |
| #if DEBUG
 | |
|   printf("do_update: updated %d (%s, %d, %d) into %d (%s, %d, %d)\n",
 | |
|       src_rp->p_endpoint, src_rp->p_name, src_rp->p_nr, priv(src_rp)->s_proc_nr,
 | |
|       dst_rp->p_endpoint, dst_rp->p_name, dst_rp->p_nr, priv(dst_rp)->s_proc_nr);
 | |
| 
 | |
|   proc_stacktrace(src_rp);
 | |
|   proc_stacktrace(dst_rp);
 | |
|   printf("do_update: curr ptproc %d\n", get_cpulocal_var(ptproc)->p_endpoint);
 | |
| #endif
 | |
| 
 | |
|   return OK;
 | |
| }
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *			     adjust_proc_slot				     *
 | |
|  *===========================================================================*/
 | |
| PRIVATE void adjust_proc_slot(struct proc *rp, struct proc *from_rp)
 | |
| {
 | |
|   /* Preserve endpoints, slot numbers, priv structure, and IPC. */
 | |
|   rp->p_endpoint = from_rp->p_endpoint;
 | |
|   rp->p_nr = from_rp->p_nr;
 | |
|   rp->p_priv = from_rp->p_priv;
 | |
|   priv(rp)->s_proc_nr = from_rp->p_nr;
 | |
|   rp->p_misc_flags |= (from_rp->p_misc_flags & MF_ASYNMSG);
 | |
|   rp->p_caller_q = from_rp->p_caller_q;
 | |
| }
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *			     adjust_priv_slot				     *
 | |
|  *===========================================================================*/
 | |
| PRIVATE void adjust_priv_slot(struct priv *privp, struct priv *from_privp)
 | |
| {
 | |
|   /* Preserve privilege ids and non-privilege stuff in the priv structure. */
 | |
|   privp->s_id = from_privp->s_id;
 | |
|   privp->s_notify_pending = from_privp->s_notify_pending;
 | |
|   privp->s_int_pending = from_privp->s_int_pending;
 | |
|   privp->s_sig_pending = from_privp->s_sig_pending;
 | |
|   privp->s_alarm_timer = from_privp->s_alarm_timer;
 | |
| }
 | |
| 
 | |
| /*===========================================================================*
 | |
|  *			   swap_proc_slot_pointer			     *
 | |
|  *===========================================================================*/
 | |
| PRIVATE void swap_proc_slot_pointer(struct proc **rpp, struct proc *src_rp,
 | |
|     struct proc *dst_rp)
 | |
| {
 | |
|   if(*rpp == src_rp) {
 | |
|       *rpp = dst_rp;
 | |
|   }
 | |
|   else if(*rpp == dst_rp) {
 | |
|       *rpp = src_rp;
 | |
|   }
 | |
| }
 | |
| 
 | |
| #endif /* USE_UPDATE */
 | |
| 
 | 
