swapcontext() fix for Mac OSX
authorBrian Norris <banorris@uci.edu>
Thu, 4 Apr 2013 02:27:06 +0000 (19:27 -0700)
committerBrian Norris <banorris@uci.edu>
Thu, 4 Apr 2013 02:29:13 +0000 (19:29 -0700)
We provide our own model_swapcontext() for Mac OSX.

common.mk
context.h [new file with mode: 0644]
model.h
snapshot.cc
threads-model.h
threads.cc

index b2adf4ca33ed25988348e712b5f57ada1a7b57c1..9fe9f09745c73ef0f75e3776c9d09c4a6b58c3d0 100644 (file)
--- a/common.mk
+++ b/common.mk
@@ -8,11 +8,9 @@ UNAME = $(shell uname)
 LIB_NAME = model
 LIB_SO = lib$(LIB_NAME).so
 
 LIB_NAME = model
 LIB_SO = lib$(LIB_NAME).so
 
-CPPFLAGS += -Wall -g
+CPPFLAGS += -Wall -g -O3
 
 # Mac OSX options
 ifeq ($(UNAME), Darwin)
 
 # Mac OSX options
 ifeq ($(UNAME), Darwin)
-CPPFLAGS += -D_XOPEN_SOURCE -DMAC -O0
-else
-CPPFLAGS += -O3
+CPPFLAGS += -D_XOPEN_SOURCE -DMAC
 endif
 endif
diff --git a/context.h b/context.h
new file mode 100644 (file)
index 0000000..862cda5
--- /dev/null
+++ b/context.h
@@ -0,0 +1,37 @@
+/**
+ * @file context.h
+ * @brief ucontext header, since Mac OSX swapcontext() is broken
+ */
+
+#ifndef __CONTEXT_H__
+#define __CONTEXT_H__
+
+#include <ucontext.h>
+
+static inline int model_swapcontext(ucontext_t *oucp, ucontext_t *ucp)
+{
+#ifdef MAC
+       /*
+        * Mac OSX swapcontext() clobbers some registers, so use a hand-rolled
+        * version with {get,set}context(). We can avoid the same problem
+        * (where optimizations can break the following code) because we don't
+        * statically link with the C library
+        */
+
+       /* volatile, so that 'i' doesn't get promoted to a register */
+       volatile int i = 0;
+
+       getcontext(oucp);
+
+       if (i == 0) {
+               i = 1;
+               setcontext(ucp);
+       }
+
+       return 0;
+#else
+       return swapcontext(oucp, ucp);
+#endif
+}
+
+#endif /* __CONTEXT_H__ */
diff --git a/model.h b/model.h
index cbd1027cf3c6874227ddf3ce9631cbea69b6eb82..12ec06c060a999e256dfb57ea0088c97a09f81c3 100644 (file)
--- a/model.h
+++ b/model.h
@@ -6,7 +6,6 @@
 #define __MODEL_H__
 
 #include <cstddef>
 #define __MODEL_H__
 
 #include <cstddef>
-#include <ucontext.h>
 #include <inttypes.h>
 
 #include "mymemory.h"
 #include <inttypes.h>
 
 #include "mymemory.h"
@@ -15,6 +14,7 @@
 #include "config.h"
 #include "modeltypes.h"
 #include "stl-model.h"
 #include "config.h"
 #include "modeltypes.h"
 #include "stl-model.h"
+#include "context.h"
 
 /* Forward declaration */
 class Node;
 
 /* Forward declaration */
 class Node;
index fb1f911557e09345ed7b8299e19d6edce97eb399..ba1c09034d6980bdfc1c841664c780668eee33b3 100644 (file)
@@ -6,12 +6,12 @@
 #include <string.h>
 #include <errno.h>
 #include <sys/wait.h>
 #include <string.h>
 #include <errno.h>
 #include <sys/wait.h>
-#include <ucontext.h>
 
 #include "hashtable.h"
 #include "snapshot.h"
 #include "mymemory.h"
 #include "common.h"
 
 #include "hashtable.h"
 #include "snapshot.h"
 #include "mymemory.h"
 #include "common.h"
+#include "context.h"
 
 #define FAILURE(mesg) { model_print("failed in the API: %s with errno relative message: %s\n", mesg, strerror(errno)); exit(EXIT_FAILURE); }
 
 
 #define FAILURE(mesg) { model_print("failed in the API: %s with errno relative message: %s\n", mesg, strerror(errno)); exit(EXIT_FAILURE); }
 
@@ -247,8 +247,6 @@ static void mprot_roll_back(snapshot_id theID)
 
 #else /* !USE_MPROTECT_SNAPSHOT */
 
 
 #else /* !USE_MPROTECT_SNAPSHOT */
 
-#include <ucontext.h>
-
 #define SHARED_MEMORY_DEFAULT  (100 * ((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
 
 #define SHARED_MEMORY_DEFAULT  (100 * ((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
 
@@ -325,7 +323,7 @@ static void fork_snapshot_init(unsigned int numbackingpages,
        newContext.uc_stack.ss_size = STACK_SIZE_DEFAULT;
        makecontext(&newContext, entryPoint, 0);
        /* switch to a new entryPoint context, on a new stack */
        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);
+       model_swapcontext(&savedSnapshotContext, &newContext);
 
        /* switch back here when takesnapshot is called */
        pid_t forkedID = 0;
 
        /* switch back here when takesnapshot is called */
        pid_t forkedID = 0;
@@ -369,7 +367,7 @@ static void fork_snapshot_init(unsigned int numbackingpages,
 
 static snapshot_id fork_take_snapshot()
 {
 
 static snapshot_id fork_take_snapshot()
 {
-       swapcontext(&savedUserSnapshotContext, &savedSnapshotContext);
+       model_swapcontext(&savedUserSnapshotContext, &savedSnapshotContext);
        DEBUG("TAKESNAPSHOT RETURN\n");
        return snapshotid;
 }
        DEBUG("TAKESNAPSHOT RETURN\n");
        return snapshotid;
 }
index ef2c9e10433559c519d1d6062963e2dd6b342f91..5fc6d675aba6a9f05b132ded2ad2aed0ad6250d5 100644 (file)
@@ -5,13 +5,13 @@
 #ifndef __THREADS_MODEL_H__
 #define __THREADS_MODEL_H__
 
 #ifndef __THREADS_MODEL_H__
 #define __THREADS_MODEL_H__
 
-#include <ucontext.h>
 #include <stdint.h>
 
 #include "mymemory.h"
 #include <threads.h>
 #include "modeltypes.h"
 #include "stl-model.h"
 #include <stdint.h>
 
 #include "mymemory.h"
 #include <threads.h>
 #include "modeltypes.h"
 #include "stl-model.h"
+#include "context.h"
 
 struct thread_params {
        thrd_start_t func;
 
 struct thread_params {
        thrd_start_t func;
index 5bfd028746aa99f314263d90d4f7234df629b63b..ae2905a9819a7d4e0159fbbf6d4f439850da1f40 100644 (file)
@@ -93,7 +93,7 @@ int Thread::create_context()
 int Thread::swap(Thread *t, ucontext_t *ctxt)
 {
        t->set_state(THREAD_READY);
 int Thread::swap(Thread *t, ucontext_t *ctxt)
 {
        t->set_state(THREAD_READY);
-       return swapcontext(&t->context, ctxt);
+       return model_swapcontext(&t->context, ctxt);
 }
 
 /**
 }
 
 /**
@@ -107,7 +107,7 @@ int Thread::swap(Thread *t, ucontext_t *ctxt)
 int Thread::swap(ucontext_t *ctxt, Thread *t)
 {
        t->set_state(THREAD_RUNNING);
 int Thread::swap(ucontext_t *ctxt, Thread *t)
 {
        t->set_state(THREAD_RUNNING);
-       return swapcontext(ctxt, &t->context);
+       return model_swapcontext(ctxt, &t->context);
 }
 
 
 }