/* PCSX2 - PS2 Emulator for PCs * Copyright (C) 2002-2014 PCSX2 Dev Team * * PCSX2 is free software: you can redistribute it and/or modify it under the terms * of the GNU Lesser General Public License as published by the Free Software Found- * ation, either version 3 of the License, or (at your option) any later version. * * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with PCSX2. * If not, see . */ #if defined(__APPLE__) #include #include #include #include #include #include #include "common/Pcsx2Types.h" #define NELEM(x) \ ((sizeof(x) / sizeof(0 [x])) / ((size_t)(!(sizeof(x) % sizeof(0 [x]))))) // Darwin (OSX) is a bit different from Linux when requesting properties of // the OS because of its BSD/Mach heritage. Helpfully, most of this code // should translate pretty well to other *BSD systems. (e.g.: the sysctl(3) // interface). // // For an overview of all of Darwin's sysctls, check: // https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/sysctl.3.html // Return the total physical memory on the machine, in bytes. Returns 0 on // failure (not supported by the operating system). u64 GetPhysicalMemory() { static u64 mem = 0; // fetch the total memory only once, as its an expensive system call and // doesn't change during the course of the program. Thread-safety is // ensured by atomic operations with full-barriers (usually compiled // down to XCHG on x86). if (__atomic_load_n(&mem, __ATOMIC_SEQ_CST) == 0) { u64 getmem = 0; size_t len = sizeof(getmem); int mib[] = {CTL_HW, HW_MEMSIZE}; if (sysctl(mib, NELEM(mib), &getmem, &len, NULL, 0) < 0) { perror("sysctl:"); } __atomic_store_n(&mem, getmem, __ATOMIC_SEQ_CST); } return mem; } void InitCPUTicks() { } // returns the performance-counter frequency: ticks per second (Hz) // // usage: // u64 seconds_passed = GetCPUTicks() / GetTickFrequency(); // u64 millis_passed = (GetCPUTicks() * 1000) / GetTickFrequency(); // // NOTE: multiply, subtract, ... your ticks before dividing by // GetTickFrequency() to maintain good precision. u64 GetTickFrequency() { static u64 freq = 0; // by the time denom is not 0, the structure will have been fully // updated and no more atomic accesses are necessary. if (__atomic_load_n(&freq, __ATOMIC_SEQ_CST) == 0) { mach_timebase_info_data_t info; // mach_timebase_info() is a syscall, very slow, that's why we take // pains to only do it once. On x86(-64), the result is guaranteed // to be info.denom == info.numer == 1 (i.e.: the frequency is 1e9, // which means GetCPUTicks is just nanoseconds). if (mach_timebase_info(&info) != KERN_SUCCESS) { abort(); } // store the calculated value atomically __atomic_store_n(&freq, (u64)1e9 * (u64)info.denom / (u64)info.numer, __ATOMIC_SEQ_CST); } return freq; } // return the number of "ticks" since some arbitrary, fixed time in the // past. On OSX x86(-64), this is actually the number of nanoseconds passed, // because mach_timebase_info.numer == denom == 1. So "ticks" == // nanoseconds. u64 GetCPUTicks() { return mach_absolute_time(); } wxString GetOSVersionString() { wxString version; static int initialized = 0; // fetch the OS description only once (thread-safely) if (__atomic_load_n(&initialized, __ATOMIC_SEQ_CST) == 0) { char type[32] = {0}; char release[32] = {0}; char arch[32] = {0}; #define SYSCTL_GET(var, base, name) \ do \ { \ int mib[] = {base, name}; \ size_t len = sizeof(var); \ sysctl(mib, NELEM(mib), NULL, &len, NULL, 0); \ sysctl(mib, NELEM(mib), var, &len, NULL, 0); \ } while (0) SYSCTL_GET(release, CTL_KERN, KERN_OSRELEASE); SYSCTL_GET(type, CTL_KERN, KERN_OSTYPE); SYSCTL_GET(arch, CTL_HW, HW_MACHINE); #undef SYSCTL_KERN // I know strcat is not good, but stpcpy is not universally // available yet. char buf[128] = {0}; strcat(buf, type); strcat(buf, " "); strcat(buf, release); strcat(buf, " "); strcat(buf, arch); version = buf; __atomic_store_n(&initialized, 1, __ATOMIC_SEQ_CST); } return version; } void ScreensaverAllow(bool allow) { // no-op } #endif