svcore  1.9
System.cpp
Go to the documentation of this file.
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2 
3 /*
4  Sonic Visualiser
5  An audio file viewer and annotation editor.
6  Centre for Digital Music, Queen Mary, University of London.
7  This file copyright 2006 Chris Cannam and QMUL.
8 
9  This program is free software; you can redistribute it and/or
10  modify it under the terms of the GNU General Public License as
11  published by the Free Software Foundation; either version 2 of the
12  License, or (at your option) any later version. See the file
13  COPYING included with this distribution for more information.
14 */
15 
16 #include "System.h"
17 
18 #include <QStringList>
19 #include <QString>
20 
21 #include <stdint.h>
22 
23 #ifndef _WIN32
24 #include <signal.h>
25 #include <sys/statvfs.h>
26 #include <locale.h>
27 #include <unistd.h>
28 #endif
29 
30 #ifdef __APPLE__
31 #include <sys/param.h>
32 #include <sys/sysctl.h>
33 #endif
34 
35 #include <limits.h>
36 #include <cstdlib>
37 
38 #include <iostream>
39 
40 #ifdef __APPLE__
41 extern "C" {
42 void *
43 rpl_realloc (void *p, size_t n)
44 {
45  p = realloc(p, n);
46  if (p == 0 && n == 0)
47  {
48  p = malloc(0);
49  }
50  return p;
51 }
52 }
53 #endif
54 
55 #ifdef _WIN32
56 
57 extern "C" {
58 
59 /* usleep is now in mingw
60 void usleep(unsigned long usec)
61 {
62  ::Sleep(usec / 1000);
63 }
64 */
65 
66 int gettimeofday(struct timeval *tv, void *tz)
67 {
68  union {
69  long long ns100;
70  FILETIME ft;
71  } now;
72 
73  ::GetSystemTimeAsFileTime(&now.ft);
74  tv->tv_usec = (long)((now.ns100 / 10LL) % 1000000LL);
75  tv->tv_sec = (long)((now.ns100 - 116444736000000000LL) / 10000000LL);
76  return 0;
77 }
78 
79 }
80 
81 #endif
82 
85 {
86 #ifdef _WIN32
87  HANDLE handle = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
88  if (!handle) {
89  return ProcessNotRunning;
90  } else {
91  CloseHandle(handle);
92  return ProcessRunning;
93  }
94 #else
95  if (kill(getpid(), 0) == 0) {
96  if (kill(pid, 0) == 0) {
97  return ProcessRunning;
98  } else {
99  return ProcessNotRunning;
100  }
101  } else {
102  return UnknownProcessStatus;
103  }
104 #endif
105 }
106 
107 #ifdef _WIN32
108 /* MEMORYSTATUSEX is missing from older Windows headers, so define a
109  local replacement. This trick from MinGW source code. Ugh */
110 typedef struct
111 {
112  DWORD dwLength;
113  DWORD dwMemoryLoad;
114  DWORDLONG ullTotalPhys;
115  DWORDLONG ullAvailPhys;
116  DWORDLONG ullTotalPageFile;
117  DWORDLONG ullAvailPageFile;
118  DWORDLONG ullTotalVirtual;
119  DWORDLONG ullAvailVirtual;
120  DWORDLONG ullAvailExtendedVirtual;
121 } lMEMORYSTATUSEX;
122 typedef WINBOOL (WINAPI *PFN_MS_EX) (lMEMORYSTATUSEX*);
123 #endif
124 
125 void
126 GetRealMemoryMBAvailable(int &available, int &total)
127 {
128  available = -1;
129  total = -1;
130 
131 #ifdef _WIN32
132 
133  static bool checked = false;
134  static bool exFound = false;
135  static PFN_MS_EX ex;
136 
137  if (!checked) {
138 
139  HMODULE h = GetModuleHandleA("kernel32.dll");
140 
141  if (h) {
142  if ((ex = (PFN_MS_EX)GetProcAddress(h, "GlobalMemoryStatusEx"))) {
143  exFound = true;
144  }
145  }
146 
147  checked = true;
148  }
149 
150  DWORDLONG wavail = 0;
151  DWORDLONG wtotal = 0;
152 
153  if (exFound) {
154 
155  lMEMORYSTATUSEX lms;
156  lms.dwLength = sizeof(lms);
157  if (!ex(&lms)) {
158  cerr << "WARNING: GlobalMemoryStatusEx failed: error code "
159  << GetLastError() << endl;
160  return;
161  }
162  wavail = lms.ullAvailPhys;
163  wtotal = lms.ullTotalPhys;
164 
165  } else {
166 
167  /* Fall back to GlobalMemoryStatus which is always available.
168  but returns wrong results for physical memory > 4GB */
169 
170  MEMORYSTATUS ms;
171  GlobalMemoryStatus(&ms);
172  wavail = ms.dwAvailPhys;
173  wtotal = ms.dwTotalPhys;
174  }
175 
176  DWORDLONG size = wavail / 1048576;
177  if (size > INT_MAX) size = INT_MAX;
178  available = int(size);
179 
180  size = wtotal / 1048576;
181  if (size > INT_MAX) size = INT_MAX;
182  total = int(size);
183 
184  return;
185 
186 #else
187 #ifdef __APPLE__
188 
189  unsigned int val;
190  int mib[2];
191  size_t size_sys;
192 
193  mib[0] = CTL_HW;
194 
195  mib[1] = HW_PHYSMEM;
196  size_sys = sizeof(val);
197  sysctl(mib, 2, &val, &size_sys, NULL, 0);
198  if (val) total = val / 1048576;
199 
200  mib[1] = HW_USERMEM;
201  size_sys = sizeof(val);
202  sysctl(mib, 2, &val, &size_sys, NULL, 0);
203  if (val) available = val / 1048576;
204 
205  return;
206 
207 #else
208 
209  FILE *meminfo = fopen("/proc/meminfo", "r");
210  if (!meminfo) return;
211 
212  char buf[256];
213  while (!feof(meminfo)) {
214  fgets(buf, 256, meminfo);
215  bool isMemFree = (strncmp(buf, "MemFree:", 8) == 0);
216  bool isMemTotal = (!isMemFree && (strncmp(buf, "MemTotal:", 9) == 0));
217  if (isMemFree || isMemTotal) {
218  QString line = QString(buf).trimmed();
219  QStringList elements = line.split(' ', QString::SkipEmptyParts);
220  QString unit = "kB";
221  if (elements.size() > 2) unit = elements[2];
222  int size = elements[1].toInt();
223 // cerr << "have size \"" << size << "\", unit \""
224 // << unit << "\"" << endl;
225  if (unit.toLower() == "gb") size = size * 1024;
226  else if (unit.toLower() == "mb") size = size;
227  else if (unit.toLower() == "kb") size = size / 1024;
228  else size = size / 1048576;
229 
230  if (isMemFree) available = size;
231  else total = size;
232  }
233  if (available != -1 && total != -1) {
234  fclose(meminfo);
235  return;
236  }
237  }
238  fclose(meminfo);
239 
240  return;
241 
242 #endif
243 #endif
244 }
245 
246 int
247 GetDiscSpaceMBAvailable(const char *path)
248 {
249 #ifdef _WIN32
250  ULARGE_INTEGER available, total, totalFree;
251  if (GetDiskFreeSpaceExA(path, &available, &total, &totalFree)) {
252  __int64 a = available.QuadPart;
253  a /= 1048576;
254  if (a > INT_MAX) a = INT_MAX;
255  return int(a);
256  } else {
257  cerr << "WARNING: GetDiskFreeSpaceEx failed: error code "
258  << GetLastError() << endl;
259  return -1;
260  }
261 #else
262  struct statvfs buf;
263  if (!statvfs(path, &buf)) {
264  // do the multiplies and divides in this order to reduce the
265  // likelihood of arithmetic overflow
266 // cerr << "statvfs(" << path << ") says available: " << buf.f_bavail << ", block size: " << buf.f_bsize << endl;
267  uint64_t available = ((buf.f_bavail / 1024) * buf.f_bsize) / 1024;
268  if (available > INT_MAX) available = INT_MAX;
269  return int(available);
270  } else {
271  perror("statvfs failed");
272  return -1;
273  }
274 #endif
275 }
276 
277 #ifdef _WIN32
278 extern void SystemMemoryBarrier()
279 {
280 #ifdef __MSVC__
281  MemoryBarrier();
282 #else /* mingw */
283  LONG Barrier = 0;
284  __asm__ __volatile__("xchgl %%eax,%0 "
285  : "=r" (Barrier));
286 #endif
287 }
288 #else /* !_WIN32 */
289 #if !defined(__APPLE__) && ((__GNUC__ < 4) || (__GNUC__ == 4 && __GNUC_MINOR__ == 0))
290 void
292 {
293  pthread_mutex_t dummy = PTHREAD_MUTEX_INITIALIZER;
294  pthread_mutex_lock(&dummy);
295  pthread_mutex_unlock(&dummy);
296 }
297 #endif /* !defined(__APPLE__) etc */
298 #endif /* !_WIN32 */
299 
300 
301 static char *startupLocale = 0;
302 
303 void
305 {
306  char *loc = setlocale(LC_ALL, 0);
307  if (!loc) return;
308  if (startupLocale) free(startupLocale);
309  startupLocale = strdup(loc);
310 }
311 
312 void
314 {
315  if (!startupLocale) {
316  setlocale(LC_ALL, "");
317  } else {
318  setlocale(LC_ALL, startupLocale);
319  }
320 }
321 
322 double mod(double x, double y) { return x - (y * floor(x / y)); }
323 float modf(float x, float y) { return x - (y * floorf(x / y)); }
324 
325 double princarg(double a) { return mod(a + M_PI, -2 * M_PI) + M_PI; }
326 float princargf(float a) { return modf(a + M_PI, -2 * M_PI) + M_PI; }
327 
double mod(double x, double y)
Definition: System.cpp:322
static char * startupLocale
Definition: System.cpp:301
ProcessStatus
Definition: System.h:142
ProcessStatus GetProcessStatus(int pid)
Definition: System.cpp:84
int GetDiscSpaceMBAvailable(const char *path)
Definition: System.cpp:247
double princarg(double a)
Definition: System.cpp:325
void SystemMemoryBarrier()
Definition: System.cpp:291
void GetRealMemoryMBAvailable(int &available, int &total)
Definition: System.cpp:126
void RestoreStartupLocale()
Definition: System.cpp:313
float modf(float x, float y)
Definition: System.cpp:323
void StoreStartupLocale()
Definition: System.cpp:304
float princargf(float a)
Definition: System.cpp:326