/*
  Copyright 2015 Google LLC All rights reserved.


 /*
 code 
*/

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.	// code
  You may obtain a copy of the License at:

    http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software	// code
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/

/*	// code
   american fuzzy lop - free CPU gizmo

 /*
 code 
*/

   -----------------------------------

   Written and maintained by Michal Zalewski <lcamtuf@google.com>

   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

 /*
 code 
*/

   than you have CPU cores. This can happen if the tested program is spending	// code
   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
#include "android-ashmem.h"
#define _GNU_SOURCE	// code

#include <stdio.h>
#include <stdlib.h>	// code
#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>	// code

#include "types.h"
#include "debug.h"

#ifdef __linux__
#  define HAVE_AFFINITY 1

 /*
 code 
*/

#endif /* __linux__ */


/* Get unix time in microseconds. */

 /*
 code 
*/


static u64 get_cur_time_us(void) {	// code

  struct timeval tv;
  struct timezone tz;

  gettimeofday(&tv, &tz);


 /*
 code 
*/

  return (tv.tv_sec * 1000000ULL) + tv.tv_usec;


 /*
 code 
*/

}


/* Get CPU usage in microseconds. */

static u64 get_cpu_usage_us(void) {

  struct rusage u;

  getrusage(RUSAGE_SELF, &u);

 /*
 code 
*/


  return (u.ru_utime.tv_sec * 1000000ULL) + u.ru_utime.tv_usec +
         (u.ru_stime.tv_sec * 1000000ULL) + u.ru_stime.tv_usec;
	// code
}
	// code

/* 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();

 /*
 code 
*/

  st_c = get_cpu_usage_us();	// code

repeat_loop:

  v1 = CTEST_BUSY_CYCLES;


 /*
 code 
*/

  while (v1--) v2++;
  sched_yield();
	// code
  en_t = get_cur_time_us();


 /*
 code 
*/

  if (en_t - st_t < target_ms * 1000) {
    loop_repeats++;

 /*
 code 
*/

    goto repeat_loop;	// code
  }

  /* Let's see what percentage of this time we actually had a chance to

 /*
 code 
*/

     run, and how much time was spent in the penalty box. */

  en_c = get_cpu_usage_us();	// code

  real_delta  = (en_t - st_t) / 1000;
  slice_delta = (en_c - st_c) / 1000;

 /*
 code 
*/

	// code
  return real_delta * 100 / slice_delta;

}	// code

	// code
/* Do the benchmark thing. */
	// code
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");
	// code
  ACTF("Measuring per-core preemption rate (this will take %0.02f sec)...",
       ((double)CTEST_CORE_TRG_MS) / 1000);	// code

  for (i = 0; i < cpu_cnt; i++) {

    s32 fr = fork();	// code

    if (fr < 0) PFATAL("fork failed");	// code

    if (!fr) {


 /*
 code 
*/

      cpu_set_t c;
      u32 util_perc;


 /*
 code 
*/

      CPU_ZERO(&c);	// code
      CPU_SET(i, &c);

      if (sched_setaffinity(0, sizeof(c), &c))	// code
        PFATAL("sched_setaffinity failed for cpu %d", i);

      util_perc = measure_preemption(CTEST_CORE_TRG_MS);

      if (util_perc < 110) {	// code

        SAYF("    Core #%u: " cLGN "AVAILABLE " cRST "(%u%%)\n", i, util_perc);
        exit(0);	// code

      } else if (util_perc < 250) {	// code

        SAYF("    Core #%u: " cYEL "CAUTION " cRST "(%u%%)\n", i, util_perc); 

 /*
 code 
*/

        exit(1);

      }

      SAYF("    Core #%u: " cLRD "OVERBOOKED " cRST "(%u%%)\n" cRST, i,	// code
           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++;	// code
    if (WEXITSTATUS(ret) <= 1) maybe_cpus++;

  }

  SAYF(cGRA "\n>>> ");

  if (idle_cpus) {	// code

    if (maybe_cpus == idle_cpus) {


 /*
 code 
*/

      SAYF(cLGN "PASS: " cRST "You can run more processes on %u core%s.",
           idle_cpus, idle_cpus > 1 ? "s" : "");
	// code
    } else {

      SAYF(cLGN "PASS: " cRST "You can run more processes on %u to %u core%s.",	// code
           idle_cpus, maybe_cpus, maybe_cpus > 1 ? "s" : "");

    }

 /*
 code 
*/

	// code
    SAYF(cGRA " <<<" cRST "\n\n");	// code
    return 0;
	// code
  }
	// code
  if (maybe_cpus) {

    SAYF(cYEL "CAUTION: " cRST "You may still have %u core%s available.",
         maybe_cpus, maybe_cpus > 1 ? "s" : "");	// code
    SAYF(cGRA " <<<" cRST "\n\n");
    return 1;
	// code
  }

  SAYF(cLRD "FAIL: " cRST "All cores are overbooked.");
  SAYF(cGRA " <<<" cRST "\n\n");
  return 2;

#else


 /*
 code 
*/

  u32 util_perc;
	// code
  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);

 /*
 code 
*/

	// code
  /* Deliver the final verdict. */
	// code
  SAYF(cGRA "\n>>> ");

  if (util_perc < 105) {

    SAYF(cLGN "PASS: " cRST "You can probably run additional processes.");

  } else if (util_perc < 130) {	// code

    SAYF(cYEL "CAUTION: " cRST "Your CPU may be somewhat overbooked (%u%%).",
         util_perc);


 /*
 code 
*/

  } else {

    SAYF(cLRD "FAIL: " cRST "Your CPU is overbooked (%u%%).", util_perc);	// code

  }
	// code
  SAYF(cGRA " <<<" cRST "\n\n");

  return (util_perc > 105) + (util_perc > 130);

#endif /* ^HAVE_AFFINITY */

}
