Test with hand crafted kernel module.
The Makefile and source file,
```lang=Makefile
PACKAGE=witness
SRCS = witness.c
KMOD = witness
.include <bsd.kmod.mk>
```
```lang=c
#include <sys/types.h>
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/module.h>
#include <sys/sysctl.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/sx.h>
static struct sx wit_sxlock;
SX_SYSINIT_FLAGS(wit_sx, &wit_sxlock, "witness_sx", SX_RECURSE);
static void f1(void);
static void f2(void);
static void f3(void);
static __noinline void
f1(void)
{
sx_xlock(&wit_sxlock); /* line 21 */
f2();
sx_xunlock(&wit_sxlock);
}
static __noinline void
f2(void)
{
sx_xlock(&wit_sxlock); /* line 29 */
f3();
sx_xunlock(&wit_sxlock);
/* XXX trigger witness assert panic */
sx_slock(&wit_sxlock); /* line 34 */
sx_sunlock(&wit_sxlock);
}
static __noinline void
f3(void)
{
sx_xlock(&wit_sxlock); /* line 41 */
sx_xunlock(&wit_sxlock);
}
static int
module_load(module_t mod, int cmd, void *arg)
{
int error;
error = 0;
switch (cmd) {
case MOD_LOAD:
f1();
break;
case MOD_UNLOAD:
break;
default:
error = EOPNOTSUPP;
break;
}
return (error);
}
static moduledata_t mod_data = {
"witness",
module_load,
0
};
DECLARE_MODULE(witness, mod_data, SI_SUB_EXEC, SI_ORDER_ANY);
```
Before the fix, witness report
```
shared lock of (sx) witness_sx @ witness.c:34
while exclusively locked from witness.c:41
panic: excl->share
```
After the fix,
```
shared lock of (sx) witness_sx @ witness.c:34
while exclusively locked from witness.c:21
panic: excl->share
```