VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/darwin/PerformanceDarwin.cpp@ 87635

Last change on this file since 87635 was 85274, checked in by vboxsync, 4 years ago

Main/PerformanceDarwin.cpp: Signed/unsigned conversion issues w/ overflow aspects (>=4TiB). RTPROCESS vs pid_t. bugref:9790

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 5.8 KB
Line 
1/* $Id: PerformanceDarwin.cpp 85274 2020-07-12 13:32:28Z vboxsync $ */
2/** @file
3 * VBox Darwin-specific Performance Classes implementation.
4 */
5
6/*
7 * Copyright (C) 2008-2020 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#include <mach/mach_error.h>
19#include <mach/mach_host.h>
20#include <mach/mach_init.h>
21#include <mach/mach_time.h>
22#include <mach/vm_statistics.h>
23#include <sys/sysctl.h>
24#include <sys/errno.h>
25#include <iprt/errcore.h>
26#include <iprt/log.h>
27#include <iprt/mp.h>
28#include <iprt/param.h>
29#include <iprt/system.h>
30#include "Performance.h"
31
32/* The following declarations are missing in 10.4.x SDK */
33/** @todo Replace them with libproc.h and sys/proc_info.h when 10.4 is no longer supported */
34extern "C" int proc_pidinfo(int pid, int flavor, uint64_t arg, void *buffer, int buffersize);
35struct proc_taskinfo {
36 uint64_t pti_virtual_size; /* virtual memory size (bytes) */
37 uint64_t pti_resident_size; /* resident memory size (bytes) */
38 uint64_t pti_total_user; /* total time */
39 uint64_t pti_total_system;
40 uint64_t pti_threads_user; /* existing threads only */
41 uint64_t pti_threads_system;
42 int32_t pti_policy; /* default policy for new threads */
43 int32_t pti_faults; /* number of page faults */
44 int32_t pti_pageins; /* number of actual pageins */
45 int32_t pti_cow_faults; /* number of copy-on-write faults */
46 int32_t pti_messages_sent; /* number of messages sent */
47 int32_t pti_messages_received; /* number of messages received */
48 int32_t pti_syscalls_mach; /* number of mach system calls */
49 int32_t pti_syscalls_unix; /* number of unix system calls */
50 int32_t pti_csw; /* number of context switches */
51 int32_t pti_threadnum; /* number of threads in the task */
52 int32_t pti_numrunning; /* number of running threads */
53 int32_t pti_priority; /* task priority*/
54};
55#define PROC_PIDTASKINFO 4
56
57namespace pm {
58
59class CollectorDarwin : public CollectorHAL
60{
61public:
62 CollectorDarwin();
63 virtual int getRawHostCpuLoad(uint64_t *user, uint64_t *kernel, uint64_t *idle);
64 virtual int getHostMemoryUsage(ULONG *total, ULONG *used, ULONG *available);
65 virtual int getRawProcessCpuLoad(RTPROCESS process, uint64_t *user, uint64_t *kernel, uint64_t *total);
66 virtual int getProcessMemoryUsage(RTPROCESS process, ULONG *used);
67private:
68 ULONG totalRAM;
69 uint32_t nCpus;
70};
71
72CollectorHAL *createHAL()
73{
74 return new CollectorDarwin();
75}
76
77CollectorDarwin::CollectorDarwin()
78{
79 uint64_t cb;
80 int rc = RTSystemQueryTotalRam(&cb);
81 if (RT_FAILURE(rc))
82 totalRAM = 0;
83 else
84 totalRAM = (ULONG)(cb / 1024);
85 nCpus = RTMpGetOnlineCount();
86 Assert(nCpus);
87 if (nCpus == 0)
88 {
89 /* It is rather unsual to have no CPUs, but the show must go on. */
90 nCpus = 1;
91 }
92}
93
94int CollectorDarwin::getRawHostCpuLoad(uint64_t *user, uint64_t *kernel, uint64_t *idle)
95{
96 kern_return_t krc;
97 mach_msg_type_number_t count;
98 host_cpu_load_info_data_t info;
99
100 count = HOST_CPU_LOAD_INFO_COUNT;
101
102 krc = host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO, (host_info_t)&info, &count);
103 if (krc != KERN_SUCCESS)
104 {
105 Log(("host_statistics() -> %s", mach_error_string(krc)));
106 return RTErrConvertFromDarwinKern(krc);
107 }
108
109 *user = (uint64_t)info.cpu_ticks[CPU_STATE_USER]
110 + info.cpu_ticks[CPU_STATE_NICE];
111 *kernel = (uint64_t)info.cpu_ticks[CPU_STATE_SYSTEM];
112 *idle = (uint64_t)info.cpu_ticks[CPU_STATE_IDLE];
113 return VINF_SUCCESS;
114}
115
116int CollectorDarwin::getHostMemoryUsage(ULONG *total, ULONG *used, ULONG *available)
117{
118 AssertReturn(totalRAM, VERR_INTERNAL_ERROR);
119 uint64_t cb;
120 int rc = RTSystemQueryAvailableRam(&cb);
121 if (RT_SUCCESS(rc))
122 {
123 *total = totalRAM;
124 cb /= 1024;
125 *available = cb < ~(ULONG)0 ? (ULONG)cb : ~(ULONG)0;
126 *used = *total - *available;
127 }
128 return rc;
129}
130
131static int getProcessInfo(RTPROCESS process, struct proc_taskinfo *tinfo)
132{
133 Log7(("getProcessInfo() getting info for %d", process));
134 int cbRet = proc_pidinfo((pid_t)process, PROC_PIDTASKINFO, 0, tinfo, sizeof(*tinfo));
135 if (cbRet <= 0)
136 {
137 int iErrNo = errno;
138 Log(("proc_pidinfo() -> %s", strerror(iErrNo)));
139 return RTErrConvertFromDarwin(iErrNo);
140 }
141 if ((unsigned int)cbRet < sizeof(*tinfo))
142 {
143 Log(("proc_pidinfo() -> too few bytes %d", cbRet));
144 return VERR_INTERNAL_ERROR;
145 }
146 return VINF_SUCCESS;
147}
148
149int CollectorDarwin::getRawProcessCpuLoad(RTPROCESS process, uint64_t *user, uint64_t *kernel, uint64_t *total)
150{
151 struct proc_taskinfo tinfo;
152
153 int rc = getProcessInfo(process, &tinfo);
154 if (RT_SUCCESS(rc))
155 {
156 /*
157 * Adjust user and kernel values so 100% is when ALL cores are fully
158 * utilized (see @bugref{6345}).
159 */
160 *user = tinfo.pti_total_user / nCpus;
161 *kernel = tinfo.pti_total_system / nCpus;
162 *total = mach_absolute_time();
163 }
164 return rc;
165}
166
167int CollectorDarwin::getProcessMemoryUsage(RTPROCESS process, ULONG *used)
168{
169 struct proc_taskinfo tinfo;
170
171 int rc = getProcessInfo(process, &tinfo);
172 if (RT_SUCCESS(rc))
173 {
174 uint64_t cKbResident = tinfo.pti_resident_size / 1024;
175 *used = cKbResident < ~(ULONG)0 ? (ULONG)cKbResident : ~(ULONG)0;
176 }
177 return rc;
178}
179
180}
181
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette