Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: LGPL-2.1
0002 /*
0003  * Copyright (C) 2017 National Instruments Corp.
0004  *
0005  * Author: Julia Cartwright <julia@ni.com>
0006  *
0007  */
0008 #include <stdio.h>
0009 #include <stdlib.h>
0010 #include <string.h>
0011 #include <linux/futex.h>
0012 
0013 #include "event-parse.h"
0014 
0015 #define ARRAY_SIZE(_a) (sizeof(_a) / sizeof((_a)[0]))
0016 
0017 struct futex_args {
0018     unsigned long long  uaddr;
0019     unsigned long long  op;
0020     unsigned long long  val;
0021     unsigned long long  utime; /* or val2 */
0022     unsigned long long  uaddr2;
0023     unsigned long long  val3;
0024 };
0025 
0026 struct futex_op {
0027     const char  *name;
0028     const char  *fmt_val;
0029     const char  *fmt_utime;
0030     const char  *fmt_uaddr2;
0031     const char  *fmt_val3;
0032 };
0033 
0034 static const struct futex_op futex_op_tbl[] = {
0035     {            "FUTEX_WAIT", " val=0x%08llx", " utime=0x%08llx",               NULL,             NULL },
0036     {            "FUTEX_WAKE",     " val=%llu",              NULL,               NULL,             NULL },
0037     {              "FUTEX_FD",     " val=%llu",              NULL,               NULL,             NULL },
0038     {         "FUTEX_REQUEUE",     " val=%llu",      " val2=%llu", " uaddr2=0x%08llx",             NULL },
0039     {     "FUTEX_CMP_REQUEUE",     " val=%llu",      " val2=%llu", " uaddr2=0x%08llx", " val3=0x%08llx" },
0040     {         "FUTEX_WAKE_OP",     " val=%llu",      " val2=%llu", " uaddr2=0x%08llx", " val3=0x%08llx" },
0041     {         "FUTEX_LOCK_PI",            NULL, " utime=0x%08llx",               NULL,             NULL },
0042     {       "FUTEX_UNLOCK_PI",            NULL,              NULL,               NULL,             NULL },
0043     {      "FUTEX_TRYLOCK_PI",            NULL,              NULL,               NULL,             NULL },
0044     {     "FUTEX_WAIT_BITSET", " val=0x%08llx", " utime=0x%08llx",               NULL, " val3=0x%08llx" },
0045     {     "FUTEX_WAKE_BITSET",     " val=%llu",              NULL,               NULL, " val3=0x%08llx" },
0046     { "FUTEX_WAIT_REQUEUE_PI", " val=0x%08llx", " utime=0x%08llx", " uaddr2=0x%08llx", " val3=0x%08llx" },
0047     {  "FUTEX_CMP_REQUEUE_PI",     " val=%llu",      " val2=%llu", " uaddr2=0x%08llx", " val3=0x%08llx" },
0048 };
0049 
0050 
0051 static void futex_print(struct trace_seq *s, const struct futex_args *args,
0052             const struct futex_op *fop)
0053 {
0054     trace_seq_printf(s, " uaddr=0x%08llx", args->uaddr);
0055 
0056     if (fop->fmt_val)
0057         trace_seq_printf(s, fop->fmt_val, args->val);
0058 
0059     if (fop->fmt_utime)
0060         trace_seq_printf(s,fop->fmt_utime, args->utime);
0061 
0062     if (fop->fmt_uaddr2)
0063         trace_seq_printf(s, fop->fmt_uaddr2, args->uaddr2);
0064 
0065     if (fop->fmt_val3)
0066         trace_seq_printf(s, fop->fmt_val3, args->val3);
0067 }
0068 
0069 static int futex_handler(struct trace_seq *s, struct tep_record *record,
0070              struct tep_event *event, void *context)
0071 {
0072     const struct futex_op *fop;
0073     struct futex_args args;
0074     unsigned long long cmd;
0075 
0076     if (tep_get_field_val(s, event, "uaddr", record, &args.uaddr, 1))
0077         return 1;
0078 
0079     if (tep_get_field_val(s, event, "op", record, &args.op, 1))
0080         return 1;
0081 
0082     if (tep_get_field_val(s, event, "val", record, &args.val, 1))
0083         return 1;
0084 
0085     if (tep_get_field_val(s, event, "utime", record, &args.utime, 1))
0086         return 1;
0087 
0088     if (tep_get_field_val(s, event, "uaddr2", record, &args.uaddr2, 1))
0089         return 1;
0090 
0091     if (tep_get_field_val(s, event, "val3", record, &args.val3, 1))
0092         return 1;
0093 
0094     cmd = args.op & FUTEX_CMD_MASK;
0095     if (cmd >= ARRAY_SIZE(futex_op_tbl))
0096         return 1;
0097 
0098     fop = &futex_op_tbl[cmd];
0099 
0100     trace_seq_printf(s, "op=%s", fop->name);
0101 
0102     if (args.op & FUTEX_PRIVATE_FLAG)
0103         trace_seq_puts(s, "|FUTEX_PRIVATE_FLAG");
0104 
0105     if (args.op & FUTEX_CLOCK_REALTIME)
0106         trace_seq_puts(s, "|FUTEX_CLOCK_REALTIME");
0107 
0108     futex_print(s, &args, fop);
0109     return 0;
0110 }
0111 
0112 int TEP_PLUGIN_LOADER(struct tep_handle *tep)
0113 {
0114     tep_register_event_handler(tep, -1, "syscalls", "sys_enter_futex",
0115                    futex_handler, NULL);
0116     return 0;
0117 }
0118 
0119 void TEP_PLUGIN_UNLOADER(struct tep_handle *tep)
0120 {
0121     tep_unregister_event_handler(tep, -1, "syscalls", "sys_enter_futex",
0122                      futex_handler, NULL);
0123 }