1
/*********************************************************
2
* Copyright (C) 2004 VMware, Inc. All rights reserved.
4
* This program is free software; you can redistribute it and/or modify it
5
* under the terms of the GNU Lesser General Public License as published
6
* by the Free Software Foundation version 2.1 and no later version.
8
* This program is distributed in the hope that it will be useful, but
9
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
11
* License for more details.
13
* You should have received a copy of the GNU Lesser General Public License
14
* along with this program; if not, write to the Free Software Foundation, Inc.,
15
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17
*********************************************************/
22
* Posix misc util functions.
27
#include <sys/param.h>
28
#include <sys/types.h>
30
#include <sys/ioctl.h>
32
#include <sys/resource.h>
39
#if !__FreeBSD__ && !sun
51
#include "vm_atomic.h"
53
#include "vm_version.h"
56
#include "syncMutex.h"
58
#include "unicodeOperations.h"
63
#define LOGLEVEL_MODULE util
64
#include "loglevel_user.h"
65
#define LGPFX "UtilPosix:"
68
/* For Util_GetProcessName() */
70
# define PROCFILE "psinfo"
72
# define PROCFILE "status"
74
* Note that the limit of what is output for the process name in
75
* /proc/<pid>/status is 15 characters (30 with '\' -> '\\' escaping) on
76
* Linux, and 19 characters (76 with ' ' -> '\040' escaping) on FreeBSD.
77
* Reading in at most 128 gives us a bit of extra room in case these fields
78
* grow in the future. The 129 in our buffer is for the NUL terminator.
84
# define PSINFOFMT "%128[^\n]"
88
# define PSINFOFMT "%128s"
92
#if defined(VMX86_STATS) && defined(__linux__) && !defined(VMX86_SERVER)
93
#define SYS_CSTATE_DIR "/sys/devices/system/cpu"
94
#define PROC_CSTATE_DIR "/proc/acpi/processor"
95
#define MAX_C_STATES 8
96
#define FREQ_ACPI 3.579545
100
#if !__FreeBSD__ && !sun
103
*-----------------------------------------------------------------------------
107
* Bump the number of file descriptor this process can open to 2048. On
108
* failure sets *cur to the number of fds we can currently open, and sets
109
* *wanted to what we want.
112
* 0 on success, errno from the failing call to setrlimit(2) otherwise.
117
*-----------------------------------------------------------------------------
121
Util_BumpNoFds(uint32 *cur, // OUT
122
uint32 *wanted) // OUT
128
* Check for minimum file descriptor limit. The number is
129
* somewhat arbitrary. Trying to do multiple snapshots of a split
130
* disk can rapidly consume descriptors however, so we ought to
131
* have a large number. This is only pushing back the problem of
132
* course. Ideally we'd have a fully scalable solution.
136
static const rlim_t fdsDesired = 8192;
138
static const rlim_t fdsDesired = 2048;
141
err = getrlimit(RLIMIT_NOFILE, &lim);
142
ASSERT_NOT_IMPLEMENTED(err >= 0);
148
*wanted = fdsDesired;
151
if (lim.rlim_cur != RLIM_INFINITY && lim.rlim_cur < fdsDesired) {
155
* First attempt to raise limit ourselves.
156
* If that fails, complain and make user do it.
159
rlim_t curFdLimit = lim.rlim_cur;
160
rlim_t maxFdLimit = lim.rlim_max;
162
lim.rlim_cur = fdsDesired;
165
* rlim_max may need to be increased as well.
168
needSu = lim.rlim_max != RLIM_INFINITY && lim.rlim_max < fdsDesired;
171
lim.rlim_max = fdsDesired;
173
err = setrlimit(RLIMIT_NOFILE, &lim) < 0 ? errno : 0;
177
* Set euid to root for the FD limit increase. Note we don't need root
178
* unless rlim_max is being increased. Revert to non-root immediately
182
if (err == EPERM || needSu) {
183
uid_t uid = Id_BeginSuperUser();
185
err = setrlimit(RLIMIT_NOFILE, &lim) < 0 ? errno : 0;
186
Id_EndSuperUser(uid);
190
* If everything else failed, simply try using rlim_max. That might be
195
lim.rlim_cur = maxFdLimit;
196
lim.rlim_max = maxFdLimit;
197
err = setrlimit(RLIMIT_NOFILE, &lim) < 0 ? errno : 0;
198
ASSERT_NOT_TESTED(err == 0);
202
Log("UTIL: Failed to set number of fds at %u, was %u: %s (%d)\n",
203
(uint32)fdsDesired, (uint32)curFdLimit, Err_Errno2String(err),
213
*-----------------------------------------------------------------------------
217
* Retrieve the name associated with a user ID. Thread-safe
221
* The allocated name on success
227
*-----------------------------------------------------------------------------
231
UtilGetUserName(uid_t uid) // IN
240
memPoolSize = _PASSWORD_LEN;
242
memPoolSize = sysconf(_SC_GETPW_R_SIZE_MAX);
243
if (memPoolSize <= 0) {
244
Warning("%s: sysconf(_SC_GETPW_R_SIZE_MAX) failed.\n", __FUNCTION__);
250
memPool = malloc(memPoolSize);
251
if (memPool == NULL) {
252
Warning("%s: Not enough memory.\n", __FUNCTION__);
257
if (Posix_Getpwuid_r(uid, &pw, memPool, memPoolSize, &pw_p) != 0) {
259
Warning("%s: Unable to retrieve the username associated with "
260
"user ID %u.\n", __FUNCTION__, uid);
265
userName = strdup(pw_p->pw_name);
267
if (userName == NULL) {
268
Warning("%s: Not enough memory.\n", __FUNCTION__);
278
*----------------------------------------------------------------------
280
* Util_MakeSafeTemp --
282
* Exactly the same as File_MakeTemp except uses a safe directory
283
* as the default temporary directory.
285
* This code is duplicated in identical form between utilPosix.c
286
* and utilWin32.c, but can't go in util.c because it depends on
287
* Util_GetSafeTmpDir whose Win32 implementation implies extra
288
* dependencies that some people who link just to util.c can't
292
* Open file descriptor or -1
295
* Creates a file if successful.
296
*----------------------------------------------------------------------
300
Util_MakeSafeTemp(ConstUnicode tag, // IN (OPT):
301
Unicode *presult) // OUT:
305
Unicode fileName = NULL;
309
if (tag && File_IsFullPath(tag)) {
310
File_GetPathName(tag, &dir, &fileName);
312
dir = Util_GetSafeTmpDir(TRUE);
313
fileName = Unicode_Duplicate(tag ? tag : "vmware");
316
fd = File_MakeTempEx(dir, fileName, presult);
319
Unicode_Free(fileName);
326
*-----------------------------------------------------------------------------
328
* UtilAcceptableSafeTmpDir --
330
* Determines if the specified path is acceptable as the safe
331
* temp directory. The directory must either be creatable
332
* with the appropriate permissions and userId or it must
333
* already exist with those settings.
336
* TRUE if path is acceptible, FALSE otherwise
339
* Directory may be created
341
*-----------------------------------------------------------------------------
345
UtilAcceptableSafeTmpDir(const char *dirname, // IN
349
static const mode_t mode = 0700;
351
result = (Posix_Mkdir(dirname, mode) == 0);
355
if (EEXIST == error) {
359
* The name already exists. Check that it is what we want: a
360
* directory owned by the current effective user with
361
* permissions 'mode'. It is crucial to use lstat() instead of
362
* stat() here, because we do not want the name to be a symlink
363
* (created by another user) pointing to a directory owned by
364
* the current effective user with permissions 'mode'.
367
if (0 == Posix_Lstat(dirname, &st)) {
369
* Our directory inherited S_ISGID if its parent had it. So it
370
* is important to ignore that bit, and it is safe to do so
371
* because that bit does not affect the owner's
375
if (S_ISDIR(st.st_mode) &&
376
(st.st_uid == userId) &&
377
((st.st_mode & 05777) == mode)) {
389
*-----------------------------------------------------------------------------
391
* UtilFindExistingSafeTmpDir --
393
* Searches the directory baseTmpDir to see if any subdirectories
394
* are suitable to use as the safe temp directory. The safe temp
395
* directory must have the correct permissions and userId.
398
* Path to discovered safe temp directory (must be freed).
399
* NULL returned if no suitable directory is found.
404
*-----------------------------------------------------------------------------
408
UtilFindExistingSafeTmpDir(uid_t userId, // IN
409
const char * userName, // IN
410
const char * baseTmpDir) // IN
415
Unicode tmpDir = NULL;
416
Unicode *fileList = NULL;
419
* We always use the pattern PRODUCT-USER-xxxx when creating
420
* alternative safe temp directories, so check for ones with
421
* those names and the appropriate permissions.
424
pattern = Unicode_Format("%s-%s-", PRODUCT_GENERIC_NAME_LOWER, userName);
425
if (pattern == NULL) {
429
numFiles = File_ListDirectory(baseTmpDir, &fileList);
431
if (numFiles == -1) {
432
Unicode_Free(pattern);
436
for (i = 0; i < numFiles; i++) {
437
if (Unicode_StartsWith(fileList[i], pattern)) {
438
Unicode path = Unicode_Join(baseTmpDir, DIRSEPS, fileList[i],
441
if (File_IsDirectory(path) &&
442
UtilAcceptableSafeTmpDir(path, userId)) {
451
Unicode_FreeList(fileList, numFiles);
452
Unicode_Free(pattern);
458
*-----------------------------------------------------------------------------
460
* UtilCreateSafeTmpDir --
462
* Creates a new directory within baseTmpDir with the correct
463
* permissions and userId to ensure it is safe from symlink attacks.
466
* Path to created safe temp directory (must be freed).
467
* NULL returned if no suitable directory could be created.
470
* Directory may be created.
472
*-----------------------------------------------------------------------------
476
UtilCreateSafeTmpDir(uid_t userId, // IN
477
const char * userName, // IN
478
const char * baseTmpDir) // IN
480
static const int MAX_DIR_ITERS = 250;
489
* We use a crypographically strong random number which is
490
* overkill for this purpose but makes it slightly more likely
491
* that we will create an unused name than if we had simply tried
492
* suffixes in numeric order.
495
if (!Random_Crypto(sizeof(suffix), &suffix)) {
496
Warning("%s: Call to Random_Crypto failed.\n", __FUNCTION__);
500
tmpDir = Str_Asprintf(NULL, "%s"DIRSEPS"%s-%s-%u", baseTmpDir,
501
PRODUCT_GENERIC_NAME_LOWER, userName, suffix);
504
Warning("%s: Out of memory error.\n", __FUNCTION__);
508
if (UtilAcceptableSafeTmpDir(tmpDir, userId)) {
512
if (++curDirIter > MAX_DIR_ITERS) {
513
Warning("%s: Failed to create a safe temporary "
514
"directory, path \"%s\". The maximum number of attempts was "
515
"exceeded.\n", __FUNCTION__, tmpDir);
529
*-----------------------------------------------------------------------------
531
* Util_GetSafeTmpDir --
533
* Return a safe temporary directory (i.e. a temporary directory
534
* which is not prone to symlink attacks, because it is only
535
* writable by the current effective user). Guaranteed to return
536
* the same directory every time it is called during the lifetime
537
* of the current process (unless that directory is deleted while
538
* the process is running).
541
* The allocated directory path on success.
547
*-----------------------------------------------------------------------------
551
Util_GetSafeTmpDir(Bool useConf) // IN
553
static Atomic_Ptr lckStorage;
554
static char *safeDir;
556
char *baseTmpDir = NULL;
557
char *userName = NULL;
563
/* Get and take lock for our safe dir. */
564
lck = SyncMutex_CreateSingleton(&lckStorage);
568
* Check if we've created a temporary dir already and if it is
571
if (safeDir && UtilAcceptableSafeTmpDir(safeDir, userId)) {
572
tmpDir = Util_SafeStrdup(safeDir);
576
/* We don't have a useable temporary dir, create one. */
577
baseTmpDir = File_GetTmpDir(useConf);
580
Warning("%s: File_GetTmpDir failed.\n", __FUNCTION__);
584
userName = UtilGetUserName(userId);
587
Warning("%s: UtilGetUserName failed, using numeric ID "
588
"as username instead.\n", __FUNCTION__);
590
/* Fallback on just using the userId as the username. */
591
userName = Str_Asprintf(NULL, "uid-%d", userId);
594
Warning("%s: Str_Asprintf error.\n", __FUNCTION__);
599
tmpDir = Str_Asprintf(NULL, "%s"DIRSEPS"%s-%s", baseTmpDir,
600
PRODUCT_GENERIC_NAME_LOWER, userName);
603
Warning("%s: Out of memory error.\n", __FUNCTION__);
607
if (!UtilAcceptableSafeTmpDir(tmpDir, userId)) {
609
* We didn't get our first choice for the safe temp directory.
610
* Search through the unsafe tmp directory to see if there is
611
* an acceptable one to use.
616
tmpDir = UtilFindExistingSafeTmpDir(userId, userName, baseTmpDir);
620
* We didn't find any usable directories, so try to create one
624
tmpDir = UtilCreateSafeTmpDir(userId, userName, baseTmpDir);
630
* We have successfully created a temporary directory, remember it for
635
safeDir = Util_SafeStrdup(tmpDir);
639
SyncMutex_Unlock(lck);
649
#if defined(__linux__) || defined(__FreeBSD__) || defined(sun)
651
*----------------------------------------------------------------------------
653
* Util_GetProcessName --
655
* Tries to locate the process name of the specified process id. The
656
* process' name is placed in bufOut.
659
* TRUE on success, FALSE on failure.
664
*----------------------------------------------------------------------------
668
Util_GetProcessName(pid_t pid, // IN : process id
669
char *bufOut, // OUT: output buffer
670
size_t bufOutSize) // IN : buffer size
676
char fileName[MAXPATHLEN];
678
char buf[sizeof (psinfo_t)];
681
char psinfo[PSINFOSZ];
687
* Open up /proc/<pid>/status on Linux/FreeBSD, and /proc/<pid>/psinfo on
691
Str_Sprintf(fileName, sizeof fileName, "/proc/%"FMTPID"/" PROCFILE, pid);
693
fd = Posix_Open(fileName, O_RDONLY);
695
Log("%s: Error: cannot open %s\n", __FUNCTION__, fileName);
700
nread = read(fd, buf, sizeof buf);
702
if (nread != sizeof buf) {
706
Log("%s: Error: could not read %s\n", __FUNCTION__, fileName);
715
psname = ((psinfo_t *)buf)->pr_fname;
716
#else /* Linux & FreeBSD */
717
ASSERT(nread <= sizeof buf);
718
buf[nread == sizeof buf ? nread - 1 : nread] = '\0';
721
* Parse the plain text formatting of the status file. Note that PSINFOFMT
722
* contains a format modifier to ensure psinfo is not overrun.
725
if (sscanf(buf, PRE PSINFOFMT POST, psinfo) != 1) {
726
Log("%s: Error, could not parse contents of %s\n", __FUNCTION__,
732
Escape_UnescapeCString(psinfo);
737
psnameLen = strlen(psname);
738
if (psnameLen + 1 > bufOutSize) {
739
Log("%s: Error, process name (%"FMTSZ"u bytes) is larger "
740
"than output buffer\n", __FUNCTION__, psnameLen);
745
memcpy(bufOut, psname, psnameLen + 1);
751
#if defined(VMX86_STATS)
752
#if defined(__linux__) && !defined(VMX86_SERVER)
754
*----------------------------------------------------------------------------
756
* UtilAllocCStArrays --
758
* (Re-)Allocate data arrays for UtilReadSysCStRes and UtilReadProcCStRes.
761
* TRUE if successful.
766
*----------------------------------------------------------------------------
770
UtilAllocCStArrays(uint32 ncpus, // IN
771
uint32 nstates, // IN
772
uint64 **transitns, // OUT
773
uint64 **residency, // OUT
774
uint64 **transTime, // OUT
775
uint64 **residTime) // OUT
782
*transitns = calloc(nstates * ncpus, sizeof **transitns);
783
*residency = calloc(nstates * ncpus, sizeof **residency);
784
*transTime = calloc(ncpus, sizeof **transTime);
785
*residTime = calloc(ncpus, sizeof **residTime);
787
if (!*transitns || !*residency || !*transTime || !*residTime) {
792
Warning("%s: Cannot allocate memory for C-state queries\n",
803
*----------------------------------------------------------------------------
805
* UtilReadSysCStRes --
806
* UtilReadProcCStRes --
808
* Read the C-state residency statistics under /sys and /proc
809
* respectively. UtilReadSysCStRes should take precedence over
810
* UtilReadProcCStRes as /proc/acpi is getting replaced by sysfs
811
* in newer kernels. See Util_QueryCStResidency for description of
815
* TRUE if successful.
820
*----------------------------------------------------------------------------
824
UtilReadSysCStRes(DIR *dir, // IN
825
uint32 *numCpus, // IN/OUT
826
uint32 *numCStates, // IN/OUT
827
uint64 **transitns, // OUT
828
uint64 **residency, // OUT
829
uint64 **transTime, // OUT
830
uint64 **residTime) // OUT
832
struct dirent *cpuEntry;
834
struct dirent *cstateEntry;
835
char pathname[PATH_MAX + 1];
839
/* Determine the number of cpus and c-states. */
840
while ((cpuEntry = readdir(dir))) {
841
if (Str_Strncasecmp(cpuEntry->d_name, "cpu", 3) == 0 &&
842
isdigit(cpuEntry->d_name[3])) {
844
if (cl != 0) { /* already found the number of c states */
847
if (Str_Snprintf(pathname, sizeof pathname,
848
SYS_CSTATE_DIR"/%s/cpuidle",
849
cpuEntry->d_name) <= 0) {
850
LOG(0, ("%s: Str_Snprintf failed\n", __FUNCTION__));
854
cpuDir = Posix_OpenDir(pathname);
855
if (cpuDir != NULL) {
858
while ((cstateEntry = readdir(cpuDir))) {
859
if (Str_Strncasecmp(cstateEntry->d_name, "state", 5) == 0 &&
860
sscanf(cstateEntry->d_name + 5, "%u", &cnum) == 1 &&
862
cl = cnum; /* state0 will be ignored */
869
if (cpu == 0 || cl == 0) {
873
if (*numCpus != cpu || *numCStates != cl) {
874
if (!UtilAllocCStArrays(cpu, cl, transitns, residency, transTime,
884
while ((cpuEntry = readdir(dir))) {
888
if (Str_Strncasecmp(cpuEntry->d_name, "cpu", 3) != 0 ||
889
!isdigit(cpuEntry->d_name[3])) {
892
pathlen = Str_Snprintf(pathname, sizeof pathname,
893
SYS_CSTATE_DIR"/%s/cpuidle", cpuEntry->d_name);
895
LOG(0, ("%s: Str_Snprintf for '%s/cpuidle' failed\n", __FUNCTION__,
900
cpuDir = Posix_OpenDir(pathname);
901
if (cpuDir == NULL) {
902
LOG(0, ("%s: Failed to open directory %s\n", __FUNCTION__, pathname));
907
* Under the "cpuidle" directory, there is one "stateX" directory for
908
* each C-state. We ignore "state0", i.e. C0, which is the running state.
909
* Under each "stateX" directory, there is a "usage" file which contains
910
* the number of entries into that state, and a "time" file which
911
* contains the total residency in that state.
914
while ((cstateEntry = readdir(cpuDir))) {
919
if (Str_Strncasecmp(cstateEntry->d_name, "state", 5) != 0) {
922
if (sscanf(cstateEntry->d_name + 5, "%u", &cl) != 1 || cl == 0) {
925
cl--; /* ignoring state0 -- cl == 0 -> state1 */
926
index = *numCStates * cpu + cl;
928
if (Str_Snprintf(pathname + pathlen, sizeof pathname - pathlen,
929
"/%s/usage", cstateEntry->d_name) <= 0) {
930
LOG(0, ("%s: Str_Snprintf for 'usage' failed\n", __FUNCTION__));
935
statsFile = Posix_Fopen(pathname, "r");
936
if (statsFile == NULL) {
939
result = fscanf(statsFile, "%"FMT64"u", &(*transitns)[index]);
945
if (Str_Snprintf(pathname + pathlen, sizeof pathname - pathlen,
946
"/%s/time", cstateEntry->d_name) <= 0) {
947
LOG(0, ("%s: Str_Snprintf for 'time' failed\n", __FUNCTION__));
952
statsFile = Posix_Fopen(pathname, "r");
953
if (statsFile == NULL) {
956
result = fscanf(statsFile, "%"FMT64"u", &(*residency)[index]);
964
timeUS = Hostinfo_SystemTimerUS();
966
LOG(0, ("%s: Hostinfo_SystemTimerUS() failed\n", __FUNCTION__));
970
(*transTime)[cpu] = timeUS;
971
(*residTime)[cpu] = timeUS;
980
UtilReadProcCStRes(DIR *dir, // IN
981
uint32 *numCpus, // IN/OUT
982
uint32 *numCStates, // IN/OUT
983
uint64 **transitns, // OUT
984
uint64 **residency, // OUT
985
uint64 **transTime, // OUT
986
uint64 **residTime) // OUT
988
struct dirent *cpuEntry;
991
/* Determine the number of cpus. */
992
while ((cpuEntry = readdir(dir))) {
993
if (cpuEntry->d_name[0] != '.') {
1001
if (*numCpus != cpu) {
1003
* We do not know the number of C-states supported until we read the
1004
* file, so we allocate for MAX_C_STATES and determine *numCStates later.
1007
if (!UtilAllocCStArrays(cpu, MAX_C_STATES, transitns, residency,
1008
transTime, residTime)) {
1017
while ((cpuEntry = readdir(dir))) {
1018
char pathname[PATH_MAX + 1];
1025
if (cpuEntry->d_name[0] == '.') {
1028
if (Str_Snprintf(pathname, sizeof pathname, PROC_CSTATE_DIR"/%s/power",
1029
cpuEntry->d_name) <= 0) {
1030
LOG(0, ("%s: Str_Snprintf for '%s/power' failed\n", __FUNCTION__,
1035
powerFile = Posix_Fopen(pathname, "r");
1036
if (powerFile == NULL) {
1041
while (StdIO_ReadNextLine(powerFile, &line, 0,
1042
&lineSize) == StdIO_Success) {
1044
uint32 index = *numCStates * cpu + cl;
1046
if ((ptr = Str_Strnstr(line, "usage[", lineSize))) {
1047
sscanf(ptr + 6, "%"FMT64"u]", &(*transitns)[index]);
1048
if ((ptr = Str_Strnstr(line, "duration[", lineSize))) {
1049
sscanf(ptr + 9, "%"FMT64"u]", &(*residency)[index]);
1057
timeUS = Hostinfo_SystemTimerUS();
1059
LOG(0, ("%s: Hostinfo_SystemTimerUS() failed\n", __FUNCTION__));
1063
(*transTime)[cpu] = timeUS;
1064
(*residTime)[cpu] = (uint64)((double)timeUS * FREQ_ACPI);
1065
if (*numCStates == 0) {
1071
return cpu > 0 && *numCStates > 0;
1076
*----------------------------------------------------------------------------
1078
* Util_QueryCStResidency --
1080
* Query CPU's C-state residency statistics exposed by the host OS.
1081
* On Linux, this is done via either the sysfs or /proc/acpi interface.
1083
* The parameters transitns, residency, transTime and residTime are
1084
* pointers to uint64 arrays, whose dimensions are specified by
1085
* *numCpus and/or *numCStates:
1086
* transitns -- number of trasitions into each c-state for each CPU
1087
* residency -- time in each c-state for each CPU (in some opaque unit)
1088
* transTime -- timestamp (microseconds) for transitns data, per CPU
1089
* residTime -- timestamp for residency data, per CPU (in same unit as
1092
* If the dimensions specified are too small, the arrays are freed
1093
* and new memory allocated.
1096
* TRUE if successful.
1101
*----------------------------------------------------------------------------
1105
Util_QueryCStResidency(uint32 *numCpus, // IN/OUT
1106
uint32 *numCStates, // IN/OUT
1107
uint64 **transitns, // OUT
1108
uint64 **residency, // OUT
1109
uint64 **transTime, // OUT
1110
uint64 **residTime) // OUT
1115
dir = Posix_OpenDir(SYS_CSTATE_DIR);
1117
ret = UtilReadSysCStRes(dir, numCpus, numCStates, transitns, residency,
1118
transTime, residTime);
1123
dir = Posix_OpenDir(PROC_CSTATE_DIR);
1125
ret = UtilReadProcCStRes(dir, numCpus, numCStates, transitns,
1126
residency, transTime, residTime);
1134
#else // #if defined(__linux__) && !defined(VMX86_SERVER)
1137
Util_QueryCStResidency(uint32 *numCpus, // IN/OUT
1138
uint32 *numCStates, // IN/OUT
1139
uint64 **transitns, // OUT
1140
uint64 **residency, // OUT
1141
uint64 **transTime, // OUT
1142
uint64 **residTime) // OUT
1147
#endif // #if defined(VMX86_STATS)