#include <string.h>
#include <unistd.h>
+#include "private/get_cpu_count_from_string.h"
#include "private/ScopedReaddir.h"
static bool __matches_cpuN(const char* s) {
}
int get_nprocs() {
- FILE* fp = fopen("/proc/stat", "re");
- if (fp == NULL) {
- return 1;
- }
-
- int result = 0;
- char buf[256];
- while (fgets(buf, sizeof(buf), fp) != NULL) {
- // Extract just the first word from the line.
- // 'cpu0 7976751 1364388 3116842 469770388 8629405 0 49047 0 0 0'
- char* p = strchr(buf, ' ');
- if (p != NULL) {
- *p = 0;
- }
- if (__matches_cpuN(buf)) {
- ++result;
+ int cpu_count = 1;
+ FILE* fp = fopen("/sys/devices/system/cpu/online", "re");
+ if (fp != nullptr) {
+ char* line = nullptr;
+ size_t len = 0;
+ if (getline(&line, &len, fp) != -1) {
+ cpu_count = GetCpuCountFromString(line);
+ free(line);
}
+ fclose(fp);
}
- fclose(fp);
- return result;
+ return cpu_count;
}
static int __get_meminfo_page_count(const char* pattern) {
--- /dev/null
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <ctype.h>
+#include <stdlib.h>
+
+// Parse a string like: 0, 2-4, 6.
+static int GetCpuCountFromString(const char* s) {
+ int cpu_count = 0;
+ int last_cpu = -1;
+ while (*s != '\0') {
+ if (isdigit(*s)) {
+ int cpu = static_cast<int>(strtol(s, const_cast<char**>(&s), 10));
+ if (last_cpu != -1) {
+ cpu_count += cpu - last_cpu;
+ } else {
+ cpu_count++;
+ }
+ last_cpu = cpu;
+ } else {
+ if (*s == ',') {
+ last_cpu = -1;
+ }
+ s++;
+ }
+ }
+ return cpu_count;
+}
#include <sys/wait.h>
#include <unistd.h>
+#include <base/file.h>
+#include <base/strings.h>
+
+#include "private/get_cpu_count_from_string.h"
+
static void* get_brk() {
return sbrk(0);
}
#endif // defined(__BIONIC__)
}
+TEST(unistd, get_cpu_count_from_string) {
+ ASSERT_EQ(0, GetCpuCountFromString(" "));
+ ASSERT_EQ(1, GetCpuCountFromString("0"));
+ ASSERT_EQ(40, GetCpuCountFromString("0-39"));
+ ASSERT_EQ(4, GetCpuCountFromString("0, 1-2, 4\n"));
+}
+
+TEST(unistd, sysconf_SC_NPROCESSORS_ONLN) {
+ std::string s;
+ ASSERT_TRUE(android::base::ReadFileToString("/sys/devices/system/cpu/online", &s));
+ std::vector<std::string> strs = android::base::Split(s, ",");
+ long online_cpus = 0;
+ for (auto& s : strs) {
+ std::vector<std::string> numbers = android::base::Split(s, "-");
+ if (numbers.size() == 1u) {
+ online_cpus++;
+ } else {
+ online_cpus += atoi(numbers[1].c_str()) - atoi(numbers[0].c_str()) + 1;
+ }
+ }
+ ASSERT_EQ(online_cpus, sysconf(_SC_NPROCESSORS_ONLN));
+}
+
TEST(unistd, dup2_same) {
// POSIX says of dup2:
// If fildes2 is already a valid open file descriptor ...