CppCommon  1.0.4.1
C++ Common Library
memory.cpp
Go to the documentation of this file.
1 
9 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
10 #define __STDC_WANT_LIB_EXT1__ 1
11 #include <stdlib.h>
12 #include <string.h>
13 #endif
14 
15 #include "memory/memory.h"
16 
17 #if defined(__APPLE__)
18 #include <mach/mach.h>
19 #include <sys/sysctl.h>
20 #include <fcntl.h>
21 #include <unistd.h>
22 #elif defined(unix) || defined(__unix) || defined(__unix__)
23 #include <sys/sysinfo.h>
24 #include <fcntl.h>
25 #include <unistd.h>
26 #elif defined(_WIN32) || defined(_WIN64)
27 #include <windows.h>
28 #include <wincrypt.h>
29 #endif
30 
31 namespace CppCommon {
32 
34 {
35 #if defined(__APPLE__)
36  int64_t memsize = 0;
37  size_t size = sizeof(memsize);
38  if (sysctlbyname("hw.memsize", &memsize, &size, nullptr, 0) == 0)
39  return memsize;
40 
41  return -1;
42 #elif defined(unix) || defined(__unix) || defined(__unix__)
43  int64_t pages = sysconf(_SC_PHYS_PAGES);
44  int64_t page_size = sysconf(_SC_PAGESIZE);
45  if ((pages > 0) && (page_size > 0))
46  return pages * page_size;
47 
48  return -1;
49 #elif defined(_WIN32) || defined(_WIN64)
50  MEMORYSTATUSEX status;
51  status.dwLength = sizeof(status);
52  GlobalMemoryStatusEx(&status);
53  return status.ullTotalPhys;
54 #else
55  #error Unsupported platform
56 #endif
57 }
58 
59 int64_t Memory::RamFree()
60 {
61 #if defined(__APPLE__)
62  mach_port_t host_port = mach_host_self();
63  if (host_port == MACH_PORT_NULL)
64  return -1;
65 
66  vm_size_t page_size = 0;
67  host_page_size(host_port, &page_size);
68 
69  vm_statistics_data_t vmstat;
70  mach_msg_type_number_t count = HOST_VM_INFO_COUNT;
71  kern_return_t kernReturn = host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vmstat, &count);
72  if (kernReturn != KERN_SUCCESS)
73  return -1;
74 
75  [[maybe_unused]] int64_t used_mem = (vmstat.active_count + vmstat.inactive_count + vmstat.wire_count) * page_size;
76  int64_t free_mem = vmstat.free_count * page_size;
77  return free_mem;
78 #elif defined(unix) || defined(__unix) || defined(__unix__)
79  int64_t pages = sysconf(_SC_AVPHYS_PAGES);
80  int64_t page_size = sysconf(_SC_PAGESIZE);
81  if ((pages > 0) && (page_size > 0))
82  return pages * page_size;
83 
84  return -1;
85 #elif defined(_WIN32) || defined(_WIN64)
86  MEMORYSTATUSEX status;
87  status.dwLength = sizeof(status);
88  GlobalMemoryStatusEx(&status);
89  return status.ullAvailPhys;
90 #else
91  #error Unsupported platform
92 #endif
93 }
94 
95 bool Memory::IsZero(const void* buffer, size_t size) noexcept
96 {
97  const char* ptr = (const char*)buffer;
98  for (size_t i = 0; i < size; ++i)
99  if (ptr[i] != 0)
100  return false;
101  return true;
102 }
103 
104 void Memory::ZeroFill(void* buffer, size_t size)
105 {
106 #ifdef __STDC_LIB_EXT1__
107  memset_s(buffer, size, 0, size);
108 #elif defined(_WIN32) || defined(_WIN64)
109  SecureZeroMemory(buffer, size);
110 #else
111  volatile char* ptr = (volatile char*)buffer;
112  while (size--)
113  *ptr++ = 0;
114 #endif
115 }
116 
117 void Memory::RandomFill(void* buffer, size_t size)
118 {
119 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
120  int fd = open("/dev/urandom", O_RDONLY);
121  if (fd < 0)
122  throwex SystemException("Cannot open '/dev/urandom' file for reading!");
123  ssize_t count = read(fd, buffer, size);
124  if (count < 0)
125  throwex SystemException("Cannot read from '/dev/urandom' file!");
126  int result = close(fd);
127  if (result != 0)
128  throwex SystemException("Cannot close '/dev/urandom' file!");
129 #elif defined(_WIN32) || defined(_WIN64)
130  char* ptr = (char*)buffer;
131  for(size_t i = 0; i < size; ++i)
132  ptr[i] = rand() % 256;
133 #endif
134 }
135 
136 void Memory::CryptoFill(void* buffer, size_t size)
137 {
138 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
139  int fd = open("/dev/random", O_RDONLY);
140  if (fd < 0)
141  throwex SystemException("Cannot open '/dev/random' file for reading!");
142  ssize_t count = read(fd, buffer, size);
143  if (count < 0)
144  throwex SystemException("Cannot read from '/dev/random' file!");
145  int result = close(fd);
146  if (result != 0)
147  throwex SystemException("Cannot close '/dev/random' file!");
148 #elif defined(_WIN32) || defined(_WIN64)
149  HCRYPTPROV hCryptContext;
150  if (!CryptAcquireContext(&hCryptContext, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
151  throwex SystemException("Cannot acquire cryptographic service provider context!");
152  if (!CryptGenRandom(hCryptContext, (DWORD)size, (BYTE*)buffer))
153  throwex SystemException("Cannot generate random bytes using cryptographic service provider context!");
154  if (!CryptReleaseContext(hCryptContext, 0))
155  throwex SystemException("Cannot release cryptographic service provider context!");
156 #endif
157 }
158 
159 } // namespace CppCommon
static bool IsZero(const void *buffer, size_t size) noexcept
Is the given memory buffer filled with zeros?
Definition: memory.cpp:95
static void CryptoFill(void *buffer, size_t size)
Fill the given memory buffer with cryptographic strong random bytes.
Definition: memory.cpp:136
static int64_t RamFree()
Free RAM in bytes.
Definition: memory.cpp:59
static int64_t RamTotal()
Total RAM in bytes.
Definition: memory.cpp:33
static void ZeroFill(void *buffer, size_t size)
Fill the given memory buffer with zeros.
Definition: memory.cpp:104
static void RandomFill(void *buffer, size_t size)
Fill the given memory buffer with random bytes.
Definition: memory.cpp:117
System exception.
Definition: exceptions.h:107
#define throwex
Throw extended exception macro.
Definition: exceptions.h:23
Memory management definition.
C++ Common project definitions.
Definition: token_bucket.h:15