[DTrace-devel] [PATCH] Add support for mutex-related subroutines

eugene.loh at oracle.com eugene.loh at oracle.com
Thu Mar 3 10:55:40 UTC 2022


From: Eugene Loh <eugene.loh at oracle.com>

Implement the relevant subroutines.  Clean up the tests.

A few tests were broken in ways that were not being detected:
early on because runtest.sh was not checking error tags and later
because the tests were marked XFAIL.  Clean these tests up.

Changes include not using kmutex_t any longer in the tests.  This
type was not recognized even in legacy DTrace.  The documentation
needs a corresponding update.

Similarly, probe lockstat:genunix:mutex_enter:adaptive-acquire was
not recognized, even by legacy DTrace, and it was not needed for the
tests in question.

There were no rw_* tests.  One has been added, but it remains
unclear how stable the test is -- specifically, whether enough
write-lock events are generated.

Signed-off-by: Eugene Loh <eugene.loh at oracle.com>
---
 bpf/Build                                     |   5 +
 bpf/mutex_owned.S                             |  38 ++++++
 bpf/mutex_owner.S                             |  29 +++++
 bpf/rw_iswriter.S                             |  29 +++++
 bpf/rw_read_held.S                            |  29 +++++
 bpf/rw_write_held.S                           |  29 +++++
 libdtrace/dt_bpf.h                            |   2 +
 libdtrace/dt_cc.c                             |  50 ++++++++
 libdtrace/dt_cg.c                             | 114 ++++++++++++++++--
 libdtrace/dt_dlibs.c                          |   2 +
 ...tabadarg.d => err.D_PROTO_ARG.mtabadarg.d} |   2 +-
 .../funcs/err.D_PROTO_ARG.mtabadarg.r         |   4 +
 .../unittest/funcs/err.D_PROTO_LEN.motoofew.d |  10 +-
 .../unittest/funcs/err.D_PROTO_LEN.motoofew.r |   2 +
 .../funcs/err.D_PROTO_LEN.motoomany.d         |  11 +-
 .../funcs/err.D_PROTO_LEN.motoomany.r         |   2 +-
 .../funcs/err.D_PROTO_LEN.mtabadarg.r         |   2 -
 .../funcs/err.D_PROTO_LEN.mtatoofew.d         |  11 +-
 .../funcs/err.D_PROTO_LEN.mtatoofew.r         |   2 +
 .../funcs/err.D_PROTO_LEN.mtatoomany.d        |  12 +-
 .../funcs/err.D_PROTO_LEN.mtatoomany.r        |   2 +-
 test/unittest/funcs/tst.mutex_owned.d         |   3 +-
 test/unittest/funcs/tst.mutex_owner.d         |   3 +-
 test/unittest/funcs/tst.mutex_type_adaptive.d |   3 +-
 test/unittest/funcs/tst.mutex_type_spin.d     |   3 +-
 test/unittest/funcs/tst.rw_.r                 |  12 ++
 test/unittest/funcs/tst.rw_.sh                |  96 +++++++++++++++
 test/unittest/funcs/tst.rw_.x                 |  15 +++
 28 files changed, 472 insertions(+), 50 deletions(-)
 create mode 100644 bpf/mutex_owned.S
 create mode 100644 bpf/mutex_owner.S
 create mode 100644 bpf/rw_iswriter.S
 create mode 100644 bpf/rw_read_held.S
 create mode 100644 bpf/rw_write_held.S
 rename test/unittest/funcs/{err.D_PROTO_LEN.mtabadarg.d => err.D_PROTO_ARG.mtabadarg.d} (90%)
 create mode 100644 test/unittest/funcs/err.D_PROTO_ARG.mtabadarg.r
 create mode 100644 test/unittest/funcs/err.D_PROTO_LEN.motoofew.r
 delete mode 100644 test/unittest/funcs/err.D_PROTO_LEN.mtabadarg.r
 create mode 100644 test/unittest/funcs/err.D_PROTO_LEN.mtatoofew.r
 create mode 100644 test/unittest/funcs/tst.rw_.r
 create mode 100755 test/unittest/funcs/tst.rw_.sh
 create mode 100755 test/unittest/funcs/tst.rw_.x

diff --git a/bpf/Build b/bpf/Build
index 5cf9c45f..43f4b638 100644
--- a/bpf/Build
+++ b/bpf/Build
@@ -30,9 +30,14 @@ bpf_dlib_SOURCES = \
 	index.S \
 	inet_ntoa.S \
 	lltostr.S \
+	mutex_owned.S \
+	mutex_owner.S \
 	progenyof.S \
 	probe_error.c \
 	rindex.S \
+	rw_iswriter.S \
+	rw_read_held.S \
+	rw_write_held.S \
 	speculation.c \
 	strchr.S \
 	strcmp.S \
diff --git a/bpf/mutex_owned.S b/bpf/mutex_owned.S
new file mode 100644
index 00000000..19c61bc5
--- /dev/null
+++ b/bpf/mutex_owned.S
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
+ */
+
+#define BPF_FUNC_probe_read	4
+#define BPF_FUNC_get_current_task	35
+#define MUTEX_FLAGS		0x07
+
+	.text
+	.align	4
+	.global	dt_mutex_owned
+	.type	dt_mutex_owned, @function
+dt_mutex_owned:
+	/* dt_mutex_owned(tmp, mutex) */
+
+	/* %r6 = tmp */
+	mov	%r6, %r1
+
+	/* probe_read(tmp, 8, &mutex->owner) */
+	lddw	%r3, MUTEX_OWNER
+	add	%r3, %r2
+	mov	%r2, 8
+	call	BPF_FUNC_probe_read
+
+	/* %r6 = *tmp & ~MUTEX_FLAGS */
+	ldxdw	%r6, [%r6+0]
+	and	%r6, ~MUTEX_FLAGS
+
+	call	BPF_FUNC_get_current_task
+	jeq	%r0, %r6, .Lowned
+	mov	%r0, 0
+	exit
+
+.Lowned:
+	mov	%r0, 1
+	exit
+	.size	dt_mutex_owned, .-dt_mutex_owned
diff --git a/bpf/mutex_owner.S b/bpf/mutex_owner.S
new file mode 100644
index 00000000..3668d643
--- /dev/null
+++ b/bpf/mutex_owner.S
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
+ */
+
+#define BPF_FUNC_probe_read	4
+#define MUTEX_FLAGS		0x07
+
+	.text
+	.align	4
+	.global	dt_mutex_owner
+	.type	dt_mutex_owner, @function
+dt_mutex_owner:
+	/* dt_mutex_owner(tmp, mutex) */
+
+	/* %r6 = tmp */
+	mov	%r6, %r1
+
+	/* probe_read(tmp, 8, &mutex->owner) */
+	lddw	%r3, MUTEX_OWNER
+	add	%r3, %r2
+	mov	%r2, 8
+	call	BPF_FUNC_probe_read
+
+	/* %r0 = *tmp & ~MUTEX_FLAGS */
+	ldxdw	%r0, [%r6+0]
+	and	%r0, ~MUTEX_FLAGS
+	exit
+	.size	dt_mutex_owner, .-dt_mutex_owner
diff --git a/bpf/rw_iswriter.S b/bpf/rw_iswriter.S
new file mode 100644
index 00000000..e324ad56
--- /dev/null
+++ b/bpf/rw_iswriter.S
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
+ */
+
+#define BPF_FUNC_probe_read	4
+#define _QW_WMASK		0x1ff
+
+	.text
+	.align	4
+	.global	dt_rw_iswriter
+	.type	dt_rw_iswriter, @function
+dt_rw_iswriter:
+	/* dt_rw_iswriter(tmp, rwlock) */
+
+	/* %r6 = tmp */
+	mov	%r6, %r1
+
+	/* probe_read(tmp, 8, &rwlock->cnts) */
+	lddw	%r3, RWLOCK_CNTS
+	add	%r3, %r2
+	mov	%r2, 8
+	call	BPF_FUNC_probe_read
+
+	/* %r0 = *tmp & _QW_WMASK */
+	ldxdw	%r0, [%r6+0]
+	and	%r0, _QW_WMASK
+	exit
+	.size	dt_rw_iswriter, .-dt_rw_iswriter
diff --git a/bpf/rw_read_held.S b/bpf/rw_read_held.S
new file mode 100644
index 00000000..efe1467c
--- /dev/null
+++ b/bpf/rw_read_held.S
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
+ */
+
+#define BPF_FUNC_probe_read	4
+#define _QW_WMASK		0x1ff
+
+	.text
+	.align	4
+	.global	dt_rw_read_held
+	.type	dt_rw_read_held, @function
+dt_rw_read_held:
+	/* dt_rw_read_held(tmp, rwlock) */
+
+	/* %r6 = tmp */
+	mov	%r6, %r1
+
+	/* probe_read(tmp, 8, &rwlock->cnts) */
+	lddw	%r3, RWLOCK_CNTS
+	add	%r3, %r2
+	mov	%r2, 8
+	call	BPF_FUNC_probe_read
+
+	/* %r0 = *tmp & ~_QW_WMASK */
+	ldxdw	%r0, [%r6+0]
+	and	%r0, ~_QW_WMASK
+	exit
+	.size	dt_rw_read_held, .-dt_rw_read_held
diff --git a/bpf/rw_write_held.S b/bpf/rw_write_held.S
new file mode 100644
index 00000000..9fdf09cd
--- /dev/null
+++ b/bpf/rw_write_held.S
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
+ */
+
+#define BPF_FUNC_probe_read	4
+#define _QW_LOCKED		0x0ff
+
+	.text
+	.align	4
+	.global	dt_rw_write_held
+	.type	dt_rw_write_held, @function
+dt_rw_write_held:
+	/* dt_rw_write_held(tmp, rwlock) */
+
+	/* %r6 = tmp */
+	mov	%r6, %r1
+
+	/* probe_read(tmp, 8, &rwlock->cnts) */
+	lddw	%r3, RWLOCK_CNTS
+	add	%r3, %r2
+	mov	%r2, 8
+	call	BPF_FUNC_probe_read
+
+	/* %r0 = *tmp & _QW_LOCKED */
+	ldxdw	%r0, [%r6+0]
+	and	%r0, _QW_LOCKED
+	exit
+	.size	dt_rw_write_held, .-dt_rw_write_held
diff --git a/libdtrace/dt_bpf.h b/libdtrace/dt_bpf.h
index 957d593e..de34bb58 100644
--- a/libdtrace/dt_bpf.h
+++ b/libdtrace/dt_bpf.h
@@ -32,6 +32,8 @@ extern "C" {
 #define DT_CONST_TASK_TGID	12
 #define DT_CONST_TASK_REAL_PARENT	13
 #define DT_CONST_TASK_COMM	14
+#define DT_CONST_MUTEX_OWNER	15
+#define DT_CONST_RWLOCK_CNTS	16
 
 extern int perf_event_open(struct perf_event_attr *attr, pid_t pid, int cpu,
 			   int group_fd, unsigned long flags);
diff --git a/libdtrace/dt_cc.c b/libdtrace/dt_cc.c
index c0556522..d33b2768 100644
--- a/libdtrace/dt_cc.c
+++ b/libdtrace/dt_cc.c
@@ -2398,6 +2398,56 @@ dt_link_construct(dtrace_hdl_t *dtp, const dt_probe_t *prp, dtrace_difo_t *dp,
 				nrp->dofr_data = ctm.ctm_offset / NBBY;
 				continue;
 			}
+			case DT_CONST_MUTEX_OWNER: {
+				ctf_file_t *cfp = dtp->dt_shared_ctf;
+				ctf_id_t type = ctf_lookup_by_name(cfp, "struct mutex");
+				ctf_membinfo_t ctm;
+				ctf_id_t rc = CTF_ERR;
+
+				if (type == CTF_ERR)
+					return -1;
+
+				rc = ctf_member_info(cfp, type, "owner", &ctm);
+				if (rc == CTF_ERR)
+					return -1;
+				nrp->dofr_data = ctm.ctm_offset / NBBY;
+				continue;
+			}
+			case DT_CONST_RWLOCK_CNTS: {
+				/*
+				 * For !CONFIG_PREEMPT_RT, in type rwlock_t, we
+				 * want the offset to member raw_lock, and then
+				 * (in type arch_rwlock_t == struct qrwlock) we
+				 * add the offset to member cnts.  (It turns
+				 * out the total offset is 0.)
+				 *
+				 * FIXME: what about CONFIG_PREEMPT_RT?
+				 */
+				ctf_file_t *cfp = dtp->dt_shared_ctf;
+				ctf_id_t type;
+				ctf_membinfo_t ctm;
+				ctf_id_t rc = CTF_ERR;
+				uint64_t total_offset;
+
+				type = ctf_lookup_by_name(cfp, "rwlock_t");
+				if (type == CTF_ERR)
+					return -1;
+				rc = ctf_member_info(cfp, type, "raw_lock", &ctm);
+				if (rc == CTF_ERR)
+					return -1;
+				total_offset = ctm.ctm_offset / NBBY;
+
+				type = ctf_lookup_by_name(cfp, "arch_rwlock_t");
+				if (type == CTF_ERR)
+					return -1;
+				rc = ctf_member_info(cfp, type, "cnts", &ctm);
+				if (rc == CTF_ERR)
+					return -1;
+				total_offset += ctm.ctm_offset / NBBY;
+
+				nrp->dofr_data = total_offset;
+				continue;
+			}
 			default:
 				/* probe name -> value is probe id */
 				if (strchr(idp->di_name, ':') != NULL)
diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
index 22ccac2b..028f1178 100644
--- a/libdtrace/dt_cg.c
+++ b/libdtrace/dt_cg.c
@@ -3547,6 +3547,106 @@ dt_cg_subr_rand(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
 	TRACE_REGSET("    subr-rand:End  ");
 }
 
+/*
+ * This function is a helper function for subroutines that take some
+ * (8-byte) temporary space and a lock argument, returning the value
+ * from a given BPF function (passed by name).
+ */
+static void
+dt_cg_subr_lock_helper(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp,
+		       const char *fname)
+{
+	dt_ident_t	*idp = dt_dlib_get_func(yypcb->pcb_hdl, fname);
+	dt_node_t	*lock = dnp->dn_args;
+	uint64_t	off = dt_cg_tstring_xalloc(yypcb);
+
+	assert(idp != NULL);
+
+	TRACE_REGSET("    subr-lock_helper:Begin");
+
+	dt_cg_node(lock, dlp, drp);
+	dt_cg_check_notnull(dlp, drp, lock->dn_reg);
+
+	if (dt_regset_xalloc_args(drp) == -1)
+		longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+
+	emit(dlp, BPF_LOAD(BPF_DW, BPF_REG_1, BPF_REG_FP, DT_STK_DCTX));
+	emit(dlp, BPF_LOAD(BPF_DW, BPF_REG_1, BPF_REG_1, DCTX_MEM));
+	emit(dlp, BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, off));
+
+	emit(dlp, BPF_MOV_REG(BPF_REG_2, lock->dn_reg));
+	dt_regset_free(drp, lock->dn_reg);
+
+	dt_regset_xalloc(drp, BPF_REG_0);
+	emite(dlp,  BPF_CALL_FUNC(idp->di_id), idp);
+	dt_regset_free_args(drp);
+	dt_cg_tstring_xfree(yypcb, off);
+
+	dnp->dn_reg = dt_regset_alloc(drp);
+	if (dnp->dn_reg == -1)
+		longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+	emit(dlp, BPF_MOV_REG(dnp->dn_reg, BPF_REG_0));
+	dt_regset_free(drp, BPF_REG_0);
+
+	TRACE_REGSET("    subr-lock_helper:End  ");
+}
+
+static void
+dt_cg_subr_mutex_owned(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
+{
+	dt_cg_subr_lock_helper(dnp, dlp, drp, "dt_mutex_owned");
+}
+
+static void
+dt_cg_subr_mutex_owner(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
+{
+	dt_cg_subr_lock_helper(dnp, dlp, drp, "dt_mutex_owner");
+}
+
+static void
+dt_cg_subr_rw_read_held(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
+{
+	dt_cg_subr_lock_helper(dnp, dlp, drp, "dt_rw_read_held");
+}
+
+static void
+dt_cg_subr_rw_write_held(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
+{
+	dt_cg_subr_lock_helper(dnp, dlp, drp, "dt_rw_write_held");
+}
+
+static void
+dt_cg_subr_rw_iswriter(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
+{
+	dt_cg_subr_lock_helper(dnp, dlp, drp, "dt_rw_iswriter");
+}
+
+/* On Linux, all mutexes are adaptive. */
+
+static void
+dt_cg_subr_mutex_type_adaptive(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
+{
+	dt_node_t	*arg = dnp->dn_args;
+
+	TRACE_REGSET("    subr-mutex_type_adaptive:Begin");
+	dt_cg_node(arg, dlp, drp);
+	dnp->dn_reg = arg->dn_reg;
+	emit(dlp,  BPF_MOV_IMM(dnp->dn_reg, 1));
+	TRACE_REGSET("    subr-mutex_type_adaptive:End  ");
+}
+
+static void
+dt_cg_subr_mutex_type_spin(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
+{
+	dt_node_t	*arg = dnp->dn_args;
+
+	TRACE_REGSET("    subr-mutex_type_spin:Begin");
+	dt_cg_node(arg, dlp, drp);
+	dnp->dn_reg = arg->dn_reg;
+	emit(dlp,  BPF_MOV_IMM(dnp->dn_reg, 0));
+	TRACE_REGSET("    subr-mutex_type_spin:End  ");
+}
+
 static void
 dt_cg_subr_rindex(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
 {
@@ -4154,13 +4254,13 @@ typedef void dt_cg_subr_f(dt_node_t *, dt_irlist_t *, dt_regset_t *);
 
 static dt_cg_subr_f *_dt_cg_subr[DIF_SUBR_MAX + 1] = {
 	[DIF_SUBR_RAND]			= &dt_cg_subr_rand,
-	[DIF_SUBR_MUTEX_OWNED]		= NULL,
-	[DIF_SUBR_MUTEX_OWNER]		= NULL,
-	[DIF_SUBR_MUTEX_TYPE_ADAPTIVE]	= NULL,
-	[DIF_SUBR_MUTEX_TYPE_SPIN]	= NULL,
-	[DIF_SUBR_RW_READ_HELD]		= NULL,
-	[DIF_SUBR_RW_WRITE_HELD]	= NULL,
-	[DIF_SUBR_RW_ISWRITER]		= NULL,
+	[DIF_SUBR_MUTEX_OWNED]		= &dt_cg_subr_mutex_owned,
+	[DIF_SUBR_MUTEX_OWNER]		= &dt_cg_subr_mutex_owner,
+	[DIF_SUBR_MUTEX_TYPE_ADAPTIVE]	= &dt_cg_subr_mutex_type_adaptive,
+	[DIF_SUBR_MUTEX_TYPE_SPIN]	= &dt_cg_subr_mutex_type_spin,
+	[DIF_SUBR_RW_READ_HELD]		= &dt_cg_subr_rw_read_held,
+	[DIF_SUBR_RW_WRITE_HELD]	= &dt_cg_subr_rw_write_held,
+	[DIF_SUBR_RW_ISWRITER]		= &dt_cg_subr_rw_iswriter,
 	[DIF_SUBR_COPYIN]		= NULL,
 	[DIF_SUBR_COPYINSTR]		= NULL,
 	[DIF_SUBR_SPECULATION]		= &dt_cg_subr_speculation,
diff --git a/libdtrace/dt_dlibs.c b/libdtrace/dt_dlibs.c
index efbd3261..9d742ab5 100644
--- a/libdtrace/dt_dlibs.c
+++ b/libdtrace/dt_dlibs.c
@@ -83,6 +83,8 @@ static const dt_ident_t		dt_bpf_symbols[] = {
 	DT_BPF_SYMBOL_ID(TASK_TGID, DT_IDENT_SCALAR, DT_CONST_TASK_TGID),
 	DT_BPF_SYMBOL_ID(TASK_REAL_PARENT, DT_IDENT_SCALAR, DT_CONST_TASK_REAL_PARENT),
 	DT_BPF_SYMBOL_ID(TASK_COMM, DT_IDENT_SCALAR, DT_CONST_TASK_COMM),
+	DT_BPF_SYMBOL_ID(MUTEX_OWNER, DT_IDENT_SCALAR, DT_CONST_MUTEX_OWNER),
+	DT_BPF_SYMBOL_ID(RWLOCK_CNTS, DT_IDENT_SCALAR, DT_CONST_RWLOCK_CNTS),
 
 	/* End-of-list marker */
 	{ NULL, }
diff --git a/test/unittest/funcs/err.D_PROTO_LEN.mtabadarg.d b/test/unittest/funcs/err.D_PROTO_ARG.mtabadarg.d
similarity index 90%
rename from test/unittest/funcs/err.D_PROTO_LEN.mtabadarg.d
rename to test/unittest/funcs/err.D_PROTO_ARG.mtabadarg.d
index 7dad4aa0..4fe39003 100644
--- a/test/unittest/funcs/err.D_PROTO_LEN.mtabadarg.d
+++ b/test/unittest/funcs/err.D_PROTO_ARG.mtabadarg.d
@@ -16,6 +16,6 @@
 
 BEGIN
 {
-	mutex_type_adaptive(trace());
+	mutex_type_adaptive(trace("badarg"));
 	exit(1);
 }
diff --git a/test/unittest/funcs/err.D_PROTO_ARG.mtabadarg.r b/test/unittest/funcs/err.D_PROTO_ARG.mtabadarg.r
new file mode 100644
index 00000000..29bdbcd9
--- /dev/null
+++ b/test/unittest/funcs/err.D_PROTO_ARG.mtabadarg.r
@@ -0,0 +1,4 @@
+-- @@stderr --
+dtrace: failed to compile script test/unittest/funcs/err.D_PROTO_ARG.mtabadarg.d: [D_PROTO_ARG] line 19: mutex_type_adaptive( ) argument #1 is incompatible with prototype:
+	prototype: struct mutex *
+	 argument: void
diff --git a/test/unittest/funcs/err.D_PROTO_LEN.motoofew.d b/test/unittest/funcs/err.D_PROTO_LEN.motoofew.d
index 779bb547..7b310c3a 100644
--- a/test/unittest/funcs/err.D_PROTO_LEN.motoofew.d
+++ b/test/unittest/funcs/err.D_PROTO_LEN.motoofew.d
@@ -1,20 +1,16 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2022, Oracle and/or its affiliates. All rights reserved.
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  */
-/* @@xfail: dtv2 */
-
 /*
- * ASSERTION:
- *	mutex_owned() should handle too few args passed
+ * ASSERTION: mutex_owned() should handle too few args passed
  *
  * SECTION: Actions and Subroutines/mutex_owned()
- *
  */
 
-lockstat:genunix:mutex_enter:adaptive-acquire
+BEGIN
 {
 	mutex_owned();
 	exit(1);
diff --git a/test/unittest/funcs/err.D_PROTO_LEN.motoofew.r b/test/unittest/funcs/err.D_PROTO_LEN.motoofew.r
new file mode 100644
index 00000000..1367ae0b
--- /dev/null
+++ b/test/unittest/funcs/err.D_PROTO_LEN.motoofew.r
@@ -0,0 +1,2 @@
+-- @@stderr --
+dtrace: failed to compile script test/unittest/funcs/err.D_PROTO_LEN.motoofew.d: [D_PROTO_LEN] line 15: mutex_owned( ) prototype mismatch: 0 args passed, 1 expected
diff --git a/test/unittest/funcs/err.D_PROTO_LEN.motoomany.d b/test/unittest/funcs/err.D_PROTO_LEN.motoomany.d
index bdeb30bc..3b197467 100644
--- a/test/unittest/funcs/err.D_PROTO_LEN.motoomany.d
+++ b/test/unittest/funcs/err.D_PROTO_LEN.motoomany.d
@@ -1,20 +1,17 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2022, Oracle and/or its affiliates. All rights reserved.
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  */
-/* @@xfail: dtv2 */
 /*
- * ASSERTION:
- *	mutex_owned() should handle too many args passed
+ * ASSERTION: mutex_owned() should handle too many args passed
  *
  * SECTION: Actions and Subroutines/mutex_owned()
- *
  */
 
-lockstat:genunix:mutex_enter:adaptive-acquire
+BEGIN
 {
-	mutex_owned((kmutex_t *)arg0, 99);
+	mutex_owned(0, 99);
 	exit(1);
 }
diff --git a/test/unittest/funcs/err.D_PROTO_LEN.motoomany.r b/test/unittest/funcs/err.D_PROTO_LEN.motoomany.r
index f0d0ca22..3cf80ef1 100644
--- a/test/unittest/funcs/err.D_PROTO_LEN.motoomany.r
+++ b/test/unittest/funcs/err.D_PROTO_LEN.motoomany.r
@@ -1,2 +1,2 @@
 -- @@stderr --
-dtrace: failed to compile script test/unittest/funcs/err.D_PROTO_LEN.motoomany.d: [D_SYNTAX] line 18: syntax error near ")"
+dtrace: failed to compile script test/unittest/funcs/err.D_PROTO_LEN.motoomany.d: [D_PROTO_LEN] line 15: mutex_owned( ) prototype mismatch: 2 args passed, 1 expected
diff --git a/test/unittest/funcs/err.D_PROTO_LEN.mtabadarg.r b/test/unittest/funcs/err.D_PROTO_LEN.mtabadarg.r
deleted file mode 100644
index 79810cfe..00000000
--- a/test/unittest/funcs/err.D_PROTO_LEN.mtabadarg.r
+++ /dev/null
@@ -1,2 +0,0 @@
--- @@stderr --
-dtrace: failed to compile script test/unittest/funcs/err.D_PROTO_LEN.mtabadarg.d: [D_PROTO_LEN] line 19: trace( ) prototype mismatch: 0 args passed, 1 expected
diff --git a/test/unittest/funcs/err.D_PROTO_LEN.mtatoofew.d b/test/unittest/funcs/err.D_PROTO_LEN.mtatoofew.d
index dce985c6..b582d554 100644
--- a/test/unittest/funcs/err.D_PROTO_LEN.mtatoofew.d
+++ b/test/unittest/funcs/err.D_PROTO_LEN.mtatoofew.d
@@ -1,21 +1,16 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved.
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  */
-/* @@xfail: dtv2 */
-
 /*
- * ASSERTION:
- *	mutex_type_adaptive() should handle too few args passed
+ * ASSERTION: mutex_type_adaptive() should handle too few args passed
  *
  * SECTION: Actions and Subroutines/mutex_type_adaptive()
- *
  */
 
-
-lockstat:genunix:mutex_enter:adaptive-acquire
+BEGIN
 {
 	mutex_type_adaptive();
 	exit(1);
diff --git a/test/unittest/funcs/err.D_PROTO_LEN.mtatoofew.r b/test/unittest/funcs/err.D_PROTO_LEN.mtatoofew.r
new file mode 100644
index 00000000..7a1936d4
--- /dev/null
+++ b/test/unittest/funcs/err.D_PROTO_LEN.mtatoofew.r
@@ -0,0 +1,2 @@
+-- @@stderr --
+dtrace: failed to compile script test/unittest/funcs/err.D_PROTO_LEN.mtatoofew.d: [D_PROTO_LEN] line 15: mutex_type_adaptive( ) prototype mismatch: 0 args passed, 1 expected
diff --git a/test/unittest/funcs/err.D_PROTO_LEN.mtatoomany.d b/test/unittest/funcs/err.D_PROTO_LEN.mtatoomany.d
index e516890c..6f08673d 100644
--- a/test/unittest/funcs/err.D_PROTO_LEN.mtatoomany.d
+++ b/test/unittest/funcs/err.D_PROTO_LEN.mtatoomany.d
@@ -1,21 +1,17 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved.
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  */
-/* @@xfail: dtv2 */
 /*
- * ASSERTION:
- *	mutex_type_adaptive() should handle too many args passed
+ * ASSERTION: mutex_type_adaptive() should handle too many args passed
  *
  * SECTION: Actions and Subroutines/mutex_type_adaptive()
- *
  */
 
-
-lockstat:genunix:mutex_enter:adaptive-acquire
+BEGIN
 {
-	mutex_type_adaptive((kmutex_t *)arg0, 99);
+	mutex_type_adaptive(0, 99);
 	exit(1);
 }
diff --git a/test/unittest/funcs/err.D_PROTO_LEN.mtatoomany.r b/test/unittest/funcs/err.D_PROTO_LEN.mtatoomany.r
index 5efeff80..efc9b4ed 100644
--- a/test/unittest/funcs/err.D_PROTO_LEN.mtatoomany.r
+++ b/test/unittest/funcs/err.D_PROTO_LEN.mtatoomany.r
@@ -1,2 +1,2 @@
 -- @@stderr --
-dtrace: failed to compile script test/unittest/funcs/err.D_PROTO_LEN.mtatoomany.d: [D_SYNTAX] line 19: syntax error near ")"
+dtrace: failed to compile script test/unittest/funcs/err.D_PROTO_LEN.mtatoomany.d: [D_PROTO_LEN] line 15: mutex_type_adaptive( ) prototype mismatch: 2 args passed, 1 expected
diff --git a/test/unittest/funcs/tst.mutex_owned.d b/test/unittest/funcs/tst.mutex_owned.d
index 8e9c2893..4fd94c35 100644
--- a/test/unittest/funcs/tst.mutex_owned.d
+++ b/test/unittest/funcs/tst.mutex_owned.d
@@ -1,10 +1,9 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved.
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  */
-/* @@xfail: dtv2 */
 
 /*
  * ASSERTION:
diff --git a/test/unittest/funcs/tst.mutex_owner.d b/test/unittest/funcs/tst.mutex_owner.d
index d68af367..162533a6 100644
--- a/test/unittest/funcs/tst.mutex_owner.d
+++ b/test/unittest/funcs/tst.mutex_owner.d
@@ -1,10 +1,9 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved.
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  */
-/* @@xfail: dtv2 */
 
 /*
  * ASSERTION:
diff --git a/test/unittest/funcs/tst.mutex_type_adaptive.d b/test/unittest/funcs/tst.mutex_type_adaptive.d
index c8c60872..e095da69 100644
--- a/test/unittest/funcs/tst.mutex_type_adaptive.d
+++ b/test/unittest/funcs/tst.mutex_type_adaptive.d
@@ -1,10 +1,9 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved.
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  */
-/* @@xfail: dtv2 */
 
 /*
  * ASSERTION:
diff --git a/test/unittest/funcs/tst.mutex_type_spin.d b/test/unittest/funcs/tst.mutex_type_spin.d
index 894f5ced..6e853387 100644
--- a/test/unittest/funcs/tst.mutex_type_spin.d
+++ b/test/unittest/funcs/tst.mutex_type_spin.d
@@ -1,10 +1,9 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved.
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  */
-/* @@xfail: dtv2 */
 
 /*
  * ASSERTION:
diff --git a/test/unittest/funcs/tst.rw_.r b/test/unittest/funcs/tst.rw_.r
new file mode 100644
index 00000000..3b7de46e
--- /dev/null
+++ b/test/unittest/funcs/tst.rw_.r
@@ -0,0 +1,12 @@
+finish
+read  entry  0 0 0
+read  entry  0 0 0
+read  entry  0 0 0
+read  entry  0 0 0
+read  return 0 1 0
+read  return 0 1 0
+read  return 0 1 0
+read  return 0 1 0
+write entry  0 0 0
+write return 1 0 1
+
diff --git a/test/unittest/funcs/tst.rw_.sh b/test/unittest/funcs/tst.rw_.sh
new file mode 100755
index 00000000..163a4f4e
--- /dev/null
+++ b/test/unittest/funcs/tst.rw_.sh
@@ -0,0 +1,96 @@
+#!/bin/bash
+#
+# Oracle Linux DTrace.
+# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
+# Licensed under the Universal Permissive License v 1.0 as shown at
+# http://oss.oracle.com/licenses/upl.
+
+# This test for the subroutines
+#     rw_read_held()
+#     rw_write_held()
+#     rw_iswriter()
+# may prove not to be very robust.  It does not identify a workload that
+# is known to exercise the read-write locks well.  So we simply sit on
+# _raw_read_lock and _raw_write_lock FBT probes and hope there is some
+# activity.  The .r file assumes the locks are uncontested.
+
+dtrace=$1
+tmpfile=$tmpdir/tst.rw_.$$
+
+$dtrace $dt_flags -qn '
+
+/* desired numbers of read and write events */
+
+BEGIN
+{
+	nr = 4;
+	nw = 1;
+}
+
+/* read events */
+
+fbt:vmlinux:_raw_read_lock:entry
+/nr > 0/
+{
+	self->rlock = (rwlock_t *)arg0;
+	nr--;
+	printf("read  entry  %x %x %x\n",
+		0 != rw_iswriter(self->rlock),
+		0 != rw_read_held(self->rlock),
+		0 != rw_write_held(self->rlock));
+}
+
+fbt:vmlinux:_raw_read_lock:return
+/self->rlock/
+{
+	printf("read  return %x %x %x\n",
+		0 != rw_iswriter(self->rlock),
+		0 != rw_read_held(self->rlock),
+		0 != rw_write_held(self->rlock));
+	self->rlock = 0;
+}
+
+/* write events */
+
+fbt:vmlinux:_raw_write_lock:entry
+/nw > 0/
+{
+	self->wlock = (rwlock_t *)arg0;
+	nw--;
+	printf("write entry  %x %x %x\n",
+		0 != rw_iswriter(self->wlock),
+		0 != rw_read_held(self->wlock),
+		0 != rw_write_held(self->wlock));
+}
+
+fbt:vmlinux:_raw_write_lock:return
+/self->wlock/
+{
+	printf("write return %x %x %x\n",
+		0 != rw_iswriter(self->wlock),
+		0 != rw_read_held(self->wlock),
+		0 != rw_write_held(self->wlock));
+	self->wlock = 0;
+}
+
+/* termination */
+
+fbt:vmlinux:_raw_read_lock:return,
+fbt:vmlinux:_raw_write_lock:return
+/nr == 0 && nw == 0/
+{
+	printf("finish\n");
+	exit(0);
+}
+' >& $tmpfile
+
+if [ $? -ne 0 ]; then
+	echo "DTrace error"
+	cat $tmpfile
+	exit 1
+fi
+
+sort $tmpfile
+
+exit 0
+
diff --git a/test/unittest/funcs/tst.rw_.x b/test/unittest/funcs/tst.rw_.x
new file mode 100755
index 00000000..29c58111
--- /dev/null
+++ b/test/unittest/funcs/tst.rw_.x
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+FUNCS=/sys/kernel/debug/tracing/available_filter_functions
+
+if ! grep -qw  _raw_read_lock $FUNCS; then
+        echo no _raw_read_lock FBT probe due to kernel config
+        exit 1
+fi
+
+if ! grep -w _raw_write_lock $FUNCS; then
+        echo no _raw_write_lock FBT probe due to kernel config
+        exit 1
+fi
+
+exit 0
-- 
2.18.4




More information about the DTrace-devel mailing list