1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2008-2009, Intel Corporation.
  23  * All Rights Reserved.
  24  */
  25 
  26 #ifndef _LATENCYTOP_H
  27 #define _LATENCYTOP_H
  28 
  29 #include <sys/types.h>
  30 
  31 #include <glib.h>
  32 
  33 #ifdef  __cplusplus
  34 extern "C" {
  35 #endif
  36 
  37 /*
  38  * Without this lint seems to be confused by glib header file.
  39  */
  40 #ifdef __lint
  41 #undef g_assert
  42 #define g_assert(x)     ((void)(x))
  43 #undef TRUE
  44 #define TRUE            1
  45 #endif
  46 
  47 /*
  48  * We define our own conversions in order to avoid compiler warnings.
  49  */
  50 #define LT_INT_TO_POINTER(a)    ((void *)(unsigned long)(a))
  51 
  52 #define TITLE                   "LatencyTOP for OpenSolaris, version 1.0"
  53 #define COPYRIGHT               "Copyright (c) 2008-2009, Intel Corporation."
  54 #define DEFAULT_KLOG_FILE       "/var/log/latencytop.log"
  55 
  56 #define INVALID_PID             (~0)
  57 #define INVALID_TID             (~0)
  58 #define PID_SYS_GLOBAL          INVALID_PID
  59 #define INVALID_CAUSE           0
  60 #define HIGHER_PRIORITY(a, b)   ((a) > (b))
  61 
  62 #ifdef EMBED_CONFIGS
  63 /*
  64  * LatencyTOP configuration is embedded in the binary.
  65  * Array will be generated by elfwrap.
  66  */
  67 extern char latencytop_d_start;
  68 extern char latencytop_d_end;
  69 extern char latencytop_trans_start;
  70 extern char latencytop_trans_end;
  71 #else
  72 /*
  73  * LatencyTOP configuration is provided externally by user.
  74  */
  75 #define DEFAULT_CONFIG_NAME     "./latencytop.trans"
  76 #define DEFAULT_D_SCRIPT_NAME   "./latencytop.d"
  77 #endif
  78 
  79 typedef enum {
  80         LT_STAT_COUNT,
  81         LT_STAT_MAX,
  82         LT_STAT_SUM,
  83 } lt_stat_type_t;
  84 
  85 #define LT_KLOG_LEVEL_NONE      0       /* Log nothing */
  86 #define LT_KLOG_LEVEL_UNMAPPED  1       /* Log only stacks not mapped */
  87 #define LT_KLOG_LEVEL_MAPPED    2       /* Log only stacks mapped */
  88 #define LT_KLOG_LEVEL_ALL       3       /* Log all stacks, mapped or not */
  89 
  90 typedef enum {
  91         LT_LEVEL_GLOBAL,        /* System wide statistics */
  92         LT_LEVEL_PROCESS,       /* Per-process statistics */
  93         LT_LEVEL_THREAD,        /* Per-thread statistics */
  94 } lt_stat_level_t;
  95 
  96 typedef enum {
  97         LT_SORT_TOTAL,
  98         LT_SORT_MAX,
  99         LT_SORT_AVG,
 100         LT_SORT_COUNT,
 101 } lt_sort_t;
 102 
 103 typedef enum {
 104         LT_FIELD_FNAME,
 105         LT_FIELD_PSARGS,
 106 } lt_field_t;
 107 
 108 typedef enum {
 109         LT_LIST_CAUSE,          /* List latency by causes (default) */
 110         LT_LIST_SPECIALS,       /* List only "special" causes */
 111         LT_LIST_SOBJ            /* List synchronization objects */
 112 } lt_list_type_t;
 113 
 114 /*
 115  * Data structure which contains statistics.
 116  */
 117 typedef struct {
 118         uint64_t lt_s_count;
 119         uint64_t lt_s_total;
 120         uint64_t lt_s_max;
 121 } lt_stat_data_t;
 122 
 123 /*
 124  * Data structure that stores statistics along with the name.
 125  */
 126 typedef struct {
 127         enum {
 128                 STAT_CAUSE,
 129                 STAT_SOBJ
 130         } lt_se_type;
 131         const char *lt_se_string;
 132         lt_stat_data_t lt_se_data;
 133         union {
 134                 struct {
 135                         int lt_se_c_id;
 136                         int lt_se_c_flags;
 137                 } lt_se_t_cause;
 138                 struct {
 139                         int lt_se_s_id;
 140                 } lt_se_t_sobj;
 141         } lt_se_tsdata; /* type specific data */
 142 } lt_stat_entry_t;
 143 
 144 typedef struct {
 145         int lt_cfg_enable_filter;
 146         int lt_cfg_trace_sched;
 147         int lt_cfg_trace_syncobj;
 148         int lt_cfg_low_overhead_mode;
 149         int lt_cfg_snap_interval;
 150         char *lt_cfg_config_name;
 151         unsigned int lt_cfg_trace_pid;
 152         unsigned int lt_cfg_trace_pgid;
 153 } lt_config_t;
 154 
 155 extern lt_config_t g_config;    /* The global settings */
 156 
 157 /*
 158  * Causes can be disabled through the configuration file.
 159  * When disabled, though D script will continue to capture causes, they will
 160  * not be counted by LatencyTOP.
 161  */
 162 #define CAUSE_FLAG_DISABLED             1
 163 /*
 164  * This flag will not show and count causes as part of summary in
 165  * "kstack window".
 166  */
 167 #define CAUSE_FLAG_HIDE_IN_SUMMARY      2
 168 /*
 169  * This is generated from D script (named cause), and is "special".
 170  */
 171 #define CAUSE_FLAG_SPECIAL              4
 172 #define CAUSE_ALL_FLAGS                 0xffffffff
 173 
 174 extern boolean_t lt_drop_detected;
 175 
 176 /*
 177  * These functions collect statistics using DTrace.
 178  */
 179 extern int lt_dtrace_init(void);
 180 extern int lt_dtrace_work(int);
 181 extern int lt_dtrace_collect(void);
 182 extern int lt_dtrace_deinit(void);
 183 
 184 /*
 185  * These functions maintain configuration, e.g. symbol to cause mapping.
 186  */
 187 extern int lt_table_init(void);
 188 extern int lt_table_cause_from_stack(const char *, int *, int *);
 189 extern const char *lt_table_get_cause_name(int);
 190 extern int lt_table_get_cause_flag(int, int);
 191 extern int lt_table_cause_from_name(char *, int, int);
 192 extern int lt_table_append_trans(FILE *fp);
 193 extern void lt_table_deinit(void);
 194 
 195 /*
 196  * These functions update statistic of all causes of latency, collected
 197  * from DTrace.
 198  */
 199 extern void lt_stat_update(pid_t, id_t, char *, char *, unsigned int,
 200     lt_stat_type_t, uint64_t);
 201 extern void lt_stat_update_cause(pid_t, id_t, int, lt_stat_type_t, uint64_t);
 202 extern void lt_stat_update_sobj(pid_t, id_t, int, unsigned long long,
 203     lt_stat_type_t, uint64_t);
 204 extern void lt_stat_clear_all(void);
 205 extern void lt_stat_free_all(void);
 206 
 207 /*
 208  * These functions produce lists for display panes.
 209  * Note: after a call to lt_stat_update_*, the old lists will become invalid.
 210  */
 211 extern void *lt_stat_list_create(lt_list_type_t, lt_stat_level_t,
 212     pid_t, id_t, int, lt_sort_t);
 213 extern int lt_stat_list_has_item(void *, int);
 214 extern const char *lt_stat_list_get_reason(void *, int);
 215 extern uint64_t lt_stat_list_get_max(void *, int);
 216 extern uint64_t lt_stat_list_get_sum(void *, int);
 217 extern uint64_t lt_stat_list_get_count(void *, int);
 218 extern uint64_t lt_stat_list_get_gtotal(void *);
 219 extern void lt_stat_list_free(void *);
 220 
 221 /*
 222  * These functions produce the process list and the thread list.
 223  */
 224 extern int lt_stat_proc_list_create(pid_t **, id_t **);
 225 extern void lt_stat_proc_list_free(pid_t *, id_t *);
 226 extern const char *lt_stat_proc_get_name(pid_t);
 227 extern int lt_stat_proc_get_nthreads(pid_t);
 228 
 229 /*
 230  * These functions use ncurses to create console-based display.
 231  */
 232 extern void lt_display_init(void);
 233 extern int lt_display_loop(int);
 234 extern void lt_display_error(const char *, ...);
 235 extern void lt_display_deinit(void);
 236 
 237 /*
 238  * Write statistics to log file - useful for debugging and offline analysis.
 239  */
 240 extern void lt_klog_init(void);
 241 extern void lt_klog_deinit(void);
 242 extern int lt_klog_set_log_file(const char *);
 243 extern int lt_klog_set_log_level(int);
 244 extern void lt_klog_write(void);
 245 extern void lt_klog_log(int, pid_t, char *, lt_stat_type_t,
 246     uint64_t);
 247 
 248 /*
 249  * Utility functions.
 250  */
 251 extern uint64_t lt_millisecond(void);
 252 extern void *lt_malloc(size_t);
 253 extern void *lt_zalloc(size_t);
 254 extern char *lt_strdup(const char *);
 255 extern void lt_check_null(void *);
 256 extern void lt_time_str(char *, int);
 257 extern char *lt_get_proc_field(pid_t, lt_field_t);
 258 extern void lt_update_stat_value(lt_stat_data_t *, lt_stat_type_t, uint64_t);
 259 extern int lt_sort_by_total_desc(lt_stat_entry_t *, lt_stat_entry_t *);
 260 extern int lt_sort_by_max_desc(lt_stat_entry_t *, lt_stat_entry_t *);
 261 extern int lt_sort_by_count_desc(lt_stat_entry_t *, lt_stat_entry_t *);
 262 extern int lt_sort_by_avg_desc(lt_stat_entry_t *, lt_stat_entry_t *);
 263 extern void lt_gpipe_init(void);
 264 extern void lt_gpipe_deinit(void);
 265 extern void lt_gpipe_break(const char *);
 266 extern int lt_gpipe_readfd(void);
 267 extern int lt_file_exist(const char *);
 268 
 269 #ifdef  __cplusplus
 270 }
 271 #endif
 272 
 273 #endif  /* _LATENCYTOP_H */