#include "mymemory.h"
#include "common.h"
#include "context.h"
+#include "model.h"
/** PageAlignedAdressUpdate return a page aligned address for the
* address being added as a side effect the numBytes are also changed.
/* Struct for each memory region */
struct MemoryRegion {
- void *basePtr; // base of memory region
- int sizeInPages; // size of memory region in pages
+ void *basePtr; // base of memory region
+ int sizeInPages; // size of memory region in pages
};
/** ReturnPageAlignedAddress returns a page aligned address for the
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
+ 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 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
+ 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
};
}
void* addr = ReturnPageAlignedAddress(si->si_addr);
- unsigned int backingpage = mprot_snap->lastBackingPage++; //Could run out of pages...
+ 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);
static void mprot_snapshot_init(unsigned int numbackingpages,
unsigned int numsnapshots, unsigned int nummemoryregions,
- unsigned int numheappages, VoidFuncPtr entryPoint)
+ unsigned int numheappages)
{
/* Setup a stack for our signal handler.... */
stack_t ss;
memset(&si, 0, sizeof(si));
si.si_addr = ss.ss_sp;
mprot_handle_pf(SIGSEGV, &si, NULL);
- mprot_snap->lastBackingPage--; //remove the fake page we copied
+ mprot_snap->lastBackingPage--; //remove the fake page we copied
void *basemySpace = model_malloc((numheappages + 1) * PAGESIZE);
void *pagealignedbase = PageAlignAddressUpward(basemySpace);
pagealignedbase = PageAlignAddressUpward(base_model_snapshot_space);
model_snapshot_space = create_mspace_with_base(pagealignedbase, numheappages * PAGESIZE, 1);
snapshot_add_memory_region(pagealignedbase, numheappages);
+}
- 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)
}
mprot_snap->lastSnapShot = theID;
mprot_snap->lastBackingPage = mprot_snap->snapShots[theID].firstBackingPage;
- mprot_take_snapshot(); //Make sure current snapshot is still good...All later ones are cleared
+ mprot_take_snapshot(); //Make sure current snapshot is still good...All later ones are cleared
}
#else /* !USE_MPROTECT_SNAPSHOT */
-#define SHARED_MEMORY_DEFAULT (100 * ((size_t)1 << 20))// 100mb for the shared memory
+#define SHARED_MEMORY_DEFAULT (200 * ((size_t)1 << 20)) // 100mb for the shared memory
#define STACK_SIZE_DEFAULT (((size_t)1 << 20) * 20) // 20 mb out of the above 100 mb for my stack
struct fork_snapshotter {
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()
static void fork_snapshot_init(unsigned int numbackingpages,
unsigned int numsnapshots, unsigned int nummemoryregions,
- unsigned int numheappages, VoidFuncPtr entryPoint)
+ unsigned int numheappages)
{
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);
-
- /* setup an "exiting" context */
- char stack[128];
- create_context(&exit_ctxt, stack, sizeof(stack), fork_exit);
+ model_snapshot_space = create_mspace(numheappages * PAGESIZE, 1);
+}
- /* 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);
+ }
while (true) {
pid_t forkedID;
fork_snap->currSnapShotID = snapshotid + 1;
+
+ modellock = 1;
forkedID = fork();
+ modellock = 0;
if (0 == forkedID) {
setcontext(&fork_snap->shared_ctxt);
}
if (fork_snap->mIDToRollback != snapshotid)
- exit(EXIT_SUCCESS);
+ _Exit(EXIT_SUCCESS);
}
}
}
-static snapshot_id fork_take_snapshot()
-{
+static void fork_startExecution(ucontext_t *context, VoidFuncPtr entryPoint) {
+ /* setup an "exiting" context */
+ char stack[128];
+ create_context(&exit_ctxt, stack, sizeof(stack), 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(&fork_snap->shared_ctxt, &private_ctxt);
DEBUG("TAKESNAPSHOT RETURN\n");
return snapshotid;
fork_snap->mIDToRollback = -1;
}
-#endif/* !USE_MPROTECT_SNAPSHOT */
+#endif /* !USE_MPROTECT_SNAPSHOT */
/**
* @brief Initializes the snapshot system
*/
void snapshot_system_init(unsigned int numbackingpages,
unsigned int numsnapshots, unsigned int nummemoryregions,
- unsigned int numheappages, VoidFuncPtr entryPoint)
+ unsigned int numheappages)
+{
+#if USE_MPROTECT_SNAPSHOT
+ mprot_snapshot_init(numbackingpages, numsnapshots, nummemoryregions, numheappages);
+#else
+ fork_snapshot_init(numbackingpages, numsnapshots, nummemoryregions, numheappages);
+#endif
+}
+
+void startExecution(ucontext_t *context, VoidFuncPtr entryPoint)
{
#if USE_MPROTECT_SNAPSHOT
- mprot_snapshot_init(numbackingpages, numsnapshots, nummemoryregions, numheappages, entryPoint);
+ mprot_startExecution(context, entryPoint);
#else
- fork_snapshot_init(numbackingpages, numsnapshots, nummemoryregions, numheappages, entryPoint);
+ fork_startExecution(context, entryPoint);
#endif
}