- Add code to detect if a system call returns with locks other than Giant

held and panic if so (conditional on witness).
- Change witness_list to return the number of locks held so this is easier.
- Add kern/syscalls.c to the kernel build if witness is defined so that the
  panic message can contain the name of the offending system call.
- Add assertions that Giant and sched_lock are not held when returning from
  a system call, which were missing for alpha and ia64.
This commit is contained in:
Jake Burkholder 2000-12-12 01:14:32 +00:00
parent d664747bfa
commit 92cf772d8d
10 changed files with 78 additions and 4 deletions

View file

@ -88,6 +88,11 @@ int unaligned_fixup __P((unsigned long, unsigned long,
static void printtrap __P((const unsigned long, const unsigned long,
const unsigned long, const unsigned long, struct trapframe *, int, int));
#ifdef WITNESS
extern char *syscallnames[];
#endif
/*
* Define the code needed before returning to user mode, for
* trap and syscall.
@ -737,6 +742,15 @@ syscall(code, framep)
*/
STOPEVENT(p, S_SCX, code);
mtx_exit(&Giant, MTX_DEF);
mtx_assert(&sched_lock, MA_NOTOWNED);
mtx_assert(&Giant, MA_NOTOWNED);
#ifdef WITNESS
if (witness_list(p)) {
panic("system call %s returning with mutex(s) held\n",
syscallnames[code]);
}
#endif
}
/*

View file

@ -164,6 +164,10 @@ static int panic_on_nmi = 1;
SYSCTL_INT(_machdep, OID_AUTO, panic_on_nmi, CTLFLAG_RW,
&panic_on_nmi, 0, "Panic on NMI");
#ifdef WITNESS
extern char *syscallnames[];
#endif
static __inline int
userret(p, frame, oticks, have_giant)
struct proc *p;
@ -1221,6 +1225,12 @@ bad:
mtx_assert(&sched_lock, MA_NOTOWNED);
mtx_assert(&Giant, MA_NOTOWNED);
#ifdef WITNESS
if (witness_list(p)) {
panic("system call %s returning with mutex(s) held\n",
syscallnames[code]);
}
#endif
}
void

View file

@ -664,6 +664,7 @@ kern/sys_generic.c standard
kern/sys_pipe.c standard
kern/sys_process.c standard
kern/sys_socket.c standard
kern/syscalls.c optional witness
kern/sysv_ipc.c standard
kern/sysv_msg.c optional sysvmsg
kern/sysv_sem.c optional sysvsem

View file

@ -164,6 +164,10 @@ static int panic_on_nmi = 1;
SYSCTL_INT(_machdep, OID_AUTO, panic_on_nmi, CTLFLAG_RW,
&panic_on_nmi, 0, "Panic on NMI");
#ifdef WITNESS
extern char *syscallnames[];
#endif
static __inline int
userret(p, frame, oticks, have_giant)
struct proc *p;
@ -1221,6 +1225,12 @@ bad:
mtx_assert(&sched_lock, MA_NOTOWNED);
mtx_assert(&Giant, MA_NOTOWNED);
#ifdef WITNESS
if (witness_list(p)) {
panic("system call %s returning with mutex(s) held\n",
syscallnames[code]);
}
#endif
}
void

View file

@ -74,6 +74,10 @@ u_int32_t want_resched;
static int unaligned_fixup(struct trapframe *framep, struct proc *p);
#ifdef WITNESS
extern char *syscallnames[];
#endif
/*
* Define the code needed before returning to user mode, for
* trap and syscall.
@ -614,6 +618,16 @@ syscall(int code, u_int64_t *args, struct trapframe *framep)
*/
STOPEVENT(p, S_SCX, code);
mtx_exit(&Giant, MTX_DEF);
mtx_assert(&sched_lock, MA_NOTOWNED);
mtx_assert(&Giant, MA_NOTOWNED);
#ifdef WITNESS
if (witness_list(p)) {
panic("system call %s returning with mutex(s) held\n",
syscallnames[code]);
}
#endif
}
}
/*

View file

@ -1353,17 +1353,22 @@ witness_free(struct witness *w)
w_free = w;
}
void
int
witness_list(struct proc *p)
{
struct mtx *m;
int nheld;
nheld = 0;
for ((m = LIST_FIRST(&p->p_heldmtx)); m != NULL;
m = LIST_NEXT(m, mtx_held)) {
printf("\t\"%s\" (%p) locked at %s:%d\n",
m->mtx_description, m,
m->mtx_witness->w_file, m->mtx_witness->w_line);
nheld++;
}
return (nheld);
}
void

View file

@ -164,6 +164,10 @@ static int panic_on_nmi = 1;
SYSCTL_INT(_machdep, OID_AUTO, panic_on_nmi, CTLFLAG_RW,
&panic_on_nmi, 0, "Panic on NMI");
#ifdef WITNESS
extern char *syscallnames[];
#endif
static __inline int
userret(p, frame, oticks, have_giant)
struct proc *p;
@ -1221,6 +1225,12 @@ bad:
mtx_assert(&sched_lock, MA_NOTOWNED);
mtx_assert(&Giant, MA_NOTOWNED);
#ifdef WITNESS
if (witness_list(p)) {
panic("system call %s returning with mutex(s) held\n",
syscallnames[code]);
}
#endif
}
void

View file

@ -1353,17 +1353,22 @@ witness_free(struct witness *w)
w_free = w;
}
void
int
witness_list(struct proc *p)
{
struct mtx *m;
int nheld;
nheld = 0;
for ((m = LIST_FIRST(&p->p_heldmtx)); m != NULL;
m = LIST_NEXT(m, mtx_held)) {
printf("\t\"%s\" (%p) locked at %s:%d\n",
m->mtx_description, m,
m->mtx_witness->w_file, m->mtx_witness->w_line);
nheld++;
}
return (nheld);
}
void

View file

@ -1353,17 +1353,22 @@ witness_free(struct witness *w)
w_free = w;
}
void
int
witness_list(struct proc *p)
{
struct mtx *m;
int nheld;
nheld = 0;
for ((m = LIST_FIRST(&p->p_heldmtx)); m != NULL;
m = LIST_NEXT(m, mtx_held)) {
printf("\t\"%s\" (%p) locked at %s:%d\n",
m->mtx_description, m,
m->mtx_witness->w_file, m->mtx_witness->w_line);
nheld++;
}
return (nheld);
}
void

View file

@ -300,7 +300,7 @@ void witness_enter(struct mtx *, int, const char *, int);
void witness_try_enter(struct mtx *, int, const char *, int);
void witness_exit(struct mtx *, int, const char *, int);
void witness_display(void(*)(const char *fmt, ...));
void witness_list(struct proc *);
int witness_list(struct proc *);
int witness_sleep(int, struct mtx *, const char *, int);
void witness_save(struct mtx *, const char **, int *);
void witness_restore(struct mtx *, const char *, int);