/* 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 "../system.h" #include "../ipc.h" #include #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; /* 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", ptproc->p_endpoint); #endif /* 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(&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", 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. */ 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; } /*===========================================================================* * 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; memcpy(privp->s_farmem, from_privp->s_farmem, sizeof(privp->s_farmem)); } /*===========================================================================* * 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 */