]> Zhao Yanbai Git Server - minix.git/commitdiff
kernel - change print*() functions for ipc to generic ipc hook functions.
authorBen Gras <ben@minix3.org>
Tue, 8 Feb 2011 13:54:33 +0000 (13:54 +0000)
committerBen Gras <ben@minix3.org>
Tue, 8 Feb 2011 13:54:33 +0000 (13:54 +0000)
  - used to implement ipc stats tracking code

kernel/debug.c
kernel/debug.h
kernel/proc.c
kernel/proto.h
kernel/system.c

index 28f032da888c9e4ed14db52c9a4ea960b05e9551..f11b49d6232be743f7f9ad3e18091f83732b75a4 100644 (file)
@@ -12,6 +12,7 @@
 #include <minix/u64.h>
 #include <limits.h>
 #include <string.h>
+#include <assert.h>
 
 #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
+
+#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)
+{
+       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));
+}
+
+PRIVATE void sortstats(void)
+{
+       /* 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 printmsgkcall(message *msg, struct proc *proc)
+#define proc2slot(p, s) { \
+       if(p) { s = p->p_nr; } \
+       else { s = KERNELIPC; } \
+       assert(s >= 0 && s < IPCPROCS); \
+}
+
+PRIVATE void statmsg(message *msg, struct proc *srcp, struct proc *dstp)
 {
+       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 printmsgkresult(message *msg, struct proc *proc)
+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 printmsgrecv(message *msg, struct proc *src, struct proc *dst)
+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 printmsgsend(message *msg, struct proc *src, struct proc *dst)
+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
index f2527761c2856c6ad0990be5698be62dd2d649b6..ce808f31ac4d894e0218f7186d4a1f5f97178eb7 100644 (file)
@@ -23,7 +23,6 @@
  * are disabled.
  */
 #define DEBUG_ENABLE_IPC_WARNINGS      1
-#define DEBUG_STACKTRACE               1
 
 /* Sanity checks. */
 #define DEBUG_SANITYCHECKS             0
  */
 #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)
index 871e04ecdf56d71435427b3ac608fb6f1076e821..ec85c9343a8e50bc93831c8d415db711a5b6515e 100644 (file)
@@ -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 */
index 844467d90b6511e0da250db6ec3484f98bcfc6aa..7a0fae38d64171080f226abb792ac96f02ad8ea3 100644 (file)
@@ -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 */
index fc144095297d85bcccd0a1636b83895821bfe628..eeae82807acc53b0832c928877ea06ffc487f56e 100644 (file)
@@ -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)