Platform.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. /*
  2. htop - solaris/Platform.c
  3. (C) 2014 Hisham H. Muhammad
  4. (C) 2015 David C. Hunt
  5. (C) 2017,2018 Guy M. Broome
  6. Released under the GNU GPLv2+, see the COPYING file
  7. in the source distribution for its full text.
  8. */
  9. #include "config.h" // IWYU pragma: keep
  10. #include "solaris/Platform.h"
  11. #include <kstat.h>
  12. #include <math.h>
  13. #include <string.h>
  14. #include <time.h>
  15. #include <utmpx.h>
  16. #include <sys/loadavg.h>
  17. #include <sys/resource.h>
  18. #include <sys/types.h>
  19. #include <sys/time.h>
  20. #include <sys/var.h>
  21. #include "Macros.h"
  22. #include "Meter.h"
  23. #include "CPUMeter.h"
  24. #include "MemoryMeter.h"
  25. #include "MemorySwapMeter.h"
  26. #include "SwapMeter.h"
  27. #include "TasksMeter.h"
  28. #include "LoadAverageMeter.h"
  29. #include "ClockMeter.h"
  30. #include "DateMeter.h"
  31. #include "DateTimeMeter.h"
  32. #include "HostnameMeter.h"
  33. #include "SysArchMeter.h"
  34. #include "UptimeMeter.h"
  35. #include "XUtils.h"
  36. #include "solaris/SolarisMachine.h"
  37. #include "zfs/ZfsArcMeter.h"
  38. #include "zfs/ZfsCompressedArcMeter.h"
  39. const ScreenDefaults Platform_defaultScreens[] = {
  40. {
  41. .name = "Default",
  42. .columns = "PID LWPID USER PRIORITY NICE M_VIRT M_RESIDENT STATE PERCENT_CPU PERCENT_MEM TIME Command",
  43. .sortKey = "PERCENT_CPU",
  44. },
  45. };
  46. const unsigned int Platform_numberOfDefaultScreens = ARRAYSIZE(Platform_defaultScreens);
  47. const SignalItem Platform_signals[] = {
  48. { .name = " 0 Cancel", .number = 0 },
  49. { .name = " 1 SIGHUP", .number = 1 },
  50. { .name = " 2 SIGINT", .number = 2 },
  51. { .name = " 3 SIGQUIT", .number = 3 },
  52. { .name = " 4 SIGILL", .number = 4 },
  53. { .name = " 5 SIGTRAP", .number = 5 },
  54. { .name = " 6 SIGABRT/IOT", .number = 6 },
  55. { .name = " 7 SIGEMT", .number = 7 },
  56. { .name = " 8 SIGFPE", .number = 8 },
  57. { .name = " 9 SIGKILL", .number = 9 },
  58. { .name = "10 SIGBUS", .number = 10 },
  59. { .name = "11 SIGSEGV", .number = 11 },
  60. { .name = "12 SIGSYS", .number = 12 },
  61. { .name = "13 SIGPIPE", .number = 13 },
  62. { .name = "14 SIGALRM", .number = 14 },
  63. { .name = "15 SIGTERM", .number = 15 },
  64. { .name = "16 SIGUSR1", .number = 16 },
  65. { .name = "17 SIGUSR2", .number = 17 },
  66. { .name = "18 SIGCHLD/CLD", .number = 18 },
  67. { .name = "19 SIGPWR", .number = 19 },
  68. { .name = "20 SIGWINCH", .number = 20 },
  69. { .name = "21 SIGURG", .number = 21 },
  70. { .name = "22 SIGPOLL/IO", .number = 22 },
  71. { .name = "23 SIGSTOP", .number = 23 },
  72. { .name = "24 SIGTSTP", .number = 24 },
  73. { .name = "25 SIGCONT", .number = 25 },
  74. { .name = "26 SIGTTIN", .number = 26 },
  75. { .name = "27 SIGTTOU", .number = 27 },
  76. { .name = "28 SIGVTALRM", .number = 28 },
  77. { .name = "29 SIGPROF", .number = 29 },
  78. { .name = "30 SIGXCPU", .number = 30 },
  79. { .name = "31 SIGXFSZ", .number = 31 },
  80. { .name = "32 SIGWAITING", .number = 32 },
  81. { .name = "33 SIGLWP", .number = 33 },
  82. { .name = "34 SIGFREEZE", .number = 34 },
  83. { .name = "35 SIGTHAW", .number = 35 },
  84. { .name = "36 SIGCANCEL", .number = 36 },
  85. { .name = "37 SIGLOST", .number = 37 },
  86. { .name = "38 SIGXRES", .number = 38 },
  87. { .name = "39 SIGJVM1", .number = 39 },
  88. { .name = "40 SIGJVM2", .number = 40 },
  89. { .name = "41 SIGINFO", .number = 41 },
  90. };
  91. const unsigned int Platform_numberOfSignals = ARRAYSIZE(Platform_signals);
  92. const MeterClass* const Platform_meterTypes[] = {
  93. &CPUMeter_class,
  94. &ClockMeter_class,
  95. &DateMeter_class,
  96. &DateTimeMeter_class,
  97. &LoadAverageMeter_class,
  98. &LoadMeter_class,
  99. &MemoryMeter_class,
  100. &SwapMeter_class,
  101. &MemorySwapMeter_class,
  102. &TasksMeter_class,
  103. &BatteryMeter_class,
  104. &HostnameMeter_class,
  105. &SysArchMeter_class,
  106. &UptimeMeter_class,
  107. &AllCPUsMeter_class,
  108. &AllCPUs2Meter_class,
  109. &AllCPUs4Meter_class,
  110. &AllCPUs8Meter_class,
  111. &LeftCPUsMeter_class,
  112. &RightCPUsMeter_class,
  113. &LeftCPUs2Meter_class,
  114. &RightCPUs2Meter_class,
  115. &LeftCPUs4Meter_class,
  116. &RightCPUs4Meter_class,
  117. &LeftCPUs8Meter_class,
  118. &RightCPUs8Meter_class,
  119. &ZfsArcMeter_class,
  120. &ZfsCompressedArcMeter_class,
  121. &BlankMeter_class,
  122. NULL
  123. };
  124. bool Platform_init(void) {
  125. /* no platform-specific setup needed */
  126. return true;
  127. }
  128. void Platform_done(void) {
  129. /* no platform-specific cleanup needed */
  130. }
  131. void Platform_setBindings(Htop_Action* keys) {
  132. /* no platform-specific key bindings */
  133. (void) keys;
  134. }
  135. int Platform_getUptime(void) {
  136. int boot_time = 0;
  137. int curr_time = time(NULL);
  138. struct utmpx* ent;
  139. while (( ent = getutxent() )) {
  140. if ( String_eq("system boot", ent->ut_line )) {
  141. boot_time = ent->ut_tv.tv_sec;
  142. }
  143. }
  144. endutxent();
  145. return (curr_time - boot_time);
  146. }
  147. void Platform_getLoadAverage(double* one, double* five, double* fifteen) {
  148. double plat_loadavg[3];
  149. if (getloadavg( plat_loadavg, 3 ) < 0) {
  150. *one = NAN;
  151. *five = NAN;
  152. *fifteen = NAN;
  153. return;
  154. }
  155. *one = plat_loadavg[LOADAVG_1MIN];
  156. *five = plat_loadavg[LOADAVG_5MIN];
  157. *fifteen = plat_loadavg[LOADAVG_15MIN];
  158. }
  159. pid_t Platform_getMaxPid(void) {
  160. int vproc = 32778; // Reasonable Solaris default
  161. kstat_ctl_t* kc = kstat_open();
  162. if (kc != NULL) {
  163. kstat_t* kshandle = kstat_lookup_wrapper(kc, "unix", 0, "var");
  164. if (kshandle != NULL) {
  165. kstat_read(kc, kshandle, NULL);
  166. kvar_t* ksvar = kshandle->ks_data;
  167. if (ksvar && ksvar->v_proc > 0) {
  168. vproc = ksvar->v_proc;
  169. }
  170. }
  171. kstat_close(kc);
  172. }
  173. return vproc;
  174. }
  175. double Platform_setCPUValues(Meter* this, unsigned int cpu) {
  176. const Machine* host = this->host;
  177. const SolarisMachine* shost = (const SolarisMachine*) host;
  178. unsigned int cpus = host->existingCPUs;
  179. const CPUData* cpuData = NULL;
  180. if (cpus == 1) {
  181. // single CPU box has everything in spl->cpus[0]
  182. cpuData = &(shost->cpus[0]);
  183. } else {
  184. cpuData = &(shost->cpus[cpu]);
  185. }
  186. if (!cpuData->online) {
  187. this->curItems = 0;
  188. return NAN;
  189. }
  190. double percent;
  191. double* v = this->values;
  192. v[CPU_METER_NICE] = cpuData->nicePercent;
  193. v[CPU_METER_NORMAL] = cpuData->userPercent;
  194. if (host->settings->detailedCPUTime) {
  195. v[CPU_METER_KERNEL] = cpuData->systemPercent;
  196. v[CPU_METER_IRQ] = cpuData->irqPercent;
  197. this->curItems = 4;
  198. } else {
  199. v[CPU_METER_KERNEL] = cpuData->systemAllPercent;
  200. this->curItems = 3;
  201. }
  202. percent = sumPositiveValues(v, this->curItems);
  203. percent = MINIMUM(percent, 100.0);
  204. v[CPU_METER_FREQUENCY] = cpuData->frequency;
  205. v[CPU_METER_TEMPERATURE] = NAN;
  206. return percent;
  207. }
  208. void Platform_setMemoryValues(Meter* this) {
  209. const Machine* host = this->host;
  210. this->total = host->totalMem;
  211. this->values[MEMORY_METER_USED] = host->usedMem;
  212. // this->values[MEMORY_METER_SHARED] = "shared memory, like tmpfs and shm"
  213. // this->values[MEMORY_METER_COMPRESSED] = "compressed memory, like zswap on linux"
  214. this->values[MEMORY_METER_BUFFERS] = host->buffersMem;
  215. this->values[MEMORY_METER_CACHE] = host->cachedMem;
  216. // this->values[MEMORY_METER_AVAILABLE] = "available memory"
  217. }
  218. void Platform_setSwapValues(Meter* this) {
  219. const Machine* host = this->host;
  220. this->total = host->totalSwap;
  221. this->values[SWAP_METER_USED] = host->usedSwap;
  222. // this->values[SWAP_METER_CACHE] = "pages that are both in swap and RAM, like SwapCached on linux"
  223. // this->values[SWAP_METER_FRONTSWAP] = "pages that are accounted to swap but stored elsewhere, like frontswap on linux"
  224. }
  225. void Platform_setZfsArcValues(Meter* this) {
  226. const SolarisMachine* shost = (const SolarisMachine*) this->host;
  227. ZfsArcMeter_readStats(this, &shost->zfs);
  228. }
  229. void Platform_setZfsCompressedArcValues(Meter* this) {
  230. const SolarisMachine* shost = (const SolarisMachine*) this->host;
  231. ZfsCompressedArcMeter_readStats(this, &shost->zfs);
  232. }
  233. static int Platform_buildenv(void* accum, struct ps_prochandle* Phandle, uintptr_t addr, const char* str) {
  234. envAccum* accump = accum;
  235. (void) Phandle;
  236. (void) addr;
  237. size_t thissz = strlen(str);
  238. while ((thissz + 2) > (accump->capacity - accump->size)) {
  239. if (accump->capacity > (SIZE_MAX / 2))
  240. return 1;
  241. accump->capacity *= 2;
  242. accump->env = xRealloc(accump->env, accump->capacity);
  243. }
  244. strlcpy( accump->env + accump->size, str, accump->capacity - accump->size);
  245. strncpy( accump->env + accump->size + thissz + 1, "\n", 2);
  246. accump->size += thissz + 1;
  247. return 0;
  248. }
  249. char* Platform_getProcessEnv(pid_t pid) {
  250. envAccum envBuilder;
  251. pid_t realpid = pid / 1024;
  252. int graberr;
  253. struct ps_prochandle* Phandle;
  254. if ((Phandle = Pgrab(realpid, PGRAB_RDONLY, &graberr)) == NULL) {
  255. return NULL;
  256. }
  257. envBuilder.capacity = 4096;
  258. envBuilder.size = 0;
  259. envBuilder.env = xMalloc(envBuilder.capacity);
  260. (void) Penv_iter(Phandle, Platform_buildenv, &envBuilder);
  261. Prelease(Phandle, 0);
  262. strncpy( envBuilder.env + envBuilder.size, "\0", 1);
  263. return xRealloc(envBuilder.env, envBuilder.size + 1);
  264. }
  265. FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid) {
  266. (void)pid;
  267. return NULL;
  268. }
  269. void Platform_getFileDescriptors(double* used, double* max) {
  270. *used = NAN;
  271. *max = NAN;
  272. }
  273. bool Platform_getDiskIO(DiskIOData* data) {
  274. // TODO
  275. (void)data;
  276. return false;
  277. }
  278. bool Platform_getNetworkIO(NetworkIOData* data) {
  279. // TODO
  280. (void)data;
  281. return false;
  282. }
  283. void Platform_getBattery(double* percent, ACPresence* isOnAC) {
  284. *percent = NAN;
  285. *isOnAC = AC_ERROR;
  286. }