Index: lib/fuzzer/FuzzerDriver.cpp =================================================================== --- lib/fuzzer/FuzzerDriver.cpp +++ lib/fuzzer/FuzzerDriver.cpp @@ -242,17 +242,29 @@ } static int RunInMultipleProcesses(const Vector &Args, - unsigned NumWorkers, unsigned NumJobs) { + Random &Rand) { std::atomic Counter(0); std::atomic HasErrors(false); + unsigned NumCores = NumberOfCpuCores(); + unsigned w = 0; Command Cmd(Args); Cmd.removeFlag("jobs"); Cmd.removeFlag("workers"); Vector V; std::thread Pulse(PulseThread); Pulse.detach(); - for (unsigned i = 0; i < NumWorkers; i++) - V.push_back(std::thread(WorkerThread, std::ref(Cmd), &Counter, NumJobs, &HasErrors)); + for (unsigned i = 0; i < Flags.workers; i++) { + std::thread Wthread(WorkerThread, std::ref(Cmd), &Counter, Flags.jobs, &HasErrors); + if (Flags.sched_workers == 1) { + if (w == NumCores) + w = 0; + SchedWorkerThread(Wthread, w++); + } else if (Flags.sched_workers == 2) { + w = Rand(NumCores); + SchedWorkerThread(Wthread, w); + } + V.push_back(std::move(Wthread)); + } for (auto &T : V) T.join(); return HasErrors ? 1 : 0; @@ -561,8 +573,16 @@ Printf("Running %u workers\n", Flags.workers); } + unsigned Seed = Flags.seed; + // Initialize Seed. + if (Seed == 0) + Seed = + std::chrono::system_clock::now().time_since_epoch().count() + GetPid(); + + Random Rand(Seed); + if (Flags.workers > 0 && Flags.jobs > 0) - return RunInMultipleProcesses(Args, Flags.workers, Flags.jobs); + return RunInMultipleProcesses(Args, Rand); FuzzingOptions Options; Options.Verbosity = Flags.verbosity; @@ -625,15 +645,15 @@ if (Flags.data_flow_trace) Options.DataFlowTrace = Flags.data_flow_trace; - unsigned Seed = Flags.seed; - // Initialize Seed. - if (Seed == 0) - Seed = - std::chrono::system_clock::now().time_since_epoch().count() + GetPid(); if (Flags.verbosity) Printf("INFO: Seed: %u\n", Seed); - Random Rand(Seed); + int CpuBind; + GetSchedWorker(&CpuBind); + + if (CpuBind >= 0) + Printf("INFO: CPU id: %d\n", CpuBind); + auto *MD = new MutationDispatcher(Rand, Options); auto *Corpus = new InputCorpus(Options.OutputCorpus); auto *F = new Fuzzer(Callback, *Corpus, *MD, Options); Index: lib/fuzzer/FuzzerFlags.def =================================================================== --- lib/fuzzer/FuzzerFlags.def +++ lib/fuzzer/FuzzerFlags.def @@ -153,3 +153,4 @@ FUZZER_FLAG_INT(analyze_dict, 0, "Experimental") FUZZER_DEPRECATED_FLAG(use_clang_coverage) FUZZER_FLAG_STRING(data_flow_trace, "Experimental: use the data flow trace") +FUZZER_FLAG_INT(sched_workers, 0, "Set workers per cpu") Index: lib/fuzzer/FuzzerUtil.h =================================================================== --- lib/fuzzer/FuzzerUtil.h +++ lib/fuzzer/FuzzerUtil.h @@ -14,6 +14,7 @@ #include "FuzzerDefs.h" #include "FuzzerCommand.h" +#include namespace fuzzer { @@ -51,6 +52,9 @@ void SleepSeconds(int Seconds); +void SchedWorkerThread(std::thread & Wthread, int C); +void GetSchedWorker(int *C); + unsigned long GetPid(); size_t GetPeakRSSMb(); Index: lib/fuzzer/FuzzerUtilFuchsia.cpp =================================================================== --- lib/fuzzer/FuzzerUtilFuchsia.cpp +++ lib/fuzzer/FuzzerUtilFuchsia.cpp @@ -135,6 +135,9 @@ return Info.koid; } +void SchedWorkerThread(std::thread &WorkerThread, int C) {} +void GetSchedWorker(int *C) { *C = -1; } + size_t GetPeakRSSMb() { zx_status_t rc; zx_info_task_stats_t Info; Index: lib/fuzzer/FuzzerUtilPosix.cpp =================================================================== --- lib/fuzzer/FuzzerUtilPosix.cpp +++ lib/fuzzer/FuzzerUtilPosix.cpp @@ -25,6 +25,10 @@ #include #include #include +#ifdef __FreeBSD__ +#include +typedef cpuset_t cpu_set_t; +#endif namespace fuzzer { @@ -114,6 +118,36 @@ unsigned long GetPid() { return (unsigned long)getpid(); } +void SchedWorkerThread(std::thread &WorkerThread, int C) { + pthread_t NativeThread = WorkerThread.native_handle(); +#if defined(__linux__) || defined(__FreeBSD__) + cpu_set_t Cset; + CPU_ZERO(&Cset); + CPU_SET(C, &Cset); + if (pthread_setaffinity_np(NativeThread, sizeof(Cset), &Cset) != 0) + fprintf(stderr, "Error thread affinity setting for cpu %d\n", C); +#endif +} + +void GetSchedWorker(int *C) { + unsigned long NumCores = std::thread::hardware_concurrency(); + *C = -1; +#if defined(__linux__) || defined(__FreeBSD__) + cpu_set_t Cset; + CPU_ZERO(&Cset); + if (pthread_getaffinity_np(pthread_self(), sizeof(Cset), &Cset) != 0) { + fprintf(stderr, "Error thread affinity capture\n"); + } else { + for (size_t i = 0; i < NumCores; i ++) { + if (CPU_ISSET(i, &Cset)) { + *C = i; + break; + } + } + } +#endif +} + size_t GetPeakRSSMb() { struct rusage usage; if (getrusage(RUSAGE_SELF, &usage)) Index: lib/fuzzer/FuzzerUtilWindows.cpp =================================================================== --- lib/fuzzer/FuzzerUtilWindows.cpp +++ lib/fuzzer/FuzzerUtilWindows.cpp @@ -141,6 +141,9 @@ unsigned long GetPid() { return GetCurrentProcessId(); } +void SchedWorkerThread(std::thread &WorkerThread, int C) {} +void GetSchedWorker(int *C) { *C = -1; } + size_t GetPeakRSSMb() { PROCESS_MEMORY_COUNTERS info; if (!GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info)))