From 85c3fce1a7fb3a166fcf9a229c7c00a76b17a21d Mon Sep 17 00:00:00 2001 From: Xiaoguang Sun Date: Thu, 6 Jun 2013 23:13:06 +0000 Subject: [PATCH] Add ipc messages, signals, context switches usage Add ipc messages, signals, context switches usage to kernel --- kernel/proc.c | 75 ++++++++++++++++++++++++++++++++++++----- kernel/proc.h | 6 ++++ kernel/proto.h | 2 ++ kernel/system.c | 2 ++ kernel/system/do_fork.c | 2 ++ 5 files changed, 78 insertions(+), 9 deletions(-) diff --git a/kernel/proc.c b/kernel/proc.c index 6dcaf9125..39f4a321c 100644 --- a/kernel/proc.c +++ b/kernel/proc.c @@ -61,6 +61,9 @@ static int try_one(struct proc *src_ptr, struct proc *dst_ptr); static struct proc * pick_proc(void); static void enqueue_head(struct proc *rp); +static void increase_context_switch_count(struct proc *rp); +static void increase_messages_count(struct proc *from, struct proc *to); + /* all idles share the same idle_priv structure */ static struct priv idle_priv; @@ -129,6 +132,7 @@ void proc_init(void) rp->p_scheduler = NULL; /* no user space scheduler */ rp->p_priority = 0; /* no priority */ rp->p_quantum_size_ms = 0; /* no quantum size */ + reset_proc_rusage(rp); /* arch-specific initialization */ arch_proc_reset(rp); @@ -807,6 +811,7 @@ int mini_send( * for this message, copy the message to it and unblock 'dst'. If 'dst' is * not waiting at all, or is waiting for another source, queue 'caller_ptr'. */ + int res = OK; register struct proc *dst_ptr; register struct proc **xpp; int dst_p; @@ -815,7 +820,8 @@ int mini_send( if (RTS_ISSET(dst_ptr, RTS_NO_ENDPOINT)) { - return EDEADSRCDST; + res = EDEADSRCDST; + goto update_rusage_and_exit; } /* Check if 'dst' is blocked waiting for this message. The destination's @@ -827,8 +833,10 @@ int mini_send( assert(!(dst_ptr->p_misc_flags & MF_DELIVERMSG)); if (!(flags & FROM_KERNEL)) { - if(copy_msg_from_user(m_ptr, &dst_ptr->p_delivermsg)) - return EFAULT; + if (copy_msg_from_user(m_ptr, &dst_ptr->p_delivermsg)) { + res = EFAULT; + goto update_rusage_and_exit; + } } else { dst_ptr->p_delivermsg = *m_ptr; IPC_STATUS_ADD_FLAGS(dst_ptr, IPC_FLG_MSG_FROM_KERNEL); @@ -851,19 +859,23 @@ int mini_send( hook_ipc_msgrecv(&dst_ptr->p_delivermsg, caller_ptr, dst_ptr); #endif } else { - if(flags & NON_BLOCKING) { - return(ENOTREADY); + if (flags & NON_BLOCKING) { + res = ENOTREADY; + goto update_rusage_and_exit; } /* Check for a possible deadlock before actually blocking. */ if (deadlock(SEND, caller_ptr, dst_e)) { - return(ELOCKED); + res = ELOCKED; + goto update_rusage_and_exit; } /* Destination is not waiting. Block and dequeue caller. */ if (!(flags & FROM_KERNEL)) { - if(copy_msg_from_user(m_ptr, &caller_ptr->p_sendmsg)) - return EFAULT; + if (copy_msg_from_user(m_ptr, &caller_ptr->p_sendmsg)) { + res = EFAULT; + goto update_rusage_and_exit; + } } else { caller_ptr->p_sendmsg = *m_ptr; /* @@ -887,7 +899,15 @@ int mini_send( hook_ipc_msgsend(&caller_ptr->p_sendmsg, caller_ptr, dst_ptr); #endif } - return(OK); + +update_rusage_and_exit: + /* When message is not actually delivered we set dst_ptr to + * NULL so it's rusage won't be updated*/ + if (res != OK) + dst_ptr = NULL; + + increase_messages_count(caller_ptr, dst_ptr); + return(res); } /*===========================================================================* @@ -1057,6 +1077,7 @@ int mini_notify( } dst_ptr = proc_addr(dst_p); + increase_messages_count(caller_ptr, dst_ptr); /* Check to see if target is blocked waiting for this message. A process * can be both sending and receiving during a SENDREC system call. @@ -1211,6 +1232,9 @@ int try_deliver_senda(struct proc *caller_ptr, r = EDEADSRCDST; } + if (r == OK) + increase_messages_count(caller_ptr, dst_ptr); + /* Check if 'dst' is blocked waiting for this message. * If AMF_NOREPLY is set, do not satisfy the receiving part of * a SENDREC. @@ -1686,6 +1710,8 @@ void dequeue(struct proc *rp) /* Process accounting for scheduling */ rp->p_accounting.dequeues++; + increase_context_switch_count(rp); + /* this is not all that accurate on virtual machines, especially with IO bound processes that only spend a short amount of time in the queue at a time. */ @@ -1906,3 +1932,34 @@ void ser_dump_proc() print_proc_recursive(pp); } } + +void reset_proc_rusage(struct proc *p) +{ + p->p_voluntary_context_switch = 0; + p->p_involuntary_context_switch = 0; + p->p_signal_received = 0; + p->p_message_sent = 0; + p->p_message_received = 0; +} + +void increase_context_switch_count(struct proc *rp) +{ + assert(!proc_is_runnable(rp)); + if (RTS_ISSET(rp, RTS_PREEMPTED) || RTS_ISSET(rp, RTS_NO_QUANTUM)) + rp->p_involuntary_context_switch++; + else + rp->p_voluntary_context_switch++; +} + +void increase_proc_signals(struct proc *p) +{ + p->p_signal_received++; +} + +void increase_messages_count(struct proc *from, struct proc *to) +{ + if (from) + from->p_message_sent++; + if (to) + to->p_message_received++; +} diff --git a/kernel/proc.h b/kernel/proc.h index 439396937..c1bbd9e22 100644 --- a/kernel/proc.h +++ b/kernel/proc.h @@ -126,6 +126,12 @@ struct proc { */ struct { reg_t r1, r2, r3; } p_defer; + u64_t p_message_sent; + u64_t p_message_received; + u64_t p_signal_received; + u64_t p_voluntary_context_switch; + u64_t p_involuntary_context_switch; + #if DEBUG_TRACE int p_schedules; #endif diff --git a/kernel/proto.h b/kernel/proto.h index 7952922dd..cfa09dee6 100644 --- a/kernel/proto.h +++ b/kernel/proto.h @@ -76,6 +76,8 @@ int isokendpt_f(endpoint_t e, int *p, int f); #endif void proc_no_time(struct proc *p); void reset_proc_accounting(struct proc *p); +void reset_proc_rusage(struct proc *p); +void increase_proc_signals(struct proc *p); void flag_account(struct proc *p, int flag); int try_deliver_senda(struct proc *caller_ptr, asynmsg_t *table, size_t size); diff --git a/kernel/system.c b/kernel/system.c index caafd9943..423b353b1 100644 --- a/kernel/system.c +++ b/kernel/system.c @@ -373,6 +373,7 @@ int send_sig(endpoint_t ep, int sig_nr) priv = priv(rp); if(!priv) return ENOENT; sigaddset(&priv->s_sig_pending, sig_nr); + increase_proc_signals(rp); mini_notify(proc_addr(SYSTEM), rp->p_endpoint); return OK; @@ -434,6 +435,7 @@ int sig_nr; /* signal to be sent */ /* Check if the signal is already pending. Process it otherwise. */ if (! sigismember(&rp->p_pending, sig_nr)) { sigaddset(&rp->p_pending, sig_nr); + increase_proc_signals(rp); if (! (RTS_ISSET(rp, RTS_SIGNALED))) { /* other pending */ RTS_SET(rp, RTS_SIGNALED | RTS_SIG_PENDING); if(OK != send_sig(sig_mgr, SIGKSIG)) diff --git a/kernel/system/do_fork.c b/kernel/system/do_fork.c index f30927025..0ed2fd150 100644 --- a/kernel/system/do_fork.c +++ b/kernel/system/do_fork.c @@ -91,6 +91,8 @@ int do_fork(struct proc * caller, message * m_ptr) make_zero64(rpc->p_kcall_cycles); make_zero64(rpc->p_kipc_cycles); + reset_proc_rusage(rpc); + /* If the parent is a privileged process, take away the privileges from the * child process and inhibit it from running by setting the NO_PRIV flag. * The caller should explicitely set the new privileges before executing.