annotate system/System.cpp @ 575:8688430850d6

* either I'm going mad or the compiler is... valgrind and sizeof both seem to think that reading or writing m_size is reading beyond the end of the object, unless I add m_spare padding... why?
author Chris Cannam
date Mon, 16 Mar 2009 16:32:02 +0000
parents d3faa6447c5b
children d7f3dfe6f9a4
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@223 26 #endif
Chris@223 27
Chris@223 28 #ifdef __APPLE__
Chris@223 29 #include <sys/param.h>
Chris@223 30 #include <sys/sysctl.h>
Chris@223 31 #endif
Chris@223 32
Chris@405 33 #include <limits.h>
Chris@405 34 #include <cstdlib>
Chris@405 35
Chris@223 36 #include <iostream>
Chris@223 37
Chris@255 38 #ifdef __APPLE__
Chris@255 39 extern "C" {
Chris@255 40 void *
Chris@255 41 rpl_realloc (void *p, size_t n)
Chris@255 42 {
Chris@255 43 p = realloc(p, n);
Chris@255 44 if (p == 0 && n == 0)
Chris@255 45 {
Chris@255 46 p = malloc(0);
Chris@255 47 }
Chris@255 48 return p;
Chris@255 49 }
Chris@255 50 }
Chris@255 51 #endif
Chris@255 52
Chris@223 53 #ifdef _WIN32
Chris@223 54
Chris@223 55 extern "C" {
Chris@223 56
Chris@223 57 void usleep(unsigned long usec)
Chris@223 58 {
Chris@223 59 ::Sleep(usec / 1000);
Chris@223 60 }
Chris@223 61
Chris@501 62 int gettimeofday(struct timeval *tv, void *tz)
Chris@223 63 {
Chris@223 64 union {
Chris@223 65 long long ns100;
Chris@223 66 FILETIME ft;
Chris@223 67 } now;
Chris@223 68
Chris@223 69 ::GetSystemTimeAsFileTime(&now.ft);
Chris@223 70 tv->tv_usec = (long)((now.ns100 / 10LL) % 1000000LL);
Chris@223 71 tv->tv_sec = (long)((now.ns100 - 116444736000000000LL) / 10000000LL);
Chris@572 72 return 0;
Chris@223 73 }
Chris@223 74
Chris@223 75 }
Chris@223 76
Chris@223 77 #endif
Chris@223 78
Chris@223 79 ProcessStatus
Chris@223 80 GetProcessStatus(int pid)
Chris@223 81 {
Chris@223 82 #ifdef _WIN32
Chris@223 83 HANDLE handle = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
Chris@223 84 if (!handle) {
Chris@223 85 return ProcessNotRunning;
Chris@223 86 } else {
Chris@223 87 CloseHandle(handle);
Chris@223 88 return ProcessRunning;
Chris@223 89 }
Chris@223 90 #else
Chris@223 91 if (kill(getpid(), 0) == 0) {
Chris@223 92 if (kill(pid, 0) == 0) {
Chris@223 93 return ProcessRunning;
Chris@223 94 } else {
Chris@223 95 return ProcessNotRunning;
Chris@223 96 }
Chris@223 97 } else {
Chris@223 98 return UnknownProcessStatus;
Chris@223 99 }
Chris@223 100 #endif
Chris@223 101 }
Chris@223 102
Chris@223 103 #ifdef _WIN32
Chris@223 104 /* MEMORYSTATUSEX is missing from older Windows headers, so define a
Chris@223 105 local replacement. This trick from MinGW source code. Ugh */
Chris@223 106 typedef struct
Chris@223 107 {
Chris@223 108 DWORD dwLength;
Chris@223 109 DWORD dwMemoryLoad;
Chris@223 110 DWORDLONG ullTotalPhys;
Chris@223 111 DWORDLONG ullAvailPhys;
Chris@223 112 DWORDLONG ullTotalPageFile;
Chris@223 113 DWORDLONG ullAvailPageFile;
Chris@223 114 DWORDLONG ullTotalVirtual;
Chris@223 115 DWORDLONG ullAvailVirtual;
Chris@223 116 DWORDLONG ullAvailExtendedVirtual;
Chris@223 117 } lMEMORYSTATUSEX;
Chris@223 118 typedef WINBOOL (WINAPI *PFN_MS_EX) (lMEMORYSTATUSEX*);
Chris@223 119 #endif
Chris@223 120
Chris@223 121 void
Chris@223 122 GetRealMemoryMBAvailable(int &available, int &total)
Chris@223 123 {
Chris@223 124 available = -1;
Chris@223 125 total = -1;
Chris@223 126
Chris@223 127 #ifdef _WIN32
Chris@223 128
Chris@223 129 static bool checked = false;
Chris@223 130 static bool exFound = false;
Chris@223 131 static PFN_MS_EX ex;
Chris@223 132
Chris@223 133 if (!checked) {
Chris@223 134
Chris@223 135 HMODULE h = GetModuleHandleA("kernel32.dll");
Chris@223 136
Chris@223 137 if (h) {
Chris@223 138 if ((ex = (PFN_MS_EX)GetProcAddress(h, "GlobalMemoryStatusEx"))) {
Chris@223 139 exFound = true;
Chris@223 140 }
Chris@223 141 }
Chris@223 142
Chris@223 143 checked = true;
Chris@223 144 }
Chris@223 145
Chris@223 146 DWORDLONG wavail = 0;
Chris@223 147 DWORDLONG wtotal = 0;
Chris@223 148
Chris@223 149 if (exFound) {
Chris@223 150
Chris@223 151 lMEMORYSTATUSEX lms;
Chris@223 152 lms.dwLength = sizeof(lms);
Chris@223 153 if (!ex(&lms)) {
Chris@223 154 std::cerr << "WARNING: GlobalMemoryStatusEx failed: error code "
Chris@223 155 << GetLastError() << std::endl;
Chris@223 156 return;
Chris@223 157 }
Chris@223 158 wavail = lms.ullAvailPhys;
Chris@223 159 wtotal = lms.ullTotalPhys;
Chris@223 160
Chris@223 161 } else {
Chris@223 162
Chris@223 163 /* Fall back to GlobalMemoryStatus which is always available.
Chris@223 164 but returns wrong results for physical memory > 4GB */
Chris@223 165
Chris@223 166 MEMORYSTATUS ms;
Chris@223 167 GlobalMemoryStatus(&ms);
Chris@223 168 wavail = ms.dwAvailPhys;
Chris@223 169 wtotal = ms.dwTotalPhys;
Chris@223 170 }
Chris@223 171
Chris@223 172 DWORDLONG size = wavail / 1048576;
Chris@223 173 if (size > INT_MAX) size = INT_MAX;
Chris@223 174 available = int(size);
Chris@223 175
Chris@223 176 size = wtotal / 1048576;
Chris@223 177 if (size > INT_MAX) size = INT_MAX;
Chris@223 178 total = int(size);
Chris@223 179
Chris@223 180 return;
Chris@223 181
Chris@223 182 #else
Chris@223 183 #ifdef __APPLE__
Chris@223 184
Chris@223 185 unsigned int val;
Chris@223 186 int mib[2];
Chris@223 187 size_t size_sys;
Chris@223 188
Chris@223 189 mib[0] = CTL_HW;
Chris@223 190
Chris@223 191 mib[1] = HW_PHYSMEM;
Chris@223 192 size_sys = sizeof(val);
Chris@223 193 sysctl(mib, 2, &val, &size_sys, NULL, 0);
Chris@223 194 if (val) total = val / 1048576;
Chris@223 195
Chris@223 196 mib[1] = HW_USERMEM;
Chris@223 197 size_sys = sizeof(val);
Chris@223 198 sysctl(mib, 2, &val, &size_sys, NULL, 0);
Chris@223 199 if (val) available = val / 1048576;
Chris@223 200
Chris@223 201 return;
Chris@223 202
Chris@223 203 #else
Chris@223 204
Chris@223 205 FILE *meminfo = fopen("/proc/meminfo", "r");
Chris@223 206 if (!meminfo) return;
Chris@223 207
Chris@223 208 char buf[256];
Chris@223 209 while (!feof(meminfo)) {
Chris@223 210 fgets(buf, 256, meminfo);
Chris@223 211 bool isMemFree = (strncmp(buf, "MemFree:", 8) == 0);
Chris@223 212 bool isMemTotal = (!isMemFree && (strncmp(buf, "MemTotal:", 9) == 0));
Chris@223 213 if (isMemFree || isMemTotal) {
Chris@223 214 QString line = QString(buf).trimmed();
Chris@223 215 QStringList elements = line.split(' ', QString::SkipEmptyParts);
Chris@223 216 QString unit = "kB";
Chris@223 217 if (elements.size() > 2) unit = elements[2];
Chris@223 218 int size = elements[1].toInt();
Chris@223 219 // std::cerr << "have size \"" << size << "\", unit \""
Chris@223 220 // << unit.toStdString() << "\"" << std::endl;
Chris@223 221 if (unit.toLower() == "gb") size = size * 1024;
Chris@223 222 else if (unit.toLower() == "mb") size = size;
Chris@223 223 else if (unit.toLower() == "kb") size = size / 1024;
Chris@223 224 else size = size / 1048576;
Chris@223 225
Chris@223 226 if (isMemFree) available = size;
Chris@223 227 else total = size;
Chris@223 228 }
Chris@223 229 if (available != -1 && total != -1) {
Chris@223 230 fclose(meminfo);
Chris@223 231 return;
Chris@223 232 }
Chris@223 233 }
Chris@223 234 fclose(meminfo);
Chris@223 235
Chris@223 236 return;
Chris@223 237
Chris@223 238 #endif
Chris@223 239 #endif
Chris@223 240 }
Chris@223 241
Chris@223 242 int
Chris@223 243 GetDiscSpaceMBAvailable(const char *path)
Chris@223 244 {
Chris@223 245 #ifdef _WIN32
Chris@223 246 ULARGE_INTEGER available, total, totalFree;
Chris@223 247 if (GetDiskFreeSpaceExA(path, &available, &total, &totalFree)) {
Chris@223 248 __int64 a = available.QuadPart;
Chris@223 249 a /= 1048576;
Chris@223 250 if (a > INT_MAX) a = INT_MAX;
Chris@223 251 return int(a);
Chris@223 252 } else {
Chris@223 253 std::cerr << "WARNING: GetDiskFreeSpaceEx failed: error code "
Chris@223 254 << GetLastError() << std::endl;
Chris@223 255 return -1;
Chris@223 256 }
Chris@223 257 #else
Chris@223 258 struct statvfs buf;
Chris@223 259 if (!statvfs(path, &buf)) {
Chris@223 260 // do the multiplies and divides in this order to reduce the
Chris@223 261 // likelihood of arithmetic overflow
Chris@436 262 // std::cerr << "statvfs(" << path << ") says available: " << buf.f_bavail << ", block size: " << buf.f_bsize << std::endl;
Chris@223 263 uint64_t available = ((buf.f_bavail / 1024) * buf.f_bsize) / 1024;
Chris@223 264 if (available > INT_MAX) available = INT_MAX;
Chris@223 265 return int(available);
Chris@223 266 } else {
Chris@223 267 perror("statvfs failed");
Chris@223 268 return -1;
Chris@223 269 }
Chris@223 270 #endif
Chris@223 271 }
Chris@303 272
Chris@303 273 static char *startupLocale = 0;
Chris@303 274
Chris@303 275 void
Chris@303 276 StoreStartupLocale()
Chris@303 277 {
Chris@303 278 char *loc = setlocale(LC_ALL, 0);
Chris@303 279 if (!loc) return;
Chris@303 280 if (startupLocale) free(startupLocale);
Chris@303 281 startupLocale = strdup(loc);
Chris@303 282 }
Chris@303 283
Chris@303 284 void
Chris@303 285 RestoreStartupLocale()
Chris@303 286 {
Chris@303 287 if (!startupLocale) {
Chris@303 288 setlocale(LC_ALL, "");
Chris@303 289 } else {
Chris@303 290 setlocale(LC_ALL, startupLocale);
Chris@303 291 }
Chris@303 292 }
Chris@223 293
Chris@223 294 double mod(double x, double y) { return x - (y * floor(x / y)); }
Chris@223 295 float modf(float x, float y) { return x - (y * floorf(x / y)); }
Chris@223 296
Chris@223 297 double princarg(double a) { return mod(a + M_PI, -2 * M_PI) + M_PI; }
Chris@223 298 float princargf(float a) { return modf(a + M_PI, -2 * M_PI) + M_PI; }
Chris@223 299