[runtime] Add a separate icall for Monitor.Enter(obj,&bool).
[mono.git] / mono / utils / mono-context.h
old mode 100755 (executable)
new mode 100644 (file)
index 1125480..33a821a
 #include <signal.h>
 #endif
 
+#ifdef HOST_WATCHOS
+#include <libunwind.h>
+#endif
+
 /*
  * General notes about mono-context.
  * Each arch defines a MonoContext struct with all GPR regs + IP/PC.
@@ -30,7 +34,9 @@
 /*HACK, move this to an eventual mono-signal.c*/
 #if defined( __linux__) || defined(__sun) || defined(__APPLE__) || defined(__NetBSD__) || \
        defined(__FreeBSD__) || defined(__OpenBSD__)
-#define MONO_SIGNAL_USE_SIGACTION
+#ifdef HAVE_SIGACTION
+#define MONO_SIGNAL_USE_SIGACTION 1
+#endif
 #endif
 
 #if defined(__native_client__)
@@ -145,40 +151,28 @@ typedef struct {
 
 #elif (defined(__x86_64__) && !defined(MONO_CROSS_COMPILE)) || (defined(TARGET_AMD64)) /* defined(__i386__) */
 
+#include <mono/arch/amd64/amd64-codegen.h>
 
 #if !defined( HOST_WIN32 ) && !defined(__native_client__) && !defined(__native_client_codegen__)
 
+#ifdef HAVE_SIGACTION
 #define MONO_SIGNAL_USE_SIGACTION 1
+#endif
 
 #endif
 
 typedef struct {
-       mgreg_t rax;
-       mgreg_t rbx;
-       mgreg_t rcx;
-       mgreg_t rdx;
-       mgreg_t rbp;
-       mgreg_t rsp;
-    mgreg_t rsi;
-       mgreg_t rdi;
-       mgreg_t r8;
-       mgreg_t r9;
-       mgreg_t r10;
-       mgreg_t r11;
-       mgreg_t r12;
-       mgreg_t r13;
-       mgreg_t r14;
-       mgreg_t r15;
-       mgreg_t rip;
+       mgreg_t gregs [AMD64_NREG];
+       double fregs [AMD64_XMM_NREG];
 } MonoContext;
 
-#define MONO_CONTEXT_SET_IP(ctx,ip) do { (ctx)->rip = (mgreg_t)(ip); } while (0); 
-#define MONO_CONTEXT_SET_BP(ctx,bp) do { (ctx)->rbp = (mgreg_t)(bp); } while (0); 
-#define MONO_CONTEXT_SET_SP(ctx,esp) do { (ctx)->rsp = (mgreg_t)(esp); } while (0); 
+#define MONO_CONTEXT_SET_IP(ctx,ip) do { (ctx)->gregs [AMD64_RIP] = (mgreg_t)(ip); } while (0);
+#define MONO_CONTEXT_SET_BP(ctx,bp) do { (ctx)->gregs [AMD64_RBP] = (mgreg_t)(bp); } while (0);
+#define MONO_CONTEXT_SET_SP(ctx,esp) do { (ctx)->gregs [AMD64_RSP] = (mgreg_t)(esp); } while (0);
 
-#define MONO_CONTEXT_GET_IP(ctx) ((gpointer)((ctx)->rip))
-#define MONO_CONTEXT_GET_BP(ctx) ((gpointer)((ctx)->rbp))
-#define MONO_CONTEXT_GET_SP(ctx) ((gpointer)((ctx)->rsp))
+#define MONO_CONTEXT_GET_IP(ctx) ((gpointer)((ctx)->gregs [AMD64_RIP]))
+#define MONO_CONTEXT_GET_BP(ctx) ((gpointer)((ctx)->gregs [AMD64_RBP]))
+#define MONO_CONTEXT_GET_SP(ctx) ((gpointer)((ctx)->gregs [AMD64_RSP]))
 
 #if defined (HOST_WIN32) && !defined(__GNUC__)
 /* msvc doesn't support inline assembly, so have to use a separate .asm file */
@@ -236,12 +230,12 @@ extern void mono_context_get_current (void *);
                : "rdx", "memory")
 #endif
 
-#if !defined(HOST_WIN32)
 #define MONO_ARCH_HAS_MONO_CONTEXT 1
-#endif
 
 #elif (defined(__arm__) && !defined(MONO_CROSS_COMPILE)) || (defined(TARGET_ARM)) /* defined(__x86_64__) */
 
+#include <mono/arch/arm/arm-codegen.h>
+
 typedef struct {
        mgreg_t pc;
        mgreg_t regs [16];
@@ -258,6 +252,33 @@ typedef struct {
 #define MONO_CONTEXT_GET_BP(ctx) ((gpointer)((ctx)->regs [ARMREG_FP]))
 #define MONO_CONTEXT_GET_SP(ctx) ((gpointer)((ctx)->regs [ARMREG_SP]))
 
+#if defined(HOST_WATCHOS)
+
+#define MONO_CONTEXT_GET_CURRENT(ctx) do { \
+       unw_context_t uctx; \
+       unw_cursor_t c; \
+       unw_word_t data; \
+       g_assert (unw_getcontext (&uctx) == 0); \
+       g_assert (unw_init_local (&c, &uctx) == 0); \
+       for (int reg = 0; reg < 13; ++reg) { \
+               unw_get_reg (&c, (unw_regnum_t) UNW_ARM_R0 + reg, &data); \
+               ctx.regs[reg] = data; \
+       } \
+       unw_get_reg (&c, UNW_ARM_SP, &data); \
+       ctx.regs[ARMREG_SP] = data; \
+       unw_get_reg (&c, UNW_ARM_LR, &data); \
+       ctx.regs[ARMREG_LR] = data; \
+       unw_get_reg (&c, UNW_ARM_IP, &data); \
+       ctx.regs[ARMREG_PC] = data; \
+       ctx.pc = ctx.regs[ARMREG_PC]; \
+       for (int reg = 0; reg < 16; ++reg) { \
+               unw_get_reg (&c, (unw_regnum_t) UNW_ARM_D0 + reg, &data); \
+               ctx.fregs[reg] = data; \
+       } \
+} while (0);
+
+#else
+
 #define MONO_CONTEXT_GET_CURRENT(ctx)  do {    \
        __asm__ __volatile__(                   \
                "push {r0}\n"                           \
@@ -281,6 +302,10 @@ typedef struct {
        ctx.pc = ctx.regs [15];                 \
 } while (0)
 
+#endif
+
+#define MONO_ARCH_HAS_MONO_CONTEXT 1
+
 #elif (defined(__aarch64__) && !defined(MONO_CROSS_COMPILE)) || (defined(TARGET_ARM64))
 
 #include <mono/arch/arm64/arm64-codegen.h>
@@ -333,6 +358,8 @@ typedef struct {
        ); \
 } while (0)
 
+#define MONO_ARCH_HAS_MONO_CONTEXT 1
+
 #elif defined(__mono_ppc__) /* defined(__arm__) */
 
 /* we define our own structure and we'll copy the data
@@ -458,6 +485,8 @@ mono_ia64_context_get_fp (MonoContext *ctx)
 
 #elif ((defined(__mips__) && !defined(MONO_CROSS_COMPILE)) || (defined(TARGET_MIPS))) && SIZEOF_REGISTER == 4 /* defined(__ia64__) */
 
+#include <mono/arch/mips/mips-codegen.h>
+
 typedef struct {
        mgreg_t     sc_pc;
        mgreg_t         sc_regs [32];
@@ -546,7 +575,18 @@ typedef struct ucontext MonoContext;
 
 #endif
 
-void mono_sigctx_to_monoctx (void *sigctx, MonoContext *mctx) MONO_INTERNAL;
-void mono_monoctx_to_sigctx (MonoContext *mctx, void *sigctx) MONO_INTERNAL;
+/*
+ * The naming is misleading, the SIGCTX argument should be the platform's context
+ * structure (ucontext_c on posix, CONTEXT on windows).
+ */
+void mono_sigctx_to_monoctx (void *sigctx, MonoContext *mctx);
+
+/*
+ * This will not completely initialize SIGCTX since MonoContext contains less
+ * information that the system context. The caller should obtain a SIGCTX from
+ * the system, and use this function to override the parts of it which are
+ * also in MonoContext.
+ */
+void mono_monoctx_to_sigctx (MonoContext *mctx, void *sigctx);
 
 #endif /* __MONO_MONO_CONTEXT_H__ */