sgen_supported=true
;;
cygwin*)
+ sgen_supported=true
have_visibility_hidden=no
;;
haiku*)
#define mono_mutex_init(mutex,attr) InitializeCriticalSection((mutex))
#define mono_mutex_lock(mutex) EnterCriticalSection((mutex))
+#define mono_mutex_trylock(mutex) TryEnterCriticalSection((mutex))
#define mono_mutex_unlock(mutex) LeaveCriticalSection((mutex))
#define mono_mutex_destroy(mutex) DeleteCriticalSection((mutex))
#define mono_cond_broadcast(cond) (!SetEvent(*(cond)))
#define mono_cond_destroy(cond) CloseHandle(*(cond))
-#define MONO_MUTEX_INITIALIZER NULL
#define MONO_COND_INITIALIZER NULL
#endif
security-manager.h \
sgen-os-posix.c \
sgen-os-mach.c \
+ sgen-os-win32.c \
sgen-gc.c \
sgen-internal.c \
sgen-pinned-allocator.c \
#define REDZONE_SIZE 0
#define ARCH_NUM_REGS 8
+
+#ifdef MONO_ARCH_HAS_MONO_CONTEXT
#define USE_MONO_CTX
+#else
+#define ARCH_STORE_REGS(ptr) \
+ __asm__ __volatile__( \
+ "mov %%edi,0(%0)\n" \
+ "mov %%esi,4(%0)\n" \
+ "mov %%ebx,8(%0)\n" \
+ "mov %%edx,12(%0)\n" \
+ "mov %%ecx,16(%0)\n" \
+ "mov %%eax,20(%0)\n" \
+ "mov %%ebp,24(%0)\n" \
+ "mov %%esp,28(%0)\n" \
+ : \
+ : "r" (ptr) \
+ )
+#endif
/*FIXME, move this to mono-sigcontext as this is generaly useful.*/
#define ARCH_SIGCTX_SP(ctx) (UCONTEXT_REG_ESP ((ctx)))
//#define CARDTABLE_STATS
#include <unistd.h>
+#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
+#endif
#include <sys/types.h>
guint8 *sgen_cardtable;
*/
//#define XDOMAIN_CHECKS_IN_WBARRIER
+#ifndef HOST_WIN32
#ifndef SGEN_BINARY_PROTOCOL
#ifndef HEAVY_STATISTICS
#define MANAGED_ALLOCATION
#endif
#endif
#endif
+#endif
static gboolean
is_ip_in_managed_allocator (MonoDomain *domain, gpointer ip);
mono_sgen_wait_for_suspend_ack (restart_count);
if (sleep_duration < 0) {
+#ifdef HOST_WIN32
+ SwitchToThread ();
+#else
sched_yield ();
+#endif
sleep_duration = 0;
} else {
g_usleep (sleep_duration);
cb.thread_unregister = sgen_thread_unregister;
cb.thread_attach = sgen_thread_attach;
cb.mono_method_is_critical = (gpointer)is_critical_method;
+#ifndef HOST_WIN32
cb.mono_gc_pthread_create = (gpointer)mono_gc_pthread_create;
+#endif
mono_threads_init (&cb, sizeof (SgenThreadInfo));
gpointer stopped_ip; /* only valid if the thread is stopped */
MonoDomain *stopped_domain; /* ditto */
-#if defined(__MACH__)
#ifdef USE_MONO_CTX
+#ifdef __MACH__
MonoContext ctx; /* ditto */
-#else
- gpointer regs[ARCH_NUM_REGS]; /* ditto */
#endif
-#endif
-
-#ifdef USE_MONO_CTX
MonoContext *monoctx; /* ditto */
+
#else
+
+#if defined(__MACH__) || defined(HOST_WIN32)
+ gpointer regs[ARCH_NUM_REGS]; /* ditto */
+#endif
gpointer *stopped_regs; /* ditto */
#endif
+
#ifndef HAVE_KW_THREAD
char *tlab_start;
char *tlab_next;
} while (InterlockedCompareExchange (&(x), __old_x + (i), __old_x) != __old_x); \
} while (0)
+#ifndef HOST_WIN32
/* we intercept pthread_create calls to know which threads exist */
#define USE_PTHREAD_INTERCEPT 1
+#endif
#ifdef HEAVY_STATISTICS
#define HEAVY_STAT(x) x
--- /dev/null
+#include "config.h"
+
+#if defined(HAVE_SGEN_GC) && defined(HOST_WIN32)
+
+#include <windows.h>
+
+#include "metadata/sgen-gc.h"
+#include "metadata/gc-internal.h"
+
+gboolean
+mono_sgen_resume_thread (SgenThreadInfo *info)
+{
+ DWORD id = mono_thread_info_get_tid (info);
+ HANDLE handle = OpenThread (THREAD_ALL_ACCESS, FALSE, id);
+ DWORD result;
+
+ g_assert (handle);
+
+ result = ResumeThread (handle);
+ g_assert (result != (DWORD)-1);
+
+ CloseHandle (handle);
+
+ return result != (DWORD)-1;
+}
+
+gboolean
+mono_sgen_suspend_thread (SgenThreadInfo *info)
+{
+ DWORD id = mono_thread_info_get_tid (info);
+ HANDLE handle = OpenThread (THREAD_ALL_ACCESS, FALSE, id);
+ CONTEXT context;
+ DWORD result;
+
+ g_assert (handle);
+
+ result = SuspendThread (handle);
+ g_assert (result != (DWORD)-1);
+ if (result == (DWORD)-1) {
+ CloseHandle (handle);
+ return FALSE;
+ }
+
+ context.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL;
+
+ if (!GetThreadContext (handle, &context)) {
+ g_assert_not_reached ();
+ ResumeThread (handle);
+ CloseHandle (handle);
+ return FALSE;
+ }
+
+ g_assert (context.ContextFlags & CONTEXT_INTEGER);
+ g_assert (context.ContextFlags & CONTEXT_CONTROL);
+
+ CloseHandle (handle);
+
+ info->stopped_domain = NULL; /* FIXME: implement! */
+ info->stopped_ip = (gpointer)context.Eip;
+ info->stack_start = (char*)context.Esp - REDZONE_SIZE;
+
+ info->regs [0] = context.Edi;
+ info->regs [1] = context.Esi;
+ info->regs [2] = context.Ebx;
+ info->regs [3] = context.Edx;
+ info->regs [4] = context.Ecx;
+ info->regs [5] = context.Eax;
+ info->regs [6] = context.Ebp;
+ info->regs [7] = context.Esp;
+ info->stopped_regs = &info->regs;
+
+ /* Notify the JIT */
+ if (mono_gc_get_gc_callbacks ()->thread_suspend_func)
+ mono_gc_get_gc_callbacks ()->thread_suspend_func (info->runtime_data, NULL);
+
+ return TRUE;
+}
+
+void
+mono_sgen_wait_for_suspend_ack (int count)
+{
+ /* Win32 suspend/resume is synchronous, so we don't need to wait for anything */
+}
+
+int
+mono_sgen_thread_handshake (BOOL suspend)
+{
+ SgenThreadInfo *info;
+ SgenThreadInfo *current = mono_thread_info_current ();
+ int count = 0;
+
+ FOREACH_THREAD_SAFE (info) {
+ if (info == current)
+ continue;
+ if (suspend) {
+ g_assert (!info->doing_handshake);
+ info->doing_handshake = TRUE;
+
+ if (!mono_sgen_suspend_thread (info))
+ continue;
+ } else {
+ g_assert (info->doing_handshake);
+ info->doing_handshake = FALSE;
+
+ if (!mono_sgen_resume_thread (info))
+ continue;
+ }
+
+ ++count;
+ } END_FOREACH_THREAD_SAFE
+ return count;
+}
+
+void
+mono_sgen_os_init (void)
+{
+}
+
+int
+mono_gc_get_suspend_signal (void)
+{
+ return -1;
+}
+
+#endif
#ifdef HOST_WIN32
DWORD real_tid;
- res = CreateThread (security, stacksize, start, param, create, &real_tid);
+ res = mono_threads_CreateThread (security, stacksize, start, param, create, &real_tid);
if (tid)
*tid = real_tid;
#else
#elif defined(HAVE_SGEN_GC)
-#if defined(HOST_WIN32)
-#define CreateThread mono_gc_CreateThread
-
-#endif
-
#else /* not Boehm and not sgen GC */
#endif
return sarea;
}
+static char*
+aligned_address (char *mem, size_t size, size_t alignment)
+{
+ char *aligned = (char*)((gulong)(mem + (alignment - 1)) & ~(alignment - 1));
+ g_assert (aligned >= mem && aligned + size <= mem + size + alignment && !((gulong)aligned & (alignment - 1)));
+ return aligned;
+}
+
#ifdef HOST_WIN32
int
return ptr;
}
+void*
+mono_valloc_aligned (size_t length, size_t alignment, int flags)
+{
+ int prot = prot_from_flags (flags);
+ char *mem = VirtualAlloc (NULL, length + alignment, MEM_RESERVE, prot);
+ char *aligned;
+
+ g_assert (mem);
+
+ aligned = aligned_address (mem, length, alignment);
+
+ aligned = VirtualAlloc (aligned, length, MEM_COMMIT, prot);
+ g_assert (aligned);
+
+ return aligned;
+}
+
+#define HAVE_VALLOC_ALIGNED
+
int
mono_vfree (void *addr, size_t length)
{
g_assert (mem);
- aligned = (char*)((gulong)(mem + (alignment - 1)) & ~(alignment - 1));
- g_assert (aligned >= mem && aligned + size <= mem + size + alignment && !((gulong)aligned & (alignment - 1)));
+ aligned = aligned_address (mem, size, alignment);
if (aligned > mem)
mono_vfree (mem, aligned - mem);
{
}
+typedef struct {
+ LPTHREAD_START_ROUTINE start_routine;
+ void *arg;
+ MonoSemType registered;
+ gboolean suspend;
+} ThreadStartInfo;
+
+static DWORD WINAPI
+inner_start_thread (LPVOID arg)
+{
+ ThreadStartInfo *start_info = arg;
+ void *t_arg = start_info->arg;
+ int post_result;
+ LPTHREAD_START_ROUTINE start_func = start_info->start_routine;
+ DWORD result;
+
+ mono_thread_info_attach (&result);
+
+ post_result = MONO_SEM_POST (&(start_info->registered));
+ g_assert (!post_result);
+
+ if (start_info->suspend)
+ SuspendThread (GetCurrentThread ());
+
+ result = start_func (t_arg);
+
+ g_assert (!mono_domain_get ());
+
+ return result;
+}
+
+HANDLE
+mono_threads_CreateThread (LPSECURITY_ATTRIBUTES attributes, SIZE_T stack_size, LPTHREAD_START_ROUTINE start_routine,
+ LPVOID arg, DWORD creation_flags, LPDWORD thread_id)
+{
+ ThreadStartInfo *start_info;
+ HANDLE result;
+
+ start_info = g_malloc0 (sizeof (ThreadStartInfo));
+ if (!start_info)
+ return NULL;
+ MONO_SEM_INIT (&(start_info->registered), 0);
+ start_info->arg = arg;
+ start_info->start_routine = start_routine;
+ start_info->suspend = creation_flags & CREATE_SUSPENDED;
+ creation_flags &= ~CREATE_SUSPENDED;
+
+ result = CreateThread (attributes, stack_size, inner_start_thread, start_info, creation_flags, thread_id);
+
+ if (result) {
+ while (MONO_SEM_WAIT (&(start_info->registered)) != 0) {
+ /*if (EINTR != errno) ABORT("sem_wait failed"); */
+ }
+ }
+ MONO_SEM_DESTROY (&(start_info->registered));
+ g_free (start_info);
+ return result;
+}
+
#endif
#include <windows.h>
typedef DWORD MonoNativeThreadId;
-typedef HANDLE MonoNativeThreadHandle;
+typedef HANDLE MonoNativeThreadHandle; /* unused */
+
+typedef DWORD mono_native_thread_return_t;
#define mono_native_thread_id_get GetCurrentThreadId
#define mono_native_thread_id_equals(a,b) ((a) == ((b))
+HANDLE mono_threads_CreateThread (LPSECURITY_ATTRIBUTES attributes, SIZE_T stack_size, LPTHREAD_START_ROUTINE start_routine,
+ LPVOID arg, DWORD creation_flags, LPDWORD thread_id) MONO_INTERNAL;
+
+#define mono_native_thread_create(id,func,arg) (CreateThread (NULL, 0, (func), (arg), 0, (id)) != NULL)
+
#else
#include <pthread.h>