+ if (sigaction(SIGSEGV, &sa, NULL) == -1) {
+ model_print("SIGACTION CANNOT BE INSTALLED\n");
+ exit(EXIT_FAILURE);
+ }
+
+ initSnapShotRecord(numbackingpages, numsnapshots, nummemoryregions);
+
+ // EVIL HACK: We need to make sure that calls into the HandlePF method don't cause dynamic links
+ // The problem is that we end up protecting state in the dynamic linker...
+ // Solution is to call our signal handler before we start protecting stuff...
+
+ siginfo_t si;
+ memset(&si, 0, sizeof(si));
+ si.si_addr = ss.ss_sp;
+ HandlePF(SIGSEGV, &si, NULL);
+ snapshotrecord->lastBackingPage--; //remove the fake page we copied
+
+ void *basemySpace = model_malloc((numheappages + 1) * PAGESIZE);
+ void *pagealignedbase = PageAlignAddressUpward(basemySpace);
+ user_snapshot_space = create_mspace_with_base(pagealignedbase, numheappages * PAGESIZE, 1);
+ addMemoryRegionToSnapShot(pagealignedbase, numheappages);
+
+ void *base_model_snapshot_space = model_malloc((numheappages + 1) * PAGESIZE);
+ pagealignedbase = PageAlignAddressUpward(base_model_snapshot_space);
+ model_snapshot_space = create_mspace_with_base(pagealignedbase, numheappages * PAGESIZE, 1);
+ addMemoryRegionToSnapShot(pagealignedbase, numheappages);
+
+ entryPoint();
+}
+#else
+void initSnapshotLibrary(unsigned int numbackingpages,
+ unsigned int numsnapshots, unsigned int nummemoryregions,
+ unsigned int numheappages, VoidFuncPtr entryPoint)
+{
+ if (!snapshotrecord)
+ createSharedMemory();
+
+ void *base_model_snapshot_space = malloc((numheappages + 1) * PAGESIZE);
+ void *pagealignedbase = PageAlignAddressUpward(base_model_snapshot_space);
+ model_snapshot_space = create_mspace_with_base(pagealignedbase, numheappages * PAGESIZE, 1);
+
+ //step 2 setup the stack context.
+ ucontext_t newContext;
+ getcontext(&newContext);
+ newContext.uc_stack.ss_sp = snapshotrecord->mStackBase;
+ newContext.uc_stack.ss_size = STACK_SIZE_DEFAULT;
+ makecontext(&newContext, entryPoint, 0);
+ /* switch to a new entryPoint context, on a new stack */
+ swapcontext(&savedSnapshotContext, &newContext);
+
+ /* switch back here when takesnapshot is called */
+ pid_t forkedID = 0;
+ snapshotid = snapshotrecord->currSnapShotID;
+ /* This bool indicates that the current process's snapshotid is same
+ as the id to which the rollback needs to occur */
+
+ bool rollback = false;
+ while (true) {
+ snapshotrecord->currSnapShotID = snapshotid + 1;
+ forkedID = fork();
+
+ if (0 == forkedID) {
+ /* If the rollback bool is set, switch to the context we need to
+ return to during a rollback. */
+ if (rollback) {
+ setcontext(&(snapshotrecord->mContextToRollback));
+ } else {
+ /*Child process which is forked as a result of takesnapshot
+ call should switch back to the takesnapshot context*/
+ setcontext(&savedUserSnapshotContext);