1 /* Copyright (c) 2017 Daniel Widdis, All Rights Reserved 2 * 3 * The contents of this file is dual-licensed under 2 4 * alternative Open Source/Free licenses: LGPL 2.1 or later and 5 * Apache License 2.0. (starting with JNA version 4.0.0). 6 * 7 * You can freely decide which license you want to apply to 8 * the project. 9 * 10 * You may obtain a copy of the LGPL License at: 11 * 12 * http://www.gnu.org/licenses/licenses.html 13 * 14 * A copy is also included in the downloadable source code package 15 * containing JNA, in file "LGPL2.1". 16 * 17 * You may obtain a copy of the Apache License at: 18 * 19 * http://www.apache.org/licenses/ 20 * 21 * A copy is also included in the downloadable source code package 22 * containing JNA, in file "AL2.0". 23 */ 24 package com.sun.jna.platform.unix.solaris; 25 26 import java.util.Arrays; 27 import java.util.List; 28 29 import com.sun.jna.Library; 30 import com.sun.jna.Native; 31 import com.sun.jna.Pointer; 32 import com.sun.jna.Structure; 33 import com.sun.jna.Structure.FieldOrder; 34 import com.sun.jna.Union; 35 36 /** 37 * Kstat library. The kstat facility is a general-purpose mechanism for 38 * providing kernel statistics to users. 39 * 40 * @author widdis[at]gmail[dot]com 41 */ 42 public interface LibKstat extends Library { 43 44 LibKstat INSTANCE = Native.load("kstat", LibKstat.class); 45 46 /* 47 * Kstat Data Types 48 */ 49 // The "raw" kstat type is just treated as an array of bytes. This is 50 // generally used to export well-known structures, like sysinfo. 51 byte KSTAT_TYPE_RAW = 0; 52 53 byte KSTAT_TYPE_NAMED = 1; // name/value pairs 54 55 byte KSTAT_TYPE_INTR = 2; // interrupt statistics 56 57 byte KSTAT_TYPE_IO = 3; // I/O statistics 58 59 byte KSTAT_TYPE_TIMER = 4; // event timers 60 61 /* 62 * KstatNamed Data Types (for selecting from Union) 63 */ 64 byte KSTAT_DATA_CHAR = 0; 65 66 byte KSTAT_DATA_INT32 = 1; 67 68 byte KSTAT_DATA_UINT32 = 2; 69 70 byte KSTAT_DATA_INT64 = 3; 71 72 byte KSTAT_DATA_UINT64 = 4; 73 74 byte KSTAT_DATA_STRING = 9; 75 76 /* 77 * KstatIntr Interrupts 78 */ 79 int KSTAT_INTR_HARD = 0; 80 81 int KSTAT_INTR_SOFT = 1; 82 83 int KSTAT_INTR_WATCHDOG = 2; 84 85 int KSTAT_INTR_SPURIOUS = 3; 86 87 int KSTAT_INTR_MULTSVC = 4; 88 89 int KSTAT_NUM_INTRS = 5; 90 91 int KSTAT_STRLEN = 31; // 30 chars + NULL; must be 16 * n - 1 92 93 int EAGAIN = 11; // Temporarily busy 94 95 /** 96 * The kernel maintains a linked list of statistics structures, or kstats. 97 * Each kstat has a common header section and a type-specific data section. 98 * The header section is defined by the kstat_t structure 99 */ 100 @FieldOrder({"ks_crtime", "ks_next", "ks_kid", "ks_module", "ks_resv", "ks_instance", 101 "ks_name", "ks_type", "ks_class", "ks_flags", "ks_data", "ks_ndata", "ks_data_size", "ks_snaptime", 102 "ks_update", "ks_private", "ks_snapshot", "ks_lock"}) 103 class Kstat extends Structure { 104 105 // Fields relevant to both kernel and user 106 public long ks_crtime; // creation time 107 108 public Pointer ks_next; // kstat chain linkage 109 110 public int ks_kid; // unique kstat ID 111 112 public byte[] ks_module = new byte[KSTAT_STRLEN]; // module name 113 114 public byte ks_resv; // reserved 115 116 public int ks_instance; // module's instance 117 118 public byte[] ks_name = new byte[KSTAT_STRLEN]; // kstat name 119 120 public byte ks_type; // kstat data type 121 122 public byte[] ks_class = new byte[KSTAT_STRLEN]; // kstat class 123 124 public byte ks_flags; // kstat flags 125 126 public Pointer ks_data; // kstat type-specific data 127 128 public int ks_ndata; // # of data records 129 130 public long ks_data_size; // size of kstat data section 131 132 public long ks_snaptime; // time of last data snapshot 133 134 // Fields relevant to kernel only 135 public int ks_update; // dynamic update function 136 137 public Pointer ks_private; // provider-private data 138 139 public int ks_snapshot; // snapshot function 140 141 public Pointer ks_lock; // protects this kstat's data 142 next()143 public Kstat next() { 144 if (ks_next == null) { 145 return null; 146 } 147 Kstat n = new Kstat(); 148 n.useMemory(ks_next); 149 n.read(); 150 return n; 151 } 152 } 153 154 /** 155 * A list of arbitrary name=value statistics. 156 */ 157 @FieldOrder({"name", "data_type", "value"}) 158 class KstatNamed extends Structure { 159 160 public byte[] name = new byte[KSTAT_STRLEN]; // name of counter 161 162 public byte data_type; // data type 163 164 public UNION value; // value of counter 165 166 public static class UNION extends Union { 167 168 public byte[] charc = new byte[16]; // enough for 128-bit ints 169 170 public int i32; 171 172 public int ui32; 173 174 public long i64; 175 176 public long ui64; 177 178 public STR str; 179 180 @FieldOrder({"addr", "len"}) 181 public static class STR extends Structure { 182 183 public Pointer addr; 184 185 public int len; // length of string 186 187 } 188 } 189 KstatNamed()190 public KstatNamed() { 191 super(); 192 } 193 KstatNamed(Pointer p)194 public KstatNamed(Pointer p) { 195 super(p); 196 read(); 197 } 198 199 @Override read()200 public void read() { 201 super.read(); 202 switch (data_type) { 203 case KSTAT_DATA_CHAR: 204 value.setType(byte[].class); 205 break; 206 case KSTAT_DATA_STRING: 207 value.setType(UNION.STR.class); 208 break; 209 case KSTAT_DATA_INT32: 210 case KSTAT_DATA_UINT32: 211 value.setType(int.class); 212 break; 213 case KSTAT_DATA_INT64: 214 case KSTAT_DATA_UINT64: 215 value.setType(long.class); 216 break; 217 default: 218 break; 219 } 220 value.read(); 221 } 222 } 223 224 /** 225 * Interrupt statistics. An interrupt is a hard interrupt (sourced from the 226 * hardware device itself), a soft interrupt (induced by the system via the 227 * use of some system interrupt source), a watchdog interrupt (induced by a 228 * periodic timer call), spurious (an interrupt entry point was entered but 229 * there was no interrupt to service), or multiple service (an interrupt was 230 * detected and serviced just prior to returning from any of the other 231 * types). 232 */ 233 @FieldOrder({"intrs"}) 234 class KstatIntr extends Structure { 235 236 public int[] intrs = new int[KSTAT_NUM_INTRS]; // interrupt counters 237 238 } 239 240 /** 241 * Event timer statistics. These provide basic counting and timing 242 * information for any type of event. 243 */ 244 @FieldOrder({"name", "resv", "num_events", "elapsed_time", "min_time", "max_time", 245 "start_time", "stop_time"}) 246 class KstatTimer extends Structure { 247 248 public byte[] name = new byte[KSTAT_STRLEN]; // event name 249 250 public byte resv; // reserved 251 252 public long num_events; // number of events 253 254 public long elapsed_time; // cumulative elapsed time 255 256 public long min_time; // shortest event duration 257 258 public long max_time; // longest event duration 259 260 public long start_time; // previous event start time 261 262 public long stop_time; // previous event stop time 263 264 } 265 266 /** 267 * IO Statistics. 268 */ 269 @FieldOrder({"nread", "nwritten", "reads", "writes", "wtime", "wlentime", 270 "wlastupdate", "rtime", "rlentime", "rlastupdate", "wcnt", "rcnt"}) 271 class KstatIO extends Structure { 272 273 // Basic counters. 274 public long nread; // number of bytes read 275 276 public long nwritten; // number of bytes written 277 278 public int reads; // number of read operations 279 280 public int writes; // number of write operations 281 /*- 282 * Accumulated time and queue length statistics. 283 * 284 * Time statistics are kept as a running sum of "active" time. 285 * Queue length statistics are kept as a running sum of the 286 * product of queue length and elapsed time at that length -- 287 * that is, a Riemann sum for queue length integrated against time. 288 * ^ 289 * | _________ 290 * 8 | i4 | 291 * | | | 292 * Queue 6 | | 293 * Length | _________ | | 294 * 4 | i2 |_______| | 295 * | | i3 | 296 * 2_______| | 297 * | i1 | 298 * |_______________________________| 299 * Time-- t1 t2 t3 t4 300 * 301 * At each change of state (entry or exit from the queue), 302 * we add the elapsed time (since the previous state change) 303 * to the active time if the queue length was non-zero during 304 * that interval; and we add the product of the elapsed time 305 * times the queue length to the running length*time sum. 306 * 307 * This method is generalizable to measuring residency 308 * in any defined system: instead of queue lengths, think 309 * of "outstanding RPC calls to server X". 310 * 311 * A large number of I/O subsystems have at least two basic 312 * "lists" of transactions they manage: one for transactions 313 * that have been accepted for processing but for which processing 314 * has yet to begin, and one for transactions which are actively 315 * being processed (but not done). For this reason, two cumulative 316 * time statistics are defined here: pre-service (wait) time, 317 * and service (run) time. 318 * 319 * The units of cumulative busy time are accumulated nanoseconds. 320 * The units of cumulative length*time products are elapsed time 321 * times queue length. 322 */ 323 324 public long wtime; // cumulative wait (pre-service) time 325 326 public long wlentime; // cumulative wait length*time product 327 328 public long wlastupdate; // last time wait queue changed 329 330 public long rtime; // cumulative run (service) time 331 332 public long rlentime; // cumulative run length*time product 333 334 public long rlastupdate; // last time run queue changed 335 336 public int wcnt; // count of elements in wait state 337 338 public int rcnt; // count of elements in run state 339 KstatIO()340 public KstatIO() { 341 super(); 342 } 343 KstatIO(Pointer p)344 public KstatIO(Pointer p) { 345 super(p); 346 read(); 347 } 348 } 349 350 /** 351 * A kstat control structure. Only one thread may actively use a KstatCtl 352 * value at any time. Synchronization is left to the application. 353 */ 354 @FieldOrder({"kc_chain_id", "kc_chain", "kc_kd"}) 355 class KstatCtl extends Structure { 356 357 public int kc_chain_id; // current kstat chain ID 358 359 public Kstat kc_chain; // pointer to kstat chain 360 361 public int kc_kd; // /dev/kstat descriptor - not public interface 362 363 } 364 365 /** 366 * The kstat_open() function initializes a kstat control structure, which 367 * provides access to the kernel statistics library. 368 * 369 * @return A pointer to this structure, which must be supplied as the kc 370 * argument in subsequent libkstat function calls. 371 */ kstat_open()372 KstatCtl kstat_open(); 373 374 /** 375 * The kstat_close() function frees all resources that were associated with 376 * kc. 377 * 378 * @param kc 379 * a kstat control structure 380 * @return 0 on success and -1 on failure. 381 */ kstat_close(KstatCtl kc)382 int kstat_close(KstatCtl kc); 383 384 /** 385 * The kstat_chain_update() function brings the user's kstat header chain in 386 * sync with that of the kernel. The kstat chain is a linked list of kstat 387 * headers (kstat_t's) pointed to by kc.kc_chain, which is initialized by 388 * kstat_open(3KSTAT). This chain constitutes a list of all kstats currently 389 * in the system. During normal operation, the kernel creates new kstats and 390 * delete old ones as various device instances are added and removed, 391 * thereby causing the user's copy of the kstat chain to become out of date. 392 * The kstat_chain_update() function detects this condition by comparing the 393 * kernel's current kstat chain ID(KCID), which is incremented every time 394 * the kstat chain changes, to the user's KCID, kc.kc_chain_id. If the KCIDs 395 * match, kstat_chain_update() does nothing. Otherwise, it deletes any 396 * invalid kstat headers from the user's kstat chain, adds any new ones, and 397 * sets kc.kc_chain_id to the new KCID. All other kstat headers in the 398 * user's kstat chain are unmodified. 399 * 400 * @param kc 401 * a kstat control structure 402 * @return the new KCID if the kstat chain has changed, 0 if it hasn't, or 403 * -1 on failure. 404 */ kstat_chain_update(KstatCtl kc)405 int kstat_chain_update(KstatCtl kc); 406 407 /** 408 * kstat_read() gets data from the kernel for the kstat pointed to by ksp. 409 * ksp.ks_data is automatically allocated (or reallocated) to be large 410 * enough to hold all of the data. ksp.ks_ndata is set to the number of data 411 * fields, ksp.ks_data_size is set to the total size of the data, and 412 * ksp.ks_snaptime is set to the high-resolution time at which the data 413 * snapshot was taken. 414 * 415 * @param kc 416 * The kstat control structure 417 * @param ksp 418 * The kstat from which to retrieve data 419 * @param p 420 * If buf is non-NULL , the data is copied from ksp.ks_data into 421 * buf. 422 * @return On success, return the current kstat chain ID (KCID). On failure, 423 * return -1. 424 */ kstat_read(KstatCtl kc, Kstat ksp, Pointer p)425 int kstat_read(KstatCtl kc, Kstat ksp, Pointer p); 426 427 /** 428 * kstat_write() writes data from buf, or from ksp.ks_data if buf is NULL, 429 * to the corresponding kstat in the kernel. Only the superuser can use 430 * kstat_write() . 431 * 432 * @param kc 433 * The kstat control structure 434 * @param ksp 435 * The kstat on which to set data 436 * @param buf 437 * If buf is non-NULL, the data is copied from buf into 438 * ksp.ks_data. 439 * @return On success, return the current kstat chain ID (KCID). On failure, 440 * return -1. 441 */ kstat_write(KstatCtl kc, Kstat ksp, Pointer buf)442 int kstat_write(KstatCtl kc, Kstat ksp, Pointer buf); 443 444 /** 445 * The kstat_lookup() function traverses the kstat chain, kc.kc_chain, 446 * searching for a kstat with the same ks_module, ks_instance, and ks_name 447 * fields; this triplet uniquely identifies a kstat. If ks_module is NULL, 448 * ks_instance is -1, or ks_name is NULL, then those fields will be ignored 449 * in the search. For example, kstat_lookup(kc, NULL, -1, "foo") will simply 450 * find the first kstat with name "foo". 451 * 452 * @param kc 453 * The kstat control structure 454 * @param ks_module 455 * The kstat module to search 456 * @param ks_instance 457 * The kstat instance number 458 * @param ks_name 459 * The kstat name to search 460 * @return a pointer to the requested kstat if it is found, or NULL if it is 461 * not. 462 */ kstat_lookup(KstatCtl kc, String ks_module, int ks_instance, String ks_name)463 Kstat kstat_lookup(KstatCtl kc, String ks_module, int ks_instance, String ks_name); 464 465 /** 466 * The kstat_data_lookup() function searches the kstat's data section for 467 * the record with the specified name . This operation is valid only for 468 * kstat types which have named data records. Currently, only the 469 * KSTAT_TYPE_NAMED and KSTAT_TYPE_TIMER kstats have named data records. 470 * 471 * @param ksp 472 * The kstat to search 473 * @param name 474 * The key for the name-value pair, or name of the timer as 475 * applicable 476 * @return a pointer to the requested data record if it is found. If the 477 * requested record is not found, or if the kstat type is invalid, 478 * returns NULL. 479 */ kstat_data_lookup(Kstat ksp, String name)480 Pointer kstat_data_lookup(Kstat ksp, String name); 481 } 482