VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/freebsd/mp-freebsd.cpp@ 54985

Last change on this file since 54985 was 54962, checked in by vboxsync, 10 years ago

On FreeBSD hosts use the correct semantics of the last parameter of sysctlbyname(). Thank you Jung-uk Kim.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 5.0 KB
Line 
1/* $Id: mp-freebsd.cpp 54962 2015-03-26 09:16:03Z vboxsync $ */
2/** @file
3 * IPRT - Multiprocessor, FreeBSD.
4 */
5
6/*
7 * Copyright (C) 2008-2011 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 * 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
27/*******************************************************************************
28* Header Files *
29*******************************************************************************/
30#define LOG_GROUP RTLOGGROUP_SYSTEM
31#include <unistd.h>
32#include <stdio.h>
33#include <errno.h>
34#include <sys/sysctl.h>
35
36#include <iprt/mp.h>
37#include <iprt/cpuset.h>
38#include <iprt/assert.h>
39#include <iprt/string.h>
40#include <iprt/alloc.h>
41#include <iprt/log.h>
42#include <iprt/once.h>
43#include <iprt/critsect.h>
44
45
46/**
47 * Internal worker that determines the max possible CPU count.
48 *
49 * @returns Max cpus.
50 */
51static RTCPUID rtMpFreeBsdMaxCpus(void)
52{
53 int aiMib[2];
54 aiMib[0] = CTL_HW;
55 aiMib[1] = HW_NCPU;
56 int cCpus = -1;
57 size_t cb = sizeof(cCpus);
58 int rc = sysctl(aiMib, RT_ELEMENTS(aiMib), &cCpus, &cb, NULL, 0);
59 if (rc != -1 && cCpus >= 1)
60 return cCpus;
61 AssertFailed();
62 return 1;
63}
64
65
66RTDECL(int) RTMpCpuIdToSetIndex(RTCPUID idCpu)
67{
68 return idCpu < RTCPUSET_MAX_CPUS && idCpu < rtMpFreeBsdMaxCpus() ? idCpu : -1;
69}
70
71
72RTDECL(RTCPUID) RTMpCpuIdFromSetIndex(int iCpu)
73{
74 return (unsigned)iCpu < rtMpFreeBsdMaxCpus() ? iCpu : NIL_RTCPUID;
75}
76
77
78RTDECL(RTCPUID) RTMpGetMaxCpuId(void)
79{
80 return rtMpFreeBsdMaxCpus() - 1;
81}
82
83
84RTDECL(bool) RTMpIsCpuOnline(RTCPUID idCpu)
85{
86 /*
87 * FreeBSD doesn't support CPU hotplugging so every CPU which appears
88 * in the tree is also online.
89 */
90 char szName[40];
91 RTStrPrintf(szName, sizeof(szName), "dev.cpu.%d.%%driver", (int)idCpu);
92
93 char szDriver[10];
94 size_t cbDriver = sizeof(szDriver);
95 RT_ZERO(szDriver); /* this shouldn't be necessary. */
96 int rcBsd = sysctlbyname(szName, szDriver, &cbDriver, NULL, 0);
97 if (rcBsd == 0)
98 return true;
99
100 return false;
101}
102
103
104RTDECL(bool) RTMpIsCpuPossible(RTCPUID idCpu)
105{
106 return idCpu != NIL_RTCPUID
107 && idCpu < rtMpFreeBsdMaxCpus();
108}
109
110
111RTDECL(PRTCPUSET) RTMpGetSet(PRTCPUSET pSet)
112{
113 RTCpuSetEmpty(pSet);
114 RTCPUID cMax = rtMpFreeBsdMaxCpus();
115 for (RTCPUID idCpu = 0; idCpu < cMax; idCpu++)
116 if (RTMpIsCpuPossible(idCpu))
117 RTCpuSetAdd(pSet, idCpu);
118 return pSet;
119}
120
121
122RTDECL(RTCPUID) RTMpGetCount(void)
123{
124 return rtMpFreeBsdMaxCpus();
125}
126
127
128RTDECL(PRTCPUSET) RTMpGetOnlineSet(PRTCPUSET pSet)
129{
130 RTCpuSetEmpty(pSet);
131 RTCPUID cMax = rtMpFreeBsdMaxCpus();
132 for (RTCPUID idCpu = 0; idCpu < cMax; idCpu++)
133 if (RTMpIsCpuOnline(idCpu))
134 RTCpuSetAdd(pSet, idCpu);
135 return pSet;
136}
137
138
139RTDECL(RTCPUID) RTMpGetOnlineCount(void)
140{
141 /*
142 * FreeBSD has sysconf.
143 */
144 return sysconf(_SC_NPROCESSORS_ONLN);
145}
146
147
148RTDECL(uint32_t) RTMpGetCurFrequency(RTCPUID idCpu)
149{
150 int uFreqCurr = 0;
151 size_t cbParameter = sizeof(uFreqCurr);
152
153 if (!RTMpIsCpuOnline(idCpu))
154 return 0;
155
156 /* CPU's have a common frequency. */
157 int rc = sysctlbyname("dev.cpu.0.freq", &uFreqCurr, &cbParameter, NULL, 0);
158 if (rc)
159 return 0;
160
161 return (uint32_t)uFreqCurr;
162}
163
164
165RTDECL(uint32_t) RTMpGetMaxFrequency(RTCPUID idCpu)
166{
167 char szFreqLevels[20]; /* Should be enough to get the highest level which is always the first. */
168 size_t cbFreqLevels = sizeof(szFreqLevels);
169
170 if (!RTMpIsCpuOnline(idCpu))
171 return 0;
172
173 memset(szFreqLevels, 0, sizeof(szFreqLevels));
174
175 /*
176 * CPU 0 has the freq levels entry. ENOMEM is ok as we don't need all supported
177 * levels but only the first one.
178 */
179 int rc = sysctlbyname("dev.cpu.0.freq_levels", szFreqLevels, &cbFreqLevels, NULL, 0);
180 if ( (rc && (errno != ENOMEM))
181 || (cbFreqLevels == 0))
182 return 0;
183
184 /* Clear everything starting from the '/' */
185 unsigned i = 0;
186
187 do
188 {
189 if (szFreqLevels[i] == '/')
190 {
191 memset(&szFreqLevels[i], 0, sizeof(szFreqLevels) - i);
192 break;
193 }
194 i++;
195 } while (i < sizeof(szFreqLevels));
196
197 /* Returns 0 on failure. */
198 return RTStrToUInt32(szFreqLevels);
199}
200
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