VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/linux/mp-linux.cpp@ 10419

Last change on this file since 10419 was 10419, checked in by vboxsync, 17 years ago

Linux implementation of the RTMp* bits we current need in ring-3.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 8.0 KB
Line 
1/* $Id: mp-linux.cpp 10419 2008-07-09 13:46:17Z vboxsync $ */
2/** @file
3 * IPRT - Multiprocessor, Linux.
4 */
5
6/*
7 * Copyright (C) 2006-2008 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.215389.xyz. 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 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 *
26 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
27 * Clara, CA 95054 USA or visit http://www.sun.com if you need
28 * additional information or have any questions.
29 */
30
31
32/*******************************************************************************
33* Header Files *
34*******************************************************************************/
35#define LOG_GROUP RTLOGGROUP_SYSTEM
36#include <unistd.h>
37#include <stdio.h>
38#include <sys/sysctl.h>
39#include <sys/stat.h>
40#include <sys/fcntl.h>
41#include <errno.h>
42
43#include <iprt/mp.h>
44#include <iprt/cpuset.h>
45#include <iprt/assert.h>
46#include <iprt/string.h>
47
48
49/** @todo move the rtLinuxSysFs* bits into sysfs.cpp and sysfs.h. */
50
51/**
52 * Checks if a sysfs file (or directory, device, symlink, whatever) exists.
53 *
54 * @returns true / false, errno is preserved.
55 * @param pszFormat The name format, without "/sys/".
56 * @param va The format args.
57 */
58bool rtLinuxSysFsExistsV(const char *pszFormat, va_list va)
59{
60 int iSavedErrno = errno;
61
62 /*
63 * Construct the filename and call stat.
64 */
65 char szFilename[128];
66 static const size_t cchPrefix = sizeof("/sys/") - 1;
67 strcpy(szFilename, "/sys/");
68 size_t cch = RTStrPrintfV(&szFilename[cchPrefix], sizeof(szFilename) - cchPrefix, pszFormat, va);
69 Assert(cch < sizeof(szFilename) - cchPrefix - 1);
70
71 struct stat st;
72 bool fRet = stat(szFilename, &st) == 0;
73
74 errno = iSavedErrno;
75 return fRet;
76}
77
78/**
79 * Checks if a sysfs file (or directory, device, symlink, whatever) exists.
80 *
81 * @returns true / false, errno is preserved.
82 * @param pszFormat The name format, without "/sys/".
83 * @param ... The format args.
84 */
85bool rtLinuxSysFsExists(const char *pszFormat, ...)
86{
87 va_list va;
88 va_start(va, pszFormat);
89 bool fRet = rtLinuxSysFsExistsV(pszFormat, va);
90 va_end(va);
91 return fRet;
92}
93
94
95/**
96 * Opens a sysfs file.
97 *
98 * @returns The file descriptor. -1 and errno on failure.
99 * @param pszFormat The name format, without "/sys/".
100 * @param va The format args.
101 */
102int rtLinuxSysFsOpenV(const char *pszFormat, va_list va)
103{
104 /*
105 * Construct the filename and call open.
106 */
107 char szFilename[128];
108 static const size_t cchPrefix = sizeof("/sys/") - 1;
109 strcpy(szFilename, "/sys/");
110 size_t cch = RTStrPrintfV(&szFilename[cchPrefix], sizeof(szFilename) - cchPrefix, pszFormat, va);
111 Assert(cch < sizeof(szFilename) - cchPrefix - 1);
112
113 return open(szFilename, O_RDONLY, 0);
114}
115
116
117/**
118 * Opens a sysfs file.
119 *
120 * @returns The file descriptor. -1 and errno on failure.
121 * @param pszFormat The name format, without "/sys/".
122 * @param ... The format args.
123 */
124int rtLinuxSysFsOpen(const char *pszFormat, ...)
125{
126 va_list va;
127 va_start(va, pszFormat);
128 int fd = rtLinuxSysFsOpenV(pszFormat, va);
129 va_end(va);
130 return fd;
131}
132
133
134/**
135 * Closes a file opened with rtLinuxSysFsOpen or rtLinuxSysFsOpenV.
136 *
137 * @param fd
138 */
139void rtLinuxSysFsClose(int fd)
140{
141 int iSavedErrno = errno;
142 close(fd);
143 errno = iSavedErrno;
144}
145
146
147/**
148 * Closes a file opened with rtLinuxSysFsOpen or rtLinuxSysFsOpenV.
149 *
150 * @returns The number of bytes read. -1 and errno on failure.
151 * @param fd The file descriptor returned by rtLinuxSysFsOpen or rtLinuxSysFsOpenV.
152 * @param pszBuf Where to store the string.
153 * @param cchBuf The size of the buffer. Must be at least 2 bytes.
154 */
155ssize_t rtLinuxSysFsReadStr(int fd, char *pszBuf, size_t cchBuf)
156{
157 Assert(cchBuf > 1);
158 ssize_t cchRead = read(fd, pszBuf, cchBuf - 1);
159 pszBuf[cchRead >= 0 ? cchRead : 0] = '\0';
160 return cchRead;
161}
162
163
164/**
165 * Reads a sysfs file.
166 *
167 * @returns 64-bit signed value on success, -1 and errno on failure.
168 * @param uBase The number base, 0 for autodetect.
169 * @param pszFormat The filename format, without "/sys/".
170 * @param va Format args.
171 */
172int64_t rtLinuxSysFsReadIntFileV(unsigned uBase, const char *pszFormat, va_list va)
173{
174 int fd = rtLinuxSysFsOpenV(pszFormat, va);
175 if (fd == -1)
176 return -1;
177
178 int64_t i64Ret = -1;
179 char szNum[128];
180 ssize_t cchNum = rtLinuxSysFsReadStr(fd, szNum, sizeof(szNum));
181 if (cchNum > 0)
182 {
183 int rc = RTStrToInt64Ex(szNum, NULL, uBase, &i64Ret);
184 if (RT_FAILURE(rc))
185 {
186 i64Ret = -1;
187 errno = -ETXTBSY; /* just something that won't happen at read / open. */
188 }
189 }
190 else if (cchNum == 0)
191 errno = -ETXTBSY; /* just something that won't happen at read / open. */
192
193 rtLinuxSysFsClose(fd);
194 return i64Ret;
195}
196
197
198/**
199 * Reads a sysfs file.
200 *
201 * @returns 64-bit signed value on success, -1 and errno on failure.
202 * @param uBase The number base, 0 for autodetect.
203 * @param pszFormat The filename format, without "/sys/".
204 * @param ... Format args.
205 */
206static int64_t rtLinuxSysFsReadIntFile(unsigned uBase, const char *pszFormat, ...)
207{
208 va_list va;
209 va_start(va, pszFormat);
210 int64_t i64Ret = rtLinuxSysFsReadIntFileV(uBase, pszFormat, va);
211 va_end(va);
212 return i64Ret;
213}
214
215
216/**
217 * Internal worker that determins the max possible CPU count.
218 *
219 * @returns Max cpus.
220 */
221DECLINLINE(RTCPUID) rtMpLinuxMaxCpus(void)
222{
223 int cMax = sysconf(_SC_NPROCESSORS_CONF);
224 Assert(cMax >= 1);
225 return cMax;
226}
227
228
229/** @todo RTmpCpuId(). */
230
231RTDECL(int) RTMpCpuIdToSetIndex(RTCPUID idCpu)
232{
233 return idCpu < rtMpLinuxMaxCpus() ? idCpu : -1;
234}
235
236
237RTDECL(RTCPUID) RTMpCpuIdFromSetIndex(int iCpu)
238{
239 return (unsigned)iCpu < rtMpLinuxMaxCpus() ? iCpu : NIL_RTCPUID;
240}
241
242
243RTDECL(RTCPUID) RTMpGetMaxCpuId(void)
244{
245 return rtMpLinuxMaxCpus() - 1;
246}
247
248
249RTDECL(bool) RTMpIsCpuOnline(RTCPUID idCpu)
250{
251 /** @todo check if there is a simpler interface than this... */
252 int i = rtLinuxSysFsReadIntFile(0, "devices/system/cpu/cpu%d/online", (int)idCpu);
253 if ( i == -1
254 && rtLinuxSysFsExists("devices/system/cpu/cpu%d", (int)idCpu))
255 {
256 Assert(!rtLinuxSysFsExists("devices/system/cpu/cpu%d/online", (int)idCpu));
257 i = 1;
258 }
259
260 Assert(i == 0 || i == -1 || i == 1);
261 return i != 0 && i != -1;
262}
263
264
265RTDECL(bool) RTMpIsCpuPossible(RTCPUID idCpu)
266{
267 /** @todo check this up with hotplugging! */
268 return rtLinuxSysFsExists("devices/system/cpu/cpu%d", (int)idCpu);
269}
270
271
272RTDECL(PRTCPUSET) RTMpGetSet(PRTCPUSET pSet)
273{
274 RTCpuSetEmpty(pSet);
275 RTCPUID cMax = rtMpLinuxMaxCpus();
276 for (RTCPUID idCpu = 0; idCpu < cMax; idCpu++)
277 if (RTMpIsCpuPossible(idCpu))
278 RTCpuSetAdd(pSet, idCpu);
279 return pSet;
280}
281
282
283RTDECL(RTCPUID) RTMpGetCount(void)
284{
285 RTCPUSET Set;
286 RTMpGetSet(&Set);
287 return RTCpuSetCount(&Set);
288}
289
290
291RTDECL(PRTCPUSET) RTMpGetOnlineSet(PRTCPUSET pSet)
292{
293 RTCpuSetEmpty(pSet);
294 RTCPUID cMax = rtMpLinuxMaxCpus();
295 for (RTCPUID idCpu = 0; idCpu < cMax; idCpu++)
296 if (RTMpIsCpuOnline(idCpu))
297 RTCpuSetAdd(pSet, idCpu);
298 return pSet;
299}
300
301
302RTDECL(RTCPUID) RTMpGetOnlineCount(void)
303{
304 RTCPUSET Set;
305 RTMpGetOnlineSet(&Set);
306 return RTCpuSetCount(&Set);
307}
308
Note: See TracBrowser for help on using the repository browser.

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