Add support for CPU cycles measurement
diff --git a/common.h b/common.h
index 3e02e19..f2d601a 100644
--- a/common.h
+++ b/common.h
@@ -52,7 +52,8 @@
     _HF_DYNFILE_NONE = 0x0,
     _HF_DYNFILE_INSTR_COUNT = 0x1,
     _HF_DYNFILE_BRANCH_COUNT = 0x2,
-    _HF_DYNFILE_UNIQUE_PC_COUNT = 0x4,
+    _HF_DYNFILE_CYCLE_COUNT = 0x4,
+    _HF_DYNFILE_UNIQUE_PC_COUNT = 0x8,
 } dynFileMethod_t;
 
 typedef struct {
@@ -82,7 +83,7 @@
     uint8_t *dynamicFileBest;
     size_t dynamicFileBestSz;
     dynFileMethod_t dynFileMethod;
-    int64_t branchBestCnt[3];
+    int64_t branchBestCnt[4];
     int dynamicRegressionCnt;
     uint64_t dynamicCutOffAddr;
     pthread_mutex_t dynamicFile_mutex;
@@ -101,7 +102,7 @@
 
     /* For linux/ code */
     uint8_t *dynamicFile;
-    int64_t branchCnt[3];
+    int64_t branchCnt[4];
     size_t dynamicFileSz;
 } fuzzer_t;
 
diff --git a/fuzz.c b/fuzz.c
index bda93ff..abbf0f0 100644
--- a/fuzz.c
+++ b/fuzz.c
@@ -69,7 +69,7 @@
     while (pthread_mutex_lock(&hfuzz->dynamicFile_mutex)) ;
 
     if (hfuzz->inputFile && hfuzz->branchBestCnt[0] == 0 && hfuzz->branchBestCnt[1] == 0
-        && hfuzz->branchBestCnt[2] == 0) {
+        && hfuzz->branchBestCnt[2] == 0 && hfuzz->branchBestCnt[3] == 0) {
         size_t fileSz = files_readFileToBufMax(hfuzz->files[rnd_index], hfuzz->dynamicFileBest,
                                                hfuzz->maxFileSz);
         if (fileSz == 0) {
@@ -91,7 +91,8 @@
     while (pthread_mutex_unlock(&hfuzz->dynamicFile_mutex)) ;
 
     /* The first pass should be on an empty/initial file */
-    if (hfuzz->branchBestCnt[0] > 0 || hfuzz->branchBestCnt[1] > 0 || hfuzz->branchBestCnt[2] > 0) {
+    if (hfuzz->branchBestCnt[0] > 0 || hfuzz->branchBestCnt[1] > 0 || hfuzz->branchBestCnt[2] > 0
+        || hfuzz->branchBestCnt[3] > 0) {
         mangle_Resize(hfuzz, &fuzzer->dynamicFileSz);
         mangle_mangleContent(hfuzz, fuzzer->dynamicFile, fuzzer->dynamicFileSz);
     }
@@ -213,9 +214,7 @@
         .exception = 0,
         .dynamicFileSz = 0,
         .dynamicFile = malloc(hfuzz->maxFileSz),
-        .branchCnt[0] = 0,
-        .branchCnt[1] = 0,
-        .branchCnt[2] = 0,
+	.branchCnt = {[0 ... (ARRAYSIZE(fuzzer.branchCnt) - 1)] = 0,},
         .report = {'\0'}
     };
     if (fuzzer.dynamicFile == NULL) {
@@ -275,16 +274,18 @@
         int64_t diff0 = hfuzz->branchBestCnt[0] - fuzzer.branchCnt[0];
         int64_t diff1 = hfuzz->branchBestCnt[1] - fuzzer.branchCnt[1];
         int64_t diff2 = hfuzz->branchBestCnt[2] - fuzzer.branchCnt[2];
+        int64_t diff3 = hfuzz->branchBestCnt[3] - fuzzer.branchCnt[3];
 
         if (diff0 <= hfuzz->dynamicRegressionCnt && diff1 <= hfuzz->dynamicRegressionCnt
-            && diff2 <= hfuzz->dynamicRegressionCnt) {
+            && diff2 <= hfuzz->dynamicRegressionCnt && diff3 <= hfuzz->dynamicRegressionCnt) {
 
             LOGMSG(l_INFO,
                    "New BEST feedback: File Size (New/Old): %zu/%zu', Perf feedback (Curr, High): %"
-                   PRId64 "/%" PRId64 "/%" PRId64 ", %" PRId64 "/%" PRId64 "/%" PRId64,
-                   fuzzer.dynamicFileSz, hfuzz->dynamicFileBestSz, fuzzer.branchCnt[0],
-                   fuzzer.branchCnt[1], fuzzer.branchCnt[2], hfuzz->branchBestCnt[0],
-                   hfuzz->branchBestCnt[1], hfuzz->branchBestCnt[2]);
+                   PRId64 "/%" PRId64 "/%" PRId64 "/%" PRId64 ", %" PRId64 "/%" PRId64 "/%" PRId64
+                   "/%" PRId64, fuzzer.dynamicFileSz, hfuzz->dynamicFileBestSz, fuzzer.branchCnt[0],
+                   fuzzer.branchCnt[1], fuzzer.branchCnt[2], fuzzer.branchCnt[3],
+                   hfuzz->branchBestCnt[0], hfuzz->branchBestCnt[1], hfuzz->branchBestCnt[2],
+                   hfuzz->branchBestCnt[3]);
 
             memcpy(hfuzz->dynamicFileBest, fuzzer.dynamicFile, fuzzer.dynamicFileSz);
 
@@ -298,6 +299,9 @@
             hfuzz->branchBestCnt[2] =
                 fuzzer.branchCnt[2] >
                 hfuzz->branchBestCnt[2] ? fuzzer.branchCnt[2] : hfuzz->branchBestCnt[2];
+            hfuzz->branchBestCnt[3] =
+                fuzzer.branchCnt[3] >
+                hfuzz->branchBestCnt[3] ? fuzzer.branchCnt[3] : hfuzz->branchBestCnt[3];
 
 #define _HF_CURRENT_BEST "CURRENT_BEST"
 #define _HF_CURRENT_BEST_TMP ".tmp.CURRENT_BEST"
@@ -336,9 +340,7 @@
         .exception = 0,
         .dynamicFileSz = 0,
         .dynamicFile = malloc(hfuzz->maxFileSz),
-        .branchCnt[0] = 0,
-        .branchCnt[1] = 0,
-        .branchCnt[2] = 0,
+	.branchCnt = {[0 ... (ARRAYSIZE(fuzzer.branchCnt) - 1)] = 0,},
         .report = {'\0'}
     };
     if (fuzzer.dynamicFile == NULL) {
diff --git a/honggfuzz.c b/honggfuzz.c
index 0c6f085..9040b03 100644
--- a/honggfuzz.c
+++ b/honggfuzz.c
@@ -90,6 +90,7 @@
            "            (default: " AB "none" AC ")\n"
            "            Available counters: \n"
            "               " AB "'i' " AC "- PERF_COUNT_HW_INSTRUCTIONS (total IPs)\n"
+           "               " AB "'c' " AC "- PERF_COUNT_HW_REF_CPU_CYCLES (total CPU cycles)\n"
            "               " AB "'b' " AC "- PERF_COUNT_HW_BRANCH_INSTRUCTIONS (total jumps/calls)\n"
            "               " AB "'p' " AC "- PERF_SAMPLE_IP/PERF_SAMPLE_ADDR (unique branches)\n"
            "                     (newer Intel CPUs only)\n"
@@ -145,9 +146,7 @@
         .dynFileMethod = _HF_DYNFILE_NONE,
         .dynamicFileBest = NULL,
         .dynamicFileBestSz = 1,
-        .branchBestCnt[0] = 0,
-        .branchBestCnt[1] = 0,
-        .branchBestCnt[2] = 0,
+	.branchBestCnt = {[0 ... (ARRAYSIZE(hfuzz.branchBestCnt) - 1)] = 0,},
         .dynamicRegressionCnt = 0,
         .dynamicCutOffAddr = ~(0ULL),
         .dynamicFile_mutex = PTHREAD_MUTEX_INITIALIZER,
@@ -202,6 +201,9 @@
             case 'b':
                 hfuzz.dynFileMethod |= _HF_DYNFILE_BRANCH_COUNT;
                 break;
+            case 'c':
+                hfuzz.dynFileMethod |= _HF_DYNFILE_CYCLE_COUNT;
+                break;
             case 'p':
                 hfuzz.dynFileMethod |= _HF_DYNFILE_UNIQUE_PC_COUNT;
                 break;
diff --git a/linux/perf.c b/linux/perf.c
index 7ad32a9..2bbc34c 100644
--- a/linux/perf.c
+++ b/linux/perf.c
@@ -220,6 +220,11 @@
         pe.config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS;
         pe.inherit = 1;
         break;
+    case _HF_DYNFILE_CYCLE_COUNT:
+        LOGMSG(l_DEBUG, "Using: PERF_COUNT_HW_REF_CPU_CYCLES for PID: %d", pid);
+        pe.config = PERF_COUNT_HW_REF_CPU_CYCLES;
+        pe.inherit = 1;
+        break;
     case _HF_DYNFILE_UNIQUE_PC_COUNT:
         bzero(perfBloom, sizeof(perfBloom));
         LOGMSG(l_DEBUG,
@@ -306,6 +311,7 @@
     perfFd[0] = -1;
     perfFd[1] = -1;
     perfFd[2] = -1;
+    perfFd[3] = -1;
 
     if (hfuzz->dynFileMethod & _HF_DYNFILE_INSTR_COUNT) {
         if (arch_perfOpen(pid, _HF_DYNFILE_INSTR_COUNT, &perfFd[0]) == false) {
@@ -313,6 +319,7 @@
             close(perfFd[0]);
             close(perfFd[1]);
             close(perfFd[2]);
+            close(perfFd[3]);
             return false;
         }
     }
@@ -322,6 +329,17 @@
             close(perfFd[0]);
             close(perfFd[1]);
             close(perfFd[2]);
+            close(perfFd[3]);
+            return false;
+        }
+    }
+    if (hfuzz->dynFileMethod & _HF_DYNFILE_CYCLE_COUNT) {
+        if (arch_perfOpen(pid, _HF_DYNFILE_CYCLE_COUNT, &perfFd[2]) == false) {
+            LOGMSG(l_ERROR, "Cannot set up perf for PID=%d (_HF_DYNFILE_CYCLE_COUNT)", pid);
+            close(perfFd[0]);
+            close(perfFd[1]);
+            close(perfFd[2]);
+            close(perfFd[3]);
             return false;
         }
     }
@@ -362,6 +380,15 @@
         close(perfFd[1]);
     }
 
+    uint64_t cycleCount = 0;
+    if (hfuzz->dynFileMethod & _HF_DYNFILE_CYCLE_COUNT) {
+        ioctl(perfFd[2], PERF_EVENT_IOC_DISABLE, 0);
+        if (read(perfFd[2], &cycleCount, sizeof(cycleCount)) != sizeof(cycleCount)) {
+            LOGMSG_P(l_ERROR, "read(perfFd='%d') failed", perfFd);
+        }
+        close(perfFd[2]);
+    }
+
     uint64_t edgeCount = 0;
     if (hfuzz->dynFileMethod & _HF_DYNFILE_UNIQUE_PC_COUNT) {
         arch_perfMmapParse();
@@ -381,13 +408,14 @@
 
     fuzzer->branchCnt[0] = instrCount;
     fuzzer->branchCnt[1] = branchCount;
-    fuzzer->branchCnt[2] = edgeCount;
+    fuzzer->branchCnt[2] = cycleCount;
+    fuzzer->branchCnt[3] = edgeCount;
 
     LOGMSG(l_INFO,
            "File size (New/Best): %zu/%zu, Perf feedback: Best: [%" PRIu64 ",%" PRIu64 ",%" PRIu64
-           "] / New: [%" PRIu64 ",%" PRIu64 ",%" PRIu64 "]", fuzzer->dynamicFileSz,
-           hfuzz->dynamicFileBestSz, hfuzz->branchBestCnt[0], hfuzz->branchBestCnt[1],
-           hfuzz->branchBestCnt[2], fuzzer->branchCnt[0], fuzzer->branchCnt[1],
-           fuzzer->branchCnt[2]);
+           ",%" PRIu64 "] / New: [%" PRIu64 ",%" PRIu64 ",%" PRIu64 ",%" PRIu64 "]",
+           fuzzer->dynamicFileSz, hfuzz->dynamicFileBestSz, hfuzz->branchBestCnt[0],
+           hfuzz->branchBestCnt[1], hfuzz->branchBestCnt[2], hfuzz->branchBestCnt[3],
+           fuzzer->branchCnt[0], fuzzer->branchCnt[1], fuzzer->branchCnt[2], fuzzer->branchCnt[3]);
     return;
 }