plugin_futex.c (3842B)
1// SPDX-License-Identifier: LGPL-2.1 2/* 3 * Copyright (C) 2017 National Instruments Corp. 4 * 5 * Author: Julia Cartwright <julia@ni.com> 6 * 7 */ 8#include <stdio.h> 9#include <stdlib.h> 10#include <string.h> 11#include <linux/futex.h> 12 13#include "event-parse.h" 14 15#define ARRAY_SIZE(_a) (sizeof(_a) / sizeof((_a)[0])) 16 17struct futex_args { 18 unsigned long long uaddr; 19 unsigned long long op; 20 unsigned long long val; 21 unsigned long long utime; /* or val2 */ 22 unsigned long long uaddr2; 23 unsigned long long val3; 24}; 25 26struct futex_op { 27 const char *name; 28 const char *fmt_val; 29 const char *fmt_utime; 30 const char *fmt_uaddr2; 31 const char *fmt_val3; 32}; 33 34static const struct futex_op futex_op_tbl[] = { 35 { "FUTEX_WAIT", " val=0x%08llx", " utime=0x%08llx", NULL, NULL }, 36 { "FUTEX_WAKE", " val=%llu", NULL, NULL, NULL }, 37 { "FUTEX_FD", " val=%llu", NULL, NULL, NULL }, 38 { "FUTEX_REQUEUE", " val=%llu", " val2=%llu", " uaddr2=0x%08llx", NULL }, 39 { "FUTEX_CMP_REQUEUE", " val=%llu", " val2=%llu", " uaddr2=0x%08llx", " val3=0x%08llx" }, 40 { "FUTEX_WAKE_OP", " val=%llu", " val2=%llu", " uaddr2=0x%08llx", " val3=0x%08llx" }, 41 { "FUTEX_LOCK_PI", NULL, " utime=0x%08llx", NULL, NULL }, 42 { "FUTEX_UNLOCK_PI", NULL, NULL, NULL, NULL }, 43 { "FUTEX_TRYLOCK_PI", NULL, NULL, NULL, NULL }, 44 { "FUTEX_WAIT_BITSET", " val=0x%08llx", " utime=0x%08llx", NULL, " val3=0x%08llx" }, 45 { "FUTEX_WAKE_BITSET", " val=%llu", NULL, NULL, " val3=0x%08llx" }, 46 { "FUTEX_WAIT_REQUEUE_PI", " val=0x%08llx", " utime=0x%08llx", " uaddr2=0x%08llx", " val3=0x%08llx" }, 47 { "FUTEX_CMP_REQUEUE_PI", " val=%llu", " val2=%llu", " uaddr2=0x%08llx", " val3=0x%08llx" }, 48}; 49 50 51static void futex_print(struct trace_seq *s, const struct futex_args *args, 52 const struct futex_op *fop) 53{ 54 trace_seq_printf(s, " uaddr=0x%08llx", args->uaddr); 55 56 if (fop->fmt_val) 57 trace_seq_printf(s, fop->fmt_val, args->val); 58 59 if (fop->fmt_utime) 60 trace_seq_printf(s,fop->fmt_utime, args->utime); 61 62 if (fop->fmt_uaddr2) 63 trace_seq_printf(s, fop->fmt_uaddr2, args->uaddr2); 64 65 if (fop->fmt_val3) 66 trace_seq_printf(s, fop->fmt_val3, args->val3); 67} 68 69static int futex_handler(struct trace_seq *s, struct tep_record *record, 70 struct tep_event *event, void *context) 71{ 72 const struct futex_op *fop; 73 struct futex_args args; 74 unsigned long long cmd; 75 76 if (tep_get_field_val(s, event, "uaddr", record, &args.uaddr, 1)) 77 return 1; 78 79 if (tep_get_field_val(s, event, "op", record, &args.op, 1)) 80 return 1; 81 82 if (tep_get_field_val(s, event, "val", record, &args.val, 1)) 83 return 1; 84 85 if (tep_get_field_val(s, event, "utime", record, &args.utime, 1)) 86 return 1; 87 88 if (tep_get_field_val(s, event, "uaddr2", record, &args.uaddr2, 1)) 89 return 1; 90 91 if (tep_get_field_val(s, event, "val3", record, &args.val3, 1)) 92 return 1; 93 94 cmd = args.op & FUTEX_CMD_MASK; 95 if (cmd >= ARRAY_SIZE(futex_op_tbl)) 96 return 1; 97 98 fop = &futex_op_tbl[cmd]; 99 100 trace_seq_printf(s, "op=%s", fop->name); 101 102 if (args.op & FUTEX_PRIVATE_FLAG) 103 trace_seq_puts(s, "|FUTEX_PRIVATE_FLAG"); 104 105 if (args.op & FUTEX_CLOCK_REALTIME) 106 trace_seq_puts(s, "|FUTEX_CLOCK_REALTIME"); 107 108 futex_print(s, &args, fop); 109 return 0; 110} 111 112int TEP_PLUGIN_LOADER(struct tep_handle *tep) 113{ 114 tep_register_event_handler(tep, -1, "syscalls", "sys_enter_futex", 115 futex_handler, NULL); 116 return 0; 117} 118 119void TEP_PLUGIN_UNLOADER(struct tep_handle *tep) 120{ 121 tep_unregister_event_handler(tep, -1, "syscalls", "sys_enter_futex", 122 futex_handler, NULL); 123}