2 * Copyright (C) 2017 National Instruments Corp.
4 * Author: Julia Cartwright <julia@ni.com>
6 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation;
10 * version 2.1 of the License (not later!)
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this program; if not, see <http://www.gnu.org/licenses>
20 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25 #include <linux/futex.h>
27 #include "event-parse.h"
29 #define ARRAY_SIZE(_a) (sizeof(_a) / sizeof((_a)[0]))
32 unsigned long long uaddr;
33 unsigned long long op;
34 unsigned long long val;
35 unsigned long long utime; /* or val2 */
36 unsigned long long uaddr2;
37 unsigned long long val3;
43 const char *fmt_utime;
44 const char *fmt_uaddr2;
48 static const struct futex_op futex_op_tbl[] = {
49 { "FUTEX_WAIT", " val=0x%08llx", " utime=0x%08llx", NULL, NULL },
50 { "FUTEX_WAKE", " val=%llu", NULL, NULL, NULL },
51 { "FUTEX_FD", " val=%llu", NULL, NULL, NULL },
52 { "FUTEX_REQUEUE", " val=%llu", " val2=%llu", " uaddr2=0x%08llx", NULL },
53 { "FUTEX_CMP_REQUEUE", " val=%llu", " val2=%llu", " uaddr2=0x%08llx", " val3=0x%08llx" },
54 { "FUTEX_WAKE_OP", " val=%llu", " val2=%llu", " uaddr2=0x%08llx", " val3=0x%08llx" },
55 { "FUTEX_LOCK_PI", NULL, " utime=0x%08llx", NULL, NULL },
56 { "FUTEX_UNLOCK_PI", NULL, NULL, NULL, NULL },
57 { "FUTEX_TRYLOCK_PI", NULL, NULL, NULL, NULL },
58 { "FUTEX_WAIT_BITSET", " val=0x%08llx", " utime=0x%08llx", NULL, " val3=0x%08llx" },
59 { "FUTEX_WAKE_BITSET", " val=%llu", NULL, NULL, " val3=0x%08llx" },
60 { "FUTEX_WAIT_REQUEUE_PI", " val=0x%08llx", " utime=0x%08llx", " uaddr2=0x%08llx", " val3=0x%08llx" },
61 { "FUTEX_CMP_REQUEUE_PI", " val=%llu", " val2=%llu", " uaddr2=0x%08llx", " val3=0x%08llx" },
65 static void futex_print(struct trace_seq *s, const struct futex_args *args,
66 const struct futex_op *fop)
68 trace_seq_printf(s, " uaddr=0x%08llx", args->uaddr);
71 trace_seq_printf(s, fop->fmt_val, args->val);
74 trace_seq_printf(s,fop->fmt_utime, args->utime);
77 trace_seq_printf(s, fop->fmt_uaddr2, args->uaddr2);
80 trace_seq_printf(s, fop->fmt_val3, args->val3);
83 static int futex_handler(struct trace_seq *s, struct tep_record *record,
84 struct tep_event *event, void *context)
86 const struct futex_op *fop;
87 struct futex_args args;
88 unsigned long long cmd;
90 if (tep_get_field_val(s, event, "uaddr", record, &args.uaddr, 1))
93 if (tep_get_field_val(s, event, "op", record, &args.op, 1))
96 if (tep_get_field_val(s, event, "val", record, &args.val, 1))
99 if (tep_get_field_val(s, event, "utime", record, &args.utime, 1))
102 if (tep_get_field_val(s, event, "uaddr2", record, &args.uaddr2, 1))
105 if (tep_get_field_val(s, event, "val3", record, &args.val3, 1))
108 cmd = args.op & FUTEX_CMD_MASK;
109 if (cmd >= ARRAY_SIZE(futex_op_tbl))
112 fop = &futex_op_tbl[cmd];
114 trace_seq_printf(s, "op=%s", fop->name);
116 if (args.op & FUTEX_PRIVATE_FLAG)
117 trace_seq_puts(s, "|FUTEX_PRIVATE_FLAG");
119 if (args.op & FUTEX_CLOCK_REALTIME)
120 trace_seq_puts(s, "|FUTEX_CLOCK_REALTIME");
122 futex_print(s, &args, fop);
126 int TEP_PLUGIN_LOADER(struct tep_handle *tep)
128 tep_register_event_handler(tep, -1, "syscalls", "sys_enter_futex",
129 futex_handler, NULL);
133 void TEP_PLUGIN_UNLOADER(struct tep_handle *tep)
135 tep_unregister_event_handler(tep, -1, "syscalls", "sys_enter_futex",
136 futex_handler, NULL);