18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* getdelays.c 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Utility to get per-pid and per-tgid delay accounting statistics 58c2ecf20Sopenharmony_ci * Also illustrates usage of the taskstats interface 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Copyright (C) Shailabh Nagar, IBM Corp. 2005 88c2ecf20Sopenharmony_ci * Copyright (C) Balbir Singh, IBM Corp. 2006 98c2ecf20Sopenharmony_ci * Copyright (c) Jay Lan, SGI. 2006 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * Compile with 128c2ecf20Sopenharmony_ci * gcc -I/usr/src/linux/include getdelays.c -o getdelays 138c2ecf20Sopenharmony_ci */ 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include <stdio.h> 168c2ecf20Sopenharmony_ci#include <stdlib.h> 178c2ecf20Sopenharmony_ci#include <errno.h> 188c2ecf20Sopenharmony_ci#include <unistd.h> 198c2ecf20Sopenharmony_ci#include <poll.h> 208c2ecf20Sopenharmony_ci#include <string.h> 218c2ecf20Sopenharmony_ci#include <fcntl.h> 228c2ecf20Sopenharmony_ci#include <sys/types.h> 238c2ecf20Sopenharmony_ci#include <sys/stat.h> 248c2ecf20Sopenharmony_ci#include <sys/socket.h> 258c2ecf20Sopenharmony_ci#include <sys/wait.h> 268c2ecf20Sopenharmony_ci#include <signal.h> 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci#include <linux/genetlink.h> 298c2ecf20Sopenharmony_ci#include <linux/taskstats.h> 308c2ecf20Sopenharmony_ci#include <linux/cgroupstats.h> 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci/* 338c2ecf20Sopenharmony_ci * Generic macros for dealing with netlink sockets. Might be duplicated 348c2ecf20Sopenharmony_ci * elsewhere. It is recommended that commercial grade applications use 358c2ecf20Sopenharmony_ci * libnl or libnetlink and use the interfaces provided by the library 368c2ecf20Sopenharmony_ci */ 378c2ecf20Sopenharmony_ci#define GENLMSG_DATA(glh) ((void *)(NLMSG_DATA(glh) + GENL_HDRLEN)) 388c2ecf20Sopenharmony_ci#define GENLMSG_PAYLOAD(glh) (NLMSG_PAYLOAD(glh, 0) - GENL_HDRLEN) 398c2ecf20Sopenharmony_ci#define NLA_DATA(na) ((void *)((char*)(na) + NLA_HDRLEN)) 408c2ecf20Sopenharmony_ci#define NLA_PAYLOAD(len) (len - NLA_HDRLEN) 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci#define err(code, fmt, arg...) \ 438c2ecf20Sopenharmony_ci do { \ 448c2ecf20Sopenharmony_ci fprintf(stderr, fmt, ##arg); \ 458c2ecf20Sopenharmony_ci exit(code); \ 468c2ecf20Sopenharmony_ci } while (0) 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ciint done; 498c2ecf20Sopenharmony_ciint rcvbufsz; 508c2ecf20Sopenharmony_cichar name[100]; 518c2ecf20Sopenharmony_ciint dbg; 528c2ecf20Sopenharmony_ciint print_delays; 538c2ecf20Sopenharmony_ciint print_io_accounting; 548c2ecf20Sopenharmony_ciint print_task_context_switch_counts; 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci#define PRINTF(fmt, arg...) { \ 578c2ecf20Sopenharmony_ci if (dbg) { \ 588c2ecf20Sopenharmony_ci printf(fmt, ##arg); \ 598c2ecf20Sopenharmony_ci } \ 608c2ecf20Sopenharmony_ci } 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci/* Maximum size of response requested or message sent */ 638c2ecf20Sopenharmony_ci#define MAX_MSG_SIZE 1024 648c2ecf20Sopenharmony_ci/* Maximum number of cpus expected to be specified in a cpumask */ 658c2ecf20Sopenharmony_ci#define MAX_CPUS 32 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_cistruct msgtemplate { 688c2ecf20Sopenharmony_ci struct nlmsghdr n; 698c2ecf20Sopenharmony_ci struct genlmsghdr g; 708c2ecf20Sopenharmony_ci char buf[MAX_MSG_SIZE]; 718c2ecf20Sopenharmony_ci}; 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_cichar cpumask[100+6*MAX_CPUS]; 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_cistatic void usage(void) 768c2ecf20Sopenharmony_ci{ 778c2ecf20Sopenharmony_ci fprintf(stderr, "getdelays [-dilv] [-w logfile] [-r bufsize] " 788c2ecf20Sopenharmony_ci "[-m cpumask] [-t tgid] [-p pid]\n"); 798c2ecf20Sopenharmony_ci fprintf(stderr, " -d: print delayacct stats\n"); 808c2ecf20Sopenharmony_ci fprintf(stderr, " -i: print IO accounting (works only with -p)\n"); 818c2ecf20Sopenharmony_ci fprintf(stderr, " -l: listen forever\n"); 828c2ecf20Sopenharmony_ci fprintf(stderr, " -v: debug on\n"); 838c2ecf20Sopenharmony_ci fprintf(stderr, " -C: container path\n"); 848c2ecf20Sopenharmony_ci} 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci/* 878c2ecf20Sopenharmony_ci * Create a raw netlink socket and bind 888c2ecf20Sopenharmony_ci */ 898c2ecf20Sopenharmony_cistatic int create_nl_socket(int protocol) 908c2ecf20Sopenharmony_ci{ 918c2ecf20Sopenharmony_ci int fd; 928c2ecf20Sopenharmony_ci struct sockaddr_nl local; 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci fd = socket(AF_NETLINK, SOCK_RAW, protocol); 958c2ecf20Sopenharmony_ci if (fd < 0) 968c2ecf20Sopenharmony_ci return -1; 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci if (rcvbufsz) 998c2ecf20Sopenharmony_ci if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, 1008c2ecf20Sopenharmony_ci &rcvbufsz, sizeof(rcvbufsz)) < 0) { 1018c2ecf20Sopenharmony_ci fprintf(stderr, "Unable to set socket rcv buf size to %d\n", 1028c2ecf20Sopenharmony_ci rcvbufsz); 1038c2ecf20Sopenharmony_ci goto error; 1048c2ecf20Sopenharmony_ci } 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci memset(&local, 0, sizeof(local)); 1078c2ecf20Sopenharmony_ci local.nl_family = AF_NETLINK; 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci if (bind(fd, (struct sockaddr *) &local, sizeof(local)) < 0) 1108c2ecf20Sopenharmony_ci goto error; 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci return fd; 1138c2ecf20Sopenharmony_cierror: 1148c2ecf20Sopenharmony_ci close(fd); 1158c2ecf20Sopenharmony_ci return -1; 1168c2ecf20Sopenharmony_ci} 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_cistatic int send_cmd(int sd, __u16 nlmsg_type, __u32 nlmsg_pid, 1208c2ecf20Sopenharmony_ci __u8 genl_cmd, __u16 nla_type, 1218c2ecf20Sopenharmony_ci void *nla_data, int nla_len) 1228c2ecf20Sopenharmony_ci{ 1238c2ecf20Sopenharmony_ci struct nlattr *na; 1248c2ecf20Sopenharmony_ci struct sockaddr_nl nladdr; 1258c2ecf20Sopenharmony_ci int r, buflen; 1268c2ecf20Sopenharmony_ci char *buf; 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci struct msgtemplate msg; 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci msg.n.nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN); 1318c2ecf20Sopenharmony_ci msg.n.nlmsg_type = nlmsg_type; 1328c2ecf20Sopenharmony_ci msg.n.nlmsg_flags = NLM_F_REQUEST; 1338c2ecf20Sopenharmony_ci msg.n.nlmsg_seq = 0; 1348c2ecf20Sopenharmony_ci msg.n.nlmsg_pid = nlmsg_pid; 1358c2ecf20Sopenharmony_ci msg.g.cmd = genl_cmd; 1368c2ecf20Sopenharmony_ci msg.g.version = 0x1; 1378c2ecf20Sopenharmony_ci na = (struct nlattr *) GENLMSG_DATA(&msg); 1388c2ecf20Sopenharmony_ci na->nla_type = nla_type; 1398c2ecf20Sopenharmony_ci na->nla_len = nla_len + NLA_HDRLEN; 1408c2ecf20Sopenharmony_ci memcpy(NLA_DATA(na), nla_data, nla_len); 1418c2ecf20Sopenharmony_ci msg.n.nlmsg_len += NLMSG_ALIGN(na->nla_len); 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci buf = (char *) &msg; 1448c2ecf20Sopenharmony_ci buflen = msg.n.nlmsg_len ; 1458c2ecf20Sopenharmony_ci memset(&nladdr, 0, sizeof(nladdr)); 1468c2ecf20Sopenharmony_ci nladdr.nl_family = AF_NETLINK; 1478c2ecf20Sopenharmony_ci while ((r = sendto(sd, buf, buflen, 0, (struct sockaddr *) &nladdr, 1488c2ecf20Sopenharmony_ci sizeof(nladdr))) < buflen) { 1498c2ecf20Sopenharmony_ci if (r > 0) { 1508c2ecf20Sopenharmony_ci buf += r; 1518c2ecf20Sopenharmony_ci buflen -= r; 1528c2ecf20Sopenharmony_ci } else if (errno != EAGAIN) 1538c2ecf20Sopenharmony_ci return -1; 1548c2ecf20Sopenharmony_ci } 1558c2ecf20Sopenharmony_ci return 0; 1568c2ecf20Sopenharmony_ci} 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci/* 1608c2ecf20Sopenharmony_ci * Probe the controller in genetlink to find the family id 1618c2ecf20Sopenharmony_ci * for the TASKSTATS family 1628c2ecf20Sopenharmony_ci */ 1638c2ecf20Sopenharmony_cistatic int get_family_id(int sd) 1648c2ecf20Sopenharmony_ci{ 1658c2ecf20Sopenharmony_ci struct { 1668c2ecf20Sopenharmony_ci struct nlmsghdr n; 1678c2ecf20Sopenharmony_ci struct genlmsghdr g; 1688c2ecf20Sopenharmony_ci char buf[256]; 1698c2ecf20Sopenharmony_ci } ans; 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci int id = 0, rc; 1728c2ecf20Sopenharmony_ci struct nlattr *na; 1738c2ecf20Sopenharmony_ci int rep_len; 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci strcpy(name, TASKSTATS_GENL_NAME); 1768c2ecf20Sopenharmony_ci rc = send_cmd(sd, GENL_ID_CTRL, getpid(), CTRL_CMD_GETFAMILY, 1778c2ecf20Sopenharmony_ci CTRL_ATTR_FAMILY_NAME, (void *)name, 1788c2ecf20Sopenharmony_ci strlen(TASKSTATS_GENL_NAME)+1); 1798c2ecf20Sopenharmony_ci if (rc < 0) 1808c2ecf20Sopenharmony_ci return 0; /* sendto() failure? */ 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci rep_len = recv(sd, &ans, sizeof(ans), 0); 1838c2ecf20Sopenharmony_ci if (ans.n.nlmsg_type == NLMSG_ERROR || 1848c2ecf20Sopenharmony_ci (rep_len < 0) || !NLMSG_OK((&ans.n), rep_len)) 1858c2ecf20Sopenharmony_ci return 0; 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci na = (struct nlattr *) GENLMSG_DATA(&ans); 1888c2ecf20Sopenharmony_ci na = (struct nlattr *) ((char *) na + NLA_ALIGN(na->nla_len)); 1898c2ecf20Sopenharmony_ci if (na->nla_type == CTRL_ATTR_FAMILY_ID) { 1908c2ecf20Sopenharmony_ci id = *(__u16 *) NLA_DATA(na); 1918c2ecf20Sopenharmony_ci } 1928c2ecf20Sopenharmony_ci return id; 1938c2ecf20Sopenharmony_ci} 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci#define average_ms(t, c) (t / 1000000ULL / (c ? c : 1)) 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_cistatic void print_delayacct(struct taskstats *t) 1988c2ecf20Sopenharmony_ci{ 1998c2ecf20Sopenharmony_ci printf("\n\nCPU %15s%15s%15s%15s%15s\n" 2008c2ecf20Sopenharmony_ci " %15llu%15llu%15llu%15llu%15.3fms\n" 2018c2ecf20Sopenharmony_ci "IO %15s%15s%15s\n" 2028c2ecf20Sopenharmony_ci " %15llu%15llu%15llums\n" 2038c2ecf20Sopenharmony_ci "SWAP %15s%15s%15s\n" 2048c2ecf20Sopenharmony_ci " %15llu%15llu%15llums\n" 2058c2ecf20Sopenharmony_ci "RECLAIM %12s%15s%15s\n" 2068c2ecf20Sopenharmony_ci " %15llu%15llu%15llums\n" 2078c2ecf20Sopenharmony_ci "THRASHING%12s%15s%15s\n" 2088c2ecf20Sopenharmony_ci " %15llu%15llu%15llums\n", 2098c2ecf20Sopenharmony_ci "count", "real total", "virtual total", 2108c2ecf20Sopenharmony_ci "delay total", "delay average", 2118c2ecf20Sopenharmony_ci (unsigned long long)t->cpu_count, 2128c2ecf20Sopenharmony_ci (unsigned long long)t->cpu_run_real_total, 2138c2ecf20Sopenharmony_ci (unsigned long long)t->cpu_run_virtual_total, 2148c2ecf20Sopenharmony_ci (unsigned long long)t->cpu_delay_total, 2158c2ecf20Sopenharmony_ci average_ms((double)t->cpu_delay_total, t->cpu_count), 2168c2ecf20Sopenharmony_ci "count", "delay total", "delay average", 2178c2ecf20Sopenharmony_ci (unsigned long long)t->blkio_count, 2188c2ecf20Sopenharmony_ci (unsigned long long)t->blkio_delay_total, 2198c2ecf20Sopenharmony_ci average_ms(t->blkio_delay_total, t->blkio_count), 2208c2ecf20Sopenharmony_ci "count", "delay total", "delay average", 2218c2ecf20Sopenharmony_ci (unsigned long long)t->swapin_count, 2228c2ecf20Sopenharmony_ci (unsigned long long)t->swapin_delay_total, 2238c2ecf20Sopenharmony_ci average_ms(t->swapin_delay_total, t->swapin_count), 2248c2ecf20Sopenharmony_ci "count", "delay total", "delay average", 2258c2ecf20Sopenharmony_ci (unsigned long long)t->freepages_count, 2268c2ecf20Sopenharmony_ci (unsigned long long)t->freepages_delay_total, 2278c2ecf20Sopenharmony_ci average_ms(t->freepages_delay_total, t->freepages_count), 2288c2ecf20Sopenharmony_ci "count", "delay total", "delay average", 2298c2ecf20Sopenharmony_ci (unsigned long long)t->thrashing_count, 2308c2ecf20Sopenharmony_ci (unsigned long long)t->thrashing_delay_total, 2318c2ecf20Sopenharmony_ci average_ms(t->thrashing_delay_total, t->thrashing_count)); 2328c2ecf20Sopenharmony_ci} 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_cistatic void task_context_switch_counts(struct taskstats *t) 2358c2ecf20Sopenharmony_ci{ 2368c2ecf20Sopenharmony_ci printf("\n\nTask %15s%15s\n" 2378c2ecf20Sopenharmony_ci " %15llu%15llu\n", 2388c2ecf20Sopenharmony_ci "voluntary", "nonvoluntary", 2398c2ecf20Sopenharmony_ci (unsigned long long)t->nvcsw, (unsigned long long)t->nivcsw); 2408c2ecf20Sopenharmony_ci} 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_cistatic void print_cgroupstats(struct cgroupstats *c) 2438c2ecf20Sopenharmony_ci{ 2448c2ecf20Sopenharmony_ci printf("sleeping %llu, blocked %llu, running %llu, stopped %llu, " 2458c2ecf20Sopenharmony_ci "uninterruptible %llu\n", (unsigned long long)c->nr_sleeping, 2468c2ecf20Sopenharmony_ci (unsigned long long)c->nr_io_wait, 2478c2ecf20Sopenharmony_ci (unsigned long long)c->nr_running, 2488c2ecf20Sopenharmony_ci (unsigned long long)c->nr_stopped, 2498c2ecf20Sopenharmony_ci (unsigned long long)c->nr_uninterruptible); 2508c2ecf20Sopenharmony_ci} 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_cistatic void print_ioacct(struct taskstats *t) 2548c2ecf20Sopenharmony_ci{ 2558c2ecf20Sopenharmony_ci printf("%s: read=%llu, write=%llu, cancelled_write=%llu\n", 2568c2ecf20Sopenharmony_ci t->ac_comm, 2578c2ecf20Sopenharmony_ci (unsigned long long)t->read_bytes, 2588c2ecf20Sopenharmony_ci (unsigned long long)t->write_bytes, 2598c2ecf20Sopenharmony_ci (unsigned long long)t->cancelled_write_bytes); 2608c2ecf20Sopenharmony_ci} 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ciint main(int argc, char *argv[]) 2638c2ecf20Sopenharmony_ci{ 2648c2ecf20Sopenharmony_ci int c, rc, rep_len, aggr_len, len2; 2658c2ecf20Sopenharmony_ci int cmd_type = TASKSTATS_CMD_ATTR_UNSPEC; 2668c2ecf20Sopenharmony_ci __u16 id; 2678c2ecf20Sopenharmony_ci __u32 mypid; 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci struct nlattr *na; 2708c2ecf20Sopenharmony_ci int nl_sd = -1; 2718c2ecf20Sopenharmony_ci int len = 0; 2728c2ecf20Sopenharmony_ci pid_t tid = 0; 2738c2ecf20Sopenharmony_ci pid_t rtid = 0; 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci int fd = 0; 2768c2ecf20Sopenharmony_ci int count = 0; 2778c2ecf20Sopenharmony_ci int write_file = 0; 2788c2ecf20Sopenharmony_ci int maskset = 0; 2798c2ecf20Sopenharmony_ci char *logfile = NULL; 2808c2ecf20Sopenharmony_ci int loop = 0; 2818c2ecf20Sopenharmony_ci int containerset = 0; 2828c2ecf20Sopenharmony_ci char *containerpath = NULL; 2838c2ecf20Sopenharmony_ci int cfd = 0; 2848c2ecf20Sopenharmony_ci int forking = 0; 2858c2ecf20Sopenharmony_ci sigset_t sigset; 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci struct msgtemplate msg; 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci while (!forking) { 2908c2ecf20Sopenharmony_ci c = getopt(argc, argv, "qdiw:r:m:t:p:vlC:c:"); 2918c2ecf20Sopenharmony_ci if (c < 0) 2928c2ecf20Sopenharmony_ci break; 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci switch (c) { 2958c2ecf20Sopenharmony_ci case 'd': 2968c2ecf20Sopenharmony_ci printf("print delayacct stats ON\n"); 2978c2ecf20Sopenharmony_ci print_delays = 1; 2988c2ecf20Sopenharmony_ci break; 2998c2ecf20Sopenharmony_ci case 'i': 3008c2ecf20Sopenharmony_ci printf("printing IO accounting\n"); 3018c2ecf20Sopenharmony_ci print_io_accounting = 1; 3028c2ecf20Sopenharmony_ci break; 3038c2ecf20Sopenharmony_ci case 'q': 3048c2ecf20Sopenharmony_ci printf("printing task/process context switch rates\n"); 3058c2ecf20Sopenharmony_ci print_task_context_switch_counts = 1; 3068c2ecf20Sopenharmony_ci break; 3078c2ecf20Sopenharmony_ci case 'C': 3088c2ecf20Sopenharmony_ci containerset = 1; 3098c2ecf20Sopenharmony_ci containerpath = optarg; 3108c2ecf20Sopenharmony_ci break; 3118c2ecf20Sopenharmony_ci case 'w': 3128c2ecf20Sopenharmony_ci logfile = strdup(optarg); 3138c2ecf20Sopenharmony_ci printf("write to file %s\n", logfile); 3148c2ecf20Sopenharmony_ci write_file = 1; 3158c2ecf20Sopenharmony_ci break; 3168c2ecf20Sopenharmony_ci case 'r': 3178c2ecf20Sopenharmony_ci rcvbufsz = atoi(optarg); 3188c2ecf20Sopenharmony_ci printf("receive buf size %d\n", rcvbufsz); 3198c2ecf20Sopenharmony_ci if (rcvbufsz < 0) 3208c2ecf20Sopenharmony_ci err(1, "Invalid rcv buf size\n"); 3218c2ecf20Sopenharmony_ci break; 3228c2ecf20Sopenharmony_ci case 'm': 3238c2ecf20Sopenharmony_ci strncpy(cpumask, optarg, sizeof(cpumask)); 3248c2ecf20Sopenharmony_ci cpumask[sizeof(cpumask) - 1] = '\0'; 3258c2ecf20Sopenharmony_ci maskset = 1; 3268c2ecf20Sopenharmony_ci printf("cpumask %s maskset %d\n", cpumask, maskset); 3278c2ecf20Sopenharmony_ci break; 3288c2ecf20Sopenharmony_ci case 't': 3298c2ecf20Sopenharmony_ci tid = atoi(optarg); 3308c2ecf20Sopenharmony_ci if (!tid) 3318c2ecf20Sopenharmony_ci err(1, "Invalid tgid\n"); 3328c2ecf20Sopenharmony_ci cmd_type = TASKSTATS_CMD_ATTR_TGID; 3338c2ecf20Sopenharmony_ci break; 3348c2ecf20Sopenharmony_ci case 'p': 3358c2ecf20Sopenharmony_ci tid = atoi(optarg); 3368c2ecf20Sopenharmony_ci if (!tid) 3378c2ecf20Sopenharmony_ci err(1, "Invalid pid\n"); 3388c2ecf20Sopenharmony_ci cmd_type = TASKSTATS_CMD_ATTR_PID; 3398c2ecf20Sopenharmony_ci break; 3408c2ecf20Sopenharmony_ci case 'c': 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci /* Block SIGCHLD for sigwait() later */ 3438c2ecf20Sopenharmony_ci if (sigemptyset(&sigset) == -1) 3448c2ecf20Sopenharmony_ci err(1, "Failed to empty sigset"); 3458c2ecf20Sopenharmony_ci if (sigaddset(&sigset, SIGCHLD)) 3468c2ecf20Sopenharmony_ci err(1, "Failed to set sigchld in sigset"); 3478c2ecf20Sopenharmony_ci sigprocmask(SIG_BLOCK, &sigset, NULL); 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci /* fork/exec a child */ 3508c2ecf20Sopenharmony_ci tid = fork(); 3518c2ecf20Sopenharmony_ci if (tid < 0) 3528c2ecf20Sopenharmony_ci err(1, "Fork failed\n"); 3538c2ecf20Sopenharmony_ci if (tid == 0) 3548c2ecf20Sopenharmony_ci if (execvp(argv[optind - 1], 3558c2ecf20Sopenharmony_ci &argv[optind - 1]) < 0) 3568c2ecf20Sopenharmony_ci exit(-1); 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci /* Set the command type and avoid further processing */ 3598c2ecf20Sopenharmony_ci cmd_type = TASKSTATS_CMD_ATTR_PID; 3608c2ecf20Sopenharmony_ci forking = 1; 3618c2ecf20Sopenharmony_ci break; 3628c2ecf20Sopenharmony_ci case 'v': 3638c2ecf20Sopenharmony_ci printf("debug on\n"); 3648c2ecf20Sopenharmony_ci dbg = 1; 3658c2ecf20Sopenharmony_ci break; 3668c2ecf20Sopenharmony_ci case 'l': 3678c2ecf20Sopenharmony_ci printf("listen forever\n"); 3688c2ecf20Sopenharmony_ci loop = 1; 3698c2ecf20Sopenharmony_ci break; 3708c2ecf20Sopenharmony_ci default: 3718c2ecf20Sopenharmony_ci usage(); 3728c2ecf20Sopenharmony_ci exit(-1); 3738c2ecf20Sopenharmony_ci } 3748c2ecf20Sopenharmony_ci } 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ci if (write_file) { 3778c2ecf20Sopenharmony_ci fd = open(logfile, O_WRONLY | O_CREAT | O_TRUNC, 3788c2ecf20Sopenharmony_ci S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); 3798c2ecf20Sopenharmony_ci if (fd == -1) { 3808c2ecf20Sopenharmony_ci perror("Cannot open output file\n"); 3818c2ecf20Sopenharmony_ci exit(1); 3828c2ecf20Sopenharmony_ci } 3838c2ecf20Sopenharmony_ci } 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci nl_sd = create_nl_socket(NETLINK_GENERIC); 3868c2ecf20Sopenharmony_ci if (nl_sd < 0) 3878c2ecf20Sopenharmony_ci err(1, "error creating Netlink socket\n"); 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci mypid = getpid(); 3918c2ecf20Sopenharmony_ci id = get_family_id(nl_sd); 3928c2ecf20Sopenharmony_ci if (!id) { 3938c2ecf20Sopenharmony_ci fprintf(stderr, "Error getting family id, errno %d\n", errno); 3948c2ecf20Sopenharmony_ci goto err; 3958c2ecf20Sopenharmony_ci } 3968c2ecf20Sopenharmony_ci PRINTF("family id %d\n", id); 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci if (maskset) { 3998c2ecf20Sopenharmony_ci rc = send_cmd(nl_sd, id, mypid, TASKSTATS_CMD_GET, 4008c2ecf20Sopenharmony_ci TASKSTATS_CMD_ATTR_REGISTER_CPUMASK, 4018c2ecf20Sopenharmony_ci &cpumask, strlen(cpumask) + 1); 4028c2ecf20Sopenharmony_ci PRINTF("Sent register cpumask, retval %d\n", rc); 4038c2ecf20Sopenharmony_ci if (rc < 0) { 4048c2ecf20Sopenharmony_ci fprintf(stderr, "error sending register cpumask\n"); 4058c2ecf20Sopenharmony_ci goto err; 4068c2ecf20Sopenharmony_ci } 4078c2ecf20Sopenharmony_ci } 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_ci if (tid && containerset) { 4108c2ecf20Sopenharmony_ci fprintf(stderr, "Select either -t or -C, not both\n"); 4118c2ecf20Sopenharmony_ci goto err; 4128c2ecf20Sopenharmony_ci } 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci /* 4158c2ecf20Sopenharmony_ci * If we forked a child, wait for it to exit. Cannot use waitpid() 4168c2ecf20Sopenharmony_ci * as all the delicious data would be reaped as part of the wait 4178c2ecf20Sopenharmony_ci */ 4188c2ecf20Sopenharmony_ci if (tid && forking) { 4198c2ecf20Sopenharmony_ci int sig_received; 4208c2ecf20Sopenharmony_ci sigwait(&sigset, &sig_received); 4218c2ecf20Sopenharmony_ci } 4228c2ecf20Sopenharmony_ci 4238c2ecf20Sopenharmony_ci if (tid) { 4248c2ecf20Sopenharmony_ci rc = send_cmd(nl_sd, id, mypid, TASKSTATS_CMD_GET, 4258c2ecf20Sopenharmony_ci cmd_type, &tid, sizeof(__u32)); 4268c2ecf20Sopenharmony_ci PRINTF("Sent pid/tgid, retval %d\n", rc); 4278c2ecf20Sopenharmony_ci if (rc < 0) { 4288c2ecf20Sopenharmony_ci fprintf(stderr, "error sending tid/tgid cmd\n"); 4298c2ecf20Sopenharmony_ci goto done; 4308c2ecf20Sopenharmony_ci } 4318c2ecf20Sopenharmony_ci } 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_ci if (containerset) { 4348c2ecf20Sopenharmony_ci cfd = open(containerpath, O_RDONLY); 4358c2ecf20Sopenharmony_ci if (cfd < 0) { 4368c2ecf20Sopenharmony_ci perror("error opening container file"); 4378c2ecf20Sopenharmony_ci goto err; 4388c2ecf20Sopenharmony_ci } 4398c2ecf20Sopenharmony_ci rc = send_cmd(nl_sd, id, mypid, CGROUPSTATS_CMD_GET, 4408c2ecf20Sopenharmony_ci CGROUPSTATS_CMD_ATTR_FD, &cfd, sizeof(__u32)); 4418c2ecf20Sopenharmony_ci if (rc < 0) { 4428c2ecf20Sopenharmony_ci perror("error sending cgroupstats command"); 4438c2ecf20Sopenharmony_ci goto err; 4448c2ecf20Sopenharmony_ci } 4458c2ecf20Sopenharmony_ci } 4468c2ecf20Sopenharmony_ci if (!maskset && !tid && !containerset) { 4478c2ecf20Sopenharmony_ci usage(); 4488c2ecf20Sopenharmony_ci goto err; 4498c2ecf20Sopenharmony_ci } 4508c2ecf20Sopenharmony_ci 4518c2ecf20Sopenharmony_ci do { 4528c2ecf20Sopenharmony_ci rep_len = recv(nl_sd, &msg, sizeof(msg), 0); 4538c2ecf20Sopenharmony_ci PRINTF("received %d bytes\n", rep_len); 4548c2ecf20Sopenharmony_ci 4558c2ecf20Sopenharmony_ci if (rep_len < 0) { 4568c2ecf20Sopenharmony_ci fprintf(stderr, "nonfatal reply error: errno %d\n", 4578c2ecf20Sopenharmony_ci errno); 4588c2ecf20Sopenharmony_ci continue; 4598c2ecf20Sopenharmony_ci } 4608c2ecf20Sopenharmony_ci if (msg.n.nlmsg_type == NLMSG_ERROR || 4618c2ecf20Sopenharmony_ci !NLMSG_OK((&msg.n), rep_len)) { 4628c2ecf20Sopenharmony_ci struct nlmsgerr *err = NLMSG_DATA(&msg); 4638c2ecf20Sopenharmony_ci fprintf(stderr, "fatal reply error, errno %d\n", 4648c2ecf20Sopenharmony_ci err->error); 4658c2ecf20Sopenharmony_ci goto done; 4668c2ecf20Sopenharmony_ci } 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_ci PRINTF("nlmsghdr size=%zu, nlmsg_len=%d, rep_len=%d\n", 4698c2ecf20Sopenharmony_ci sizeof(struct nlmsghdr), msg.n.nlmsg_len, rep_len); 4708c2ecf20Sopenharmony_ci 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_ci rep_len = GENLMSG_PAYLOAD(&msg.n); 4738c2ecf20Sopenharmony_ci 4748c2ecf20Sopenharmony_ci na = (struct nlattr *) GENLMSG_DATA(&msg); 4758c2ecf20Sopenharmony_ci len = 0; 4768c2ecf20Sopenharmony_ci while (len < rep_len) { 4778c2ecf20Sopenharmony_ci len += NLA_ALIGN(na->nla_len); 4788c2ecf20Sopenharmony_ci switch (na->nla_type) { 4798c2ecf20Sopenharmony_ci case TASKSTATS_TYPE_AGGR_TGID: 4808c2ecf20Sopenharmony_ci /* Fall through */ 4818c2ecf20Sopenharmony_ci case TASKSTATS_TYPE_AGGR_PID: 4828c2ecf20Sopenharmony_ci aggr_len = NLA_PAYLOAD(na->nla_len); 4838c2ecf20Sopenharmony_ci len2 = 0; 4848c2ecf20Sopenharmony_ci /* For nested attributes, na follows */ 4858c2ecf20Sopenharmony_ci na = (struct nlattr *) NLA_DATA(na); 4868c2ecf20Sopenharmony_ci done = 0; 4878c2ecf20Sopenharmony_ci while (len2 < aggr_len) { 4888c2ecf20Sopenharmony_ci switch (na->nla_type) { 4898c2ecf20Sopenharmony_ci case TASKSTATS_TYPE_PID: 4908c2ecf20Sopenharmony_ci rtid = *(int *) NLA_DATA(na); 4918c2ecf20Sopenharmony_ci if (print_delays) 4928c2ecf20Sopenharmony_ci printf("PID\t%d\n", rtid); 4938c2ecf20Sopenharmony_ci break; 4948c2ecf20Sopenharmony_ci case TASKSTATS_TYPE_TGID: 4958c2ecf20Sopenharmony_ci rtid = *(int *) NLA_DATA(na); 4968c2ecf20Sopenharmony_ci if (print_delays) 4978c2ecf20Sopenharmony_ci printf("TGID\t%d\n", rtid); 4988c2ecf20Sopenharmony_ci break; 4998c2ecf20Sopenharmony_ci case TASKSTATS_TYPE_STATS: 5008c2ecf20Sopenharmony_ci count++; 5018c2ecf20Sopenharmony_ci if (print_delays) 5028c2ecf20Sopenharmony_ci print_delayacct((struct taskstats *) NLA_DATA(na)); 5038c2ecf20Sopenharmony_ci if (print_io_accounting) 5048c2ecf20Sopenharmony_ci print_ioacct((struct taskstats *) NLA_DATA(na)); 5058c2ecf20Sopenharmony_ci if (print_task_context_switch_counts) 5068c2ecf20Sopenharmony_ci task_context_switch_counts((struct taskstats *) NLA_DATA(na)); 5078c2ecf20Sopenharmony_ci if (fd) { 5088c2ecf20Sopenharmony_ci if (write(fd, NLA_DATA(na), na->nla_len) < 0) { 5098c2ecf20Sopenharmony_ci err(1,"write error\n"); 5108c2ecf20Sopenharmony_ci } 5118c2ecf20Sopenharmony_ci } 5128c2ecf20Sopenharmony_ci if (!loop) 5138c2ecf20Sopenharmony_ci goto done; 5148c2ecf20Sopenharmony_ci break; 5158c2ecf20Sopenharmony_ci case TASKSTATS_TYPE_NULL: 5168c2ecf20Sopenharmony_ci break; 5178c2ecf20Sopenharmony_ci default: 5188c2ecf20Sopenharmony_ci fprintf(stderr, "Unknown nested" 5198c2ecf20Sopenharmony_ci " nla_type %d\n", 5208c2ecf20Sopenharmony_ci na->nla_type); 5218c2ecf20Sopenharmony_ci break; 5228c2ecf20Sopenharmony_ci } 5238c2ecf20Sopenharmony_ci len2 += NLA_ALIGN(na->nla_len); 5248c2ecf20Sopenharmony_ci na = (struct nlattr *)((char *)na + 5258c2ecf20Sopenharmony_ci NLA_ALIGN(na->nla_len)); 5268c2ecf20Sopenharmony_ci } 5278c2ecf20Sopenharmony_ci break; 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_ci case CGROUPSTATS_TYPE_CGROUP_STATS: 5308c2ecf20Sopenharmony_ci print_cgroupstats(NLA_DATA(na)); 5318c2ecf20Sopenharmony_ci break; 5328c2ecf20Sopenharmony_ci default: 5338c2ecf20Sopenharmony_ci fprintf(stderr, "Unknown nla_type %d\n", 5348c2ecf20Sopenharmony_ci na->nla_type); 5358c2ecf20Sopenharmony_ci case TASKSTATS_TYPE_NULL: 5368c2ecf20Sopenharmony_ci break; 5378c2ecf20Sopenharmony_ci } 5388c2ecf20Sopenharmony_ci na = (struct nlattr *) (GENLMSG_DATA(&msg) + len); 5398c2ecf20Sopenharmony_ci } 5408c2ecf20Sopenharmony_ci } while (loop); 5418c2ecf20Sopenharmony_cidone: 5428c2ecf20Sopenharmony_ci if (maskset) { 5438c2ecf20Sopenharmony_ci rc = send_cmd(nl_sd, id, mypid, TASKSTATS_CMD_GET, 5448c2ecf20Sopenharmony_ci TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK, 5458c2ecf20Sopenharmony_ci &cpumask, strlen(cpumask) + 1); 5468c2ecf20Sopenharmony_ci printf("Sent deregister mask, retval %d\n", rc); 5478c2ecf20Sopenharmony_ci if (rc < 0) 5488c2ecf20Sopenharmony_ci err(rc, "error sending deregister cpumask\n"); 5498c2ecf20Sopenharmony_ci } 5508c2ecf20Sopenharmony_cierr: 5518c2ecf20Sopenharmony_ci close(nl_sd); 5528c2ecf20Sopenharmony_ci if (fd) 5538c2ecf20Sopenharmony_ci close(fd); 5548c2ecf20Sopenharmony_ci if (cfd) 5558c2ecf20Sopenharmony_ci close(cfd); 5568c2ecf20Sopenharmony_ci return 0; 5578c2ecf20Sopenharmony_ci} 558