691
static void get_cpu_info_haiku(HOST_INFO& host) {
692
/* This function has been adapted from Haiku's sysinfo.c
693
* which spits out a bunch of formatted CPU info to
694
* the terminal, it was easier to copy some of the logic
697
system_info sys_info;
698
int32 cpu = 0; // always use first CPU for now
700
int32 maxStandardFunction;
701
int32 maxExtendedFunction = 0;
703
char brand_string[256];
705
if (get_system_info(&sys_info) != B_OK) {
706
msg_printf(NULL, MSG_INTERNAL_ERROR, "Error getting Haiku system information!\n");
710
if (get_cpuid(&cpuInfo, 0, cpu) != B_OK) {
711
// this CPU doesn't support cpuid
715
snprintf(host.p_vendor, sizeof(host.p_vendor), "%.12s",
716
cpuInfo.eax_0.vendor_id);
718
maxStandardFunction = cpuInfo.eax_0.max_eax;
719
if (maxStandardFunction >= 500)
720
maxStandardFunction = 0; /* old Pentium sample chips has
721
cpu signature here */
724
get_cpuid(&cpuInfo, 0x80000000, cpu);
726
// extended cpuid is only supported if max_eax is greater
727
// than the service id
728
if (cpuInfo.eax_0.max_eax > 0x80000000)
729
maxExtendedFunction = cpuInfo.eax_0.max_eax & 0xff;
731
if (maxExtendedFunction >=4 ) {
736
memset(buffer, 0, sizeof(buffer));
738
for (i = 0; i < 3; i++) {
740
get_cpuid(&nameInfo, 0x80000002 + i, cpu);
742
memcpy(name, &nameInfo.regs.eax, 4);
743
memcpy(name + 4, &nameInfo.regs.ebx, 4);
744
memcpy(name + 8, &nameInfo.regs.ecx, 4);
745
memcpy(name + 12, &nameInfo.regs.edx, 4);
749
// cut off leading spaces (names are right aligned)
751
while (name[0] == ' ')
754
// the BIOS may not have set the processor name
756
strlcpy(brand_string, name, sizeof(brand_string));
758
// Intel CPUs don't seem to have the genuine vendor field
759
snprintf(brand_string, sizeof(brand_string), "%.12s",
760
cpuInfo.eax_0.vendor_id);
764
get_cpuid(&cpuInfo, 1, cpu);
766
int family, stepping, model;
768
family = cpuInfo.eax_1.family + (cpuInfo.eax_1.family == 0xf ?
769
cpuInfo.eax_1.extended_family : 0);
771
// model calculation is different for AMD and INTEL
772
if ((sys_info.cpu_type & B_CPU_x86_VENDOR_MASK) == B_CPU_AMD_x86) {
773
model = cpuInfo.eax_1.model + (cpuInfo.eax_1.model == 0xf ?
774
cpuInfo.eax_1.extended_model << 4 : 0);
775
} else if ((sys_info.cpu_type & B_CPU_x86_VENDOR_MASK) == B_CPU_INTEL_x86) {
776
model = cpuInfo.eax_1.model + ((cpuInfo.eax_1.family == 0xf ||
777
cpuInfo.eax_1.family == 0x6) ? cpuInfo.eax_1.extended_model << 4 : 0);
780
stepping = cpuInfo.eax_1.stepping;
782
snprintf(host.p_model, sizeof(host.p_model),
783
"%s [Family %u Model %u Stepping %u]", brand_string, family, model,
786
static const char *kFeatures[32] = {
787
"fpu", "vme", "de", "pse",
788
"tsc", "msr", "pae", "mce",
789
"cx8", "apic", NULL, "sep",
790
"mtrr", "pge", "mca", "cmov",
791
"pat", "pse36", "psnum", "clflush",
792
NULL, "ds", "acpi", "mmx",
793
"fxsr", "sse", "sse2", "ss",
794
"htt", "tm", "ia64", "pbe",
801
for (i = 0; i < 32; i++) {
802
if ((cpuInfo.eax_1.features & (1UL << i)) && kFeatures[i] != NULL) {
803
snprintf(buf, sizeof(buf), "%s%s", found == 0 ? "" : " ",
805
strlcat(host.p_features, buf, sizeof(host.p_features));
810
if (maxStandardFunction >= 1) {
811
/* Extended features */
812
static const char *kFeatures2[32] = {
813
"sse3", NULL, "dtes64", "monitor", "ds-cpl", "vmx", "smx" "est",
814
"tm2", "ssse3", "cnxt-id", NULL, NULL, "cx16", "xtpr", "pdcm",
815
NULL, NULL, "dca", "sse4.1", "sse4.2", "x2apic", "movbe", "popcnt",
816
NULL, NULL, "xsave", "osxsave", NULL, NULL, NULL, NULL
819
for (i = 0; i < 32; i++) {
820
if ((cpuInfo.eax_1.extended_features & (1UL << i)) &&
821
kFeatures2[i] != NULL) {
822
snprintf(buf, sizeof(buf), "%s%s", found == 0 ? "" : " ",
824
strlcat(host.p_features, buf, sizeof(host.p_features));
830
//TODO: there are additional AMD features that probably need to be queried
835
// Note: this may also work on other UNIX-like systems in addition to Macintosh
839
#include <net/if_dl.h>
840
#include <net/route.h>
842
// detect the network usage totals for the host.
844
int get_network_usage_totals(unsigned int& total_received, unsigned int& total_sent) {
845
static size_t sysctlBufferSize = 0;
846
static uint8_t *sysctlBuffer = NULL;
848
int mib[] = { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, 0 };
849
struct if_msghdr *ifmsg;
850
size_t currentSize = 0;
855
if (sysctl(mib, 6, NULL, ¤tSize, NULL, 0) != 0) return errno;
856
if (!sysctlBuffer || (currentSize > sysctlBufferSize)) {
857
if (sysctlBuffer) free(sysctlBuffer);
858
sysctlBufferSize = 0;
859
sysctlBuffer = (uint8_t*)malloc(currentSize);
860
if (!sysctlBuffer) return ERR_MALLOC;
861
sysctlBufferSize = currentSize;
865
if (sysctl(mib, 6, sysctlBuffer, ¤tSize, NULL, 0) != 0) return errno;
867
// Walk through the reply
868
uint8_t *currentData = sysctlBuffer;
869
uint8_t *currentDataEnd = sysctlBuffer + currentSize;
871
while (currentData < currentDataEnd) {
872
// Expecting interface data
873
ifmsg = (struct if_msghdr *)currentData;
874
if (ifmsg->ifm_type != RTM_IFINFO) {
875
currentData += ifmsg->ifm_msglen;
878
// Must not be loopback
879
if (ifmsg->ifm_flags & IFF_LOOPBACK) {
880
currentData += ifmsg->ifm_msglen;
883
// Only look at link layer items
884
struct sockaddr_dl *sdl = (struct sockaddr_dl *)(ifmsg + 1);
885
if (sdl->sdl_family != AF_LINK) {
886
currentData += ifmsg->ifm_msglen;
890
#if 0 // Use this code if we want only Ethernet interface 0
891
if (!strcmp(sdl->sdl_data, "en0")) {
892
total_received = ifmsg->ifm_data.ifi_ibytes;
893
total_sent = ifmsg->ifm_data.ifi_obytes;
896
#else // Use this code if we want total of all non-loopback interfaces
897
total_received += ifmsg->ifm_data.ifi_ibytes;
898
total_sent += ifmsg->ifm_data.ifi_obytes;
906
#if defined(__i386__) || defined(__x86_64__)
908
// Code to get maximum CPU temperature (Apple Intel only)
909
// Adapted from Apple System Management Control (SMC) Tool under the GPL
911
#define KERNEL_INDEX_SMC 2
913
#define SMC_CMD_READ_BYTES 5
914
#define SMC_CMD_READ_KEYINFO 9
930
} SMCKeyData_pLimitData_t;
936
} SMCKeyData_keyInfo_t;
938
typedef char SMCBytes_t[32];
942
SMCKeyData_vers_t vers;
943
SMCKeyData_pLimitData_t pLimitData;
944
SMCKeyData_keyInfo_t keyInfo;
952
static io_connect_t conn;
954
kern_return_t SMCOpen()
956
kern_return_t result;
957
mach_port_t masterPort;
958
io_iterator_t iterator;
961
result = IOMasterPort(MACH_PORT_NULL, &masterPort);
963
CFMutableDictionaryRef matchingDictionary = IOServiceMatching("AppleSMC");
964
result = IOServiceGetMatchingServices(masterPort, matchingDictionary, &iterator);
965
if (result != kIOReturnSuccess)
970
device = IOIteratorNext(iterator);
971
IOObjectRelease(iterator);
977
result = IOServiceOpen(device, mach_task_self(), 0, &conn);
978
IOObjectRelease(device);
979
if (result != kIOReturnSuccess)
984
return kIOReturnSuccess;
987
kern_return_t SMCClose()
990
return IOServiceClose(conn);
992
return kIOReturnSuccess;
996
kern_return_t SMCReadKey(UInt32 key, SMCBytes_t val)
998
kern_return_t result;
999
SMCKeyData_t inputStructure;
1000
SMCKeyData_t outputStructure;
1001
size_t structureInputSize;
1002
size_t structureOutputSize;
1004
memset(&inputStructure, 0, sizeof(SMCKeyData_t));
1005
memset(&outputStructure, 0, sizeof(SMCKeyData_t));
1006
memset(val, 0, sizeof(val));
1008
inputStructure.key = key;
1009
inputStructure.data8 = SMC_CMD_READ_KEYINFO;
1011
structureInputSize = sizeof(inputStructure);
1012
structureOutputSize = sizeof(outputStructure);
1013
result = IOConnectMethodStructureIStructureO(
1014
conn, KERNEL_INDEX_SMC, structureInputSize, &structureOutputSize,
1015
&inputStructure, &outputStructure
1017
if (result != kIOReturnSuccess)
1020
inputStructure.keyInfo.dataSize = outputStructure.keyInfo.dataSize;
1021
inputStructure.data8 = SMC_CMD_READ_BYTES;
1023
result = IOConnectMethodStructureIStructureO(
1024
conn, KERNEL_INDEX_SMC, structureInputSize, &structureOutputSize,
1025
&inputStructure, &outputStructure
1027
if (result != kIOReturnSuccess)
1030
memcpy(val, outputStructure.bytes, sizeof(outputStructure.bytes));
1032
return kIOReturnSuccess;
1036
// Check up to 10 die temperatures (TC0D, TC1D, etc.) and
1037
// 10 heatsink temperatures (TCAH, TCBH, etc.)
1038
// Returns the highest current CPU temperature as degrees Celsius.
1039
// Returns zero if it fails (or on a PowerPC Mac).
1040
int get_max_cpu_temperature() {
1041
kern_return_t result;
1042
int maxTemp = 0, thisTemp, i;
1049
static bool skip[20];
1051
// open connection to SMC kext if this is the first time
1054
if (result != kIOReturnSuccess) {
1059
for (i=0; i<20; ++i) {
1060
if (skip[i]) continue;
1063
key.bytes[1] += i; // TC0D, TC1D, TC2D, etc.
1066
key.bytes[1] += (i - 10); // TCAH, TCBH, TCCH, etc.
1068
result = SMCReadKey(key.word, val);
1069
if (result != kIOReturnSuccess) {
1080
if (val[1] & 0x80) ++thisTemp;
1081
if (thisTemp > maxTemp) {
1091
int GetMaxCPUTemperature() {
1098
// see if Virtualbox is installed
1100
int HOST_INFO::get_virtualbox_version() {
1101
char path[MAXPATHLEN];
1102
char cmd [MAXPATHLEN+35];
1106
#if LINUX_LIKE_SYSTEM
1107
strcpy(path, "/usr/lib/virtualbox/VBoxManage");
1108
#elif defined( __APPLE__)
1110
OSStatus status = noErr;
1112
// First try to locate the VirtualBox application by Bundle ID and Creator Code
1113
status = LSFindApplicationForInfo('VBOX', CFSTR("org.virtualbox.app.VirtualBox"),
1114
NULL, &theFSRef, NULL
1116
if (status == noErr) {
1117
status = FSRefMakePath(&theFSRef, (unsigned char *)path, sizeof(path));
1119
// If that failed, try its default location
1120
if (status != noErr) {
1121
strcpy(path, "/Applications/VirtualBox.app");
1125
if (boinc_file_exists(path)) {
1126
#if LINUX_LIKE_SYSTEM
1127
safe_strcpy(cmd, path);
1128
safe_strcat(cmd, " --version");
1129
#elif defined( __APPLE__)
1130
safe_strcpy(cmd, "defaults read ");
1131
safe_strcat(cmd, path);
1132
safe_strcat(cmd, "/Contents/Info CFBundleShortVersionString");
1134
fd = popen(cmd, "r");
1136
fgets(virtualbox_version, sizeof(virtualbox_version), fd);
1137
newlinePtr = strchr(virtualbox_version, '\n');
1138
if (newlinePtr) *newlinePtr = '\0';
1139
newlinePtr = strchr(virtualbox_version, '\r');
1140
if (newlinePtr) *newlinePtr = '\0';
679
1149
// - Keep code in the right place
680
1150
// - only one level of #if
682
1152
int HOST_INFO::get_host_info() {
683
1153
get_filesystem_info(d_total, d_free);
1154
get_virtualbox_version();
685
1156
///////////// p_vendor, p_model, p_features /////////////////
686
1157
#if LINUX_LIKE_SYSTEM
1074
1561
#ifdef __APPLE__
1563
// NXIdleTime() is an undocumented Apple API to return user idle time, which
1564
// was implemented from before OS 10.0 through OS 10.5. In OS 10.4, Apple
1565
// added the CGEventSourceSecondsSinceLastEventType() API as a replacement for
1566
// NXIdleTime(). However, BOINC could not use this newer API when configured
1567
// as a pre-login launchd daemon unless that daemon was running as root,
1568
// because it could not connect to the Window Server. So BOINC continued to
1569
// use NXIdleTime().
1571
// In OS 10.6, Apple removed the NXIdleTime() API. BOINC can instead use the
1572
// IOHIDGetParameter() API in OS 10.6. When BOINC is a pre-login launchd
1573
// daemon running as user boinc_master, this API works properly under OS 10.6
1574
// but fails under OS 10.5 and earlier.
1576
// So we use weak-linking of NxIdleTime() to prevent a run-time crash from the
1577
// dynamic linker, and use the IOHIDGetParameter() API if NXIdleTime does not
1076
1580
bool HOST_INFO::users_idle(
1077
1581
bool check_all_logins, double idle_time_to_run, double *actual_idle_time
1079
double idleTime = 0;
1082
idleTime = NXIdleTime(gEventHandle);
1084
// Initialize Mac OS X idle time measurement / idle detection
1085
// Do this here because NXOpenEventStatus() may not be available
1086
// immediately on system startup when running as a deaemon.
1087
gEventHandle = NXOpenEventStatus();
1583
static bool error_posted = false;
1584
double idleTime = 0;
1585
io_service_t service;
1586
kern_return_t kernResult = kIOReturnError;
1588
IOByteCount rcnt = sizeof(UInt64);
1590
if (error_posted) goto bail;
1592
if (NXIdleTime) { // Use NXIdleTime API in OS 10.5 and earlier
1594
idleTime = NXIdleTime(gEventHandle);
1596
// Initialize Mac OS X idle time measurement / idle detection
1597
// Do this here because NXOpenEventStatus() may not be available
1598
// immediately on system startup when running as a deaemon.
1600
gEventHandle = NXOpenEventStatus();
1601
if (!gEventHandle) {
1602
if (TickCount() > (120*60)) { // If system has been up for more than 2 minutes
1603
msg_printf(NULL, MSG_INFO,
1604
"User idle detection is disabled: initialization failed."
1606
error_posted = true;
1611
} else { // NXIdleTime API does not exist in OS 10.6 and later
1613
kernResult = IOHIDGetParameter( gEventHandle, CFSTR(EVSIOIDLE), sizeof(UInt64), ¶ms, &rcnt );
1614
if ( kernResult != kIOReturnSuccess ) {
1615
msg_printf(NULL, MSG_INFO,
1616
"User idle time measurement failed because IOHIDGetParameter failed."
1618
error_posted = true;
1621
idleTime = ((double)params) / 1000.0 / 1000.0 / 1000.0;
1623
service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching(kIOHIDSystemClass));
1625
kernResult = IOServiceOpen(service, mach_task_self(), kIOHIDParamConnectType, &gEventHandle);
1627
if ( (!service) || (kernResult != KERN_SUCCESS) ) {
1628
// When the system first starts up, allow time for HIDSystem to be available if needed
1629
if (TickCount() > (120*60)) { // If system has been up for more than 2 minutes
1630
msg_printf(NULL, MSG_INFO,
1631
"Could not connect to HIDSystem: user idle detection is disabled."
1633
error_posted = true;
1637
} // End gEventHandle == NULL
1638
} // End NXIdleTime API does not exist
1090
1641
if (actual_idle_time) {
1091
1642
*actual_idle_time = idleTime;