kernel - change print*() functions for ipc to generic ipc hook functions.
- used to implement ipc stats tracking code
This commit is contained in:
parent
fa59fc6eb4
commit
b2d1109737
152
kernel/debug.c
152
kernel/debug.c
|
@ -12,6 +12,7 @@
|
||||||
#include <minix/u64.h>
|
#include <minix/u64.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#define MAX_LOOP (NR_PROCS + NR_TASKS)
|
#define MAX_LOOP (NR_PROCS + NR_TASKS)
|
||||||
|
|
||||||
|
@ -338,6 +339,14 @@ PRIVATE const char *mtypename(int mtype, int iscall)
|
||||||
return NULL;
|
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)
|
PRIVATE void printparam(const char *name, const void *data, size_t size)
|
||||||
{
|
{
|
||||||
printf(" %s=", name);
|
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,
|
PRIVATE void printmsg(message *msg, struct proc *src, struct proc *dst,
|
||||||
char operation, int iscall, int printparams)
|
char operation, int iscall, int printparams)
|
||||||
{
|
{
|
||||||
|
@ -381,24 +382,141 @@ PRIVATE void printmsg(message *msg, struct proc *src, struct proc *dst,
|
||||||
}
|
}
|
||||||
printf("\n");
|
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)
|
#define proc2slot(p, s) { \
|
||||||
{
|
if(p) { s = p->p_nr; } \
|
||||||
printmsg(msg, src, dst, 'r', src->p_misc_flags & MF_REPLY_PEND, 0);
|
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
|
#endif
|
||||||
|
|
|
@ -23,7 +23,6 @@
|
||||||
* are disabled.
|
* are disabled.
|
||||||
*/
|
*/
|
||||||
#define DEBUG_ENABLE_IPC_WARNINGS 1
|
#define DEBUG_ENABLE_IPC_WARNINGS 1
|
||||||
#define DEBUG_STACKTRACE 1
|
|
||||||
|
|
||||||
/* Sanity checks. */
|
/* Sanity checks. */
|
||||||
#define DEBUG_SANITYCHECKS 0
|
#define DEBUG_SANITYCHECKS 0
|
||||||
|
@ -45,6 +44,13 @@
|
||||||
*/
|
*/
|
||||||
#define DEBUG_DUMPIPC 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
|
#if DEBUG_TRACE
|
||||||
|
|
||||||
#define VF_SCHEDULING (1L << 1)
|
#define VF_SCHEDULING (1L << 1)
|
||||||
|
|
|
@ -738,9 +738,9 @@ PUBLIC int mini_send(
|
||||||
|
|
||||||
RTS_UNSET(dst_ptr, RTS_RECEIVING);
|
RTS_UNSET(dst_ptr, RTS_RECEIVING);
|
||||||
|
|
||||||
#if DEBUG_DUMPIPC
|
#if DEBUG_IPC_HOOK
|
||||||
printmsgsend(&dst_ptr->p_delivermsg, caller_ptr, dst_ptr);
|
hook_ipc_msgsend(&dst_ptr->p_delivermsg, caller_ptr, dst_ptr);
|
||||||
printmsgrecv(&dst_ptr->p_delivermsg, caller_ptr, dst_ptr);
|
hook_ipc_msgrecv(&dst_ptr->p_delivermsg, caller_ptr, dst_ptr);
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
if(flags & NON_BLOCKING) {
|
if(flags & NON_BLOCKING) {
|
||||||
|
@ -775,8 +775,8 @@ PUBLIC int mini_send(
|
||||||
while (*xpp) xpp = &(*xpp)->p_q_link;
|
while (*xpp) xpp = &(*xpp)->p_q_link;
|
||||||
*xpp = caller_ptr; /* add caller to end */
|
*xpp = caller_ptr; /* add caller to end */
|
||||||
|
|
||||||
#if DEBUG_DUMPIPC
|
#if DEBUG_IPC_HOOK
|
||||||
printmsgsend(&caller_ptr->p_sendmsg, caller_ptr, dst_ptr);
|
hook_ipc_msgsend(&caller_ptr->p_sendmsg, caller_ptr, dst_ptr);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
return(OK);
|
return(OK);
|
||||||
|
@ -917,8 +917,8 @@ PRIVATE int mini_receive(struct proc * caller_ptr,
|
||||||
if (sender->p_misc_flags & MF_SIG_DELAY)
|
if (sender->p_misc_flags & MF_SIG_DELAY)
|
||||||
sig_delay_done(sender);
|
sig_delay_done(sender);
|
||||||
|
|
||||||
#if DEBUG_DUMPIPC
|
#if DEBUG_IPC_HOOK
|
||||||
printmsgrecv(&caller_ptr->p_delivermsg, *xpp, caller_ptr);
|
hook_ipc_msgrecv(&caller_ptr->p_delivermsg, *xpp, caller_ptr);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
*xpp = sender->p_q_link; /* remove from queue */
|
*xpp = sender->p_q_link; /* remove from queue */
|
||||||
|
|
|
@ -122,13 +122,14 @@ _PROTOTYPE( char *schedulerstr, (struct proc *scheduler) );
|
||||||
_PROTOTYPE( void print_proc, (struct proc *pp));
|
_PROTOTYPE( void print_proc, (struct proc *pp));
|
||||||
/* prints the given process and recursively all processes it depends on */
|
/* prints the given process and recursively all processes it depends on */
|
||||||
_PROTOTYPE( void print_proc_recursive, (struct proc *pp));
|
_PROTOTYPE( void print_proc_recursive, (struct proc *pp));
|
||||||
#if DEBUG_DUMPIPC
|
#if DEBUG_IPC_HOOK
|
||||||
_PROTOTYPE( void printmsgrecv, (message *msg, struct proc *src,
|
_PROTOTYPE( void hook_ipc_msgrecv, (message *msg, struct proc *src,
|
||||||
struct proc *dst) );
|
struct proc *dst) );
|
||||||
_PROTOTYPE( void printmsgsend, (message *msg, struct proc *src,
|
_PROTOTYPE( void hook_ipc_msgsend, (message *msg, struct proc *src,
|
||||||
struct proc *dst) );
|
struct proc *dst) );
|
||||||
_PROTOTYPE( void printmsgkcall, (message *msg, struct proc *proc) );
|
_PROTOTYPE( void hook_ipc_msgkcall, (message *msg, struct proc *proc) );
|
||||||
_PROTOTYPE( void printmsgkresult, (message *msg, struct proc *proc) );
|
_PROTOTYPE( void hook_ipc_msgkresult, (message *msg, struct proc *proc) );
|
||||||
|
_PROTOTYPE( void hook_ipc_clear, (struct proc *proc) );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* system/do_safemap.c */
|
/* system/do_safemap.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 */
|
/* copy the result as a message to the original user buffer */
|
||||||
msg->m_source = SYSTEM;
|
msg->m_source = SYSTEM;
|
||||||
msg->m_type = result; /* report status of call */
|
msg->m_type = result; /* report status of call */
|
||||||
#if DEBUG_DUMPIPC
|
#if DEBUG_IPC_HOOK
|
||||||
printmsgkresult(msg, caller);
|
hook_ipc_msgkresult(msg, caller);
|
||||||
#endif
|
#endif
|
||||||
if (copy_msg_to_user(caller, msg,
|
if (copy_msg_to_user(caller, msg,
|
||||||
(message *)caller->p_delivermsg_vir)) {
|
(message *)caller->p_delivermsg_vir)) {
|
||||||
|
@ -99,8 +99,8 @@ PRIVATE int kernel_call_dispatch(struct proc * caller, message *msg)
|
||||||
int result = OK;
|
int result = OK;
|
||||||
int call_nr;
|
int call_nr;
|
||||||
|
|
||||||
#if DEBUG_DUMPIPC
|
#if DEBUG_IPC_HOOK
|
||||||
printmsgkcall(msg, caller);
|
hook_ipc_msgkcall(msg, caller);
|
||||||
#endif
|
#endif
|
||||||
call_nr = msg->m_type - KERNEL_CALL;
|
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(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. */
|
/* Make sure that the exiting process is no longer scheduled. */
|
||||||
RTS_SET(rc, RTS_NO_ENDPOINT);
|
RTS_SET(rc, RTS_NO_ENDPOINT);
|
||||||
if (priv(rc)->s_flags & SYS_PROC)
|
if (priv(rc)->s_flags & SYS_PROC)
|
||||||
|
|
Loading…
Reference in a new issue