+
+/* Primary struct for snapshotting system */
+struct mprot_snapshotter {
+ mprot_snapshotter(unsigned int numbackingpages, unsigned int numsnapshots, unsigned int nummemoryregions);
+ ~mprot_snapshotter();
+
+ struct MemoryRegion *regionsToSnapShot; //This pointer references an array of memory regions to snapshot
+ snapshot_page_t *backingStore; //This pointer references an array of snapshotpage's that form the backing store
+ void *backingStoreBasePtr; //This pointer references an array of snapshotpage's that form the backing store
+ struct BackingPageRecord *backingRecords; //This pointer references an array of backingpagerecord's (same number of elements as backingstore
+ struct SnapShotRecord *snapShots; //This pointer references the snapshot array
+
+ unsigned int lastSnapShot; //Stores the next snapshot record we should use
+ unsigned int lastBackingPage; //Stores the next backingpage we should use
+ unsigned int lastRegion; //Stores the next memory region to be used
+
+ unsigned int maxRegions; //Stores the max number of memory regions we support
+ unsigned int maxBackingPages; //Stores the total number of backing pages
+ unsigned int maxSnapShots; //Stores the total number of snapshots we allow
+
+ MEMALLOC
+};
+
+static struct mprot_snapshotter *mprot_snap = NULL;
+
+mprot_snapshotter::mprot_snapshotter(unsigned int backing_pages, unsigned int snapshots, unsigned int regions) :
+ lastSnapShot(0),
+ lastBackingPage(0),
+ lastRegion(0),
+ maxRegions(regions),
+ maxBackingPages(backing_pages),
+ maxSnapShots(snapshots)
+{
+ regionsToSnapShot = (struct MemoryRegion *)model_malloc(sizeof(struct MemoryRegion) * regions);
+ backingStoreBasePtr = (void *)model_malloc(sizeof(snapshot_page_t) * (backing_pages + 1));
+ //Page align the backingstorepages
+ backingStore = (snapshot_page_t *)PageAlignAddressUpward(backingStoreBasePtr);
+ backingRecords = (struct BackingPageRecord *)model_malloc(sizeof(struct BackingPageRecord) * backing_pages);
+ snapShots = (struct SnapShotRecord *)model_malloc(sizeof(struct SnapShotRecord) * snapshots);
+}
+
+mprot_snapshotter::~mprot_snapshotter()
+{
+ model_free(regionsToSnapShot);
+ model_free(backingStoreBasePtr);
+ model_free(backingRecords);
+ model_free(snapShots);
+}
+
+/** mprot_handle_pf is the page fault handler for mprotect based snapshotting
+ * algorithm.
+ */
+static void mprot_handle_pf(int sig, siginfo_t *si, void *unused)
+{
+ if (si->si_code == SEGV_MAPERR) {
+ model_print("Real Fault at %p\n", si->si_addr);
+ print_trace();
+ model_print("For debugging, place breakpoint at: %s:%d\n",
+ __FILE__, __LINE__);
+ exit(EXIT_FAILURE);
+ }
+ void* addr = ReturnPageAlignedAddress(si->si_addr);
+
+ unsigned int backingpage = mprot_snap->lastBackingPage++; //Could run out of pages...
+ if (backingpage == mprot_snap->maxBackingPages) {
+ model_print("Out of backing pages at %p\n", si->si_addr);
+ exit(EXIT_FAILURE);
+ }
+
+ //copy page
+ memcpy(&(mprot_snap->backingStore[backingpage]), addr, sizeof(snapshot_page_t));
+ //remember where to copy page back to
+ mprot_snap->backingRecords[backingpage].basePtrOfPage = addr;
+ //set protection to read/write
+ if (mprotect(addr, sizeof(snapshot_page_t), PROT_READ | PROT_WRITE)) {
+ perror("mprotect");
+ // Handle error by quitting?
+ }
+}
+
+static void mprot_snapshot_init(unsigned int numbackingpages,
+ unsigned int numsnapshots, unsigned int nummemoryregions,
+ unsigned int numheappages, VoidFuncPtr entryPoint)
+{
+ /* Setup a stack for our signal handler.... */
+ stack_t ss;
+ ss.ss_sp = PageAlignAddressUpward(model_malloc(SIGSTACKSIZE + PAGESIZE - 1));
+ ss.ss_size = SIGSTACKSIZE;
+ ss.ss_flags = 0;
+ sigaltstack(&ss, NULL);
+
+ struct sigaction sa;
+ sa.sa_flags = SA_SIGINFO | SA_NODEFER | SA_RESTART | SA_ONSTACK;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_sigaction = mprot_handle_pf;
+#ifdef MAC
+ if (sigaction(SIGBUS, &sa, NULL) == -1) {
+ model_print("SIGACTION CANNOT BE INSTALLED\n");
+ exit(EXIT_FAILURE);
+ }