Switch to using timef instead of gettimeofday

This encapsulates the tricky arithmetic inside timef(), which uses
gettimeofday.
This commit is contained in:
ridiculousfish 2021-08-27 16:20:30 -07:00
parent 7d537eefbb
commit 7a1c005b42
6 changed files with 19 additions and 43 deletions

View File

@ -29,24 +29,13 @@ enum {
/// Calculates the cpu usage (in percent) of the specified job.
static int cpu_use(const job_t *j) {
double u = 0;
for (const process_ptr_t &p : j->processes) {
struct timeval t;
unsigned long jiffies;
gettimeofday(&t, nullptr);
jiffies = proc_get_jiffies(p->pid);
double t1 = 1000000.0 * p->last_time.tv_sec + p->last_time.tv_usec;
double t2 = 1000000.0 * t.tv_sec + t.tv_usec;
// Check for a race condition that can cause negative CPU usage to be reported (#7066)
unsigned long cached_last_jiffies = p->last_jiffies;
if (t2 < t1 || jiffies < cached_last_jiffies) {
continue;
timepoint_t now = timef();
unsigned long jiffies = proc_get_jiffies(p->pid);
double since = now - p->last_time;
if (since > 0 && jiffies > p->last_jiffies) {
u += (jiffies - p->last_jiffies) / since;
}
// std::fwprintf( stderr, L"t1 %f t2 %f p1 %d p2 %d\n", t1, t2, jiffies, p->last_jiffies );
u += (static_cast<double>(jiffies - cached_last_jiffies)) / (t2 - t1);
}
return u * 1000000;
}

View File

@ -1723,13 +1723,10 @@ void format_size_safe(char buff[128], unsigned long long sz) {
}
}
/// Return the number of seconds from the UNIX epoch, with subsecond precision. This function uses
/// the gettimeofday function and will have the same precision as that function.
double timef() {
struct timeval tv;
assert_with_errno(gettimeofday(&tv, nullptr) != -1);
// return (double)tv.tv_sec + 0.000001 * tv.tv_usec;
return static_cast<double>(tv.tv_sec) + 1e-6 * tv.tv_usec;
return static_cast<timepoint_t>(tv.tv_sec) + 1e-6 * tv.tv_usec;
}
void exit_without_destructors(int code) { _exit(code); }

View File

@ -13,6 +13,7 @@
#include <algorithm>
#include <atomic>
#include <cmath>
#include <functional>
#include <memory>
#include <mutex>
@ -516,7 +517,8 @@ void bugreport();
/// Return the number of seconds from the UNIX epoch, with subsecond precision. This function uses
/// the gettimeofday function and will have the same precision as that function.
double timef();
using timepoint_t = double;
timepoint_t timef();
/// Call the following function early in main to set the main thread. This is our replacement for
/// pthread_main_np().

View File

@ -765,7 +765,7 @@ unsigned long proc_get_jiffies(pid_t inpid) {
void proc_update_jiffies(parser_t &parser) {
for (const auto &job : parser.jobs()) {
for (process_ptr_t &p : job->processes) {
gettimeofday(&p->last_time, nullptr);
p->last_time = timef();
p->last_jiffies = proc_get_jiffies(p->pid);
}
}

View File

@ -277,8 +277,8 @@ class process_t : noncopyable_t {
/// Reported status value.
proc_status_t status{};
/// Last time of cpu time check.
struct timeval last_time {};
/// Last time of cpu time check, in seconds (per timef).
timepoint_t last_time{0};
/// Number of jiffies spent in process at last cpu time check.
unsigned long last_jiffies{0};

View File

@ -2408,23 +2408,9 @@ void reader_data_t::set_buffer_maintaining_pager(const wcstring &b, size_t pos,
history_search.reset();
}
static void set_env_cmd_duration(struct timeval *after, struct timeval *before, env_stack_t &vars) {
time_t secs = after->tv_sec - before->tv_sec;
suseconds_t usecs = after->tv_usec - before->tv_usec;
if (after->tv_usec < before->tv_usec) {
usecs += 1000000;
secs -= 1;
}
vars.set_one(ENV_CMD_DURATION, ENV_UNEXPORT, std::to_wstring((secs * 1000) + (usecs / 1000)));
}
/// Run the specified command with the correct terminal modes, and while taking care to perform job
/// notification, set the title, etc.
static eval_res_t reader_run_command(parser_t &parser, const wcstring &cmd) {
struct timeval time_before, time_after;
wcstring ft = tok_command(cmd);
// For compatibility with fish 2.0's $_, now replaced with `status current-command`
@ -2435,16 +2421,18 @@ static eval_res_t reader_run_command(parser_t &parser, const wcstring &cmd) {
outp.set_color(rgb_color_t::normal(), rgb_color_t::normal());
term_donate();
gettimeofday(&time_before, nullptr);
timepoint_t time_before = timef();
auto eval_res = parser.eval(cmd, io_chain_t{});
job_reap(parser, true);
gettimeofday(&time_after, nullptr);
// update the execution duration iff a command is requested for execution
// issue - #4926
if (!ft.empty()) set_env_cmd_duration(&time_after, &time_before, parser.vars());
if (!ft.empty()) {
timepoint_t time_after = timef();
double duration = time_after - time_before;
long duration_ms = std::round(duration * 1000);
parser.vars().set_one(ENV_CMD_DURATION, ENV_UNEXPORT, to_string(duration_ms));
}
term_steal();