top_srcdir = ../../../../..
 include ../../lib.mk
 
-all: $(TEST_GEN_PROGS) ebb
+all: $(TEST_GEN_PROGS) ebb sampling_tests
 
 $(TEST_GEN_PROGS): $(EXTRA_SOURCES)
 
 override define RUN_TESTS
        $(DEFAULT_RUN_TESTS)
        TARGET=ebb; BUILD_TARGET=$$OUTPUT/$$TARGET; $(MAKE) OUTPUT=$$BUILD_TARGET -C $$TARGET run_tests
+       TARGET=sampling_tests; BUILD_TARGET=$$OUTPUT/$$TARGET; $(MAKE) OUTPUT=$$BUILD_TARGET -C $$TARGET run_tests
 endef
 
 DEFAULT_EMIT_TESTS := $(EMIT_TESTS)
 override define EMIT_TESTS
        $(DEFAULT_EMIT_TESTS)
        TARGET=ebb; BUILD_TARGET=$$OUTPUT/$$TARGET; $(MAKE) OUTPUT=$$BUILD_TARGET -s -C $$TARGET emit_tests
+       TARGET=sampling_tests; BUILD_TARGET=$$OUTPUT/$$TARGET; $(MAKE) OUTPUT=$$BUILD_TARGET -s -C $$TARGET emit_tests
 endef
 
 DEFAULT_INSTALL_RULE := $(INSTALL_RULE)
 override define INSTALL_RULE
        $(DEFAULT_INSTALL_RULE)
        TARGET=ebb; BUILD_TARGET=$$OUTPUT/$$TARGET; $(MAKE) OUTPUT=$$BUILD_TARGET -C $$TARGET install
+       TARGET=sampling_tests; BUILD_TARGET=$$OUTPUT/$$TARGET; $(MAKE) OUTPUT=$$BUILD_TARGET -C $$TARGET install
 endef
 
 clean:
        $(RM) $(TEST_GEN_PROGS) $(OUTPUT)/loop.o
        TARGET=ebb; BUILD_TARGET=$$OUTPUT/$$TARGET; $(MAKE) OUTPUT=$$BUILD_TARGET -C $$TARGET clean
+       TARGET=sampling_tests; BUILD_TARGET=$$OUTPUT/$$TARGET; $(MAKE) OUTPUT=$$BUILD_TARGET -C $$TARGET clean
 
 ebb:
        TARGET=$@; BUILD_TARGET=$$OUTPUT/$$TARGET; mkdir -p $$BUILD_TARGET; $(MAKE) OUTPUT=$$BUILD_TARGET -k -C $$TARGET all
 
-.PHONY: all run_tests clean ebb
+sampling_tests:
+       TARGET=$@; BUILD_TARGET=$$OUTPUT/$$TARGET; mkdir -p $$BUILD_TARGET; $(MAKE) OUTPUT=$$BUILD_TARGET -k -C $$TARGET all
+
+.PHONY: all run_tests clean ebb sampling_tests
 
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright 2022, Athira Rajeev, IBM Corp.
+ */
+
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include "misc.h"
+
+#define PAGE_SIZE               sysconf(_SC_PAGESIZE)
+
+/*
+ * Allocate mmap buffer of "mmap_pages" number of
+ * pages.
+ */
+void *event_sample_buf_mmap(int fd, int mmap_pages)
+{
+       size_t page_size = sysconf(_SC_PAGESIZE);
+       size_t mmap_size;
+       void *buff;
+
+       if (mmap_pages <= 0)
+               return NULL;
+
+       if (fd <= 0)
+               return NULL;
+
+       mmap_size =  page_size * (1 + mmap_pages);
+       buff = mmap(NULL, mmap_size,
+               PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+
+       if (buff == MAP_FAILED) {
+               perror("mmap() failed.");
+               return NULL;
+       }
+       return buff;
+}
+
+/*
+ * Post process the mmap buffer.
+ * - If sample_count != NULL then return count of total
+ *   number of samples present in the mmap buffer.
+ * - If sample_count == NULL then return the address
+ *   of first sample from the mmap buffer
+ */
+void *__event_read_samples(void *sample_buff, size_t *size, u64 *sample_count)
+{
+       size_t page_size = sysconf(_SC_PAGESIZE);
+       struct perf_event_header *header = sample_buff + page_size;
+       struct perf_event_mmap_page *metadata_page = sample_buff;
+       unsigned long data_head, data_tail;
+
+       /*
+        * PERF_RECORD_SAMPLE:
+        * struct {
+        *     struct perf_event_header hdr;
+        *     u64 data[];
+        * };
+        */
+
+       data_head = metadata_page->data_head;
+       /* sync memory before reading sample */
+       mb();
+       data_tail = metadata_page->data_tail;
+
+       /* Check for sample_count */
+       if (sample_count)
+               *sample_count = 0;
+
+       while (1) {
+               /*
+                * Reads the mmap data buffer by moving
+                * the data_tail to know the last read data.
+                * data_head points to head in data buffer.
+                * refer "struct perf_event_mmap_page" in
+                * "include/uapi/linux/perf_event.h".
+                */
+               if (data_head - data_tail < sizeof(header))
+                       return NULL;
+
+               data_tail += sizeof(header);
+               if (header->type == PERF_RECORD_SAMPLE) {
+                       *size = (header->size - sizeof(header));
+                       if (!sample_count)
+                               return sample_buff + page_size + data_tail;
+                       data_tail += *size;
+                       *sample_count += 1;
+               } else {
+                       *size = (header->size - sizeof(header));
+                       if ((metadata_page->data_tail + *size) > metadata_page->data_head)
+                               data_tail = metadata_page->data_head;
+                       else
+                               data_tail += *size;
+               }
+               header = (struct perf_event_header *)((void *)header + header->size);
+       }
+       return NULL;
+}