diff --git a/orchestrator/BUILD b/orchestrator/BUILD index a354b998..61f24c4b 100644 --- a/orchestrator/BUILD +++ b/orchestrator/BUILD @@ -32,6 +32,7 @@ cc_binary( "@silifuzz//proto:corpus_metadata_cc_proto", "@silifuzz//runner/driver:runner_options", "@silifuzz//util:checks", + "@silifuzz//util:cpu_id", "@silifuzz//util:itoa", "@silifuzz//util:tool_util", "@com_google_absl//absl/flags:flag", @@ -96,6 +97,7 @@ cc_library( "@silifuzz//proto:snapshot_execution_result_cc_proto", "@silifuzz//runner/driver:runner_driver", "@silifuzz//util:checks", + "@silifuzz//util:cpu_id", "@silifuzz//util:hostname", "@silifuzz//util:itoa", "@com_google_absl//absl/flags:flag", diff --git a/orchestrator/result_collector.cc b/orchestrator/result_collector.cc index 4f2c3688..f0431ff5 100644 --- a/orchestrator/result_collector.cc +++ b/orchestrator/result_collector.cc @@ -14,7 +14,6 @@ #include "./orchestrator/result_collector.h" -#include #include #include #include @@ -44,6 +43,7 @@ #include "./proto/snapshot_execution_result.pb.h" #include "./runner/driver/runner_driver.h" #include "./util/checks.h" +#include "./util/cpu_id.h" #include "./util/hostname.h" #include "./util/itoa.h" @@ -105,18 +105,8 @@ absl::StatusOr RunResultToSnapshotExecutionResult( // Returns the number of CPUs available according to sched_getaffinity. int NumCpus() { - cpu_set_t all_cpus; - CPU_ZERO(&all_cpus); int num_cpus = 0; - bool success = sched_getaffinity(0, sizeof(all_cpus), &all_cpus) == 0; - if (!success) { - LOG_FATAL("Cannot get current CPU affinity mask: ", ErrnoStr(errno)); - } - for (int cpu = 0; cpu < CPU_SETSIZE; ++cpu) { - if (CPU_ISSET(cpu, &all_cpus)) { - num_cpus++; - } - } + ForEachAvailableCPU([&](int cpu) { num_cpus++; }); return num_cpus; } diff --git a/orchestrator/silifuzz_orchestrator_main.cc b/orchestrator/silifuzz_orchestrator_main.cc index 4772f917..bdb4095a 100644 --- a/orchestrator/silifuzz_orchestrator_main.cc +++ b/orchestrator/silifuzz_orchestrator_main.cc @@ -78,6 +78,7 @@ #include "./proto/corpus_metadata.pb.h" #include "./runner/driver/runner_options.h" #include "./util/checks.h" +#include "./util/cpu_id.h" #include "./util/itoa.h" #include "./util/tool_util.h" @@ -135,20 +136,7 @@ namespace { // Lists all available CPUs according to sched_getaffinity(2). std::vector AvailableCpus() { std::vector available_cpus; - cpu_set_t all_cpus; - CPU_ZERO(&all_cpus); - bool success = - sched_getaffinity(0 /* this thread */, sizeof(all_cpus), &all_cpus) == 0; - if (!success) { - LOG_FATAL("Cannot get current CPU affinity mask: ", ErrnoStr(errno)); - } - - // Find all usable CPU. - for (int cpu = 0; cpu < CPU_SETSIZE; ++cpu) { - if (CPU_ISSET(cpu, &all_cpus)) { - available_cpus.push_back(cpu); - } - } + ForEachAvailableCPU([&](int cpu) { available_cpus.push_back(cpu); }); CHECK(!available_cpus.empty()); return available_cpus; } diff --git a/proxies/pmu_event_proxy/BUILD b/proxies/pmu_event_proxy/BUILD index ad91263a..07e5ad8a 100644 --- a/proxies/pmu_event_proxy/BUILD +++ b/proxies/pmu_event_proxy/BUILD @@ -142,6 +142,7 @@ cc_test( deps = [ ":perf_event_buffer", ":perf_event_records", + "@silifuzz//util:cpu_id", "@silifuzz//util/testing:status_macros", "@com_google_absl//absl/log", "@com_google_absl//absl/random", diff --git a/proxies/pmu_event_proxy/perf_event_buffer_test.cc b/proxies/pmu_event_proxy/perf_event_buffer_test.cc index 918709cc..a71d6dcb 100644 --- a/proxies/pmu_event_proxy/perf_event_buffer_test.cc +++ b/proxies/pmu_event_proxy/perf_event_buffer_test.cc @@ -16,7 +16,6 @@ #include /* Definition of HW_* constants */ #include -#include #include #include @@ -40,6 +39,7 @@ #include "absl/time/clock.h" #include "absl/time/time.h" #include "./proxies/pmu_event_proxy/perf_event_records.h" +#include "./util/cpu_id.h" #include "./util/testing/status_macros.h" #include "external/libpfm4/include/perfmon/pfmlib.h" #include "external/libpfm4/include/perfmon/pfmlib_perf_event.h" @@ -47,30 +47,16 @@ namespace silifuzz { namespace { void BindToARandomCPU() { - cpu_set_t cpu_set; - const pid_t pid = getpid(); - if (sched_getaffinity(pid, sizeof(cpu_set_t), &cpu_set) != 0) { - LOG(ERROR) << "sched_getaffinity failed: " << strerror(errno); - return; - } std::vector cpus; - for (int cpu = 0; cpu < CPU_SETSIZE; ++cpu) { - if (CPU_ISSET(cpu, &cpu_set)) { - cpus.push_back(cpu); - } - } + ForEachAvailableCPU([&](int cpu) { cpus.push_back(cpu); }); if (cpus.empty()) { LOG(ERROR) << "No CPU found"; return; } size_t index = absl::Uniform(absl::BitGen(), 0, cpus.size()); int cpu = cpus[index]; - cpu_set_t single; - CPU_ZERO(&single); - CPU_SET(cpu, &single); - - if (sched_setaffinity(pid, sizeof(single), &single) < 0) { - LOG(ERROR) << "sched_setaffinity failed: " << strerror(errno); + if (SetCPUAffinity(cpu) != 0) { + LOG(ERROR) << "SetCPUAffinity failed: " << strerror(errno); } } diff --git a/util/BUILD b/util/BUILD index b21954c3..89ae8044 100644 --- a/util/BUILD +++ b/util/BUILD @@ -847,6 +847,7 @@ cc_library_plus_nolibc( ], deps = [ ":checks", + ":itoa", ":x86_cpuid", ], ) diff --git a/util/cpu_id.h b/util/cpu_id.h index 33a1d09f..c26fb12c 100644 --- a/util/cpu_id.h +++ b/util/cpu_id.h @@ -15,6 +15,12 @@ #ifndef THIRD_PARTY_SILIFUZZ_UTIL_CPU_ID_H_ #define THIRD_PARTY_SILIFUZZ_UTIL_CPU_ID_H_ +#include +#include + +#include "./util/checks.h" +#include "./util/itoa.h" + namespace silifuzz { // No preference for choice of CPU. @@ -34,6 +40,25 @@ int GetCPUIdNoSyscall(); // successful or an error number from sched_setaffinity(). int SetCPUAffinity(int cpu_id); +// Invoke a callback for each CPU in this threads affinity mask. +template +inline void ForEachAvailableCPU(F callback) { + cpu_set_t all_cpus; + CPU_ZERO(&all_cpus); + bool success = + sched_getaffinity(0 /* this thread */, sizeof(all_cpus), &all_cpus) == 0; + if (!success) { + LOG_FATAL("Cannot get current CPU affinity mask: ", ErrnoStr(errno)); + } + + // Find all usable CPU. + for (int cpu = 0; cpu < CPU_SETSIZE; ++cpu) { + if (CPU_ISSET(cpu, &all_cpus)) { + callback(cpu); + } + } +} + } // namespace silifuzz #endif // THIRD_PARTY_SILIFUZZ_UTIL_CPU_ID_H_ diff --git a/util/cpu_id_test.cc b/util/cpu_id_test.cc index e65bdf20..d389f44d 100644 --- a/util/cpu_id_test.cc +++ b/util/cpu_id_test.cc @@ -36,24 +36,21 @@ double RecordConsistency(int (*callback)(), int expected) { } TEST(CPUId, BasicTest) { - cpu_set_t all_cpus; - ASSERT_EQ(sched_getaffinity(0, sizeof(all_cpus), &all_cpus), 0); - double normal_consistency_sum = 0; double nosys_consistency_sum = 0; int num_trials = 0; - for (int i = 0; i < CPU_SETSIZE; i++) { - if (CPU_ISSET(i, &all_cpus)) { - if (SetCPUAffinity(i) != 0) { - LOG_ERROR("Cannot bind to CPU ", IntStr(i)); - continue; - } - normal_consistency_sum += RecordConsistency(&GetCPUId, i); - nosys_consistency_sum += RecordConsistency(&GetCPUIdNoSyscall, i); - num_trials += 1; + ForEachAvailableCPU([&](int cpu) { + if (SetCPUAffinity(cpu) != 0) { + LOG_ERROR("Cannot bind to CPU ", IntStr(cpu)); + return; } - } + normal_consistency_sum += RecordConsistency(&GetCPUId, cpu); + nosys_consistency_sum += RecordConsistency(&GetCPUIdNoSyscall, cpu); + num_trials += 1; + }); + + EXPECT_GE(num_trials, 0); // This is chosen empirically to keep failure rate below 1 in 10000. constexpr double kAcceptableErrorRate = 0.10;