aboutsummaryrefslogtreecommitdiff
path: root/src/linux/processors.c
diff options
context:
space:
mode:
authorMarat Dukhan <marat@fb.com>2017-08-09 13:49:39 -0700
committerMarat Dukhan <marat@fb.com>2017-08-09 13:49:39 -0700
commita8fb3dd0aa41013e8ec5c93900a1c81e26ef6552 (patch)
tree79de3423eb2c5c76bae4ba04c8f3f7e4973dd8ea /src/linux/processors.c
parent43576d6ca7c58e9931d068c2e5f878611f55eb2b (diff)
downloadcpuinfo-a8fb3dd0aa41013e8ec5c93900a1c81e26ef6552.tar.gz
Detect big.LITTLE ARM systems
Diffstat (limited to 'src/linux/processors.c')
-rw-r--r--src/linux/processors.c484
1 files changed, 484 insertions, 0 deletions
diff --git a/src/linux/processors.c b/src/linux/processors.c
new file mode 100644
index 0000000..1234657
--- /dev/null
+++ b/src/linux/processors.c
@@ -0,0 +1,484 @@
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if !defined(__ANDROID__)
+ /*
+ * sched.h is only used for CPU_SETSIZE constant.
+ * Android NDK headers before platform 21 do have this constant in sched.h
+ */
+ #include <sched.h>
+#endif
+
+#include <linux/api.h>
+#include <log.h>
+
+
+#define STRINGIFY(token) #token
+
+#define KERNEL_MAX_FILENAME "/sys/devices/system/cpu/kernel_max"
+#define KERNEL_MAX_FILESIZE 32
+#define FREQUENCY_FILENAME_SIZE (sizeof("/sys/devices/system/cpu/cpu" STRINGIFY(UINT32_MAX) "/cpufreq/cpuinfo_max_freq"))
+#define MAX_FREQUENCY_FILENAME_FORMAT "/sys/devices/system/cpu/cpu%" PRIu32 "/cpufreq/cpuinfo_max_freq"
+#define MIN_FREQUENCY_FILENAME_FORMAT "/sys/devices/system/cpu/cpu%" PRIu32 "/cpufreq/cpuinfo_min_freq"
+#define FREQUENCY_FILESIZE 32
+#define PACKAGE_ID_FILENAME_SIZE (sizeof("/sys/devices/system/cpu/cpu" STRINGIFY(UINT32_MAX) "/topology/physical_package_id"))
+#define PACKAGE_ID_FILENAME_FORMAT "/sys/devices/system/cpu/cpu%" PRIu32 "/topology/physical_package_id"
+#define PACKAGE_ID_FILESIZE 32
+#define CORE_ID_FILENAME_SIZE (sizeof("/sys/devices/system/cpu/cpu" STRINGIFY(UINT32_MAX) "/topology/core_id"))
+#define CORE_ID_FILENAME_FORMAT "/sys/devices/system/cpu/cpu%" PRIu32 "/topology/core_id"
+#define CORE_ID_FILESIZE 32
+
+#define CORE_SIBLINGS_FILENAME_SIZE (sizeof("/sys/devices/system/cpu/cpu" STRINGIFY(UINT32_MAX) "/topology/core_siblings_list"))
+#define CORE_SIBLINGS_FILENAME_FORMAT "/sys/devices/system/cpu/cpu%" PRIu32 "/topology/core_siblings_list"
+#define THREAD_SIBLINGS_FILENAME_SIZE (sizeof("/sys/devices/system/cpu/cpu" STRINGIFY(UINT32_MAX) "/topology/thread_siblings_list"))
+#define THREAD_SIBLINGS_FILENAME_FORMAT "/sys/devices/system/cpu/cpu%" PRIu32 "/topology/thread_siblings_list"
+
+#define POSSIBLE_CPULIST_FILENAME "/sys/devices/system/cpu/possible"
+#define PRESENT_CPULIST_FILENAME "/sys/devices/system/cpu/present"
+
+
+inline static const char* parse_number(const char* string, const char* end, uint32_t number_ptr[restrict static 1]) {
+ uint32_t number = 0;
+ while (string != end) {
+ const uint32_t digit = (uint32_t) (*string) - (uint32_t) '0';
+ if (digit >= 10) {
+ break;
+ }
+ number = number * UINT32_C(10) + digit;
+ string += 1;
+ }
+ *number_ptr = number;
+ return end;
+}
+
+/* Locale-independent */
+inline static bool is_whitespace(char c) {
+ switch (c) {
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\r':
+ return true;
+ default:
+ return false;
+ }
+}
+
+#if defined(__ANDROID__) && !defined(CPU_SETSIZE)
+ /*
+ * Android NDK headers before platform 21 do not define CPU_SETSIZE,
+ * so we hard-code its value, as defined in platform 21 headers
+ */
+ #if defined(__LP64__)
+ static const uint32_t default_max_processors_count = 1024;
+ #else
+ static const uint32_t default_max_processors_count = 32;
+ #endif
+#else
+ static const uint32_t default_max_processors_count = CPU_SETSIZE;
+#endif
+
+static bool uint32_parser(const char* text_start, const char* text_end, void* context) {
+ if (text_start == text_end) {
+ cpuinfo_log_error("failed to parse file %s: file is empty", KERNEL_MAX_FILENAME);
+ return false;
+ }
+
+ uint32_t kernel_max = 0;
+ const char* parsed_end = parse_number(text_start, text_end, &kernel_max);
+ if (parsed_end == text_start) {
+ cpuinfo_log_error("failed to parse file %s: \"%*.s\" is not an unsigned number",
+ KERNEL_MAX_FILENAME, (int) (text_end - text_start), text_start);
+ return false;
+ } else {
+ for (const char* char_ptr = parsed_end; char_ptr != text_end; char_ptr++) {
+ if (!is_whitespace(*char_ptr)) {
+ cpuinfo_log_warning("non-whitespace characters \"%*.s\" following number in file %s are ignored",
+ (int) (text_end - char_ptr), char_ptr, KERNEL_MAX_FILENAME);
+ break;
+ }
+ }
+ }
+
+ uint32_t* kernel_max_ptr = (uint32_t*) context;
+ *kernel_max_ptr = kernel_max;
+ return true;
+}
+
+uint32_t cpuinfo_linux_get_max_processors_count(void) {
+ uint32_t kernel_max;
+ if (cpuinfo_linux_parse_small_file(KERNEL_MAX_FILENAME, KERNEL_MAX_FILESIZE, uint32_parser, &kernel_max)) {
+ cpuinfo_log_debug("parsed kernel_max value of %"PRIu32" from %s", kernel_max, KERNEL_MAX_FILENAME);
+
+ if (kernel_max >= default_max_processors_count) {
+ cpuinfo_log_warning("kernel_max value of %"PRIu32" parsed from %s exceeds platform-default limit %"PRIu32,
+ kernel_max, KERNEL_MAX_FILENAME, default_max_processors_count - 1);
+ }
+
+ return kernel_max + 1;
+ } else {
+ cpuinfo_log_warning("using platform-default max processors count = %"PRIu32, default_max_processors_count);
+ return default_max_processors_count;
+ }
+}
+
+uint32_t cpuinfo_linux_get_processor_max_frequency(uint32_t processor) {
+ char max_frequency_filename[FREQUENCY_FILENAME_SIZE];
+ const int chars_formatted = snprintf(
+ max_frequency_filename, FREQUENCY_FILENAME_SIZE, MAX_FREQUENCY_FILENAME_FORMAT, processor);
+ if ((unsigned int) chars_formatted >= FREQUENCY_FILENAME_SIZE) {
+ cpuinfo_log_warning("failed to format filename for max frequency of processor %"PRIu32, processor);
+ return 0;
+ }
+
+ uint32_t max_frequency;
+ if (cpuinfo_linux_parse_small_file(max_frequency_filename, FREQUENCY_FILESIZE, uint32_parser, &max_frequency)) {
+ cpuinfo_log_debug("parsed max frequency value of %"PRIu32" KHz for logical processor %"PRIu32" from %s",
+ max_frequency, processor, max_frequency_filename);
+ return max_frequency;
+ } else {
+ cpuinfo_log_warning("failed to parse max frequency for processor %"PRIu32" from %s",
+ processor, max_frequency_filename);
+ return 0;
+ }
+}
+
+uint32_t cpuinfo_linux_get_processor_min_frequency(uint32_t processor) {
+ char min_frequency_filename[FREQUENCY_FILENAME_SIZE];
+ const int chars_formatted = snprintf(
+ min_frequency_filename, FREQUENCY_FILENAME_SIZE, MIN_FREQUENCY_FILENAME_FORMAT, processor);
+ if ((unsigned int) chars_formatted >= FREQUENCY_FILENAME_SIZE) {
+ cpuinfo_log_warning("failed to format filename for min frequency of processor %"PRIu32, processor);
+ return 0;
+ }
+
+ uint32_t min_frequency;
+ if (cpuinfo_linux_parse_small_file(min_frequency_filename, FREQUENCY_FILESIZE, uint32_parser, &min_frequency)) {
+ cpuinfo_log_debug("parsed min frequency value of %"PRIu32" KHz for logical processor %"PRIu32" from %s",
+ min_frequency, processor, min_frequency_filename);
+ return min_frequency;
+ } else {
+ /*
+ * This error is less severe than parsing max frequency, because min frequency is only useful for clustering,
+ * while max frequency is also needed for peak FLOPS calculation.
+ */
+ cpuinfo_log_info("failed to parse min frequency for processor %"PRIu32" from %s",
+ processor, min_frequency_filename);
+ return 0;
+ }
+}
+
+bool cpuinfo_linux_get_processor_core_id(uint32_t processor, uint32_t core_id_ptr[restrict static 1]) {
+ char core_id_filename[PACKAGE_ID_FILENAME_SIZE];
+ const int chars_formatted = snprintf(
+ core_id_filename, CORE_ID_FILENAME_SIZE, CORE_ID_FILENAME_FORMAT, processor);
+ if ((unsigned int) chars_formatted >= CORE_ID_FILENAME_SIZE) {
+ cpuinfo_log_warning("failed to format filename for core id of processor %"PRIu32, processor);
+ return 0;
+ }
+
+ uint32_t core_id;
+ if (cpuinfo_linux_parse_small_file(core_id_filename, CORE_ID_FILESIZE, uint32_parser, &core_id)) {
+ cpuinfo_log_debug("parsed core id value of %"PRIu32" for logical processor %"PRIu32" from %s",
+ core_id, processor, core_id_filename);
+ *core_id_ptr = core_id;
+ return true;
+ } else {
+ cpuinfo_log_info("failed to parse core id for processor %"PRIu32" from %s",
+ processor, core_id_filename);
+ return false;
+ }
+}
+
+bool cpuinfo_linux_get_processor_package_id(uint32_t processor, uint32_t package_id_ptr[restrict static 1]) {
+ char package_id_filename[PACKAGE_ID_FILENAME_SIZE];
+ const int chars_formatted = snprintf(
+ package_id_filename, PACKAGE_ID_FILENAME_SIZE, PACKAGE_ID_FILENAME_FORMAT, processor);
+ if ((unsigned int) chars_formatted >= PACKAGE_ID_FILENAME_SIZE) {
+ cpuinfo_log_warning("failed to format filename for package id of processor %"PRIu32, processor);
+ return 0;
+ }
+
+ uint32_t package_id;
+ if (cpuinfo_linux_parse_small_file(package_id_filename, PACKAGE_ID_FILESIZE, uint32_parser, &package_id)) {
+ cpuinfo_log_debug("parsed package id value of %"PRIu32" for logical processor %"PRIu32" from %s",
+ package_id, processor, package_id_filename);
+ *package_id_ptr = package_id;
+ return true;
+ } else {
+ cpuinfo_log_info("failed to parse package id for processor %"PRIu32" from %s",
+ processor, package_id_filename);
+ return false;
+ }
+}
+
+static bool max_processor_number_parser(uint32_t processor_list_start, uint32_t processor_list_end, void* context) {
+ uint32_t* processor_number_ptr = (uint32_t*) context;
+ const uint32_t processor_list_last = processor_list_end - 1;
+ if (*processor_number_ptr < processor_list_last) {
+ *processor_number_ptr = processor_list_last;
+ }
+ return true;
+}
+
+uint32_t cpuinfo_linux_get_max_possible_processor(uint32_t max_processors_count) {
+ uint32_t max_possible_processor = 0;
+ if (!cpuinfo_linux_parse_cpulist(POSSIBLE_CPULIST_FILENAME, max_processor_number_parser, &max_possible_processor)) {
+ cpuinfo_log_error("failed to parse the list of possible procesors in %s", POSSIBLE_CPULIST_FILENAME);
+ return max_processors_count;
+ }
+ if (max_possible_processor >= max_processors_count) {
+ cpuinfo_log_warning(
+ "maximum possible processor number %"PRIu32" exceeds system limit %"PRIu32": truncating to the latter",
+ max_possible_processor, max_processors_count - 1);
+ max_possible_processor = max_processors_count - 1;
+ }
+ return max_possible_processor;
+}
+
+uint32_t cpuinfo_linux_get_max_present_processor(uint32_t max_processors_count) {
+ uint32_t max_present_processor = 0;
+ if (!cpuinfo_linux_parse_cpulist(PRESENT_CPULIST_FILENAME, max_processor_number_parser, &max_present_processor)) {
+ cpuinfo_log_error("failed to parse the list of present procesors in %s", PRESENT_CPULIST_FILENAME);
+ return max_processors_count;
+ }
+ if (max_present_processor >= max_processors_count) {
+ cpuinfo_log_warning(
+ "maximum present processor number %"PRIu32" exceeds system limit %"PRIu32": truncating to the latter",
+ max_present_processor, max_processors_count - 1);
+ max_present_processor = max_processors_count - 1;
+ }
+ return max_present_processor;
+}
+
+struct detect_processors_context {
+ uint32_t max_processors_count;
+ uint32_t* processor0_flags;
+ uint32_t processor_struct_size;
+ uint32_t detected_flag;
+};
+
+static bool detect_processor_parser(uint32_t processor_list_start, uint32_t processor_list_end, void* context) {
+ const uint32_t max_processors_count = ((struct detect_processors_context*) context)->max_processors_count;
+ const uint32_t* processor0_flags = ((struct detect_processors_context*) context)->processor0_flags;
+ const uint32_t processor_struct_size = ((struct detect_processors_context*) context)->processor_struct_size;
+ const uint32_t detected_flag = ((struct detect_processors_context*) context)->detected_flag;
+
+ for (uint32_t processor = processor_list_start; processor < processor_list_end; processor++) {
+ if (processor >= max_processors_count) {
+ break;
+ }
+ *((uint32_t*) ((void*) processor0_flags + processor_struct_size * processor)) |= detected_flag;
+ }
+ return true;
+}
+
+bool cpuinfo_linux_detect_possible_processors(uint32_t max_processors_count,
+ uint32_t* processor0_flags, uint32_t processor_struct_size, uint32_t possible_flag)
+{
+ struct detect_processors_context context = {
+ .max_processors_count = max_processors_count,
+ .processor0_flags = processor0_flags,
+ .processor_struct_size = processor_struct_size,
+ .detected_flag = possible_flag,
+ };
+ if (cpuinfo_linux_parse_cpulist(POSSIBLE_CPULIST_FILENAME, detect_processor_parser, &context)) {
+ return true;
+ } else {
+ cpuinfo_log_warning("failed to parse the list of possible procesors in %s", POSSIBLE_CPULIST_FILENAME);
+ return false;
+ }
+}
+
+bool cpuinfo_linux_detect_present_processors(uint32_t max_processors_count,
+ uint32_t* processor0_flags, uint32_t processor_struct_size, uint32_t present_flag)
+{
+ struct detect_processors_context context = {
+ .max_processors_count = max_processors_count,
+ .processor0_flags = processor0_flags,
+ .processor_struct_size = processor_struct_size,
+ .detected_flag = present_flag,
+ };
+ if (cpuinfo_linux_parse_cpulist(PRESENT_CPULIST_FILENAME, detect_processor_parser, &context)) {
+ return true;
+ } else {
+ cpuinfo_log_warning("failed to parse the list of present procesors in %s", PRESENT_CPULIST_FILENAME);
+ return false;
+ }
+}
+
+struct siblings_context {
+ const char* group_name;
+ const char* item_name;
+ uint32_t max_processors_count;
+ uint32_t processor;
+ uint32_t* processor_flags;
+ uint32_t* processor_group_id;
+ uint32_t* processor_group_min;
+ uint32_t* processor_group_max;
+ uint32_t* processor0_flags;
+ uint32_t* processor0_group_id;
+ uint32_t* processor0_group_min;
+ uint32_t* processor0_group_max;
+ uint32_t processor_struct_size;
+ uint32_t group_cluster_flag;
+ uint32_t group_id_flag;
+};
+
+static inline uint32_t min(uint32_t a, uint32_t b) {
+ return a < b ? a : b;
+}
+
+static inline uint32_t max(uint32_t a, uint32_t b) {
+ return a > b ? a : b;
+}
+
+static bool siblings_parser(uint32_t sibling_list_start, uint32_t sibling_list_end, struct siblings_context* context) {
+ const char* group_name = context->group_name;
+ const char* item_name = context->item_name;
+ const uint32_t max_processors_count = context->max_processors_count;
+ const uint32_t processor = context->processor;
+ uint32_t* processor_flags_ptr = context->processor_flags;
+ uint32_t* processor_group_id_ptr = context->processor_group_id;
+ uint32_t* processor_group_min_ptr = context->processor_group_min;
+ uint32_t* processor_group_max_ptr = context->processor_group_max;
+ void* processor0_flags_ptr = context->processor0_flags;
+ void* processor0_group_id_ptr = context->processor0_group_id;
+ void* processor0_group_min_ptr = context->processor0_group_min;
+ void* processor0_group_max_ptr = context->processor0_group_max;
+ const uint32_t processor_struct_size = context->processor_struct_size;
+ const uint32_t group_cluster_flag = context->group_cluster_flag;
+ const uint32_t group_id_flag = context->group_id_flag;
+
+ *processor_flags_ptr |= group_cluster_flag;
+
+ for (uint32_t sibling = sibling_list_start; sibling < sibling_list_end; sibling++) {
+ if (sibling >= max_processors_count) {
+ cpuinfo_log_warning("ignore siblings %"PRIu32"-%"PRIu32" of processor %"PRIu32,
+ sibling, sibling_list_end - 1, processor);
+ break;
+ }
+
+ uint32_t* sibling_flags_ptr = (uint32_t*) (processor0_flags_ptr + processor_struct_size * sibling);
+ uint32_t* sibling_group_id_ptr = (uint32_t*) (processor0_group_id_ptr + processor_struct_size * sibling);
+ uint32_t* sibling_group_min_ptr = (uint32_t*) (processor0_group_min_ptr + processor_struct_size * sibling);
+ uint32_t* sibling_group_max_ptr = (uint32_t*) (processor0_group_max_ptr + processor_struct_size * sibling);
+
+ *sibling_group_min_ptr = *processor_group_min_ptr = min(*sibling_group_min_ptr, *processor_group_min_ptr);
+ *sibling_group_max_ptr = *processor_group_max_ptr = max(*sibling_group_max_ptr, *processor_group_max_ptr);
+
+ if (*sibling_flags_ptr & group_id_flag) {
+ if (*processor_flags_ptr & group_id_flag) {
+ if (*sibling_group_id_ptr != *processor_group_id_ptr) {
+ cpuinfo_log_warning("%s sibling processors %"PRIu32" and %"PRIu32" have different %s IDs %"PRIu32" and %"PRIu32,
+ item_name, processor, sibling,
+ group_name, *processor_group_id_ptr, *sibling_group_id_ptr);
+ }
+ } else {
+ cpuinfo_log_debug("propagate %s ID %"PRIu32" from processor %"PRIu32" to processor %"PRIu32,
+ group_name, *sibling_group_id_ptr, sibling, processor);
+ *processor_flags_ptr |= group_id_flag;
+ }
+ *sibling_flags_ptr |= group_cluster_flag;
+ } else {
+ cpuinfo_log_debug("propagate %s ID %"PRIu32" from processor %"PRIu32" to processor %"PRIu32,
+ group_name, *processor_group_id_ptr, processor, sibling);
+ *sibling_group_id_ptr = *processor_group_id_ptr;
+ *sibling_flags_ptr |= group_cluster_flag | group_id_flag;
+ }
+ }
+ return true;
+}
+
+bool cpuinfo_linux_detect_core_siblings(
+ uint32_t max_processors_count,
+ uint32_t processor,
+ uint32_t* processor0_flags,
+ uint32_t* processor0_package_id,
+ uint32_t* processor0_package_group_min,
+ uint32_t* processor0_package_group_max,
+ uint32_t processor_struct_size)
+{
+ char core_siblings_filename[CORE_SIBLINGS_FILENAME_SIZE];
+ const int chars_formatted = snprintf(
+ core_siblings_filename, CORE_SIBLINGS_FILENAME_SIZE, CORE_SIBLINGS_FILENAME_FORMAT, processor);
+ if ((unsigned int) chars_formatted >= CORE_SIBLINGS_FILENAME_SIZE) {
+ cpuinfo_log_warning("failed to format filename for core siblings of processor %"PRIu32, processor);
+ return false;
+ }
+
+ struct siblings_context context = {
+ .group_name = "package",
+ .item_name = "core",
+ .max_processors_count = max_processors_count,
+ .processor = processor,
+ .processor_flags = (uint32_t*) ((void*) processor0_flags + processor * processor_struct_size),
+ .processor_group_id = (uint32_t*) ((void*) processor0_package_id + processor * processor_struct_size),
+ .processor_group_min = (uint32_t*) ((void*) processor0_package_group_min + processor * processor_struct_size),
+ .processor_group_max = (uint32_t*) ((void*) processor0_package_group_max + processor * processor_struct_size),
+ .processor0_flags = processor0_flags,
+ .processor0_group_id = processor0_package_id,
+ .processor0_group_min = processor0_package_group_min,
+ .processor0_group_max = processor0_package_group_max,
+ .processor_struct_size = processor_struct_size,
+ .group_cluster_flag = CPUINFO_LINUX_FLAG_PACKAGE_CLUSTER,
+ .group_id_flag = CPUINFO_LINUX_FLAG_PACKAGE_ID,
+ };
+ if (cpuinfo_linux_parse_cpulist(core_siblings_filename,
+ (cpuinfo_cpulist_callback) siblings_parser, &context))
+ {
+ return true;
+ } else {
+ cpuinfo_log_info("failed to parse the list of core siblings for processor %"PRIu32" from %s",
+ processor, core_siblings_filename);
+ return false;
+ }
+}
+
+bool cpuinfo_linux_detect_thread_siblings(
+ uint32_t max_processors_count,
+ uint32_t processor,
+ uint32_t* processor0_flags,
+ uint32_t* processor0_core_id,
+ uint32_t* processor0_core_group_min,
+ uint32_t* processor0_core_group_max,
+ uint32_t processor_struct_size)
+{
+ char thread_siblings_filename[THREAD_SIBLINGS_FILENAME_SIZE];
+ const int chars_formatted = snprintf(
+ thread_siblings_filename, THREAD_SIBLINGS_FILENAME_SIZE, THREAD_SIBLINGS_FILENAME_FORMAT, processor);
+ if ((unsigned int) chars_formatted >= THREAD_SIBLINGS_FILENAME_SIZE) {
+ cpuinfo_log_warning("failed to format filename for thread siblings of processor %"PRIu32, processor);
+ return false;
+ }
+
+ struct siblings_context context = {
+ .group_name = "core",
+ .item_name = "thread",
+ .max_processors_count = max_processors_count,
+ .processor = processor,
+ .processor_flags = (uint32_t*) ((void*) processor0_flags + processor * processor_struct_size),
+ .processor_group_id = (uint32_t*) ((void*) processor0_core_id + processor * processor_struct_size),
+ .processor_group_min = (uint32_t*) ((void*) processor0_core_group_min + processor * processor_struct_size),
+ .processor_group_max = (uint32_t*) ((void*) processor0_core_group_max + processor * processor_struct_size),
+ .processor0_flags = processor0_flags,
+ .processor0_group_id = processor0_core_id,
+ .processor0_group_min = processor0_core_group_min,
+ .processor0_group_max = processor0_core_group_max,
+ .processor_struct_size = processor_struct_size,
+ .group_cluster_flag = CPUINFO_LINUX_FLAG_CORE_CLUSTER,
+ .group_id_flag = CPUINFO_LINUX_FLAG_CORE_ID,
+ };
+ if (cpuinfo_linux_parse_cpulist(thread_siblings_filename,
+ (cpuinfo_cpulist_callback) siblings_parser, &context))
+ {
+ return true;
+ } else {
+ cpuinfo_log_info("failed to parse the list of thread siblings for processor %"PRIu32" from %s",
+ processor, thread_siblings_filename);
+ return false;
+ }
+}
+