annotate system/System.cpp @ 1247:8f076d02569a piper

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