diff --git a/kernel/arch/i386/arch_system.c b/kernel/arch/i386/arch_system.c index 376586cd6..15ffa5cd5 100644 --- a/kernel/arch/i386/arch_system.c +++ b/kernel/arch/i386/arch_system.c @@ -491,8 +491,9 @@ void arch_do_syscall(struct proc *proc) /* do_ipc assumes that it's running because of the current process */ assert(proc == get_cpulocal_var(proc_ptr)); /* Make the system call, for real this time. */ + assert(proc->p_misc_flags & MF_SC_DEFER); proc->p_reg.retreg = - do_ipc(proc->p_reg.cx, proc->p_reg.retreg, proc->p_reg.bx); + do_ipc(proc->p_defer.r1, proc->p_defer.r2, proc->p_defer.r3); } struct proc * arch_finish_switch_to_user(void) diff --git a/kernel/proc.c b/kernel/proc.c index 0518551e1..3bdabd25f 100644 --- a/kernel/proc.c +++ b/kernel/proc.c @@ -546,7 +546,11 @@ int do_ipc(reg_t r1, reg_t r2, reg_t r3) * input message. Postpone the entire system call. */ caller_ptr->p_misc_flags &= ~MF_SC_TRACE; + assert(!(caller_ptr->p_misc_flags & MF_SC_DEFER)); caller_ptr->p_misc_flags |= MF_SC_DEFER; + caller_ptr->p_defer.r1 = r1; + caller_ptr->p_defer.r2 = r2; + caller_ptr->p_defer.r3 = r3; /* Signal the "enter system call" event. Block the process. */ cause_sig(proc_nr(caller_ptr), SIGTRAP); diff --git a/kernel/proc.h b/kernel/proc.h index 0d2d9148e..f645d3ea5 100644 --- a/kernel/proc.h +++ b/kernel/proc.h @@ -121,6 +121,11 @@ struct proc { int p_found; /* consistency checking variables */ int p_magic; /* check validity of proc pointers */ + /* if MF_SC_DEFER is set, this struct is valid and contains the + * do_ipc() arguments that are still to be executed + */ + struct { reg_t r1, r2, r3; } p_defer; + #if DEBUG_TRACE int p_schedules; #endif