#endif
#include <unistd.h>
+#include <errno.h>
#ifdef USE_WIN32_API
+#include <winsock2.h>
#include <windows.h>
#include <io.h>
#else
#include <glib.h>
#include "rawbuffer.h"
+#include <mono/io-layer/io-layer.h>
+
#define ROUND_DOWN(VALUE,SIZE) ((VALUE) & ~((SIZE) - 1))
#define ROUND_UP(VALUE,SIZE) (ROUND_DOWN((VALUE) + (SIZE) - 1, (SIZE)))
+#if SIZEOF_VOID_P == 8
+#define UINTPTR_TYPE guint64
+#else
+#define UINTPTR_TYPE guint32
+#endif
static GHashTable *mmap_map = NULL;
static size_t alignment = 0;
+static CRITICAL_SECTION mmap_mutex;
static void
-get_alignment ()
+get_alignment (void)
{
#ifdef USE_WIN32_API
SYSTEM_INFO info;
g_free (base);
}
+void
+mono_raw_buffer_init (void)
+{
+ InitializeCriticalSection (&mmap_mutex);
+
+ get_alignment ();
+
+ mmap_map = g_hash_table_new (NULL, NULL);
+}
+
static void *
mono_raw_buffer_load_mmap (int fd, int is_writable, guint32 base, size_t size)
{
void *ptr;
HANDLE file, mapping;
- if (alignment == 0)
- get_alignment ();
start = ROUND_DOWN (base, alignment);
end = base + size;
return 0;
}
- if (mmap_map == NULL)
- mmap_map = g_hash_table_new (g_direct_hash, g_direct_equal);
-
+ EnterCriticalSection (&mmap_mutex);
g_hash_table_insert (mmap_map, ptr, GINT_TO_POINTER (mapping));
+ LeaveCriticalSection (&mmap_mutex);
return ((char *)ptr) + (base - start);
int flags = 0;
void *ptr;
- if (alignment == 0)
- get_alignment ();
start = ROUND_DOWN (base, alignment);
end = ROUND_UP (base + size, alignment);
if (ptr == (void *) -1)
return 0;
+
+ /*
+ * This seems to prevent segmentation faults on Fedora Linux, no
+ * idea why :). See
+ * http://bugzilla.ximian.com/show_bug.cgi?id=49499
+ * for more info.
+ */
+ if (mprotect (ptr, end - start, prot | PROT_EXEC) != 0)
+ g_warning (G_GNUC_PRETTY_FUNCTION
+ ": mprotect failed: %s", g_strerror (errno));
- if (mmap_map == NULL)
- mmap_map = g_hash_table_new (g_direct_hash, g_direct_equal);
-
+ EnterCriticalSection (&mmap_mutex);
g_hash_table_insert (mmap_map, ptr, GINT_TO_POINTER (size));
+ LeaveCriticalSection (&mmap_mutex);
return ((char *)ptr) + (base - start);
#endif
{
int value;
+ EnterCriticalSection (&mmap_mutex);
value = GPOINTER_TO_INT (g_hash_table_lookup (mmap_map, base));
+ LeaveCriticalSection (&mmap_mutex);
#ifdef USE_WIN32_API
UnmapViewOfFile (base);
mono_raw_buffer_update (void *buffer, size_t size)
{
char *mmap_base;
+ gboolean exists;
- mmap_base = GINT_TO_POINTER (ROUND_DOWN (GPOINTER_TO_INT (buffer), alignment));
-
- if (mmap_map && g_hash_table_lookup (mmap_map, mmap_base))
+ mmap_base = (gpointer)(ROUND_DOWN ((UINTPTR_TYPE) (buffer), alignment));
+
+ EnterCriticalSection (&mmap_mutex);
+ exists = g_hash_table_lookup (mmap_map, mmap_base) != NULL;
+ LeaveCriticalSection (&mmap_mutex);
+ if (exists)
mono_raw_buffer_update_mmap (mmap_base, size);
}
mono_raw_buffer_free (void *buffer)
{
char *mmap_base;
+ gboolean exists;
- mmap_base = GINT_TO_POINTER (ROUND_DOWN (GPOINTER_TO_INT (buffer), alignment));
+ mmap_base = (gpointer)(ROUND_DOWN ((UINTPTR_TYPE) (buffer), alignment));
- if (mmap_map && g_hash_table_lookup (mmap_map, mmap_base))
+ exists = g_hash_table_lookup (mmap_map, mmap_base) != NULL;
+ if (exists)
mono_raw_buffer_free_mmap (mmap_base);
else
mono_raw_buffer_free_malloc (buffer);