From b2d1109737c7efe0fe4c8d2f5d2539b9a3b18b17 Mon Sep 17 00:00:00 2001 From: Ben Gras Date: Tue, 8 Feb 2011 13:54:33 +0000 Subject: [PATCH] kernel - change print*() functions for ipc to generic ipc hook functions. - used to implement ipc stats tracking code --- kernel/debug.c | 152 ++++++++++++++++++++++++++++++++++++++++++------ kernel/debug.h | 8 ++- kernel/proc.c | 14 ++--- kernel/proto.h | 11 ++-- kernel/system.c | 13 +++-- 5 files changed, 164 insertions(+), 34 deletions(-) diff --git a/kernel/debug.c b/kernel/debug.c index 28f032da8..f11b49d62 100644 --- a/kernel/debug.c +++ b/kernel/debug.c @@ -12,6 +12,7 @@ #include #include #include +#include #define MAX_LOOP (NR_PROCS + NR_TASKS) @@ -338,6 +339,14 @@ PRIVATE const char *mtypename(int mtype, int iscall) return NULL; } +PRIVATE void printproc(struct proc *rp) +{ + if (rp) + printf(" %s(%d)", rp->p_name, rp - proc); + else + printf(" kernel"); +} + PRIVATE void printparam(const char *name, const void *data, size_t size) { printf(" %s=", name); @@ -349,14 +358,6 @@ PRIVATE void printparam(const char *name, const void *data, size_t size) } } -PRIVATE void printproc(struct proc *rp) -{ - if (rp) - printf(" %s(%d)", rp->p_name, rp - proc); - else - printf(" kernel"); -} - PRIVATE void printmsg(message *msg, struct proc *src, struct proc *dst, char operation, int iscall, int printparams) { @@ -381,24 +382,141 @@ PRIVATE void printmsg(message *msg, struct proc *src, struct proc *dst, } printf("\n"); } +#endif -PUBLIC void printmsgkcall(message *msg, struct proc *proc) +#if DEBUG_IPCSTATS +#define IPCPROCS (NR_PROCS+1) /* number of slots we need */ +#define KERNELIPC NR_PROCS /* slot number to use for kernel calls */ +PRIVATE int messages[IPCPROCS][IPCPROCS]; + +#define PRINTSLOTS 20 +PRIVATE struct { + int src, dst, messages; +} winners[PRINTSLOTS]; +PRIVATE int total, goodslots; + +PRIVATE void printstats(int ticks) { - printmsg(msg, proc, NULL, 'k', 1, 1); + int i; + for(i = 0; i < goodslots; i++) { +#define name(s) (s == KERNELIPC ? "kernel" : proc_addr(s)->p_name) +#define persec(n) (system_hz*(n)/ticks) + char *n1 = name(winners[i].src), + *n2 = name(winners[i].dst); + printf("%2d. %8s -> %8s %9d/s\n", + i, n1, n2, persec(winners[i].messages)); + } + printf("total %d/s\n", persec(total)); } -PUBLIC void printmsgkresult(message *msg, struct proc *proc) +PRIVATE void sortstats(void) { - printmsg(msg, NULL, proc, 'k', 0, 0); + /* Print top message senders/receivers. */ + int src_slot, dst_slot; + total = goodslots = 0; + for(src_slot = 0; src_slot < IPCPROCS; src_slot++) { + for(dst_slot = 0; dst_slot < IPCPROCS; dst_slot++) { + int w = PRINTSLOTS, rem, + n = messages[src_slot][dst_slot]; + total += n; + while(w > 0 && n > winners[w-1].messages) + w--; + if(w >= PRINTSLOTS) continue; + + /* This combination has beaten the current winners + * and should be inserted at position 'w.' + */ + rem = PRINTSLOTS-w-1; + assert(rem >= 0); + assert(rem < PRINTSLOTS); + if(rem > 0) { + assert(w+1 <= PRINTSLOTS-1); + assert(w >= 0); + memmove(&winners[w+1], &winners[w], + rem*sizeof(winners[0])); + } + winners[w].src = src_slot; + winners[w].dst = dst_slot; + winners[w].messages = n; + if(goodslots < PRINTSLOTS) goodslots++; + } + } } -PUBLIC void printmsgrecv(message *msg, struct proc *src, struct proc *dst) -{ - printmsg(msg, src, dst, 'r', src->p_misc_flags & MF_REPLY_PEND, 0); +#define proc2slot(p, s) { \ + if(p) { s = p->p_nr; } \ + else { s = KERNELIPC; } \ + assert(s >= 0 && s < IPCPROCS); \ } -PUBLIC void printmsgsend(message *msg, struct proc *src, struct proc *dst) +PRIVATE void statmsg(message *msg, struct proc *srcp, struct proc *dstp) { - printmsg(msg, src, dst, 's', src->p_misc_flags & MF_REPLY_PEND, 1); + int src, dst, now, secs, dt; + static int lastprint; + + /* Stat message. */ + assert(src); + proc2slot(srcp, src); + proc2slot(dstp, dst); + messages[src][dst]++; + + /* Print something? */ + now = get_uptime(); + dt = now - lastprint; + secs = dt/system_hz; + if(secs >= 30) { + memset(winners, 0, sizeof(winners)); + sortstats(); + printstats(dt); + memset(messages, 0, sizeof(messages)); + lastprint = now; + } +} +#endif + +#if DEBUG_IPC_HOOK +PUBLIC void hook_ipc_msgkcall(message *msg, struct proc *proc) +{ +#if DEBUG_DUMPIPC + printmsg(msg, proc, NULL, 'k', 1, 1); +#endif +} + +PUBLIC void hook_ipc_msgkresult(message *msg, struct proc *proc) +{ +#if DEBUG_DUMPIPC + printmsg(msg, NULL, proc, 'k', 0, 0); +#endif +#if DEBUG_IPCSTATS + statmsg(msg, proc, NULL); +#endif +} + +PUBLIC void hook_ipc_msgrecv(message *msg, struct proc *src, struct proc *dst) +{ +#if DEBUG_DUMPIPC + printmsg(msg, src, dst, 'r', src->p_misc_flags & MF_REPLY_PEND, 0); +#endif +#if DEBUG_IPCSTATS + statmsg(msg, src, dst); +#endif +} + +PUBLIC void hook_ipc_msgsend(message *msg, struct proc *src, struct proc *dst) +{ +#if DEBUG_DUMPIPC + printmsg(msg, src, dst, 's', src->p_misc_flags & MF_REPLY_PEND, 1); +#endif +} + +PUBLIC void hook_ipc_clear(struct proc *p) +{ +#if DEBUG_IPCSTATS + int slot, i; + assert(p); + proc2slot(p, slot); + for(i = 0; i < IPCPROCS; i++) + messages[slot][i] = messages[i][slot] = 0; +#endif } #endif diff --git a/kernel/debug.h b/kernel/debug.h index f2527761c..ce808f31a 100644 --- a/kernel/debug.h +++ b/kernel/debug.h @@ -23,7 +23,6 @@ * are disabled. */ #define DEBUG_ENABLE_IPC_WARNINGS 1 -#define DEBUG_STACKTRACE 1 /* Sanity checks. */ #define DEBUG_SANITYCHECKS 0 @@ -45,6 +44,13 @@ */ #define DEBUG_DUMPIPC 0 +/* DEBUG_IPCSTATS collects information on who sends messages to whom. */ +#define DEBUG_IPCSTATS 0 + +#if DEBUG_DUMPIPC || DEBUG_IPCSTATS /* either of these needs the hook */ +#define DEBUG_IPC_HOOK 1 +#endif + #if DEBUG_TRACE #define VF_SCHEDULING (1L << 1) diff --git a/kernel/proc.c b/kernel/proc.c index 871e04ecd..ec85c9343 100644 --- a/kernel/proc.c +++ b/kernel/proc.c @@ -738,9 +738,9 @@ PUBLIC int mini_send( RTS_UNSET(dst_ptr, RTS_RECEIVING); -#if DEBUG_DUMPIPC - printmsgsend(&dst_ptr->p_delivermsg, caller_ptr, dst_ptr); - printmsgrecv(&dst_ptr->p_delivermsg, caller_ptr, dst_ptr); +#if DEBUG_IPC_HOOK + hook_ipc_msgsend(&dst_ptr->p_delivermsg, caller_ptr, dst_ptr); + hook_ipc_msgrecv(&dst_ptr->p_delivermsg, caller_ptr, dst_ptr); #endif } else { if(flags & NON_BLOCKING) { @@ -775,8 +775,8 @@ PUBLIC int mini_send( while (*xpp) xpp = &(*xpp)->p_q_link; *xpp = caller_ptr; /* add caller to end */ -#if DEBUG_DUMPIPC - printmsgsend(&caller_ptr->p_sendmsg, caller_ptr, dst_ptr); +#if DEBUG_IPC_HOOK + hook_ipc_msgsend(&caller_ptr->p_sendmsg, caller_ptr, dst_ptr); #endif } return(OK); @@ -917,8 +917,8 @@ PRIVATE int mini_receive(struct proc * caller_ptr, if (sender->p_misc_flags & MF_SIG_DELAY) sig_delay_done(sender); -#if DEBUG_DUMPIPC - printmsgrecv(&caller_ptr->p_delivermsg, *xpp, caller_ptr); +#if DEBUG_IPC_HOOK + hook_ipc_msgrecv(&caller_ptr->p_delivermsg, *xpp, caller_ptr); #endif *xpp = sender->p_q_link; /* remove from queue */ diff --git a/kernel/proto.h b/kernel/proto.h index 844467d90..7a0fae38d 100644 --- a/kernel/proto.h +++ b/kernel/proto.h @@ -122,13 +122,14 @@ _PROTOTYPE( char *schedulerstr, (struct proc *scheduler) ); _PROTOTYPE( void print_proc, (struct proc *pp)); /* prints the given process and recursively all processes it depends on */ _PROTOTYPE( void print_proc_recursive, (struct proc *pp)); -#if DEBUG_DUMPIPC -_PROTOTYPE( void printmsgrecv, (message *msg, struct proc *src, +#if DEBUG_IPC_HOOK +_PROTOTYPE( void hook_ipc_msgrecv, (message *msg, struct proc *src, struct proc *dst) ); -_PROTOTYPE( void printmsgsend, (message *msg, struct proc *src, +_PROTOTYPE( void hook_ipc_msgsend, (message *msg, struct proc *src, struct proc *dst) ); -_PROTOTYPE( void printmsgkcall, (message *msg, struct proc *proc) ); -_PROTOTYPE( void printmsgkresult, (message *msg, struct proc *proc) ); +_PROTOTYPE( void hook_ipc_msgkcall, (message *msg, struct proc *proc) ); +_PROTOTYPE( void hook_ipc_msgkresult, (message *msg, struct proc *proc) ); +_PROTOTYPE( void hook_ipc_clear, (struct proc *proc) ); #endif /* system/do_safemap.c */ diff --git a/kernel/system.c b/kernel/system.c index fc1440952..eeae82807 100644 --- a/kernel/system.c +++ b/kernel/system.c @@ -79,8 +79,8 @@ PRIVATE void kernel_call_finish(struct proc * caller, message *msg, int result) /* copy the result as a message to the original user buffer */ msg->m_source = SYSTEM; msg->m_type = result; /* report status of call */ -#if DEBUG_DUMPIPC - printmsgkresult(msg, caller); +#if DEBUG_IPC_HOOK + hook_ipc_msgkresult(msg, caller); #endif if (copy_msg_to_user(caller, msg, (message *)caller->p_delivermsg_vir)) { @@ -99,8 +99,8 @@ PRIVATE int kernel_call_dispatch(struct proc * caller, message *msg) int result = OK; int call_nr; -#if DEBUG_DUMPIPC - printmsgkcall(msg, caller); +#if DEBUG_IPC_HOOK + hook_ipc_msgkcall(msg, caller); #endif call_nr = msg->m_type - KERNEL_CALL; @@ -553,6 +553,11 @@ register struct proc *rc; /* slot of process to clean up */ { if(isemptyp(rc)) panic("clear_proc: empty process: %d", rc->p_endpoint); + +#if DEBUG_IPC_HOOK + hook_ipc_clear(rc); +#endif + /* Make sure that the exiting process is no longer scheduled. */ RTS_SET(rc, RTS_NO_ENDPOINT); if (priv(rc)->s_flags & SYS_PROC)