kernel ipc debug: various fixes

. add receive hooks in the kernel to print asynchronously
	  delivered messages
	. do not rely on MF_REPLY_PEND to decide between calls and errors,
	  as that isn't reliable for asynchronous messages; try both instead
	. add _sendcall() that extract-mfield.sh can then reliably recognize
	  the fields for messages that are sent with just send()
	. add DEBUG_DUMPIPC_NAMES to restrict printed messages to
	  from/to given process names

Change-Id: Ia65eb02a69a2b58e73bf9f009987be06dda774a3
This commit is contained in:
Ben Gras 2013-05-01 19:02:06 +00:00
parent 85fd078707
commit 80846c4a79
10 changed files with 112 additions and 38 deletions

View file

@ -1660,25 +1660,12 @@ int proc_nr; /* to whom should the reply go? */
int status; /* reply code */ int status; /* reply code */
{ {
/* Send a reply to a process that wanted to read or write data. */ /* Send a reply to a process that wanted to read or write data. */
message tty_mess; assert(code == TASK_REPLY);
tty_mess.m_type = code;
tty_mess.REP_ENDPT = proc_nr;
tty_mess.REP_STATUS = status;
/* Don't reply to KERNEL (kernel messages) */ /* Don't reply to KERNEL (kernel messages) */
if (replyee == KERNEL) return; if (replyee == KERNEL) return;
/* TTY is not supposed to send a TTY_REVIVE message. The status = send_taskreply(replyee, proc_nr, status);
* REVIVE message is gone, TTY_REVIVE is only used as an internal
* placeholder for something that is not supposed to be a message.
*/
if(code == TTY_REVIVE) {
printf("%s:%d: ", file, line);
panic("tty_reply sending TTY_REVIVE");
}
status = send(replyee, &tty_mess);
if (status != OK) if (status != OK)
printf("tty`tty_reply: send to %d failed: %d\n", replyee, status); printf("tty`tty_reply: send to %d failed: %d\n", replyee, status);
} }

View file

@ -25,6 +25,7 @@ struct rs_pci;
*==========================================================================*/ *==========================================================================*/
int _taskcall(endpoint_t who, int syscallnr, message *msgptr); int _taskcall(endpoint_t who, int syscallnr, message *msgptr);
int _kernel_call(int syscallnr, message *msgptr); int _kernel_call(int syscallnr, message *msgptr);
int _sendcall(endpoint_t who, int type, message *msgptr);
int sys_abort(int how); int sys_abort(int how);
int sys_enable_iop(endpoint_t proc_ep); int sys_enable_iop(endpoint_t proc_ep);
@ -157,6 +158,8 @@ int sys_umap_data_fb(endpoint_t proc_ep, vir_bytes vir_addr, vir_bytes
int sys_umap_remote(endpoint_t proc_ep, endpoint_t grantee, int seg, int sys_umap_remote(endpoint_t proc_ep, endpoint_t grantee, int seg,
vir_bytes vir_addr, vir_bytes bytes, phys_bytes *phys_addr); vir_bytes vir_addr, vir_bytes bytes, phys_bytes *phys_addr);
int send_taskreply(endpoint_t who, endpoint_t endpoint, int status);
/* Shorthands for sys_getinfo() system call. */ /* Shorthands for sys_getinfo() system call. */
#define sys_getkinfo(dst) sys_getinfo(GET_KINFO, dst, 0,0,0) #define sys_getkinfo(dst) sys_getinfo(GET_KINFO, dst, 0,0,0)
#define sys_getloadinfo(dst) sys_getinfo(GET_LOADINFO, dst, 0,0,0) #define sys_getloadinfo(dst) sys_getinfo(GET_LOADINFO, dst, 0,0,0)

View file

@ -72,7 +72,7 @@ CPPFLAGS+= -DUSE_TRACE
CLEANFILES+=extracted-errno.h extracted-mfield.h extracted-mtype.h procoffsets.h CLEANFILES+=extracted-errno.h extracted-mfield.h extracted-mtype.h procoffsets.h
debug.d: extracted-errno.h extracted-mfield.h extracted-mtype.h debug.o: extracted-errno.h extracted-mfield.h extracted-mtype.h
extracted-errno.h: extract-errno.sh ../include/errno.h extracted-errno.h: extract-errno.sh ../include/errno.h
${_MKTARGET_CREATE} ${_MKTARGET_CREATE}

View file

@ -313,25 +313,45 @@ void print_proc_recursive(struct proc *pp)
} }
#if DEBUG_DUMPIPC #if DEBUG_DUMPIPC
static const char *mtypename(int mtype, int iscall) static const char *mtypename(int mtype, int *possible_callname)
{ {
/* use generated file to recognize message types */ char *callname = NULL, *errname = NULL;
if (iscall) { /* use generated file to recognize message types
switch(mtype) { *
#define IDENT(x) case x: return #x; * we try to match both error numbers and call numbers, as the
* reader can probably decide from context what's going on.
*
* whenever it might be a call number we tell the caller so the
* call message fields can be decoded if known.
*/
switch(mtype) {
#define IDENT(x) case x: callname = #x; *possible_callname = 1; break;
#include "extracted-mtype.h" #include "extracted-mtype.h"
#undef IDENT #undef IDENT
} }
} else { switch(mtype) {
switch(mtype) { #define IDENT(x) case x: errname = #x; break;
#define IDENT(x) case x: return #x;
#include "extracted-errno.h" #include "extracted-errno.h"
#undef IDENT #undef IDENT
}
} }
/* no match */ /* no match */
return NULL; if(!errname && !callname)
return NULL;
/* 2 matches */
if(errname && callname) {
static char typename[100];
strcpy(typename, errname);
strcat(typename, " / ");
strcat(typename, callname);
return typename;
}
if(errname) return errname;
assert(callname);
return callname;
} }
static void printproc(struct proc *rp) static void printproc(struct proc *rp)
@ -353,24 +373,51 @@ static void printparam(const char *name, const void *data, size_t size)
} }
} }
#ifdef DEBUG_DUMPIPC_NAMES
static int namematch(char **names, int nnames, char *name)
{
int i;
for(i = 0; i < nnames; i++)
if(!strcmp(names[i], name))
return 1;
return 0;
}
#endif
static void printmsg(message *msg, struct proc *src, struct proc *dst, static void printmsg(message *msg, struct proc *src, struct proc *dst,
char operation, int iscall, int printparams) char operation, int printparams)
{ {
const char *name; const char *name;
int mtype = msg->m_type; int mtype = msg->m_type, mightbecall = 0;
#ifdef DEBUG_DUMPIPC_NAMES
{
char *names[] = DEBUG_DUMPIPC_NAMES;
int nnames = sizeof(names)/sizeof(names[0]);
/* skip printing messages for messages neither to
* or from DEBUG_DUMPIPC_EP if it is defined; either
* can be NULL to indicate kernel
*/
if(!(src && namematch(names, nnames, src->p_name)) &&
!(dst && namematch(names, nnames, dst->p_name))) {
return;
}
}
#endif
/* source, destination and message type */ /* source, destination and message type */
printf("%c", operation); printf("%c", operation);
printproc(src); printproc(src);
printproc(dst); printproc(dst);
name = mtypename(mtype, iscall); name = mtypename(mtype, &mightbecall);
if (name) { if (name) {
printf(" %s(%d)", name, mtype); printf(" %s(%d/0x%x)", name, mtype, mtype);
} else { } else {
printf(" %d", mtype); printf(" %d/0x%x", mtype, mtype);
} }
if (iscall && printparams) { if (mightbecall && printparams) {
#define IDENT(x, y) if (mtype == x) printparam(#y, &msg->y, sizeof(msg->y)); #define IDENT(x, y) if (mtype == x) printparam(#y, &msg->y, sizeof(msg->y));
#include "extracted-mfield.h" #include "extracted-mfield.h"
#undef IDENT #undef IDENT
@ -473,14 +520,14 @@ static void statmsg(message *msg, struct proc *srcp, struct proc *dstp)
void hook_ipc_msgkcall(message *msg, struct proc *proc) void hook_ipc_msgkcall(message *msg, struct proc *proc)
{ {
#if DEBUG_DUMPIPC #if DEBUG_DUMPIPC
printmsg(msg, proc, NULL, 'k', 1, 1); printmsg(msg, proc, NULL, 'k', 1);
#endif #endif
} }
void hook_ipc_msgkresult(message *msg, struct proc *proc) void hook_ipc_msgkresult(message *msg, struct proc *proc)
{ {
#if DEBUG_DUMPIPC #if DEBUG_DUMPIPC
printmsg(msg, NULL, proc, 'k', 0, 0); printmsg(msg, NULL, proc, 'k', 0);
#endif #endif
#if DEBUG_IPCSTATS #if DEBUG_IPCSTATS
statmsg(msg, proc, NULL); statmsg(msg, proc, NULL);
@ -490,7 +537,7 @@ void hook_ipc_msgkresult(message *msg, struct proc *proc)
void hook_ipc_msgrecv(message *msg, struct proc *src, struct proc *dst) void hook_ipc_msgrecv(message *msg, struct proc *src, struct proc *dst)
{ {
#if DEBUG_DUMPIPC #if DEBUG_DUMPIPC
printmsg(msg, src, dst, 'r', src->p_misc_flags & MF_REPLY_PEND, 0); printmsg(msg, src, dst, 'r', 0);
#endif #endif
#if DEBUG_IPCSTATS #if DEBUG_IPCSTATS
statmsg(msg, src, dst); statmsg(msg, src, dst);
@ -500,7 +547,7 @@ void hook_ipc_msgrecv(message *msg, struct proc *src, struct proc *dst)
void hook_ipc_msgsend(message *msg, struct proc *src, struct proc *dst) void hook_ipc_msgsend(message *msg, struct proc *src, struct proc *dst)
{ {
#if DEBUG_DUMPIPC #if DEBUG_DUMPIPC
printmsg(msg, src, dst, 's', src->p_misc_flags & MF_REPLY_PEND, 1); printmsg(msg, src, dst, 's', 1);
#endif #endif
} }

View file

@ -46,6 +46,9 @@
*/ */
#define DEBUG_DUMPIPC 0 #define DEBUG_DUMPIPC 0
/* If defined, restrict DEBUG_DUMPIPC to particular process names */
/* #define DEBUG_DUMPIPC_NAMES { "tty", "inet" } */
/* DEBUG_IPCSTATS collects information on who sends messages to whom. */ /* DEBUG_IPCSTATS collects information on who sends messages to whom. */
#define DEBUG_IPCSTATS 0 #define DEBUG_IPCSTATS 0

View file

@ -5,7 +5,7 @@ set -e
find_files_and_lines() find_files_and_lines()
( (
find ../lib/libc/sys-minix ../lib/libsys -name '*.c' | \ find ../lib/libc/sys-minix ../lib/libsys -name '*.c' | \
xargs egrep -n '((_syscall|_taskcall)\([^,][^,]*,[ ]*|_kernel_call\()[A-Z_][A-Z0-9_]*,[ ]*&m\)' | \ xargs egrep -n '((_sendcall|_syscall|_taskcall)\([^,][^,]*,[ ]*|_kernel_call\()[A-Z_][A-Z0-9_]*,[ ]*&m\)' | \
cut -d: -f1,2 cut -d: -f1,2
) )

View file

@ -1223,6 +1223,9 @@ int try_deliver_senda(struct proc *caller_ptr,
dst_ptr->p_misc_flags |= MF_DELIVERMSG; dst_ptr->p_misc_flags |= MF_DELIVERMSG;
IPC_STATUS_ADD_CALL(dst_ptr, SENDA); IPC_STATUS_ADD_CALL(dst_ptr, SENDA);
RTS_UNSET(dst_ptr, RTS_RECEIVING); RTS_UNSET(dst_ptr, RTS_RECEIVING);
#if DEBUG_IPC_HOOK
hook_ipc_msgrecv(&dst_ptr->p_delivermsg, caller_ptr, dst_ptr);
#endif
} else if (r == OK) { } else if (r == OK) {
/* Inform receiver that something is pending */ /* Inform receiver that something is pending */
set_sys_bit(priv(dst_ptr)->s_asyn_pending, set_sys_bit(priv(dst_ptr)->s_asyn_pending,
@ -1398,6 +1401,9 @@ static int try_one(struct proc *src_ptr, struct proc *dst_ptr)
dst_ptr->p_delivermsg = tabent.msg; dst_ptr->p_delivermsg = tabent.msg;
dst_ptr->p_delivermsg.m_source = src_ptr->p_endpoint; dst_ptr->p_delivermsg.m_source = src_ptr->p_endpoint;
dst_ptr->p_misc_flags |= MF_DELIVERMSG; dst_ptr->p_misc_flags |= MF_DELIVERMSG;
#if DEBUG_IPC_HOOK
hook_ipc_msgrecv(&dst_ptr->p_delivermsg, src_ptr, dst_ptr);
#endif
store_result: store_result:
/* Store results for sender */ /* Store results for sender */

View file

@ -75,6 +75,7 @@ SRCS+= \
sys_vsafecopy.c \ sys_vsafecopy.c \
sys_vtimer.c \ sys_vtimer.c \
sys_vumap.c \ sys_vumap.c \
send_taskreply.c \
taskcall.c \ taskcall.c \
tickdelay.c \ tickdelay.c \
timers.c \ timers.c \

View file

@ -0,0 +1,20 @@
#include <string.h>
#include "syslib.h"
/*===========================================================================*
* sys_taskreply *
*===========================================================================*/
int send_taskreply(endpoint_t who, endpoint_t endpoint, int status)
{
message m;
memset(&m, 0, sizeof(m));
m.REP_ENDPT = endpoint;
m.REP_STATUS = status;
return _sendcall(who, TASK_REPLY, &m);
}

View file

@ -6,6 +6,13 @@
#include <lib.h> #include <lib.h>
#include <minix/syslib.h> #include <minix/syslib.h>
int _sendcall(endpoint_t who, int type, message *msgptr)
{
msgptr->m_type = type;
return send(who, msgptr);
}
int _taskcall(who, syscallnr, msgptr) int _taskcall(who, syscallnr, msgptr)
endpoint_t who; endpoint_t who;
int syscallnr; int syscallnr;