24#ifndef CASA_HOSTINFOLINUX_H
25#define CASA_HOSTINFOLINUX_H
27#if defined(HOSTINFO_DO_IMPLEMENT)
58#include <sys/resource.h>
81#include <linux/proc_fs.h>
83#define PROC_SUPER_MAGIC 0x9fa0
87#define CPUINFO "/proc/cpuinfo"
88#define MEMINFO "/proc/meminfo"
90#define bytetok(x) (((x) + 512) >> 10)
94class HostMachineInfo {
95 friend class HostInfo;
103 ptrdiff_t memory_total;
104 ptrdiff_t memory_used;
105 ptrdiff_t memory_free;
107 ptrdiff_t swap_total;
114static inline char *skip_ws(
const char *p) {
115 while (isspace(*p)) p++;
119static inline char *skip_token(
const char *p) {
120 while (isspace(*p)) p++;
121 while (*p && !isspace(*p)) p++;
131static inline uInt64 get_cgroup_limit(std::string group, std::string
value,
132 std::string sub_value =
"") {
133 uInt64 result = std::numeric_limits<uInt64>::max();
135 const std::string cgroup = std::string(
"/sys/fs/cgroup/") + group +
"/";
139 std::ifstream ifs(
"/proc/self/cgroup", std::ifstream::in);
140 std::string hierarchy;
141 while (getline(ifs, line)) {
142 std::stringstream ss(line);
144 std::vector<std::string> fields;
145 while (getline(ss, token,
':')) {
146 fields.push_back(token);
148 if (fields.size() % 3 != 0) {
151 for (std::vector<std::string>::size_type i = 1; i < fields.size(); i += 3) {
152 if (fields[i].find(group) != std::string::npos) {
153 hierarchy = fields[i + 1] +
"/";
157 if (hierarchy.size() == 0) {
161 std::ifstream flimit((cgroup + hierarchy +
value).c_str(), std::ifstream::in);
163 if (!flimit.is_open()) {
164 flimit.open((cgroup +
value).c_str(), std::ifstream::in);
166 if (flimit.is_open()) {
167 if (!sub_value.empty()) {
169 while (getline(flimit, line)) {
170 std::stringstream ss(line);
173 if (token == sub_value) {
185HostMachineInfo::HostMachineInfo() : valid(1) {
186 char buffer[4096 + 1];
191 if (sched_getaffinity(0,
sizeof(cpuset), &cpuset) == 0) {
193 cpus = CPU_COUNT(&cpuset);
195 for (
int i = 0; i < CPU_SETSIZE; i++) {
196 if (CPU_ISSET(i, &cpuset)) {
206 if (statfs(PROCFS, &sb) < 0 || sb.f_type != PROC_SUPER_MAGIC) {
207 fprintf(stderr,
"proc filesystem not mounted on " PROCFS
"\n");
217 FILE *fptr = fopen(CPUINFO,
"r");
218 while ((p = fgets(buffer,
sizeof(buffer), fptr))) {
219 if (!strncmp(p,
"processor", 9)) ++cpus;
228void HostMachineInfo::update_info() {
229 char buffer[4096 + 1];
235 unsigned long sys_mem_total, sys_mem_free, sys_mem_cached, sys_mem_avail, sys_swap_total,
238 fd = open(MEMINFO, O_RDONLY);
239 len = ::read(fd, buffer,
sizeof(buffer) - 1);
243 p = strstr(buffer,
"MemTotal:");
245 if (sscanf(p,
"MemTotal: %lu kB\nMemFree: %lu kB\n", &sys_mem_total, &sys_mem_free) != 2)
246 cerr <<
"Error parsing MemTotal and MemFree in /proc/meminfo\n";
248 p = strstr(buffer,
"Cached:");
249 if (sscanf(p,
"Cached: %lu kB\n", &sys_mem_cached) != 1)
250 cerr <<
"Error parsing Cached in /proc/meminfo\n";
254 p = strstr(buffer,
"MemAvailable:");
255 if (!p || sscanf(p,
"MemAvailable: %lu kB\n", &sys_mem_avail) != 1) {
257 sys_mem_avail = sys_mem_cached + sys_mem_free;
262 if (getrlimit(RLIMIT_RSS, &rlim) == 0 && rlim.rlim_cur > 0) {
263 sys_mem_total = std::min(rlim.rlim_cur / 1024, (rlim_t)sys_mem_total);
265 sys_mem_avail = std::min(sys_mem_total, sys_mem_avail);
269 uInt64 proc_mem_max = get_cgroup_limit(
"memory",
"memory.limit_in_bytes") / 1024;
271 uInt64 proc_mem_used = get_cgroup_limit(
"memory",
"memory.stat",
"total_rss") / 1024;
274 memory_total = std::min((uInt64)sys_mem_total, proc_mem_max);
277 if (proc_mem_max <= sys_mem_total && proc_mem_used <= proc_mem_max) {
278 memory_free = proc_mem_max - proc_mem_used;
281 memory_free = std::min((uInt64)sys_mem_avail, (uInt64)memory_total);
283 memory_used = memory_total - memory_free;
285 p = strstr(buffer,
"SwapTotal:");
286 if (sscanf(p,
"SwapTotal: %lu kB\nSwapFree: %lu kB\n", &sys_swap_total, &sys_swap_free) != 2)
287 cerr <<
"Error parsing SwapTotal and SwapFree in /proc/meminfo\n";
290 uInt64 proc_swap_max = get_cgroup_limit(
"memory",
"memory.memsw.limit_in_bytes") / 1024;
291 uInt64 proc_swap_used = get_cgroup_limit(
"memory",
"memory.stat",
"total_swap") / 1024;
293 if (proc_mem_max <= sys_mem_total && proc_mem_max <= proc_swap_max) {
294 proc_swap_max = proc_swap_max - proc_mem_max;
298 swap_total = std::min((uInt64)sys_swap_total, proc_swap_max);
300 if (proc_swap_max <= (uInt64)swap_total && proc_swap_used <= proc_swap_max) {
301 swap_free = proc_swap_max - proc_swap_used;
303 swap_free = sys_swap_free;
305 swap_used = swap_total - swap_free;
For temporary backward namespace compatibility, use casa as alias for casacore.
void close() override
Flush and close the file.
NewDelAllocator< T > NewDelAllocator< T >::value
unsigned long long uInt64