| /* | |
| * Licensed to the Apache Software Foundation (ASF) under one | |
| * or more contributor license agreements. See the NOTICE file | |
| * distributed with this work for additional information | |
| * regarding copyright ownership. The ASF licenses this file | |
| * to you under the Apache License, Version 2.0 (the | |
| * "License"); you may not use this file except in compliance | |
| * with the License. You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, | |
| * software distributed under the License is distributed on an | |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| * KIND, either express or implied. See the License for the | |
| * specific language governing permissions and limitations | |
| * under the License. | |
| */ | |
| #include "qpid/dispatch/platform.h" | |
| #include "config.h" | |
| #include "qpid/dispatch/ctools.h" | |
| #include <inttypes.h> | |
| #include <stdbool.h> | |
| #include <stdio.h> | |
| #include <sys/resource.h> | |
| uintmax_t qd_platform_memory_size(void) | |
| { | |
| bool found = false; | |
| uintmax_t rlimit = UINTMAX_MAX; | |
| #if QD_HAVE_GETRLIMIT | |
| { | |
| // determine if this process has a hard or soft limit set for its total | |
| // virtual address space | |
| struct rlimit rl = {0}; | |
| // note rlim_max >= rlim_cur (see man getrlimit) use smallest value | |
| if (getrlimit(RLIMIT_AS, &rl) == 0) { | |
| if (rl.rlim_cur != RLIM_INFINITY) { | |
| rlimit = (uintmax_t)rl.rlim_cur; | |
| found = true; | |
| } else if (rl.rlim_max != RLIM_INFINITY) { | |
| rlimit = (uintmax_t)rl.rlim_max; | |
| found = true; | |
| } | |
| } | |
| } | |
| #endif // QD_HAVE_GETRLIMIT | |
| // although a resource limit may be set be sure it does not exceed the | |
| // available "fast" memory. | |
| // @TODO(kgiusti) this is linux-specific (see man proc) | |
| uintmax_t mlimit = UINTMAX_MAX; | |
| FILE *minfo_fp = fopen("/proc/meminfo", "r"); | |
| if (minfo_fp) { | |
| size_t buflen = 0; | |
| char *buffer = 0; | |
| uintmax_t tmp; | |
| while (getline(&buffer, &buflen, minfo_fp) != -1) { | |
| if (sscanf(buffer, "MemTotal: %"SCNuMAX, &tmp) == 1) { | |
| mlimit = tmp * 1024; // MemTotal is in KiB | |
| found = true; | |
| break; | |
| } | |
| } | |
| free(buffer); // allocated by getline | |
| fclose(minfo_fp); | |
| } | |
| // and if qdrouterd is running within a container check the cgroups memory | |
| // controller. Hard and soft memory limits can be set. | |
| uintmax_t climit = UINTMAX_MAX; | |
| { | |
| uintmax_t soft = UINTMAX_MAX; | |
| uintmax_t hard = UINTMAX_MAX; | |
| bool c_set = false; | |
| FILE *cg_fp = fopen("/sys/fs/cgroup/memory/memory.limit_in_bytes", "r"); | |
| if (cg_fp) { | |
| if (fscanf(cg_fp, "%"SCNuMAX, &hard) == 1) { | |
| c_set = true; | |
| } | |
| fclose(cg_fp); | |
| } | |
| cg_fp = fopen("/sys/fs/cgroup/memory/memory.soft_limit_in_bytes", "r"); | |
| if (cg_fp) { | |
| if (fscanf(cg_fp, "%"SCNuMAX, &soft) == 1) { | |
| c_set = true; | |
| } | |
| fclose(cg_fp); | |
| } | |
| if (c_set) { | |
| climit = MIN(soft, hard); | |
| found = true; | |
| } | |
| } | |
| if (found) { | |
| uintmax_t tmp = MIN(mlimit, climit); | |
| return MIN(rlimit, tmp); | |
| } | |
| return 0; | |
| } |