#include #include #include #include #include #include #include static int sysctl_int(const char* name) { int value = 0; size_t value_size = sizeof(value); if (sysctlbyname(name, &value, &value_size, NULL, 0) != 0) { cpuinfo_log_error("sysctlbyname(\"%s\") failed: %s", name, strerror(errno)); } else if (value <= 0) { cpuinfo_log_error("sysctlbyname(\"%s\") returned invalid value %d %zu", name, value, value_size); value = 0; } return value; } static char* sysctl_str(const char* name) { size_t value_size = 0; if (sysctlbyname(name, NULL, &value_size, NULL, 0) != 0) { cpuinfo_log_error("sysctlbyname(\"%s\") failed: %s", name, strerror(errno)); return NULL; } else if (value_size <= 0) { cpuinfo_log_error("sysctlbyname(\"%s\") returned invalid value size %zu", name, value_size); return NULL; } value_size += 1; char* value = calloc(value_size, 1); if (!value) { cpuinfo_log_error("calloc %zu bytes failed", value_size); return NULL; } if (sysctlbyname(name, value, &value_size, NULL, 0) != 0) { cpuinfo_log_error("sysctlbyname(\"%s\") failed: %s", name, strerror(errno)); free(value); return NULL; } return value; } struct cpuinfo_freebsd_topology cpuinfo_freebsd_detect_topology(void) { struct cpuinfo_freebsd_topology topology = { .packages = 0, .cores = 0, .threads_per_core = 0, .threads = 0, }; char* topology_spec = sysctl_str("kern.sched.topology_spec"); if (!topology_spec) { return topology; } const char* group_tags[] = {"", " 0) { break; } } if (topology.packages == 0) { cpuinfo_log_error("failed to parse topology_spec: %s", topology_spec); free(topology_spec); goto fail; } free(topology_spec); topology.cores = sysctl_int("kern.smp.cores"); if (topology.cores == 0) { goto fail; } if (topology.cores < topology.packages) { cpuinfo_log_error("invalid numbers of package and core: %d %d", topology.packages, topology.cores); goto fail; } topology.threads_per_core = sysctl_int("kern.smp.threads_per_core"); if (topology.threads_per_core == 0) { goto fail; } cpuinfo_log_debug( "freebsd topology: packages = %d, cores = %d, " "threads_per_core = %d", topology.packages, topology.cores, topology.threads_per_core); topology.threads = topology.threads_per_core * topology.cores; return topology; fail: topology.packages = 0; return topology; }