svcore
1.9
|
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ 00002 00003 /* 00004 Sonic Visualiser 00005 An audio file viewer and annotation editor. 00006 Centre for Digital Music, Queen Mary, University of London. 00007 This file copyright 2006 Chris Cannam and QMUL. 00008 00009 This program is free software; you can redistribute it and/or 00010 modify it under the terms of the GNU General Public License as 00011 published by the Free Software Foundation; either version 2 of the 00012 License, or (at your option) any later version. See the file 00013 COPYING included with this distribution for more information. 00014 */ 00015 00016 #include "System.h" 00017 00018 #include <QStringList> 00019 #include <QString> 00020 00021 #include <stdint.h> 00022 00023 #ifndef _WIN32 00024 #include <signal.h> 00025 #include <sys/statvfs.h> 00026 #include <locale.h> 00027 #include <unistd.h> 00028 #endif 00029 00030 #ifdef __APPLE__ 00031 #include <sys/param.h> 00032 #include <sys/sysctl.h> 00033 #endif 00034 00035 #include <limits.h> 00036 #include <cstdlib> 00037 00038 #include <iostream> 00039 00040 #ifdef __APPLE__ 00041 extern "C" { 00042 void * 00043 rpl_realloc (void *p, size_t n) 00044 { 00045 p = realloc(p, n); 00046 if (p == 0 && n == 0) 00047 { 00048 p = malloc(0); 00049 } 00050 return p; 00051 } 00052 } 00053 #endif 00054 00055 #ifdef _WIN32 00056 00057 extern "C" { 00058 00059 /* usleep is now in mingw 00060 void usleep(unsigned long usec) 00061 { 00062 ::Sleep(usec / 1000); 00063 } 00064 */ 00065 00066 int gettimeofday(struct timeval *tv, void *tz) 00067 { 00068 union { 00069 long long ns100; 00070 FILETIME ft; 00071 } now; 00072 00073 ::GetSystemTimeAsFileTime(&now.ft); 00074 tv->tv_usec = (long)((now.ns100 / 10LL) % 1000000LL); 00075 tv->tv_sec = (long)((now.ns100 - 116444736000000000LL) / 10000000LL); 00076 return 0; 00077 } 00078 00079 } 00080 00081 #endif 00082 00083 ProcessStatus 00084 GetProcessStatus(int pid) 00085 { 00086 #ifdef _WIN32 00087 HANDLE handle = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid); 00088 if (!handle) { 00089 return ProcessNotRunning; 00090 } else { 00091 CloseHandle(handle); 00092 return ProcessRunning; 00093 } 00094 #else 00095 if (kill(getpid(), 0) == 0) { 00096 if (kill(pid, 0) == 0) { 00097 return ProcessRunning; 00098 } else { 00099 return ProcessNotRunning; 00100 } 00101 } else { 00102 return UnknownProcessStatus; 00103 } 00104 #endif 00105 } 00106 00107 #ifdef _WIN32 00108 /* MEMORYSTATUSEX is missing from older Windows headers, so define a 00109 local replacement. This trick from MinGW source code. Ugh */ 00110 typedef struct 00111 { 00112 DWORD dwLength; 00113 DWORD dwMemoryLoad; 00114 DWORDLONG ullTotalPhys; 00115 DWORDLONG ullAvailPhys; 00116 DWORDLONG ullTotalPageFile; 00117 DWORDLONG ullAvailPageFile; 00118 DWORDLONG ullTotalVirtual; 00119 DWORDLONG ullAvailVirtual; 00120 DWORDLONG ullAvailExtendedVirtual; 00121 } lMEMORYSTATUSEX; 00122 typedef WINBOOL (WINAPI *PFN_MS_EX) (lMEMORYSTATUSEX*); 00123 #endif 00124 00125 void 00126 GetRealMemoryMBAvailable(int &available, int &total) 00127 { 00128 available = -1; 00129 total = -1; 00130 00131 #ifdef _WIN32 00132 00133 static bool checked = false; 00134 static bool exFound = false; 00135 static PFN_MS_EX ex; 00136 00137 if (!checked) { 00138 00139 HMODULE h = GetModuleHandleA("kernel32.dll"); 00140 00141 if (h) { 00142 if ((ex = (PFN_MS_EX)GetProcAddress(h, "GlobalMemoryStatusEx"))) { 00143 exFound = true; 00144 } 00145 } 00146 00147 checked = true; 00148 } 00149 00150 DWORDLONG wavail = 0; 00151 DWORDLONG wtotal = 0; 00152 00153 if (exFound) { 00154 00155 lMEMORYSTATUSEX lms; 00156 lms.dwLength = sizeof(lms); 00157 if (!ex(&lms)) { 00158 cerr << "WARNING: GlobalMemoryStatusEx failed: error code " 00159 << GetLastError() << endl; 00160 return; 00161 } 00162 wavail = lms.ullAvailPhys; 00163 wtotal = lms.ullTotalPhys; 00164 00165 } else { 00166 00167 /* Fall back to GlobalMemoryStatus which is always available. 00168 but returns wrong results for physical memory > 4GB */ 00169 00170 MEMORYSTATUS ms; 00171 GlobalMemoryStatus(&ms); 00172 wavail = ms.dwAvailPhys; 00173 wtotal = ms.dwTotalPhys; 00174 } 00175 00176 DWORDLONG size = wavail / 1048576; 00177 if (size > INT_MAX) size = INT_MAX; 00178 available = int(size); 00179 00180 size = wtotal / 1048576; 00181 if (size > INT_MAX) size = INT_MAX; 00182 total = int(size); 00183 00184 return; 00185 00186 #else 00187 #ifdef __APPLE__ 00188 00189 unsigned int val; 00190 int mib[2]; 00191 size_t size_sys; 00192 00193 mib[0] = CTL_HW; 00194 00195 mib[1] = HW_PHYSMEM; 00196 size_sys = sizeof(val); 00197 sysctl(mib, 2, &val, &size_sys, NULL, 0); 00198 if (val) total = val / 1048576; 00199 00200 mib[1] = HW_USERMEM; 00201 size_sys = sizeof(val); 00202 sysctl(mib, 2, &val, &size_sys, NULL, 0); 00203 if (val) available = val / 1048576; 00204 00205 return; 00206 00207 #else 00208 00209 FILE *meminfo = fopen("/proc/meminfo", "r"); 00210 if (!meminfo) return; 00211 00212 char buf[256]; 00213 while (!feof(meminfo)) { 00214 fgets(buf, 256, meminfo); 00215 bool isMemFree = (strncmp(buf, "MemFree:", 8) == 0); 00216 bool isMemTotal = (!isMemFree && (strncmp(buf, "MemTotal:", 9) == 0)); 00217 if (isMemFree || isMemTotal) { 00218 QString line = QString(buf).trimmed(); 00219 QStringList elements = line.split(' ', QString::SkipEmptyParts); 00220 QString unit = "kB"; 00221 if (elements.size() > 2) unit = elements[2]; 00222 int size = elements[1].toInt(); 00223 // cerr << "have size \"" << size << "\", unit \"" 00224 // << unit << "\"" << endl; 00225 if (unit.toLower() == "gb") size = size * 1024; 00226 else if (unit.toLower() == "mb") size = size; 00227 else if (unit.toLower() == "kb") size = size / 1024; 00228 else size = size / 1048576; 00229 00230 if (isMemFree) available = size; 00231 else total = size; 00232 } 00233 if (available != -1 && total != -1) { 00234 fclose(meminfo); 00235 return; 00236 } 00237 } 00238 fclose(meminfo); 00239 00240 return; 00241 00242 #endif 00243 #endif 00244 } 00245 00246 int 00247 GetDiscSpaceMBAvailable(const char *path) 00248 { 00249 #ifdef _WIN32 00250 ULARGE_INTEGER available, total, totalFree; 00251 if (GetDiskFreeSpaceExA(path, &available, &total, &totalFree)) { 00252 __int64 a = available.QuadPart; 00253 a /= 1048576; 00254 if (a > INT_MAX) a = INT_MAX; 00255 return int(a); 00256 } else { 00257 cerr << "WARNING: GetDiskFreeSpaceEx failed: error code " 00258 << GetLastError() << endl; 00259 return -1; 00260 } 00261 #else 00262 struct statvfs buf; 00263 if (!statvfs(path, &buf)) { 00264 // do the multiplies and divides in this order to reduce the 00265 // likelihood of arithmetic overflow 00266 // cerr << "statvfs(" << path << ") says available: " << buf.f_bavail << ", block size: " << buf.f_bsize << endl; 00267 uint64_t available = ((buf.f_bavail / 1024) * buf.f_bsize) / 1024; 00268 if (available > INT_MAX) available = INT_MAX; 00269 return int(available); 00270 } else { 00271 perror("statvfs failed"); 00272 return -1; 00273 } 00274 #endif 00275 } 00276 00277 #ifdef _WIN32 00278 extern void SystemMemoryBarrier() 00279 { 00280 #ifdef __MSVC__ 00281 MemoryBarrier(); 00282 #else /* mingw */ 00283 LONG Barrier = 0; 00284 __asm__ __volatile__("xchgl %%eax,%0 " 00285 : "=r" (Barrier)); 00286 #endif 00287 } 00288 #else /* !_WIN32 */ 00289 #if !defined(__APPLE__) && ((__GNUC__ < 4) || (__GNUC__ == 4 && __GNUC_MINOR__ == 0)) 00290 void 00291 SystemMemoryBarrier() 00292 { 00293 pthread_mutex_t dummy = PTHREAD_MUTEX_INITIALIZER; 00294 pthread_mutex_lock(&dummy); 00295 pthread_mutex_unlock(&dummy); 00296 } 00297 #endif /* !defined(__APPLE__) etc */ 00298 #endif /* !_WIN32 */ 00299 00300 00301 static char *startupLocale = 0; 00302 00303 void 00304 StoreStartupLocale() 00305 { 00306 char *loc = setlocale(LC_ALL, 0); 00307 if (!loc) return; 00308 if (startupLocale) free(startupLocale); 00309 startupLocale = strdup(loc); 00310 } 00311 00312 void 00313 RestoreStartupLocale() 00314 { 00315 if (!startupLocale) { 00316 setlocale(LC_ALL, ""); 00317 } else { 00318 setlocale(LC_ALL, startupLocale); 00319 } 00320 } 00321 00322 double mod(double x, double y) { return x - (y * floor(x / y)); } 00323 float modf(float x, float y) { return x - (y * floorf(x / y)); } 00324 00325 double princarg(double a) { return mod(a + M_PI, -2 * M_PI) + M_PI; } 00326 float princargf(float a) { return modf(a + M_PI, -2 * M_PI) + M_PI; } 00327