1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322
|
/* SPDX-License-Identifier: GPL-2.0-or-later
Copyright (C) 2014 Vyacheslav Trushkin
Copyright (C) 2020-2025 Boian Bonev
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __IOTOP_H__
#define __IOTOP_H__
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#ifndef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE
#endif
#ifndef _DEFAULT_SOURCE
#define _DEFAULT_SOURCE
#endif
#include <regex.h>
#include <stdint.h>
#include <sys/types.h>
#include "ucell.h"
#define VERSION "1.30"
typedef enum {
E_GR_IO,
E_GR_R,
E_GR_W,
E_GR_RW,
E_GR_SW,
E_GR_MIN=E_GR_IO,
E_GR_MAX=E_GR_SW,
} e_grtype;
typedef union {
struct _flags {
int batch_mode;
int only;
int processes;
int accumulated;
int kilobytes;
int timestamp;
int quiet;
int fullcmdline;
int hidepid;
int hideprio;
int hideuser;
int hideread;
int hidewrite;
int hideswapin;
int hideio;
int hidegraph;
int hidecmd;
int deadx;
int hideexited;
int nocolor;
int reverse_graph;
int hideclock;
int accumbw;
int inverse;
int unicode; // this and below are not part of opts
e_grtype grtype;
int helptype;
int sort_by;
int sort_order;
int base; // 1000 or 1024
int threshold; // 1..10
int norenice;
} f;
int opts[24];
} config_t;
typedef struct {
int iter;
int delay;
int pid;
int user_id;
char *search_str; // search regex string
regex_t search_regx; // search regex
int search_regx_ok; // search regex compiles ok
ucell *search_uc; // utf cell array
} params_t;
extern config_t config;
extern params_t params;
extern int maxpidlen;
extern unsigned taskstats_ver;
#define IOTOP_TASKSTATS_MINVER 4
#define IOTOP_TASKSTATS_VERSION 15
#define HISTORY_POS 60
#define HISTORY_CNT (HISTORY_POS*2)
struct xxxid_stats_arr {
struct xxxid_stats **arr;
struct xxxid_stats **sor;
int length;
int size;
};
struct xxxid_stats {
pid_t pid;
pid_t tid;
uint64_t swapin_delay_total; // nanoseconds
uint64_t blkio_delay_total; // nanoseconds
uint64_t read_bytes;
uint64_t write_bytes;
uint64_t swapin_delay_total_p; // aggregated data from all threads
uint64_t blkio_delay_total_p; // used for process view
uint64_t read_bytes_p;
uint64_t write_bytes_p;
uint64_t ts_s; // start timestamp for accum-bw
uint64_t ts_e; // end timestamp for accum-bw
double blkio_val;
double swapin_val;
double read_val;
double write_val;
double read_val_acc;
double write_val_acc;
double read_val_abw;
double write_val_abw;
double blkio_val_p;
double swapin_val_p;
double read_val_p;
double write_val_p;
double read_val_acc_p;
double write_val_acc_p;
double read_val_abw_p;
double write_val_abw_p;
int io_prio;
int euid;
char *cmdline1;
char *cmdline2;
char *pw_name;
uint8_t iohist[HISTORY_CNT]; // io history data
uint8_t sihist[HISTORY_CNT]; // swapin history data
double readhist[HISTORY_CNT]; // read history data
double writehist[HISTORY_CNT]; // write history data
uint8_t iohist_p[HISTORY_CNT]; // io history data (aggregated in main process)
uint8_t sihist_p[HISTORY_CNT]; // swapin history data (aggregated in main process)
double readhist_p[HISTORY_CNT]; // read history data (aggregated in main process)
double writehist_p[HISTORY_CNT]; // write history data (aggregated in main process)
int exited; // exited>0 shows for how many refresh cycles the process is gone
int error_x; // netlink api did not return valid data
int error_i; // get_ioprio did not return valid data
// there is no point to keep in memory data for processes exited before HISTORY_CNT cycles
struct xxxid_stats_arr *threads;
};
// arrays are used both for main process/thread list and for inner thread list belonging to a process
// always start small
#define PROC_LIST_SZ_INI 16
// afterwards grow big
#define PROC_LIST_SZ_INC 2048
struct act_stats {
uint64_t read_bytes;
uint64_t write_bytes;
uint64_t read_bytes_o;
uint64_t write_bytes_o;
uint64_t ts_c;
uint64_t ts_o;
uint8_t have_o;
};
inline void nl_init(void);
inline void nl_fini(void);
inline int nl_xxxid_info(pid_t tid,pid_t pid,struct xxxid_stats *stats);
typedef int (*filter_callback)(struct xxxid_stats *);
typedef int (*filter_callback_w)(struct xxxid_stats *,int width);
inline struct xxxid_stats_arr *fetch_data(filter_callback);
inline void free_stats(struct xxxid_stats *s);
typedef void (*view_loop)(void);
typedef void (*view_init)(void);
typedef void (*view_fini)(void);
inline void view_batch_loop(void);
inline void view_batch_init(void);
inline void view_batch_fini(void);
inline void view_curses_loop(void);
inline void view_curses_init(void);
inline void view_curses_fini(void);
inline unsigned int curses_sleep(unsigned int seconds);
inline e_grtype masked_grtype(int isforward);
inline int masked_sort_by(int isforward);
/* utils.c */
inline char *read_cmdline(int pid,int isshort);
inline int64_t monotime(void);
inline char *u8strpadt(const char *s,ssize_t len);
inline char *esc_low_ascii(char *p);
typedef void (*pg_cb)(pid_t pid,pid_t tid,struct xxxid_stats_arr *hint1,filter_callback hint2);
inline void pidgen_cb(pg_cb cb,struct xxxid_stats_arr *hint1,filter_callback hint2);
inline int is_a_dir(const char *p);
inline int is_a_file(const char *p);
inline int is_a_process(pid_t tid);
inline double timediff_in_s(uint64_t sta,uint64_t end);
/* ioprio.c */
enum {
IOPRIO_CLASS_NONE,
IOPRIO_CLASS_RT,
IOPRIO_CLASS_BE,
IOPRIO_CLASS_IDLE,
IOPRIO_CLASS_MAX,
IOPRIO_CLASS_MIN=IOPRIO_CLASS_RT,
};
enum {
IOPRIO_WHO_PROCESS=1,
IOPRIO_WHO_PGRP,
IOPRIO_WHO_USER
};
enum {
SORT_BY_TID,
SORT_BY_PRIO,
SORT_BY_USER,
SORT_BY_READ,
SORT_BY_WRITE,
SORT_BY_SWAPIN,
SORT_BY_IO,
SORT_BY_GRAPH,
SORT_BY_COMMAND,
SORT_BY_MAX
};
enum {
SORT_DESC,
SORT_ASC
};
extern const char *str_ioprio_class[];
inline int get_ioprio(pid_t pid);
inline const char *str_ioprio(int io_prio);
inline int ioprio_value(int class,int prio);
inline int set_ioprio(int which,int who,int ioprio_class,int ioprio_prio);
inline int ioprio2class(int ioprio);
inline int ioprio2prio(int ioprio);
/* vmstat.c */
inline int get_vm_counters(uint64_t *pgpgin,uint64_t *pgpgou);
/* checks.c */
inline int system_checks(void);
/* arr.c */
inline struct xxxid_stats_arr *arr_alloc(void);
inline int arr_add(struct xxxid_stats_arr *a,struct xxxid_stats *s);
inline struct xxxid_stats *arr_find(struct xxxid_stats_arr *pa,pid_t tid);
inline void arr_free(struct xxxid_stats_arr *pa);
inline void arr_free_noitem(struct xxxid_stats_arr *pa);
inline void arr_sort(struct xxxid_stats_arr *pa,int (*cb)(const void *a,const void *b));
#define HEADER1_FORMAT " Total DISK READ: %7.2f %s%s | Total DISK WRITE: %7.2f %s%s"
#define HEADER2_FORMAT "Current DISK READ: %7.2f %s%s | Current DISK WRITE: %7.2f %s%s"
inline void calc_total(struct xxxid_stats_arr *cs,double *read,double *write);
inline void calc_a_total(struct act_stats *act,double *read,double *write,double time_s);
inline void humanize_val(double *value,char *str,int allow_accum);
inline int iotop_sort_cb(const void *a,const void *b);
inline int create_diff(struct xxxid_stats_arr *cs,struct xxxid_stats_arr *ps,double time_s,uint64_t ts_c,filter_callback_w cb,int width,int *cnt);
inline int value2scale(double val,double mx);
inline int filter1(struct xxxid_stats *s);
/* delayacct.c */
inline int has_task_delayacct(void);
inline int read_task_delayacct(void);
inline int write_task_delayacct(int da);
/* configfile.c */
inline int config_file_load(int *pac,char ***pav);
inline void config_file_free(void);
inline int config_file_save(void);
/* main.c */
inline void init_params(void);
inline void init_config(void);
#define mymax(a,b) (((a)>(b))?(a):(b))
#endif // __IOTOP_H__
|