Developer Documentation
RAMInfo.cc
1 /*===========================================================================*\
2 * *
3  * OpenFlipper *
4  * Copyright (c) 2001-2015, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openflipper.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenFlipper. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39  * *
40  \*===========================================================================*/
41 
42 #include "RAMInfo.hh"
43 
44 #include <QString>
45 #include <stdio.h>
46 
47 // Main Memory information
48 #ifdef WIN32
49 #include <Windows.h>
50 #elif defined ARCH_DARWIN
51 #include <mach/mach_host.h>
52 #include <mach/vm_statistics.h>
53 #include <sys/sysctl.h>
54 #include <sys/types.h>
55 #endif
56 // private struct to get ram information
57 namespace{
58 struct MemoryVacancy{
59  unsigned long totalRamMB;
60  unsigned long freeRamMB;
61  unsigned long bufferRamMB;
62 };
63 
64 void parseMeminfo(int& total, int& free, int& buffer)
65 {
66  int memcache;
67  int memfree;
68  FILE* info = fopen("/proc/meminfo","r");
69  if(fscanf (info, "MemTotal: %d kB MemFree: %d kB Buffers: %d kB Cached: %d kB",&total, &memfree, &buffer, &memcache) < 4) //try to parse the old meminfo format
70  {
71  fclose(info);
72  info = fopen("/proc/meminfo","r");
73  //parsing the old format failed so we try to parse using the new format
74  if(fscanf(info, "MemTotal: %d kB MemFree: %d kB MemAvailable: %d kB Buffers: %d kB Cached: %d kB",&total, &memfree, &free, &buffer, &memcache) < 5)
75  {
76  //parsing failed overall so return -1 for all values
77  total = -1;
78  free = -1;
79  buffer = -1;
80  }
81  else
82  {
83  free = memfree + (buffer + memcache); //everything is fine
84  }
85 
86  }
87  else //compute available memory
88  {
89  free = memfree + (buffer + memcache);
90  }
91  fclose(info);
92 }
93 
94 }
95 namespace Utils
96 {
97  namespace Memory
98  {
99  void MemoryInfoUpdate(MemoryVacancy & _outMemoryVacancy) {
100 
101  //initialize to 0 just in case something fails or cant be read
102  _outMemoryVacancy.totalRamMB = 0;
103  _outMemoryVacancy.freeRamMB = 0;
104  _outMemoryVacancy.bufferRamMB = 0;
105 
106  // Main Memory information
107  #ifdef WIN32 //Windows
108  // Define memory structure
109  MEMORYSTATUSEX ms;
110  // Set the size ( required according to spec ... why???? )
111  ms.dwLength = sizeof(ms);
112  // Get the info
113  GlobalMemoryStatusEx(&ms);
114 
115  _outMemoryVacancy.totalRamMB = ms.ullTotalPhys / 1024 / 1024;
116  _outMemoryVacancy.freeRamMB = ms.ullAvailPhys / 1024 / 1024;
117 
118  #elif defined ARCH_DARWIN // Apple (sadly cant query free memory)
119  mach_msg_type_number_t count = HOST_VM_INFO_COUNT;
120  vm_statistics_data_t vmstat;
121  if(KERN_SUCCESS != host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&vmstat, &count))
122  { // An error occurred
123  }
124  else
125  {
126  //retrieve real physical memory
127  int mib[2];
128  uint64_t physical_memory;
129  size_t length;
130  mib[0] = CTL_HW;
131  mib[1] = HW_MEMSIZE;
132  length = sizeof(uint64_t);
133  if( sysctl(mib, 2, &physical_memory, &length, NULL, 0) == -1 )
134  {
135  physical_memory = 0;
136  }
137  // retrieve free memory
138  _outMemoryVacancy.totalRamMB = physical_memory / 1024 / 1024;
139  unsigned long active = vmstat.active_count * PAGE_SIZE / 1024 / 1024;
140  _outMemoryVacancy.freeRamMB = _outMemoryVacancy.totalRamMB - active;
141  _outMemoryVacancy.bufferRamMB =0;
142  }
143 
144  #else // Linux
145 
146  int total, free, buffer;
147  parseMeminfo(total, free, buffer);
148 
149  // Unit in kbytes ; /1024 -> MB
150  _outMemoryVacancy.totalRamMB = (long)total / 1024;
151  _outMemoryVacancy.freeRamMB = (long)free / 1024;
152  _outMemoryVacancy.bufferRamMB = (long)buffer / 1024; // Buffers get freed, if we don't have enough free ram
153  #endif
154  }
155 
156  unsigned long queryFreeRAM()
157  {
158  MemoryVacancy vac;
159  MemoryInfoUpdate(vac);
160  return vac.freeRamMB;
161  }
162 
163  unsigned long queryTotalRAM()
164  {
165  MemoryVacancy vac;
166  MemoryInfoUpdate(vac);
167  return vac.totalRamMB;
168  }
169 
170  unsigned long queryBufferedRAM()
171  {
172  MemoryVacancy vac;
173  MemoryInfoUpdate(vac);
174  return vac.bufferRamMB;
175  }
176  }
177 }