From: Brian Norris <banorris@uci.edu>
Date: Thu, 4 Apr 2013 02:27:06 +0000 (-0700)
Subject: swapcontext() fix for Mac OSX
X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=2b004336a919f74a5ca8f6d87ad5414360a949c7;p=cdsspec-compiler.git

swapcontext() fix for Mac OSX

We provide our own model_swapcontext() for Mac OSX.
---

diff --git a/common.mk b/common.mk
index b2adf4c..9fe9f09 100644
--- a/common.mk
+++ b/common.mk
@@ -8,11 +8,9 @@ UNAME = $(shell uname)
 LIB_NAME = model
 LIB_SO = lib$(LIB_NAME).so
 
-CPPFLAGS += -Wall -g
+CPPFLAGS += -Wall -g -O3
 
 # Mac OSX options
 ifeq ($(UNAME), Darwin)
-CPPFLAGS += -D_XOPEN_SOURCE -DMAC -O0
-else
-CPPFLAGS += -O3
+CPPFLAGS += -D_XOPEN_SOURCE -DMAC
 endif
diff --git a/context.h b/context.h
new file mode 100644
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 cbd1027..12ec06c 100644
--- a/model.h
+++ b/model.h
@@ -6,7 +6,6 @@
 #define __MODEL_H__
 
 #include <cstddef>
-#include <ucontext.h>
 #include <inttypes.h>
 
 #include "mymemory.h"
@@ -15,6 +14,7 @@
 #include "config.h"
 #include "modeltypes.h"
 #include "stl-model.h"
+#include "context.h"
 
 /* Forward declaration */
 class Node;
diff --git a/snapshot.cc b/snapshot.cc
index fb1f911..ba1c090 100644
--- a/snapshot.cc
+++ b/snapshot.cc
@@ -6,12 +6,12 @@
 #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 "context.h"
 
 #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 */
 
-#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
 
@@ -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 */
-	swapcontext(&savedSnapshotContext, &newContext);
+	model_swapcontext(&savedSnapshotContext, &newContext);
 
 	/* 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()
 {
-	swapcontext(&savedUserSnapshotContext, &savedSnapshotContext);
+	model_swapcontext(&savedUserSnapshotContext, &savedSnapshotContext);
 	DEBUG("TAKESNAPSHOT RETURN\n");
 	return snapshotid;
 }
diff --git a/threads-model.h b/threads-model.h
index ef2c9e1..5fc6d67 100644
--- a/threads-model.h
+++ b/threads-model.h
@@ -5,13 +5,13 @@
 #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 "context.h"
 
 struct thread_params {
 	thrd_start_t func;
diff --git a/threads.cc b/threads.cc
index 5bfd028..ae2905a 100644
--- a/threads.cc
+++ b/threads.cc
@@ -93,7 +93,7 @@ int Thread::create_context()
 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);
-	return swapcontext(ctxt, &t->context);
+	return model_swapcontext(ctxt, &t->context);
 }