Changeset 15399 in vbox for trunk/src/VBox/Runtime/r3/linux
- Timestamp:
- Dec 12, 2008 10:02:14 PM (16 years ago)
- Location:
- trunk/src/VBox/Runtime/r3/linux
- Files:
-
- 1 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r3/linux/mp-linux.cpp
r10482 r15399 34 34 *******************************************************************************/ 35 35 #define LOG_GROUP RTLOGGROUP_SYSTEM 36 #include <unistd.h>37 36 #include <stdio.h> 38 #include <sys/sysctl.h>39 #include <sys/stat.h>40 #include <sys/fcntl.h>41 37 #include <errno.h> 42 38 … … 45 41 #include <iprt/assert.h> 46 42 #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 */ 58 bool 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); NOREF(cch); 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 */ 85 bool 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 */ 102 int 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); NOREF(cch); 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 */ 124 int 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 */ 139 void 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 */ 155 ssize_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 */ 172 int64_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 */ 206 static 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 } 43 #include <iprt/linux/sysfs.h> 214 44 215 45 … … 231 61 int cMax = 1; 232 62 for (unsigned iCpu = 0; iCpu < RTCPUSET_MAX_CPUS; iCpu++) 233 if ( rtLinuxSysFsExists("devices/system/cpu/cpu%d", iCpu))63 if (RTLinuxSysFsExists("devices/system/cpu/cpu%d", iCpu)) 234 64 cMax = iCpu + 1; 235 65 ASMAtomicUoWriteU32((uint32_t volatile *)&s_cMax, cMax); … … 310 140 { 311 141 /** @todo check if there is a simpler interface than this... */ 312 int i = rtLinuxSysFsReadIntFile(0, "devices/system/cpu/cpu%d/online", (int)idCpu);142 int i = RTLinuxSysFsReadIntFile(0, "devices/system/cpu/cpu%d/online", (int)idCpu); 313 143 if ( i == -1 314 && rtLinuxSysFsExists("devices/system/cpu/cpu%d", (int)idCpu))315 { 316 Assert(! rtLinuxSysFsExists("devices/system/cpu/cpu%d/online", (int)idCpu));144 && RTLinuxSysFsExists("devices/system/cpu/cpu%d", (int)idCpu)) 145 { 146 Assert(!RTLinuxSysFsExists("devices/system/cpu/cpu%d/online", (int)idCpu)); 317 147 i = 1; 318 148 } … … 326 156 { 327 157 /** @todo check this up with hotplugging! */ 328 return rtLinuxSysFsExists("devices/system/cpu/cpu%d", (int)idCpu);158 return RTLinuxSysFsExists("devices/system/cpu/cpu%d", (int)idCpu); 329 159 } 330 160 … … 370 200 RTDECL(uint32_t) RTMpGetCurFrequency(RTCPUID idCpu) 371 201 { 372 int64_t kHz = rtLinuxSysFsReadIntFile(0, "devices/system/cpu/cpu%d/cpufreq/cpuinfo_cur_freq", (int)idCpu);202 int64_t kHz = RTLinuxSysFsReadIntFile(0, "devices/system/cpu/cpu%d/cpufreq/cpuinfo_cur_freq", (int)idCpu); 373 203 if (kHz == -1) 374 204 { … … 388 218 RTDECL(uint32_t) RTMpGetMaxFrequency(RTCPUID idCpu) 389 219 { 390 int64_t kHz = rtLinuxSysFsReadIntFile(0, "devices/system/cpu/cpu%d/cpufreq/cpuinfo_max_freq", (int)idCpu);220 int64_t kHz = RTLinuxSysFsReadIntFile(0, "devices/system/cpu/cpu%d/cpufreq/cpuinfo_max_freq", (int)idCpu); 391 221 if (kHz == -1) 392 222 { … … 395 225 * would provide current frequency information, which is wrong. 396 226 */ 397 if (! rtLinuxSysFsExists("devices/system/cpu/cpu%d/cpufreq/cpuinfo_max_freq", (int)idCpu))227 if (!RTLinuxSysFsExists("devices/system/cpu/cpu%d/cpufreq/cpuinfo_max_freq", (int)idCpu)) 398 228 kHz = rtMpLinuxGetFrequency(idCpu) * 1000; 399 229 else -
trunk/src/VBox/Runtime/r3/linux/sysfs.cpp
r14990 r15399 1 1 /* $Id$ */ 2 2 /** @file 3 * IPRT - Multiprocessor, Linux.3 * IPRT - Linux sysfs access. 4 4 */ 5 5 … … 41 41 #include <errno.h> 42 42 43 #include <iprt/mp.h> 44 #include <iprt/cpuset.h> 43 #include <iprt/linux/sysfs.h> 45 44 #include <iprt/assert.h> 45 #include <iprt/param.h> 46 46 #include <iprt/string.h> 47 47 48 48 49 /** @todo move the rtLinuxSysFs* bits into sysfs.cpp and sysfs.h. */ 49 /** 50 * Constructs the path of a sysfs file from the format paramaters passed, 51 * prepending "/sys/" if the path is relative. 52 * 53 * @returns The number of characters written, or -1 and errno on failure. 54 * @param pszBuf Where to write the path. Must be at least 55 * sizeof("/sys/") characters long 56 * @param cchBuf The size of the buffer pointed to by @a pszBuf 57 * @param pszFormat The name format, either absolute or relative to "/sys/". 58 * @param va The format args. 59 */ 60 static ssize_t rtLinuxSysFsConstructPath(char *pszBuf, size_t cchBuf, 61 const char *pszFormat, va_list va) 62 { 63 char szFilename[RTPATH_MAX]; 64 const char szPrefix[] = "/sys/"; 65 if (cchBuf < sizeof(szPrefix)) 66 AssertFailedReturnStmt(errno = EINVAL, -1); 67 size_t cch = RTStrPrintfV(szFilename, sizeof(szFilename), pszFormat, va); 68 if (szFilename[0] == '/') 69 *pszBuf = '\0'; 70 else 71 strcpy(pszBuf, szPrefix); 72 strncat(pszBuf, szFilename, cchBuf); 73 return strlen(pszBuf); 74 } 50 75 51 76 /** … … 53 78 * 54 79 * @returns true / false, errno is preserved. 55 * @param pszFormat The name format, without"/sys/".80 * @param pszFormat The name format, either absolute or relative to "/sys/". 56 81 * @param va The format args. 57 82 */ 58 bool rtLinuxSysFsExistsV(const char *pszFormat, va_list va)83 bool RTLinuxSysFsExistsV(const char *pszFormat, va_list va) 59 84 { 60 85 int iSavedErrno = errno; … … 63 88 * Construct the filename and call stat. 64 89 */ 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); NOREF(cch); 70 71 struct stat st; 72 bool fRet = stat(szFilename, &st) == 0; 90 char szFilename[RTPATH_MAX]; 91 bool fRet = false; 92 ssize_t rc = rtLinuxSysFsConstructPath(szFilename, sizeof(szFilename), 93 pszFormat, va); 94 if (rc > 0 && static_cast<size_t>(rc) < sizeof(szFilename)) 95 { 96 struct stat st; 97 fRet = stat(szFilename, &st) == 0; 98 } 73 99 74 100 errno = iSavedErrno; … … 80 106 * 81 107 * @returns true / false, errno is preserved. 82 * @param pszFormat The name format, without"/sys/".108 * @param pszFormat The name format, either absolute or relative to "/sys/". 83 109 * @param ... The format args. 84 110 */ 85 bool rtLinuxSysFsExists(const char *pszFormat, ...)86 { 87 va_list va; 88 va_start(va, pszFormat); 89 bool fRet = rtLinuxSysFsExistsV(pszFormat, va);111 bool RTLinuxSysFsExists(const char *pszFormat, ...) 112 { 113 va_list va; 114 va_start(va, pszFormat); 115 bool fRet = RTLinuxSysFsExistsV(pszFormat, va); 90 116 va_end(va); 91 117 return fRet; … … 97 123 * 98 124 * @returns The file descriptor. -1 and errno on failure. 99 * @param pszFormat The name format, without"/sys/".125 * @param pszFormat The name format, either absolute or relative to "/sys/". 100 126 * @param va The format args. 101 127 */ 102 int rtLinuxSysFsOpenV(const char *pszFormat, va_list va)128 int RTLinuxSysFsOpenV(const char *pszFormat, va_list va) 103 129 { 104 130 /* 105 131 * Construct the filename and call open. 106 132 */ 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); NOREF(cch); 112 113 return open(szFilename, O_RDONLY, 0); 133 char szFilename[RTPATH_MAX]; 134 ssize_t rc = rtLinuxSysFsConstructPath(szFilename, sizeof(szFilename), 135 pszFormat, va); 136 if (rc > 0 && static_cast<size_t>(rc) < sizeof(szFilename)) 137 rc = open(szFilename, O_RDONLY, 0); 138 return rc; 114 139 } 115 140 … … 119 144 * 120 145 * @returns The file descriptor. -1 and errno on failure. 121 * @param pszFormat The name format, without"/sys/".146 * @param pszFormat The name format, either absolute or relative to "/sys/". 122 147 * @param ... The format args. 123 148 */ 124 int rtLinuxSysFsOpen(const char *pszFormat, ...)125 { 126 va_list va; 127 va_start(va, pszFormat); 128 int fd = rtLinuxSysFsOpenV(pszFormat, va);149 int RTLinuxSysFsOpen(const char *pszFormat, ...) 150 { 151 va_list va; 152 va_start(va, pszFormat); 153 int fd = RTLinuxSysFsOpenV(pszFormat, va); 129 154 va_end(va); 130 155 return fd; … … 133 158 134 159 /** 135 * Closes a file opened with rtLinuxSysFsOpen or rtLinuxSysFsOpenV.160 * Closes a file opened with RTLinuxSysFsOpen or RTLinuxSysFsOpenV. 136 161 * 137 162 * @param fd 138 163 */ 139 void rtLinuxSysFsClose(int fd)164 void RTLinuxSysFsClose(int fd) 140 165 { 141 166 int iSavedErrno = errno; … … 146 171 147 172 /** 148 * Closes a file opened with rtLinuxSysFsOpen or rtLinuxSysFsOpenV.173 * Reads a string from a file opened with RTLinuxSysFsOpen or RTLinuxSysFsOpenV. 149 174 * 150 175 * @returns The number of bytes read. -1 and errno on failure. 151 * @param fd The file descriptor returned by rtLinuxSysFsOpen or rtLinuxSysFsOpenV.176 * @param fd The file descriptor returned by RTLinuxSysFsOpen or RTLinuxSysFsOpenV. 152 177 * @param pszBuf Where to store the string. 153 178 * @param cchBuf The size of the buffer. Must be at least 2 bytes. 154 179 */ 155 ssize_t rtLinuxSysFsReadStr(int fd, char *pszBuf, size_t cchBuf)180 ssize_t RTLinuxSysFsReadStr(int fd, char *pszBuf, size_t cchBuf) 156 181 { 157 182 Assert(cchBuf > 1); … … 163 188 164 189 /** 165 * Reads a sysfs file.190 * Reads a number from a sysfs file. 166 191 * 167 192 * @returns 64-bit signed value on success, -1 and errno on failure. 168 193 * @param uBase The number base, 0 for autodetect. 169 * @param pszFormat The filename format, without"/sys/".194 * @param pszFormat The filename format, either absolute or relative to "/sys/". 170 195 * @param va Format args. 171 196 */ 172 int64_t rtLinuxSysFsReadIntFileV(unsigned uBase, const char *pszFormat, va_list va)173 { 174 int fd = rtLinuxSysFsOpenV(pszFormat, va);197 int64_t RTLinuxSysFsReadIntFileV(unsigned uBase, const char *pszFormat, va_list va) 198 { 199 int fd = RTLinuxSysFsOpenV(pszFormat, va); 175 200 if (fd == -1) 176 201 return -1; … … 178 203 int64_t i64Ret = -1; 179 204 char szNum[128]; 180 ssize_t cchNum = rtLinuxSysFsReadStr(fd, szNum, sizeof(szNum));205 ssize_t cchNum = RTLinuxSysFsReadStr(fd, szNum, sizeof(szNum)); 181 206 if (cchNum > 0) 182 207 { … … 191 216 errno = -ETXTBSY; /* just something that won't happen at read / open. */ 192 217 193 rtLinuxSysFsClose(fd);218 RTLinuxSysFsClose(fd); 194 219 return i64Ret; 195 220 } … … 197 222 198 223 /** 199 * Reads a sysfs file.224 * Reads a number from a sysfs file. 200 225 * 201 226 * @returns 64-bit signed value on success, -1 and errno on failure. 202 227 * @param uBase The number base, 0 for autodetect. 203 * @param pszFormat The filename format, without"/sys/".228 * @param pszFormat The filename format, either absolute or relative to "/sys/". 204 229 * @param ... Format args. 205 230 */ 206 static 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);231 int64_t RTLinuxSysFsReadIntFile(unsigned uBase, const char *pszFormat, ...) 232 { 233 va_list va; 234 va_start(va, pszFormat); 235 int64_t i64Ret = RTLinuxSysFsReadIntFileV(uBase, pszFormat, va); 211 236 va_end(va); 212 237 return i64Ret; … … 215 240 216 241 /** 217 * Internal worker that determins the max possible CPU count. 218 * 219 * @returns Max cpus. 220 */ 221 static RTCPUID rtMpLinuxMaxCpus(void) 222 { 223 #if 0 /* this doesn't do the right thing :-/ */ 224 int cMax = sysconf(_SC_NPROCESSORS_CONF); 225 Assert(cMax >= 1); 226 return cMax; 227 #else 228 static uint32_t s_cMax = 0; 229 if (!s_cMax) 230 { 231 int cMax = 1; 232 for (unsigned iCpu = 0; iCpu < RTCPUSET_MAX_CPUS; iCpu++) 233 if (rtLinuxSysFsExists("devices/system/cpu/cpu%d", iCpu)) 234 cMax = iCpu + 1; 235 ASMAtomicUoWriteU32((uint32_t volatile *)&s_cMax, cMax); 236 return cMax; 237 } 238 return s_cMax; 239 #endif 240 } 241 242 /** 243 * Internal worker that picks the processor speed in MHz from /proc/cpuinfo. 244 * 245 * @returns CPU frequency. 246 */ 247 static uint32_t rtMpLinuxGetFrequency(RTCPUID idCpu) 248 { 249 FILE *pFile = fopen("/proc/cpuinfo", "r"); 250 if (!pFile) 251 return 0; 252 253 char sz[256]; 254 RTCPUID idCpuFound = NIL_RTCPUID; 255 uint32_t Frequency = 0; 256 while (fgets(sz, sizeof(sz), pFile)) 257 { 258 char *psz; 259 if ( !strncmp(sz, "processor", 9) 260 && (sz[10] == ' ' || sz[10] == '\t' || sz[10] == ':') 261 && (psz = strchr(sz, ':'))) 262 { 263 psz += 2; 264 int64_t iCpu; 265 int rc = RTStrToInt64Ex(psz, NULL, 0, &iCpu); 266 if (RT_SUCCESS(rc)) 267 idCpuFound = iCpu; 268 } 269 else if ( idCpu == idCpuFound 270 && !strncmp(sz, "cpu MHz", 7) 271 && (sz[10] == ' ' || sz[10] == '\t' || sz[10] == ':') 272 && (psz = strchr(sz, ':'))) 273 { 274 psz += 2; 275 int64_t v; 276 int rc = RTStrToInt64Ex(psz, &psz, 0, &v); 277 if (RT_SUCCESS(rc)) 278 { 279 Frequency = v; 280 break; 281 } 282 } 283 } 284 fclose(pFile); 285 return Frequency; 286 } 287 288 289 /** @todo RTmpCpuId(). */ 290 291 RTDECL(int) RTMpCpuIdToSetIndex(RTCPUID idCpu) 292 { 293 return idCpu < rtMpLinuxMaxCpus() ? idCpu : -1; 294 } 295 296 297 RTDECL(RTCPUID) RTMpCpuIdFromSetIndex(int iCpu) 298 { 299 return (unsigned)iCpu < rtMpLinuxMaxCpus() ? iCpu : NIL_RTCPUID; 300 } 301 302 303 RTDECL(RTCPUID) RTMpGetMaxCpuId(void) 304 { 305 return rtMpLinuxMaxCpus() - 1; 306 } 307 308 309 RTDECL(bool) RTMpIsCpuOnline(RTCPUID idCpu) 310 { 311 /** @todo check if there is a simpler interface than this... */ 312 int i = rtLinuxSysFsReadIntFile(0, "devices/system/cpu/cpu%d/online", (int)idCpu); 313 if ( i == -1 314 && rtLinuxSysFsExists("devices/system/cpu/cpu%d", (int)idCpu)) 315 { 316 Assert(!rtLinuxSysFsExists("devices/system/cpu/cpu%d/online", (int)idCpu)); 317 i = 1; 318 } 319 320 Assert(i == 0 || i == -1 || i == 1); 321 return i != 0 && i != -1; 322 } 323 324 325 RTDECL(bool) RTMpIsCpuPossible(RTCPUID idCpu) 326 { 327 /** @todo check this up with hotplugging! */ 328 return rtLinuxSysFsExists("devices/system/cpu/cpu%d", (int)idCpu); 329 } 330 331 332 RTDECL(PRTCPUSET) RTMpGetSet(PRTCPUSET pSet) 333 { 334 RTCpuSetEmpty(pSet); 335 RTCPUID cMax = rtMpLinuxMaxCpus(); 336 for (RTCPUID idCpu = 0; idCpu < cMax; idCpu++) 337 if (RTMpIsCpuPossible(idCpu)) 338 RTCpuSetAdd(pSet, idCpu); 339 return pSet; 340 } 341 342 343 RTDECL(RTCPUID) RTMpGetCount(void) 344 { 345 RTCPUSET Set; 346 RTMpGetSet(&Set); 347 return RTCpuSetCount(&Set); 348 } 349 350 351 RTDECL(PRTCPUSET) RTMpGetOnlineSet(PRTCPUSET pSet) 352 { 353 RTCpuSetEmpty(pSet); 354 RTCPUID cMax = rtMpLinuxMaxCpus(); 355 for (RTCPUID idCpu = 0; idCpu < cMax; idCpu++) 356 if (RTMpIsCpuOnline(idCpu)) 357 RTCpuSetAdd(pSet, idCpu); 358 return pSet; 359 } 360 361 362 RTDECL(RTCPUID) RTMpGetOnlineCount(void) 363 { 364 RTCPUSET Set; 365 RTMpGetOnlineSet(&Set); 366 return RTCpuSetCount(&Set); 367 } 368 369 370 RTDECL(uint32_t) RTMpGetCurFrequency(RTCPUID idCpu) 371 { 372 int64_t kHz = rtLinuxSysFsReadIntFile(0, "devices/system/cpu/cpu%d/cpufreq/cpuinfo_cur_freq", (int)idCpu); 373 if (kHz == -1) 374 { 375 /* 376 * The file may be just unreadable - in that case use plan B, i.e. 377 * /proc/cpuinfo to get the data we want. The assumption is that if 378 * cpuinfo_cur_freq doesn't exist then the speed won't change, and 379 * thus cur == max. If it does exist then cpuinfo contains the 380 * current frequency. 381 */ 382 kHz = rtMpLinuxGetFrequency(idCpu) * 1000; 383 } 384 return (kHz + 999) / 1000; 385 } 386 387 388 RTDECL(uint32_t) RTMpGetMaxFrequency(RTCPUID idCpu) 389 { 390 int64_t kHz = rtLinuxSysFsReadIntFile(0, "devices/system/cpu/cpu%d/cpufreq/cpuinfo_max_freq", (int)idCpu); 391 if (kHz == -1) 392 { 393 /* 394 * Check if the file isn't there - if it is there, then /proc/cpuinfo 395 * would provide current frequency information, which is wrong. 396 */ 397 if (!rtLinuxSysFsExists("devices/system/cpu/cpu%d/cpufreq/cpuinfo_max_freq", (int)idCpu)) 398 kHz = rtMpLinuxGetFrequency(idCpu) * 1000; 399 else 400 kHz = 0; 401 } 402 return (kHz + 999) / 1000; 403 } 242 * Reads a string from a sysfs file. If the file contains a newline, we only 243 * return the text up until there. 244 * 245 * @returns number of characters read on success, -1 and errno on failure. 246 * @param pszBuf Where to store the path element. Must be at least two 247 * characters, but a longer buffer would be advisable. 248 * @param cchBuf The size of the buffer pointed to by @a pszBuf. 249 * @param pszFormat The filename format, either absolute or relative to "/sys/". 250 * @param va Format args. 251 */ 252 ssize_t RTLinuxSysFsReadStrFileV(char *pszBuf, size_t cchBuf, const char *pszFormat, va_list va) 253 { 254 int fd = RTLinuxSysFsOpenV(pszFormat, va); 255 if (fd == -1) 256 return -1; 257 258 ssize_t cchRet = RTLinuxSysFsReadStr(fd, pszBuf, cchBuf); 259 RTLinuxSysFsClose(fd); 260 char *pchNewLine = NULL; 261 if (cchRet > 0) 262 pchNewLine = reinterpret_cast<char *>(memchr(pszBuf, '\n', cchRet)); 263 if (pchNewLine != NULL) 264 *pchNewLine = '\0'; 265 return cchRet; 266 } 267 268 269 /** 270 * Reads a string from a sysfs file. If the file contains a newline, we only 271 * return the text up until there. 272 * 273 * @returns number of characters read on success, -1 and errno on failure. 274 * @param pszBuf Where to store the path element. Must be at least two 275 * characters, but a longer buffer would be advisable. 276 * @param cchBuf The size of the buffer pointed to by @a pszBuf. 277 * @param pszFormat The filename format, either absolute or relative to "/sys/". 278 * @param ... Format args. 279 */ 280 ssize_t RTLinuxSysFsReadStrFile(char *pszBuf, size_t cchBuf, const char *pszFormat, ...) 281 { 282 va_list va; 283 va_start(va, pszFormat); 284 ssize_t cchRet = RTLinuxSysFsReadStrFileV(pszBuf, cchBuf, pszFormat, va); 285 va_end(va); 286 return cchRet; 287 } 288 289 290 /** 291 * Reads the last element of the path of the file pointed to by the symbolic 292 * link specified. This is needed at least to get the name of the driver 293 * associated with a device, where pszFormat should be the "driver" link in the 294 * devices sysfs directory. 295 * 296 * @returns The number of characters written on success, -1 and errno on failure. 297 * @param pszBuf Where to store the path element. Must be at least two 298 * characters, but a longer buffer would be advisable. 299 * @param cchBuf The size of the buffer pointed to by @a pszBuf. 300 * @param pszFormat The filename format, either absolute or relative to "/sys/". 301 * @param ... Format args. 302 */ 303 int RTLinuxSysFsGetLinkDest(char *pszBuf, size_t cchBuf, const char *pszFormat, ...) 304 { 305 if (cchBuf < 2) 306 AssertFailedReturnStmt(errno = EINVAL, -1); 307 va_list va; 308 va_start(va, pszFormat); 309 char szFilename[RTPATH_MAX], szLink[RTPATH_MAX]; 310 int rc = rtLinuxSysFsConstructPath(szFilename, sizeof(szFilename), pszFormat, va); 311 va_end(va); 312 if (rc == sizeof(szFilename)) 313 { 314 rc = -1; 315 errno = EINVAL; /* Bad format arguements */ 316 } 317 if (rc > 0) 318 rc = readlink(szFilename, szLink, sizeof(szLink)); 319 if (rc > 0 && static_cast<size_t>(rc) > sizeof(szLink) - 1) 320 { 321 rc = -1; 322 errno = EIO; /* The path name can't be this big. */ 323 } 324 if (rc >= 0) 325 { 326 szLink[rc] = '\0'; 327 char *lastPart = strrchr(szLink, '/'); 328 Assert(lastPart != NULL); /* rtLinuxSysFsConstructPath guarantees a path 329 * starting with '/'. */ 330 *pszBuf = '\0'; 331 strncat(pszBuf, lastPart + 1, cchBuf); 332 rc = strlen(pszBuf); 333 } 334 return rc; 335 } 336
Note:
See TracChangeset
for help on using the changeset viewer.