Skip to content

Commit

Permalink
Implement the sched provider (first part)
Browse files Browse the repository at this point in the history
Partial implementation of the sched SDT provider.  The following probes
are implemented:

sched:::dequeue (arg1 is NULL)
sched:::enqueue (arg1 is NULL)
sched:::off-cpu
sched:::on-cpu (limited trigger locations)
sched:::surrender
sched:::tick
sched:::wakeup

Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
Reviewed-by: Nick Alcock <nick.alcock@oracle.com>
  • Loading branch information
kvanhees committed May 25, 2023
1 parent cbee253 commit b90e4f5
Show file tree
Hide file tree
Showing 36 changed files with 357 additions and 11 deletions.
2 changes: 2 additions & 0 deletions libdtrace/Build
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ libdtrace-build_SOURCES = dt_aggregate.c \
dt_prov_proc.c \
dt_prov_profile.c \
dt_prov_rawtp.c \
dt_prov_sched.c \
dt_prov_sdt.c \
dt_prov_syscall.c \
dt_prov_uprobe.c \
Expand Down Expand Up @@ -96,6 +97,7 @@ dt_prov_fbt.c_CFLAGS := -Wno-pedantic
dt_prov_proc.c_CFLAGS := -Wno-pedantic
dt_prov_profile.c_CFLAGS := -Wno-pedantic
dt_prov_rawtp.c_CFLAGS := -Wno-pedantic
dt_prov_sched.c_CFLAGS := -Wno-pedantic
dt_prov_sdt.c_CFLAGS := -Wno-pedantic
dt_prov_syscall.c_CFLAGS := -Wno-pedantic
dt_prov_uprobe.c_CFLAGS := -Wno-pedantic
Expand Down
1 change: 1 addition & 0 deletions libdtrace/dt_open.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ static const dt_provimpl_t *dt_providers[] = {
&dt_proc,
&dt_profile,
&dt_rawtp,
&dt_sched,
&dt_sdt,
&dt_syscall,
&dt_uprobe,
Expand Down
151 changes: 151 additions & 0 deletions libdtrace/dt_prov_sched.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
/*
* Oracle Linux DTrace.
* Copyright (c) 2023, 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.
*
* The 'sched' SDT provider for DTrace-specific probes.
*/
#include <assert.h>
#include <errno.h>

#include "dt_dctx.h"
#include "dt_cg.h"
#include "dt_provider_sdt.h"
#include "dt_probe.h"

static const char prvname[] = "sched";
static const char modname[] = "vmlinux";

static probe_dep_t probes[] = {
{ "dequeue",
DTRACE_PROBESPEC_NAME, "fbt::dequeue_task_*:entry" },
{ "enqueue",
DTRACE_PROBESPEC_NAME, "fbt::enqueue_task_*:entry" },
{ "off-cpu",
DTRACE_PROBESPEC_NAME, "rawtp:sched::sched_switch" },
{ "on-cpu",
DTRACE_PROBESPEC_NAME, "fbt::schedule_tail:entry" },
{ "surrender",
DTRACE_PROBESPEC_NAME, "fbt::do_sched_yield:entry" },
{ "tick",
DTRACE_PROBESPEC_NAME, "fbt::scheduler_tick:entry" },
{ "wakeup",
DTRACE_PROBESPEC_NAME, "rawtp:sched::sched_wakeup" },
{ NULL, }
};

static probe_arg_t probe_args[] = {
#if 0
{ "change-pri", 0, { 0, 0, "struct task_struct *", "lwpsinfo_t *" } },
{ "change-pri", 1, { 0, 0, "struct task_struct *", "psinfo_t *" } },
{ "change-pri", 2, { 1, 0, "int", } },
#endif
{ "dequeue", 0, { 0, 0, "struct task_struct *", "lwpsinfo_t *" } },
{ "dequeue", 1, { 0, 0, "struct task_struct *", "psinfo_t *" } },
{ "dequeue", 2, { 1, 0, "cpuinfo_t *", } },
{ "dequeue", 3, { 2, 0, "int", } },
{ "enqueue", 0, { 0, 0, "struct task_struct *", "lwpsinfo_t *" } },
{ "enqueue", 1, { 0, 0, "struct task_struct *", "psinfo_t *" } },
{ "enqueue", 2, { 1, 0, "cpuinfo_t *", } },
{ "off-cpu", 0, { 0, 0, "struct task_struct *", "lwpsinfo_t *" } },
{ "off-cpu", 1, { 0, 0, "struct task_struct *", "psinfo_t *" } },
{ "on-cpu", },
#if 0
{ "preempt", },
{ "remain-cpu", },
{ "sleep", },
#endif
{ "surrender", 0, { 0, 0, "struct task_struct *", "lwpsinfo_t *" } },
{ "surrender", 1, { 0, 0, "struct task_struct *", "psinfo_t *" } },
{ "tick", 0, { 0, 0, "struct task_struct *", "lwpsinfo_t *" } },
{ "tick", 1, { 0, 0, "struct task_struct *", "psinfo_t *" } },
{ "wakeup", 0, { 0, 0, "struct task_struct *", "lwpsinfo_t *" } },
{ "wakeup", 1, { 0, 0, "struct task_struct *", "psinfo_t *" } },
{ NULL, }
};

static const dtrace_pattr_t pattr = {
{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },
{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },
{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },
};

/*
* Provide all the "sched" SDT probes.
*/
static int populate(dtrace_hdl_t *dtp)
{
return dt_sdt_populate(dtp, prvname, modname, &dt_sched, &pattr,
probe_args, probes);
}

/*
* Generate a BPF trampoline for a SDT probe.
*
* The trampoline function is called when a SDT probe triggers, and it must
* satisfy the following prototype:
*
* int dt_sched(void *data)
*
* The trampoline will populate a dt_dctx_t struct and then call the function
* that implements the compiled D clause. It returns the value that it gets
* back from that function.
*/
static int trampoline(dt_pcb_t *pcb, uint_t exitlbl)
{
dt_irlist_t *dlp = &pcb->pcb_ir;
dt_probe_t *prp = pcb->pcb_probe;

if (strcmp(prp->desc->prb, "dequeue") == 0) {
emit(dlp, BPF_LOAD(BPF_DW, BPF_REG_0, BPF_REG_7, DMST_ARG(1)));
emit(dlp, BPF_STORE(BPF_DW, BPF_REG_7, DMST_ARG(0), BPF_REG_0));
/*
* FIXME: arg1 should be a pointer to cpuinfo_t for the CPU
* associated with the runqueue.
*/
emit(dlp, BPF_STORE_IMM(BPF_DW, BPF_REG_7, DMST_ARG(1), 0));
} else if (strcmp(prp->desc->prb, "enqueue") == 0) {
/*
* This is ugly but necessary... enqueue_task() takes a flags argument and the
* ENQUEUE_HEAD flag is used to indicate that the task is to be placed at the
* head of the queue. We need to be able to pass this special case as arg2
* in the enqueue probe.
*
* The flag values are found in kernel/sched/sched.h which is not exposed
* outside the kernel source tree.
*/
#define ENQUEUE_HEAD 0x10

emit(dlp, BPF_LOAD(BPF_DW, BPF_REG_0, BPF_REG_7, DMST_ARG(1)));
emit(dlp, BPF_STORE(BPF_DW, BPF_REG_7, DMST_ARG(0), BPF_REG_0));
/*
* FIXME: arg1 should be a pointer to cpuinfo_t for the CPU
* associated with the runqueue.
*/
emit(dlp, BPF_STORE_IMM(BPF_DW, BPF_REG_7, DMST_ARG(1), 0));
emit(dlp, BPF_LOAD(BPF_DW, BPF_REG_0, BPF_REG_7, DMST_ARG(2)));
emit(dlp, BPF_ALU64_IMM(BPF_AND, BPF_REG_0, ENQUEUE_HEAD));
emit(dlp, BPF_STORE(BPF_DW, BPF_REG_7, DMST_ARG(2), BPF_REG_0));
} else if (strcmp(prp->desc->prb, "off-cpu") == 0) {
emit(dlp, BPF_LOAD(BPF_DW, BPF_REG_0, BPF_REG_7, DMST_ARG(2)));
emit(dlp, BPF_STORE(BPF_DW, BPF_REG_7, DMST_ARG(0), BPF_REG_0));
} else if (strcmp(prp->desc->prb, "surrender") == 0 ||
strcmp(prp->desc->prb, "tick") == 0) {
emit(dlp, BPF_CALL_HELPER(BPF_FUNC_get_current_task));
emit(dlp, BPF_STORE(BPF_DW, BPF_REG_7, DMST_ARG(0), BPF_REG_0));
}

return 0;
}

dt_provimpl_t dt_sched = {
.name = prvname,
.prog_type = BPF_PROG_TYPE_UNSPEC,
.populate = &populate,
.enable = &dt_sdt_enable,
.trampoline = &trampoline,
.probe_info = &dt_sdt_probe_info,
};
1 change: 1 addition & 0 deletions libdtrace/dt_provider.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ extern dt_provimpl_t dt_fbt;
extern dt_provimpl_t dt_proc;
extern dt_provimpl_t dt_profile;
extern dt_provimpl_t dt_rawtp;
extern dt_provimpl_t dt_sched;
extern dt_provimpl_t dt_sdt;
extern dt_provimpl_t dt_syscall;
extern dt_provimpl_t dt_uprobe;
Expand Down
1 change: 0 additions & 1 deletion test/demo/sched/dtrace.d
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
* Licensed under the Universal Permissive License v 1.0 as shown at
* http://oss.oracle.com/licenses/upl.
*/
/* @@xfail: dtv2 */

#pragma D option quiet

Expand Down
1 change: 0 additions & 1 deletion test/demo/sched/howlong.d
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
* Licensed under the Universal Permissive License v 1.0 as shown at
* http://oss.oracle.com/licenses/upl.
*/
/* @@xfail: dtv2 */

sched:::off-cpu
/curlwpsinfo->pr_state == SSLEEP/
Expand Down
1 change: 0 additions & 1 deletion test/demo/sched/qlen.d
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
* Licensed under the Universal Permissive License v 1.0 as shown at
* http://oss.oracle.com/licenses/upl.
*/
/* @@xfail: dtv2 */

sched:::enqueue
{
Expand Down
1 change: 0 additions & 1 deletion test/demo/sched/qtime.d
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
* Licensed under the Universal Permissive License v 1.0 as shown at
* http://oss.oracle.com/licenses/upl.
*/
/* @@xfail: dtv2 */

sched:::enqueue
{
Expand Down
1 change: 0 additions & 1 deletion test/demo/sched/tick.d
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
* Licensed under the Universal Permissive License v 1.0 as shown at
* http://oss.oracle.com/licenses/upl.
*/
/* @@xfail: dtv2 */

sched:::tick,
sched:::enqueue
Expand Down
1 change: 0 additions & 1 deletion test/demo/sched/ticktime.d
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
* Licensed under the Universal Permissive License v 1.0 as shown at
* http://oss.oracle.com/licenses/upl.
*/
/* @@xfail: dtv2 */

uint64_t last[int];

Expand Down
1 change: 0 additions & 1 deletion test/demo/sched/where.d
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
* Licensed under the Universal Permissive License v 1.0 as shown at
* http://oss.oracle.com/licenses/upl.
*/
/* @@xfail: dtv2 */

sched:::on-cpu
{
Expand Down
1 change: 0 additions & 1 deletion test/demo/sched/whoqueue.d
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
* Licensed under the Universal Permissive License v 1.0 as shown at
* http://oss.oracle.com/licenses/upl.
*/
/* @@xfail: dtv2 */

#pragma D option quiet
#pragma D option nspec=4
Expand Down
1 change: 0 additions & 1 deletion test/demo/sched/whosteal.d
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
* Licensed under the Universal Permissive License v 1.0 as shown at
* http://oss.oracle.com/licenses/upl.
*/
/* @@xfail: dtv2 */

#pragma D option quiet

Expand Down
1 change: 0 additions & 1 deletion test/unittest/buffering/tst.cputime.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
# http://oss.oracle.com/licenses/upl.
#
# @@timeout: 12
# @@xfail: dtv2

script()
{
Expand Down
18 changes: 18 additions & 0 deletions test/unittest/sched/tst.lv-dequeue.r
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
PROBE sched vmlinux dequeue

Probe Description Attributes
Identifier Names: Private
Data Semantics: Private
Dependency Class: Unknown

Argument Attributes
Identifier Names: Evolving
Data Semantics: Evolving
Dependency Class: ISA

Argument Types
args[0]: lwpsinfo_t *
args[1]: psinfo_t *
args[2]: cpuinfo_t *
args[3]: int

5 changes: 5 additions & 0 deletions test/unittest/sched/tst.lv-dequeue.r.p
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/usr/bin/awk -f
NR == 1 { next; }
NR == 2 { print "PROBE", $2, $3, $NF; next; }
/^ *[0-9]+/ { exit; }
{ print; }
11 changes: 11 additions & 0 deletions test/unittest/sched/tst.lv-dequeue.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/bin/bash
#
# Oracle Linux DTrace.
# Copyright (c) 2023, 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.

dtrace=$1

$dtrace $dt_flags -lvn sched:::dequeue
exit $?
17 changes: 17 additions & 0 deletions test/unittest/sched/tst.lv-enqueue.r
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
PROBE sched vmlinux enqueue

Probe Description Attributes
Identifier Names: Private
Data Semantics: Private
Dependency Class: Unknown

Argument Attributes
Identifier Names: Evolving
Data Semantics: Evolving
Dependency Class: ISA

Argument Types
args[0]: lwpsinfo_t *
args[1]: psinfo_t *
args[2]: cpuinfo_t *

1 change: 1 addition & 0 deletions test/unittest/sched/tst.lv-enqueue.r.p
11 changes: 11 additions & 0 deletions test/unittest/sched/tst.lv-enqueue.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/bin/bash
#
# Oracle Linux DTrace.
# Copyright (c) 2023, 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.

dtrace=$1

$dtrace $dt_flags -lvn sched:::enqueue
exit $?
16 changes: 16 additions & 0 deletions test/unittest/sched/tst.lv-off-cpu.r
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
PROBE sched vmlinux off-cpu

Probe Description Attributes
Identifier Names: Private
Data Semantics: Private
Dependency Class: Unknown

Argument Attributes
Identifier Names: Evolving
Data Semantics: Evolving
Dependency Class: ISA

Argument Types
args[0]: lwpsinfo_t *
args[1]: psinfo_t *

1 change: 1 addition & 0 deletions test/unittest/sched/tst.lv-off-cpu.r.p
11 changes: 11 additions & 0 deletions test/unittest/sched/tst.lv-off-cpu.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/bin/bash
#
# Oracle Linux DTrace.
# Copyright (c) 2023, 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.

dtrace=$1

$dtrace $dt_flags -lvn sched:::off-cpu
exit $?
15 changes: 15 additions & 0 deletions test/unittest/sched/tst.lv-on-cpu.r
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
PROBE sched vmlinux on-cpu

Probe Description Attributes
Identifier Names: Private
Data Semantics: Private
Dependency Class: Unknown

Argument Attributes
Identifier Names: Evolving
Data Semantics: Evolving
Dependency Class: ISA

Argument Types
None

1 change: 1 addition & 0 deletions test/unittest/sched/tst.lv-on-cpu.r.p
11 changes: 11 additions & 0 deletions test/unittest/sched/tst.lv-on-cpu.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/bin/bash
#
# Oracle Linux DTrace.
# Copyright (c) 2023, 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.

dtrace=$1

$dtrace $dt_flags -lvn sched:::on-cpu
exit $?

0 comments on commit b90e4f5

Please sign in to comment.