annotate system/System.cpp @ 251:db0dd744fa8d

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