blob: cd3baf58c360fb82484f5be3d592046c0a2d409f [file] [log] [blame]
Benny Baumanne0229b22022-05-01 22:43:00 +02001/*
2htop - FileDescriptorMeter.c
3(C) 2022 htop dev team
4Released under the GNU GPLv2+, see the COPYING file
5in the source distribution for its full text.
6*/
7
Daniel Lange179aeb02023-11-29 17:44:20 +01008#include "config.h" // IWYU pragma: keep
9
Benny Baumanne0229b22022-05-01 22:43:00 +020010#include "FileDescriptorMeter.h"
11
12#include <math.h>
Benny Baumanne0229b22022-05-01 22:43:00 +020013
14#include "CRT.h"
Explorer09b4164332023-07-29 16:24:12 +080015#include "Macros.h"
Benny Baumanne0229b22022-05-01 22:43:00 +020016#include "Meter.h"
17#include "Object.h"
18#include "Platform.h"
19#include "RichString.h"
20#include "XUtils.h"
21
22
Explorer09b4164332023-07-29 16:24:12 +080023#define FD_EFFECTIVE_UNLIMITED(x) (!isgreaterequal((double)(1<<30), (x)))
Benny Baumann89872e32023-02-14 10:59:04 +010024
Benny Baumanne0229b22022-05-01 22:43:00 +020025static const int FileDescriptorMeter_attributes[] = {
26 FILE_DESCRIPTOR_USED,
27 FILE_DESCRIPTOR_MAX
28};
29
30static void FileDescriptorMeter_updateValues(Meter* this) {
31 this->values[0] = 0;
32 this->values[1] = 1;
33
34 Platform_getFileDescriptors(&this->values[0], &this->values[1]);
35
36 /* only print bar for first value */
37 this->curItems = 1;
38
Benny Baumann89872e32023-02-14 10:59:04 +010039 /* Use maximum value for scaling of bar mode
40 *
41 * As the plain total value can be very large compared to
42 * the actually used value, this is capped in the following way:
43 *
44 * 1. If the maximum value is below (or equal to) 1<<16, use it directly
45 * 2. If the maximum value is above, use powers of 2 starting at 1<<16 and
46 * double it until it's larger than 16 times the used file handles
47 * (capped at the maximum number of files)
48 * 3. If the maximum is effectively unlimited (AKA > 1<<30),
49 * Do the same as for 2, but cap at 1<<30.
50 */
Benny Baumannda255cb2023-04-11 22:49:39 +020051 if (this->values[1] <= 1 << 16) {
Benny Baumann89872e32023-02-14 10:59:04 +010052 this->total = this->values[1];
53 } else {
54 if (this->total < 16 * this->values[0]) {
Benny Baumannda255cb2023-04-11 22:49:39 +020055 for (this->total = 1 << 16; this->total < 16 * this->values[0]; this->total *= 2) {
56 if (this->total >= 1 << 30) {
Benny Baumann89872e32023-02-14 10:59:04 +010057 break;
58 }
59 }
60 }
61
62 if (this->total > this->values[1]) {
63 this->total = this->values[1];
64 }
65
Benny Baumannda255cb2023-04-11 22:49:39 +020066 if (this->total > 1 << 30) {
67 this->total = 1 << 30;
Benny Baumann89872e32023-02-14 10:59:04 +010068 }
69 }
Benny Baumanne0229b22022-05-01 22:43:00 +020070
Explorer09b4164332023-07-29 16:24:12 +080071 if (!isNonnegative(this->values[0])) {
Benny Baumanne0229b22022-05-01 22:43:00 +020072 xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "unknown/unknown");
Explorer09b4164332023-07-29 16:24:12 +080073 } else if (FD_EFFECTIVE_UNLIMITED(this->values[1])) {
Benny Baumann89872e32023-02-14 10:59:04 +010074 xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "%.0lf/unlimited", this->values[0]);
Benny Baumanne0229b22022-05-01 22:43:00 +020075 } else {
76 xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "%.0lf/%.0lf", this->values[0], this->values[1]);
77 }
78}
79
80static void FileDescriptorMeter_display(const Object* cast, RichString* out) {
81 const Meter* this = (const Meter*)cast;
82 char buffer[50];
83 int len;
84
Explorer09b4164332023-07-29 16:24:12 +080085 if (!isNonnegative(this->values[0])) {
Benny Baumanne0229b22022-05-01 22:43:00 +020086 RichString_appendAscii(out, CRT_colors[METER_TEXT], "unknown");
87 return;
88 }
89
90 RichString_appendAscii(out, CRT_colors[METER_TEXT], "used: ");
91 len = xSnprintf(buffer, sizeof(buffer), "%.0lf", this->values[0]);
92 RichString_appendnAscii(out, CRT_colors[FILE_DESCRIPTOR_USED], buffer, len);
93
94 RichString_appendAscii(out, CRT_colors[METER_TEXT], " max: ");
Explorer09b4164332023-07-29 16:24:12 +080095 if (FD_EFFECTIVE_UNLIMITED(this->values[1])) {
Benny Baumann89872e32023-02-14 10:59:04 +010096 RichString_appendAscii(out, CRT_colors[FILE_DESCRIPTOR_MAX], "unlimited");
97 } else {
98 len = xSnprintf(buffer, sizeof(buffer), "%.0lf", this->values[1]);
99 RichString_appendnAscii(out, CRT_colors[FILE_DESCRIPTOR_MAX], buffer, len);
100 }
Benny Baumanne0229b22022-05-01 22:43:00 +0200101}
102
103const MeterClass FileDescriptorMeter_class = {
104 .super = {
105 .extends = Class(Meter),
106 .delete = Meter_delete,
107 .display = FileDescriptorMeter_display,
108 },
109 .updateValues = FileDescriptorMeter_updateValues,
110 .defaultMode = TEXT_METERMODE,
Explorer0936626ce2024-05-03 03:52:57 +0800111 .supportedModes = METERMODE_DEFAULT_SUPPORTED,
Benny Baumanne0229b22022-05-01 22:43:00 +0200112 .maxItems = 2,
Benny Baumann89872e32023-02-14 10:59:04 +0100113 .total = 65536.0,
Benny Baumanne0229b22022-05-01 22:43:00 +0200114 .attributes = FileDescriptorMeter_attributes,
115 .name = "FileDescriptors",
116 .uiName = "File Descriptors",
117 .caption = "FDs: ",
118 .description = "Number of allocated/available file descriptors"
119};