+/*
+ * mono_raw_buffer_set_make_unreadable:
+ *
+ * Set whenever to make all mmaped memory unreadable. In conjuction with a
+ * SIGSEGV handler, this is useful to find out which pages the runtime tries to read.
+ */
+void
+mono_raw_buffer_set_make_unreadable (gboolean unreadable)
+{
+ make_unreadable = unreadable;
+}
+
+typedef struct {
+ gboolean found;
+ void *ptr;
+} FindMapUserData;
+
+static void
+find_map (void *start, guint32 size, gpointer user_data)
+{
+ FindMapUserData *data = (FindMapUserData*)user_data;
+
+ if (!data->found)
+ if (((guint8*)data->ptr >= (guint8*)start) && ((guint8*)data->ptr < (guint8*)start + size))
+ data->found = TRUE;
+}
+
+/*
+ * mono_raw_buffer_is_pagefault:
+ *
+ * Should be called from a SIGSEGV signal handler to find out whenever @ptr is
+ * within memory allocated by this module.
+ */
+gboolean
+mono_raw_buffer_is_pagefault (void *ptr)
+{
+ FindMapUserData data;
+
+ if (!make_unreadable)
+ return FALSE;
+
+ data.found = FALSE;
+ data.ptr = ptr;
+
+ mono_mmap_lock ();
+ g_hash_table_foreach (mmap_map, (GHFunc)find_map, &data);
+ mono_mmap_unlock ();
+
+ return data.found;
+}
+
+/*
+ * mono_raw_buffer_handle_pagefault:
+ *
+ * Handle a pagefault caused by an unreadable page by making it readable again.
+ */
+void
+mono_raw_buffer_handle_pagefault (void *ptr)
+{
+#ifndef PLATFORM_WIN32
+ guint8* start = (guint8*)ROUND_DOWN (((gssize)ptr), alignment);
+ int res;
+
+ mono_mmap_lock ();
+ res = mprotect (start, alignment, PROT_READ);
+ g_assert (res == 0);
+
+ n_pagefaults ++;
+ mono_mmap_unlock ();
+#endif
+}
+
+/*
+ * mono_raw_buffer_get_n_pagefaults:
+ *
+ * Return the number of times handle_pagefault is called.
+ * To count the number of pagefaults caused by a block of code use code like this:
+ *
+ * int prev_pagefaults = mono_raw_buffer_get_n_pagefaults ();
+ * <CODE>
+ * int new_pagefaults = mono_raw_buffer_get_n_pagefaults () - prev_pagefaults;
+ */
+guint32
+mono_raw_buffer_get_n_pagefaults (void)
+{
+ return n_pagefaults;
+}