#include "context.h"
#include "model.h"
+
+#if USE_MPROTECT_SNAPSHOT
+
/** PageAlignedAdressUpdate return a page aligned address for the
* address being added as a side effect the numBytes are also changed.
*/
return (void *)((((uintptr_t)addr) + PAGESIZE - 1) & ~(PAGESIZE - 1));
}
-#if USE_MPROTECT_SNAPSHOT
-
/* Each SnapShotRecord lists the firstbackingpage that must be written to
* revert to that snapshot */
struct SnapShotRecord {
snapshot_add_memory_region(pagealignedbase, numheappages);
}
-
-static void mprot_startExecution(VoidFuncPtr entryPoint) {
- entryPoint();
+static void mprot_startExecution(ucontext_t * context, VoidFuncPtr entryPoint) {
+ /* setup the shared-stack context */
+ create_context(context, fork_snap->mStackBase, model_calloc(STACK_SIZE_DEFAULT, 1), STACK_SIZE_DEFAULT, entryPoint);
}
static void mprot_add_to_snapshot(void *addr, unsigned int numPages)
*/
volatile snapshot_id mIDToRollback;
- /**
- * @brief The context for the shared (non-snapshot) stack
- *
- * This context is passed between the various processes which represent
- * various snapshot states. It should be used primarily for the
- * "client-side" code, not the main snapshot loop.
- */
- ucontext_t shared_ctxt;
+
/** @brief Inter-process tracking of the next snapshot ID */
snapshot_id currSnapShotID;
};
static struct fork_snapshotter *fork_snap = NULL;
+ucontext_t shared_ctxt;
/** @statics
* These variables are necessary because the stack is shared region and
getcontext(ctxt);
ctxt->uc_stack.ss_sp = stack;
ctxt->uc_stack.ss_size = stacksize;
+ ctxt->uc_link = NULL;
makecontext(ctxt, func, 0);
}
* process */
static void fork_exit()
{
- /* Intentionally empty */
+ _Exit(EXIT_SUCCESS);
}
static void createSharedMemory()
if (!fork_snap)
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);
+ model_snapshot_space = create_mspace(numheappages * PAGESIZE, 1);
}
-static void fork_startExecution(VoidFuncPtr entryPoint) {
- /* setup an "exiting" context */
- char stack[128];
- create_context(&exit_ctxt, stack, sizeof(stack), fork_exit);
-
- /* setup the shared-stack context */
- create_context(&fork_snap->shared_ctxt, fork_snap->mStackBase,
- STACK_SIZE_DEFAULT, entryPoint);
- /* switch to a new entryPoint context, on a new stack */
- model_swapcontext(&private_ctxt, &fork_snap->shared_ctxt);
+volatile int modellock = 0;
+static void fork_loop() {
/* switch back here when takesnapshot is called */
snapshotid = fork_snap->currSnapShotID;
if (model->params.nofork) {
- setcontext(&fork_snap->shared_ctxt);
- exit(EXIT_SUCCESS);
+ setcontext(&shared_ctxt);
+ _Exit(EXIT_SUCCESS);
}
while (true) {
pid_t forkedID;
fork_snap->currSnapShotID = snapshotid + 1;
+
+ modellock = 1;
forkedID = fork();
+ modellock = 0;
if (0 == forkedID) {
- setcontext(&fork_snap->shared_ctxt);
+ setcontext(&shared_ctxt);
} else {
DEBUG("parent PID: %d, child PID: %d, snapshot ID: %d\n",
getpid(), forkedID, snapshotid);
}
if (fork_snap->mIDToRollback != snapshotid)
- exit(EXIT_SUCCESS);
+ _Exit(EXIT_SUCCESS);
}
}
}
-static snapshot_id fork_take_snapshot()
-{
- model_swapcontext(&fork_snap->shared_ctxt, &private_ctxt);
+static void fork_startExecution(ucontext_t *context, VoidFuncPtr entryPoint) {
+ /* setup an "exiting" context */
+ int exit_stack_size = 256;
+ create_context(&exit_ctxt, snapshot_calloc(exit_stack_size, 1), exit_stack_size, fork_exit);
+
+ /* setup the system context */
+ create_context(context, fork_snap->mStackBase, STACK_SIZE_DEFAULT, entryPoint);
+ /* switch to a new entryPoint context, on a new stack */
+ create_context(&private_ctxt, snapshot_calloc(STACK_SIZE_DEFAULT, 1), STACK_SIZE_DEFAULT, fork_loop);
+}
+
+static snapshot_id fork_take_snapshot() {
+ model_swapcontext(&shared_ctxt, &private_ctxt);
DEBUG("TAKESNAPSHOT RETURN\n");
return snapshotid;
}
{
DEBUG("Rollback\n");
fork_snap->mIDToRollback = theID;
- model_swapcontext(&fork_snap->shared_ctxt, &exit_ctxt);
+ model_swapcontext(model->get_system_context(), &exit_ctxt);
fork_snap->mIDToRollback = -1;
}
#endif
}
-void startExecution(VoidFuncPtr entryPoint)
+void startExecution(ucontext_t *context, VoidFuncPtr entryPoint)
{
#if USE_MPROTECT_SNAPSHOT
- mprot_startExecution(entryPoint);
+ mprot_startExecution(context, entryPoint);
#else
- fork_startExecution(entryPoint);
+ fork_startExecution(context, entryPoint);
#endif
}