--- /dev/null
+#include "test_fault_helper.h"
+#include "fail.h"
+#include <sys/mman.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <assert.h>
+#include <TargetConditionals.h>
+
+#define MEMSIZE (1L<<30)
+
+static char* memblock;
+
+int test_fault_setup() {
+ char *ptr;
+ int pgsz = getpagesize();
+ int retval;
+
+ memblock = (char *)mmap(NULL, MEMSIZE, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
+ VERIFY(memblock != MAP_FAILED, "mmap failed");
+
+ /* make sure memory is paged */
+ for(ptr = memblock; ptr<memblock+MEMSIZE; ptr+= pgsz) {
+ *ptr = 1;
+ }
+
+ /* set to read only, then back to read write so it faults on first write */
+ retval = mprotect(memblock, MEMSIZE, PROT_READ);
+ VERIFY(retval == 0, "mprotect failed");
+
+ retval = mprotect(memblock, MEMSIZE, PROT_READ | PROT_WRITE);
+ VERIFY(retval == 0, "mprotect failed");
+
+ return PERFINDEX_SUCCESS;
+}
+
+int test_fault_helper(int thread_id, int num_threads, long long length, testtype_t testtype) {
+ char *ptr;
+ int pgsz = getpagesize();
+ int retval;
+
+ long long num_pages = MEMSIZE / pgsz;
+ long long region_len = num_pages/num_threads;
+ long long region_start = region_len * thread_id;
+ long long region_end;
+
+ if(thread_id < num_pages % num_threads) {
+ region_start += thread_id;
+ region_len++;
+ }
+ else {
+ region_start += num_pages % num_threads;
+ }
+
+ region_start *= pgsz;
+ region_len *= pgsz;
+ region_end = region_start + region_len;
+
+ long long left = length;
+
+ while(1) {
+ for(ptr = memblock+region_start; ptr<memblock+region_end; ptr+= pgsz) {
+ *ptr = 1;
+ left--;
+ if(left==0)
+ break;
+ }
+
+ if(left==0)
+ break;
+
+ if(testtype == TESTFAULT) {
+ retval = mprotect(memblock+region_start, region_len, PROT_READ) == 0;
+ VERIFY(retval == 0, "mprotect failed");
+ retval = mprotect(memblock+region_start, region_len, PROT_READ | PROT_WRITE) == 0;
+ VERIFY(retval == 0, "mprotect failed");
+ }
+
+ else if(testtype == TESTZFOD) {
+ retval = munmap(memblock+region_start, region_len) == 0;
+ VERIFY(retval == 0, "munmap failed");
+ ptr = mmap(memblock+region_start, region_len, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0);
+ VERIFY(ptr != 0, "mmap failed");
+ }
+ }
+ return PERFINDEX_SUCCESS;
+}