diff --git a/tdutils/td/utils/port/Stat.cpp b/tdutils/td/utils/port/Stat.cpp index a7f33260..0005d963 100644 --- a/tdutils/td/utils/port/Stat.cpp +++ b/tdutils/td/utils/port/Stat.cpp @@ -75,7 +75,6 @@ Status update_atime(int native_fd) { times[0].tv_nsec = UTIME_NOW; // modify time times[1].tv_nsec = UTIME_OMIT; - // if (utimensat(native_fd, nullptr, times, 0) < 0) { if (futimens(native_fd, times) < 0) { auto status = OS_ERROR(PSLICE() << "futimens " << tag("fd", native_fd)); LOG(WARNING) << status; @@ -211,9 +210,87 @@ Result mem_stat() { return Status::Error("Not supported"); #endif } -} // namespace td + +#if TD_LINUX +Status cpu_stat_self(CpuStat &stat) { + TRY_RESULT(fd, FileFd::open("/proc/self/stat", FileFd::Read)); + SCOPE_EXIT { + fd.close(); + }; + + constexpr int TMEM_SIZE = 10000; + char mem[TMEM_SIZE]; + TRY_RESULT(size, fd.read(MutableSlice(mem, TMEM_SIZE - 1))); + CHECK(size < TMEM_SIZE - 1); + mem[size] = 0; + + char *s = mem; + char *t = mem + size; + int pass_cnt = 0; + + while (pass_cnt < 15) { + if (pass_cnt == 13) { + stat.process_user_ticks = to_integer(Slice(s, t)); + } + if (pass_cnt == 14) { + stat.process_system_ticks = to_integer(Slice(s, t)); + } + while (*s && *s != ' ') { + s++; + } + if (*s == ' ') { + s++; + pass_cnt++; + } else { + return Status::Error("unexpected end of proc file"); + } + } + return Status::OK(); +} +Status cpu_stat_total(CpuStat &stat) { + TRY_RESULT(fd, FileFd::open("/proc/stat", FileFd::Read)); + SCOPE_EXIT { + fd.close(); + }; + + constexpr int TMEM_SIZE = 10000; + char mem[TMEM_SIZE]; + TRY_RESULT(size, fd.read(MutableSlice(mem, TMEM_SIZE - 1))); + CHECK(size < TMEM_SIZE - 1); + mem[size] = 0; + + uint64 sum = 0, cur = 0; + for (size_t i = 0; i < size; i++) { + int c = mem[i]; + if (c >= '0' && c <= '9') { + cur = cur * 10 + (uint64)c - '0'; + } else { + sum += cur; + cur = 0; + if (c == '\n') { + break; + } + } + } + + stat.total_ticks = sum; + return Status::OK(); +} #endif +Result cpu_stat() { +#if TD_LINUX + CpuStat stat; + TRY_STATUS(cpu_stat_self(stat)); + TRY_STATUS(cpu_stat_total(stat)); + return stat; +#else + return Status::Error("Not supported"); +#endif +} +#endif +} + #if TD_PORT_WINDOWS namespace td { diff --git a/tdutils/td/utils/port/Stat.h b/tdutils/td/utils/port/Stat.h index 73b1bfc0..e4cb7f9a 100644 --- a/tdutils/td/utils/port/Stat.h +++ b/tdutils/td/utils/port/Stat.h @@ -41,6 +41,13 @@ struct MemStat { Result mem_stat() TD_WARN_UNUSED_RESULT; +struct CpuStat { + uint64 total_ticks{0}; + uint64 process_user_ticks{0}; + uint64 process_system_ticks{0}; +}; +Result cpu_stat() TD_WARN_UNUSED_RESULT; + #endif } // namespace td