#include "lib/meminfo/meminfo.h"
#include "lib/cc/compat_compiler.h"
#include "lib/cc/torint.h"
#include "lib/fs/files.h"
#include "lib/log/log.h"
#include "lib/malloc/malloc.h"
#include "lib/string/util_string.h"
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef _WIN32
#include <windows.h>
#endif
#include <string.h>
#if defined(HAVE_SYS_SYSCTL_H) && !defined(_WIN32) && !defined(__linux__)
#include <sys/sysctl.h>
#endif
#if defined(HW_PHYSMEM64)
#define INT64_HW_MEM HW_PHYSMEM64
#elif defined(HW_MEMSIZE)
#define INT64_HW_MEM HW_MEMSIZE
#endif
static uint64_t
get_total_system_memory_impl(void)
{
#if defined(__linux__)
unsigned long long result=0;
int fd = -1;
char *s = NULL;
const char *cp;
size_t file_size=0;
if (-1 == (fd = tor_open_cloexec("/proc/meminfo",O_RDONLY,0)))
return 0;
s = read_file_to_str_until_eof(fd, 65536, &file_size);
if (!s)
goto err;
cp = find_str_at_start_of_line(s, "MemTotal:");
if (!cp)
goto err;
if (sscanf(cp, "MemTotal: %llu kB\n", &result) != 1)
goto err;
close(fd);
tor_free(s);
return result * 1024;
err:
tor_free(s);
close(fd);
return 0;
#elif defined (_WIN32)
MEMORYSTATUSEX ms;
memset(&ms, 0, sizeof(ms));
ms.dwLength = sizeof(ms);
if (! GlobalMemoryStatusEx(&ms))
return 0;
return ms.ullTotalPhys;
#elif defined(HAVE_SYSCTL) && defined(INT64_HW_MEM)
uint64_t memsize = 0;
size_t len = sizeof(memsize);
int mib[2] = {CTL_HW, INT64_HW_MEM};
if (sysctl(mib,2,&memsize,&len,NULL,0))
return 0;
return memsize;
#elif defined(HAVE_SYSCTL) && defined(HW_PHYSMEM)
size_t memsize=0;
size_t len = sizeof(memsize);
int mib[2] = {CTL_HW, HW_PHYSMEM};
if (sysctl(mib,2,&memsize,&len,NULL,0))
return 0;
return memsize;
#else
return 0;
#endif
}
MOCK_IMPL(int,
get_total_system_memory, (size_t *mem_out))
{
static size_t mem_cached=0;
uint64_t m = get_total_system_memory_impl();
if (0 == m) {
if (0 == mem_cached) {
*mem_out = 0;
return -1;
}
*mem_out = mem_cached;
return 0;
}
#if SIZE_MAX != UINT64_MAX
if (m > SIZE_MAX) {
m = SIZE_MAX;
}
#endif
*mem_out = mem_cached = (size_t) m;
return 0;
}