blob: 31c8a54aee7dd8585482deec3fa8dfcbfcfa80d0 [file] [log] [blame]
/*
* 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;
}