@@ 70,6 70,18 @@ struct process_lookup_error: public std::runtime_error {
using std::runtime_error::runtime_error;
};
+constexpr auto tspec_diff(const timespec& t0, const timespec& t1) {
+ timespec t {
+ .tv_sec = t1.tv_sec - t0.tv_sec,
+ .tv_nsec = t1.tv_nsec - t0.tv_nsec
+ };
+ if (t.tv_nsec < 0) {
+ --t.tv_sec;
+ t.tv_nsec += 1000000000;
+ }
+ return t;
+}
+
struct config {
#if 0 // unused for now
fs::path dump_path{ "/var/lib/prelockdpp/dump.json" };
@@ 181,6 193,27 @@ struct context {
}
return t;
}
+ auto tspec_from_ticks(auto ticks) {
+ timespec tspec;
+ tspec.tv_sec = ticks / info.sc_clk_tck;
+ tspec.tv_nsec = ticks % info.sc_clk_tck;
+ return tspec;
+ }
+ auto parse_timespec(auto begin, auto end) {
+ auto from_chars = [&](auto begin, auto end, auto& out) {
+ if (auto [_, ec] = std::from_chars(begin, end, out); ec != std::errc()) {
+ throw std::runtime_error{ "Failed to read timespec value" };
+ }
+ };
+ auto end1 = std::find(begin, end, '.');
+ if (end1 == end) {
+ throw std::logic_error{ "Unexpected timespec fmt" };
+ }
+ timespec t;
+ from_chars(begin, end1, t.tv_sec);
+ from_chars(end1 + 1, end, t.tv_nsec);
+ return t;
+ }
auto get_uptime() {
int fd = open("/proc/uptime", O_RDONLY);
if (fd == -1) {
@@ 205,34 238,20 @@ struct context {
total += r;
}
- auto from_chars = [&](auto begin, auto end, auto& out) {
- if (auto [_, ec] = std::from_chars(begin, end, out); ec != std::errc()) {
- throw std::runtime_error{ "Failed to read /proc/uptime value" };
- }
- };
if (total > 0) {
- auto begin = buffer;
- auto end = begin + total;
-
- auto end1 = std::find(begin, end, '.');
- if (end1 == end) {
- throw std::logic_error{ "Unexpected /proc/uptime fmt" };
- }
-
- timespec uptime;
- from_chars(begin, end1, uptime.tv_sec);
- from_chars(end1 + 1, begin, uptime.tv_nsec);
- return uptime;
+ return parse_timespec(buffer, buffer + total);
}
throw std::logic_error{ "read(/proc/uptime) was empty" };
}
+ // replace FILE part of path_buf with `file`
constexpr auto fmt_proc_pid_file(std::string_view file) {
auto end = std::copy(file.begin(), file.end(), pid_end);
assert(end < std::end(path_buf));
*end = '\0';
return end;
}
+ // return whether cgroup matches on any of specified regexes
auto match_cgroup(std::string_view cgroup) {
std::cout << "match_cgroup(" << cgroup << "): unimplemented\n";
return true;
@@ 331,17 350,34 @@ struct context {
std::cout << pid << '\n';
with_uniq_id(path_buf, [&](auto start_time, auto prefix){
- std::cout << "start_time: " << start_time << '\n';
- std::cout << "prefix: " << prefix << '\n';
+ auto start_time_ = [=,this] {
+ unsigned long long ticks;
+ auto [p, ec] = std::from_chars(
+ start_time.begin(),
+ start_time.end(),
+ ticks
+ );
+ if (ec != std::errc()) {
+ throw std::logic_error{ "Failed to parse start_time value" };
+ }
+ return tspec_from_ticks(ticks);
+ }();
+
+ std::cout << "prefix: " << prefix << '\n';
+ std::cout << "start_time: " << start_time << '\n';
+ std::cout << "start_time (tspc): " << start_time_.tv_sec << '.' << start_time_.tv_nsec << '\n';
});
}
if (errno) {
throw errno_exception("readdir(proc) failed", errno);
}
+ auto m = tspec_diff(m0, get_clock_time(CLOCK_MONOTONIC));
+ auto p = tspec_diff(p0, get_clock_time(CLOCK_PROCESS_CPUTIME_ID));
+
std::cout << "Uptime: " << uptime.tv_sec << '.' << uptime.tv_nsec << '\n';
- std::cout << "Monotonic time: " << m0.tv_sec << '.' << m0.tv_nsec << '\n';
- std::cout << "Proc CPU time: " << p0.tv_sec << '.' << p0.tv_nsec << '\n';
+ std::cout << "Monotonic time: " << m.tv_sec << '.' << m.tv_nsec << '\n';
+ std::cout << "Proc CPU time: " << p.tv_sec << '.' << p.tv_nsec << '\n';
}
context(config& cfg):