diff options
author | Explorer09 <explorer09@gmail.com> | 2023-07-29 16:24:12 +0800 |
---|---|---|
committer | BenBE <BenBE@geshi.org> | 2023-08-18 12:52:28 +0200 |
commit | b416433fbe7ccf935ad4e268396aa423143c2318 (patch) | |
tree | 55a38c76f4f0091ed6b06d7369706bd2f1f6f61e /linux/LinuxProcess.c | |
parent | c6fd64fce8502a4e557711abe9fee394763ac52c (diff) |
Replace isnan() with better comparisons (isgreater(), etc.)
The standard isnan() function is defined to never throw FP exceptions
even when the argument is a "signaling" NaN. This makes isnan() more
expensive than (x != x) expression unless the compiler flag
'-fno-signaling-nans' is given.
Introduce functions isNaN(), isNonnegative(), isPositive(),
sumPositiveValues() and compareRealNumbers(), and replace isnan() in
htop's codebase with the new functions. These functions utilize
isgreater() and isgreaterequal() comparisons, which do not throw FP
exceptions on "quiet" NaNs, which htop uses extensively.
With isnan() removed, there is no need to suppress the warning
'-Wno-c11-extensions' in FreeBSD. Remove the code from 'configure.ac'.
Signed-off-by: Kang-Che Sung <explorer09@gmail.com>
Diffstat (limited to 'linux/LinuxProcess.c')
-rw-r--r-- | linux/LinuxProcess.c | 46 |
1 files changed, 25 insertions, 21 deletions
diff --git a/linux/LinuxProcess.c b/linux/LinuxProcess.c index b815c5b5..0a88644c 100644 --- a/linux/LinuxProcess.c +++ b/linux/LinuxProcess.c @@ -192,6 +192,19 @@ bool LinuxProcess_changeAutogroupPriorityBy(Process* this, Arg delta) { return success; } +static double LinuxProcess_totalIORate(const LinuxProcess* lp) { + double totalRate = NAN; + if (isNonnegative(lp->io_rate_read_bps)) { + totalRate = lp->io_rate_read_bps; + if (isNonnegative(lp->io_rate_write_bps)) { + totalRate += lp->io_rate_write_bps; + } + } else if (isNonnegative(lp->io_rate_write_bps)) { + totalRate = lp->io_rate_write_bps; + } + return totalRate; +} + static void LinuxProcess_writeField(const Process* this, RichString* str, ProcessField field) { const LinuxProcess* lp = (const LinuxProcess*) this; const LinuxMachine* lhost = (const LinuxMachine*) this->host; @@ -230,19 +243,7 @@ static void LinuxProcess_writeField(const Process* this, RichString* str, Proces case CNCLWB: Process_printBytes(str, lp->io_cancelled_write_bytes, coloring); return; case IO_READ_RATE: Process_printRate(str, lp->io_rate_read_bps, coloring); return; case IO_WRITE_RATE: Process_printRate(str, lp->io_rate_write_bps, coloring); return; - case IO_RATE: { - double totalRate; - if (!isnan(lp->io_rate_read_bps) && !isnan(lp->io_rate_write_bps)) - totalRate = lp->io_rate_read_bps + lp->io_rate_write_bps; - else if (!isnan(lp->io_rate_read_bps)) - totalRate = lp->io_rate_read_bps; - else if (!isnan(lp->io_rate_write_bps)) - totalRate = lp->io_rate_write_bps; - else - totalRate = NAN; - Process_printRate(str, totalRate, coloring); - return; - } + case IO_RATE: Process_printRate(str, LinuxProcess_totalIORate(lp), coloring); return; #ifdef HAVE_OPENVZ case CTID: xSnprintf(buffer, n, "%-8s ", lp->ctid ? lp->ctid : ""); break; case VPID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, lp->vpid); break; @@ -309,11 +310,14 @@ static void LinuxProcess_writeField(const Process* this, RichString* str, Proces RichString_appendAscii(str, attr, buffer); } -static double adjustNaN(double num) { - if (isnan(num)) - return -0.0005; - - return num; +/* Compares floating point values for ordering data entries. In this function, + NaN is considered "less than" any other floating point value (regardless of + sign), and two NaNs are considered "equal" regardless of payload. */ +static int compareRealNumbers(double a, double b) { + int result = isgreater(a, b) - isgreater(b, a); + if (result) + return result; + return !isNaN(a) - !isNaN(b); } static int LinuxProcess_compareByKey(const Process* v1, const Process* v2, ProcessField key) { @@ -358,11 +362,11 @@ static int LinuxProcess_compareByKey(const Process* v1, const Process* v2, Proce case CNCLWB: return SPACESHIP_NUMBER(p1->io_cancelled_write_bytes, p2->io_cancelled_write_bytes); case IO_READ_RATE: - return SPACESHIP_NUMBER(adjustNaN(p1->io_rate_read_bps), adjustNaN(p2->io_rate_read_bps)); + return compareRealNumbers(p1->io_rate_read_bps, p2->io_rate_read_bps); case IO_WRITE_RATE: - return SPACESHIP_NUMBER(adjustNaN(p1->io_rate_write_bps), adjustNaN(p2->io_rate_write_bps)); + return compareRealNumbers(p1->io_rate_write_bps, p2->io_rate_write_bps); case IO_RATE: - return SPACESHIP_NUMBER(adjustNaN(p1->io_rate_read_bps) + adjustNaN(p1->io_rate_write_bps), adjustNaN(p2->io_rate_read_bps) + adjustNaN(p2->io_rate_write_bps)); + return compareRealNumbers(LinuxProcess_totalIORate(p1), LinuxProcess_totalIORate(p2)); #ifdef HAVE_OPENVZ case CTID: return SPACESHIP_NULLSTR(p1->ctid, p2->ctid); |