Effective memory limit from a cgroup file tree. See header for contract. */
| 174 | |
| 175 | /* Effective memory limit from a cgroup file tree. See header for contract. */ |
| 176 | size_t cbm_detect_cgroup_mem(const char *cgroup_root) { |
| 177 | char path[CBM_PATH_MAX]; |
| 178 | char buf[CBM_SZ_64]; |
| 179 | |
| 180 | /* cgroup v2: "<root>/memory.max" — "max" or integer bytes. */ |
| 181 | snprintf(path, sizeof(path), "%s/memory.max", cgroup_root); |
| 182 | if (read_small_file(path, buf, sizeof(buf)) > 0) { |
| 183 | if (strncmp(buf, "max", 3) == 0) { |
| 184 | return 0; |
| 185 | } |
| 186 | char *end = NULL; |
| 187 | unsigned long long n = strtoull(buf, &end, CBM_DECIMAL_BASE); |
| 188 | if (end == buf || n == 0) { |
| 189 | return 0; |
| 190 | } |
| 191 | return (size_t)n; |
| 192 | } |
| 193 | |
| 194 | /* cgroup v1: ".../memory/memory.limit_in_bytes". The sentinel for |
| 195 | * "unlimited" is a very large value (~PAGE_COUNTER_MAX); treat anything |
| 196 | * past half of ULLONG_MAX as effectively unlimited. */ |
| 197 | snprintf(path, sizeof(path), "%s/memory/memory.limit_in_bytes", cgroup_root); |
| 198 | if (read_small_file(path, buf, sizeof(buf)) <= 0) { |
| 199 | return 0; |
| 200 | } |
| 201 | char *end = NULL; |
| 202 | unsigned long long n = strtoull(buf, &end, CBM_DECIMAL_BASE); |
| 203 | if (end == buf || n == 0 || n >= (ULLONG_MAX / 2)) { |
| 204 | return 0; |
| 205 | } |
| 206 | return (size_t)n; |
| 207 | } |
| 208 | |
| 209 | static cbm_system_info_t detect_system_linux(void) { |
| 210 | cbm_system_info_t info; |
no test coverage detected