| Index: third_party/afl/src/afl-gotcpu.c
|
| diff --git a/third_party/afl/src/afl-gotcpu.c b/third_party/afl/src/afl-gotcpu.c
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..c296993bf50b0b5db304a0680f0d50ef47358e02
|
| --- /dev/null
|
| +++ b/third_party/afl/src/afl-gotcpu.c
|
| @@ -0,0 +1,252 @@
|
| +/*
|
| + american fuzzy lop - free CPU gizmo
|
| + -----------------------------------
|
| +
|
| + Written and maintained by Michal Zalewski <lcamtuf@google.com>
|
| +
|
| + Copyright 2015, 2016 Google Inc. All rights reserved.
|
| +
|
| + Licensed under the Apache License, Version 2.0 (the "License");
|
| + you may not use this file except in compliance with the License.
|
| + You may obtain a copy of the License at:
|
| +
|
| + http://www.apache.org/licenses/LICENSE-2.0
|
| +
|
| + This tool provides a fairly accurate measurement of CPU preemption rate.
|
| + It is meant to complement the quick-and-dirty load average widget shown
|
| + in the afl-fuzz UI. See docs/parallel_fuzzing.txt for more info.
|
| +
|
| + For some work loads, the tool may actually suggest running more instances
|
| + than you have CPU cores. This can happen if the tested program is spending
|
| + a portion of its run time waiting for I/O, rather than being 100%
|
| + CPU-bound.
|
| +
|
| + The idea for the getrusage()-based approach comes from Jakub Wilk.
|
| +
|
| + */
|
| +
|
| +#define AFL_MAIN
|
| +#define _GNU_SOURCE
|
| +
|
| +#include <stdio.h>
|
| +#include <stdlib.h>
|
| +#include <unistd.h>
|
| +#include <string.h>
|
| +#include <sched.h>
|
| +
|
| +#include <sys/time.h>
|
| +#include <sys/times.h>
|
| +#include <sys/resource.h>
|
| +#include <sys/wait.h>
|
| +
|
| +#include "types.h"
|
| +#include "debug.h"
|
| +
|
| +#ifdef __linux__
|
| +# define HAVE_AFFINITY 1
|
| +#endif /* __linux__ */
|
| +
|
| +
|
| +/* Get unix time in microseconds. */
|
| +
|
| +static u64 get_cur_time_us(void) {
|
| +
|
| + struct timeval tv;
|
| + struct timezone tz;
|
| +
|
| + gettimeofday(&tv, &tz);
|
| +
|
| + return (tv.tv_sec * 1000000ULL) + tv.tv_usec;
|
| +
|
| +}
|
| +
|
| +
|
| +/* Get CPU usage in microseconds. */
|
| +
|
| +static u64 get_cpu_usage_us(void) {
|
| +
|
| + struct rusage u;
|
| +
|
| + getrusage(RUSAGE_SELF, &u);
|
| +
|
| + return (u.ru_utime.tv_sec * 1000000ULL) + u.ru_utime.tv_usec +
|
| + (u.ru_stime.tv_sec * 1000000ULL) + u.ru_stime.tv_usec;
|
| +
|
| +}
|
| +
|
| +
|
| +/* Measure preemption rate. */
|
| +
|
| +static u32 measure_preemption(u32 target_ms) {
|
| +
|
| + static volatile u32 v1, v2;
|
| +
|
| + u64 st_t, en_t, st_c, en_c, real_delta, slice_delta;
|
| + s32 loop_repeats = 0;
|
| +
|
| + st_t = get_cur_time_us();
|
| + st_c = get_cpu_usage_us();
|
| +
|
| +repeat_loop:
|
| +
|
| + v1 = CTEST_BUSY_CYCLES;
|
| +
|
| + while (v1--) v2++;
|
| + sched_yield();
|
| +
|
| + en_t = get_cur_time_us();
|
| +
|
| + if (en_t - st_t < target_ms * 1000) {
|
| + loop_repeats++;
|
| + goto repeat_loop;
|
| + }
|
| +
|
| + /* Let's see what percentage of this time we actually had a chance to
|
| + run, and how much time was spent in the penalty box. */
|
| +
|
| + en_c = get_cpu_usage_us();
|
| +
|
| + real_delta = (en_t - st_t) / 1000;
|
| + slice_delta = (en_c - st_c) / 1000;
|
| +
|
| + return real_delta * 100 / slice_delta;
|
| +
|
| +}
|
| +
|
| +
|
| +/* Do the benchmark thing. */
|
| +
|
| +int main(int argc, char** argv) {
|
| +
|
| +#ifdef HAVE_AFFINITY
|
| +
|
| + u32 cpu_cnt = sysconf(_SC_NPROCESSORS_ONLN),
|
| + idle_cpus = 0, maybe_cpus = 0, i;
|
| +
|
| + SAYF(cCYA "afl-gotcpu " cBRI VERSION cRST " by <lcamtuf@google.com>\n");
|
| +
|
| + ACTF("Measuring per-core preemption rate (this will take %0.02f sec)...",
|
| + ((double)CTEST_CORE_TRG_MS) / 1000);
|
| +
|
| + for (i = 0; i < cpu_cnt; i++) {
|
| +
|
| + s32 fr = fork();
|
| +
|
| + if (fr < 0) PFATAL("fork failed");
|
| +
|
| + if (!fr) {
|
| +
|
| + cpu_set_t c;
|
| + u32 util_perc;
|
| +
|
| + CPU_ZERO(&c);
|
| + CPU_SET(i, &c);
|
| +
|
| + if (sched_setaffinity(0, sizeof(c), &c))
|
| + PFATAL("sched_setaffinity failed");
|
| +
|
| + util_perc = measure_preemption(CTEST_CORE_TRG_MS);
|
| +
|
| + if (util_perc < 110) {
|
| +
|
| + SAYF(" Core #%u: " cLGN "AVAILABLE\n" cRST, i);
|
| + exit(0);
|
| +
|
| + } else if (util_perc < 250) {
|
| +
|
| + SAYF(" Core #%u: " cYEL "CAUTION " cRST "(%u%%)\n", i, util_perc);
|
| + exit(1);
|
| +
|
| + }
|
| +
|
| + SAYF(" Core #%u: " cLRD "OVERBOOKED " cRST "(%u%%)\n" cRST, i,
|
| + util_perc);
|
| + exit(2);
|
| +
|
| + }
|
| +
|
| + }
|
| +
|
| + for (i = 0; i < cpu_cnt; i++) {
|
| +
|
| + int ret;
|
| + if (waitpid(-1, &ret, 0) < 0) PFATAL("waitpid failed");
|
| +
|
| + if (WEXITSTATUS(ret) == 0) idle_cpus++;
|
| + if (WEXITSTATUS(ret) <= 1) maybe_cpus++;
|
| +
|
| + }
|
| +
|
| + SAYF(cGRA "\n>>> ");
|
| +
|
| + if (idle_cpus) {
|
| +
|
| + if (maybe_cpus == idle_cpus) {
|
| +
|
| + SAYF(cLGN "PASS: " cRST "You can run more processes on %u core%s.",
|
| + idle_cpus, idle_cpus > 1 ? "s" : "");
|
| +
|
| + } else {
|
| +
|
| + SAYF(cLGN "PASS: " cRST "You can run more processes on %u to %u core%s.",
|
| + idle_cpus, maybe_cpus, maybe_cpus > 1 ? "s" : "");
|
| +
|
| + }
|
| +
|
| + SAYF(cGRA " <<<" cRST "\n\n");
|
| + return 0;
|
| +
|
| + }
|
| +
|
| + if (maybe_cpus) {
|
| +
|
| + SAYF(cYEL "CAUTION: " cRST "You may still have %u core%s available.",
|
| + maybe_cpus, maybe_cpus > 1 ? "s" : "");
|
| + SAYF(cGRA " <<<" cRST "\n\n");
|
| + return 1;
|
| +
|
| + }
|
| +
|
| + SAYF(cLRD "FAIL: " cRST "All cores are overbooked.");
|
| + SAYF(cGRA " <<<" cRST "\n\n");
|
| + return 2;
|
| +
|
| +#else
|
| +
|
| + u32 util_perc;
|
| +
|
| + SAYF(cCYA "afl-gotcpu " cBRI VERSION cRST " by <lcamtuf@google.com>\n");
|
| +
|
| + /* Run a busy loop for CTEST_TARGET_MS. */
|
| +
|
| + ACTF("Measuring gross preemption rate (this will take %0.02f sec)...",
|
| + ((double)CTEST_TARGET_MS) / 1000);
|
| +
|
| + util_perc = measure_preemption(CTEST_TARGET_MS);
|
| +
|
| + /* Deliver the final verdict. */
|
| +
|
| + SAYF(cGRA "\n>>> ");
|
| +
|
| + if (util_perc < 105) {
|
| +
|
| + SAYF(cLGN "PASS: " cRST "You can probably run additional processes.");
|
| +
|
| + } else if (util_perc < 130) {
|
| +
|
| + SAYF(cYEL "CAUTION: " cRST "Your CPU may be somewhat overbooked (%u%%).",
|
| + util_perc);
|
| +
|
| + } else {
|
| +
|
| + SAYF(cLRD "FAIL: " cRST "Your CPU is overbooked (%u%%).", util_perc);
|
| +
|
| + }
|
| +
|
| + SAYF(cGRA " <<<" cRST "\n\n");
|
| +
|
| + return (util_perc > 105) + (util_perc > 130);
|
| +
|
| +#endif /* ^HAVE_AFFINITY */
|
| +
|
| +}
|
|
|