If no terminal name can be found, fall back to generic display method
with major and minor device numbers.
Print special value '(none)' in case both are zero.
Use only one enum instead of a global and a platform specific one.
Drop Platform_numberOfFields global variable.
Set known size of Process_fields array
This acheives two things:
- Allows for simple tie-breaking if values compare equal (needed to make sorting the tree-view stable)
- Allows for platform-dependent overriding of the sort-order for specific fields
Also fixes a small oversight on DragonFlyBSD when default-sorting.
Implements the suggestion from https://github.com/htop-dev/htop/issues/399#issuecomment-747861013
Thanks to the refactors from 0bd5c8fb5da and 6393baa74e5, this was really easy
and clean to do.
It maintains the "Tree view always by PID" option in the Settings, which
results in some specific behaviors such as "clicking on the column header to
exit tree view" and "picking a new sort order to exit tree view", for the sake
of the muscle memory of long time htop users. :)
* This removes duplicated code that adjusts the sort direction from every
OS-specific folder.
* Most fields in a regular htop screen are OS-independent, so trying
Process_compare first and only falling back to the OS-specific
compareByKey function if it's an OS-specific field makes sense.
* This will allow us to override the sortKey in a global way without having
to edit each OS-specific file.
By storing the per-process m_resident and m_virt values in the form
htop wants to display them in (KB, not pages), we no longer need to
have definitions of pageSize and pageSizeKB in the common CRT code.
These variables were never really CRT (i.e. display) related in the
first place. It turns out the darwin platform code doesn't need to
use these at all (the process values are extracted from the kernel
in bytes not pages) and the other platforms can each use their own
local pagesize variables, in more appropriate locations.
Some platforms were actually already doing this, so this change is
removing duplication of logic and variables there.
RichString_writeFrom takes a top spot during performance analysis due to the
calls to mbstowcs() and iswprint().
Most of the time we know in advance that we are only going to print regular
ASCII characters.
If currently two unsigned values are compared via `a - b`, in the case b
is actually bigger than a, the result will not be an negative number (as
-1 is expected) but a huge positive number as the subtraction is an
unsigned subtraction.
Avoid over-/underflow affected operations; use comparisons.
Modern compilers will generate sane code, like:
xor eax, eax
cmp rdi, rsi
seta al
sbb eax, 0
ret
man:sysconf(3) states:
The values obtained from these functions are system configuration constants.
They do not change during the lifetime of a process.
When building on a 32-bit system, the compiler warned that the
following line uses a constant whose value is the overflow result
of a compile-time computation:
Process.c (line 109): } else if (number < 10000 * ONE_M) {
Namely, this constant expression:
10000 * ONE_M
was intended to produce the following value:
10485760000
However, the result overflowed to produce:
1895825408
The reason for this overflow is as follows:
o The macros are expanded:
10000 * (ONE_K * ONE_K)
10000 * (1024L * 1024L)
o The untyped constant expression "10000" is typed:
10000U * (1024L * 1024L)
o The parenthesized expression is evaluated:
10000U * (1048576L)
o The left operand ("10000U") is converted:
10000L * (1048576L)
Unbound by integer sizes, that last multiplication
would produce the following value:
10485760000
However, on a 32-bit machine, where a long is 32 bits
(really 31 bits when talking about positive numbers),
the maximum value that can be computed is 2**31-1:
2147483647
Consequently, the computation overflows.
o The compiler produces a long int value that is the
the result of overflow (10485760000 % 2**31):
1895825408L
Actually, I think this overflow is implementation-defined,
so it's not even a portable description of what happens.
The solution is to use a long long int (or, even better,
an unsigned long long int) type for the constant expression;
the C standard mandates a sufficiently large maximum value
for such types.
Hence, the following change is made to the bad line:
- } else if (number < 10000 * ONE_M) {
+ } else if (number < 10000ULL * ONE_M) {
However, the whole line is now patently silly, because the
variable "number" is typed "unsigned long", and so it will
always be less than the constant expression (the compiler
will warn about this, too).
Hence, "number" must be typed "unsigned long long"; however,
this necessitates changing all of the string formats from
something like "%lu" to something like "%llu".
Et voila! This commit is born.
Then, for the sake of completeness, the declared types of the
constant-expression macros are updated:
o ONE_K is made unsigned (a "UL" instead of "L")
o ONE_T is computed by introducing "1ULL *"
o Similar changes are made for ONE_DECIMAL_{K,T}
Also, a non-portable overflow-conversion to a signed value
has been replaced with a portable comparison:
- if ((long long) number == -1LL) {
+ if (number == ULLONG_MAX) {
It might be worth reviewing the rest of the code for other
cases where overflows are not handled correctly; even at
runtime, it's often necessary to check for overflow unless
such behavior is expected (especially for signed integer
values, for which overflow has implementation-defined
behavior).