[w32event] Use coop handles for System.Threading.NativeEventCalls.CreateEvent_internal
authorAleksey Kliger <aleksey@xamarin.com>
Thu, 25 May 2017 22:21:31 +0000 (18:21 -0400)
committerAleksey Kliger <aleksey@xamarin.com>
Fri, 26 May 2017 18:26:18 +0000 (14:26 -0400)
- Make a new mono_w32event_create_full on unix
- Convert the MonoString to utf8 (unix) or utf16 (win32) in the icall, then
  call an implementation func.
- transition to GC safe mode around the win32 api call on Windows

mono/metadata/icall-def.h
mono/metadata/w32event-unix.c
mono/metadata/w32event-win32.c
mono/metadata/w32event.h

index 99d8537b253cd0e36dd3ca2e3d9938a15007c8ca..6657624616e88248fb2738e2b142c5ea2cf4399e 100644 (file)
@@ -918,7 +918,7 @@ ICALL(MUTEX_3, "ReleaseMutex_internal(intptr)", ves_icall_System_Threading_Mutex
 
 ICALL_TYPE(NATIVEC, "System.Threading.NativeEventCalls", NATIVEC_1)
 ICALL(NATIVEC_1, "CloseEvent_internal", ves_icall_System_Threading_Events_CloseEvent_internal)
-ICALL(NATIVEC_2, "CreateEvent_internal(bool,bool,string,int&)", ves_icall_System_Threading_Events_CreateEvent_internal)
+HANDLES(ICALL(NATIVEC_2, "CreateEvent_internal(bool,bool,string,int&)", ves_icall_System_Threading_Events_CreateEvent_internal))
 ICALL(NATIVEC_3, "OpenEvent_internal(string,System.Security.AccessControl.EventWaitHandleRights,int&)", ves_icall_System_Threading_Events_OpenEvent_internal)
 ICALL(NATIVEC_4, "ResetEvent_internal",  ves_icall_System_Threading_Events_ResetEvent_internal)
 ICALL(NATIVEC_5, "SetEvent_internal",    ves_icall_System_Threading_Events_SetEvent_internal)
index 246ddadf3f751a0e8b599a5b7b6f648891345f31..50beb4b72b020216597b4f99f5f63745f0251245 100644 (file)
 
 #include "w32error.h"
 #include "w32handle-namespace.h"
+#include "mono/utils/mono-error-internals.h"
 #include "mono/utils/mono-logger-internals.h"
+#include "mono/metadata/handle.h"
+#include "mono/metadata/object-internals.h"
 #include "mono/metadata/w32handle.h"
 
 #define MAX_PATH 260
 
+static gpointer
+mono_w32event_create_full (MonoBoolean manual, MonoBoolean initial, const gchar *name, gint32 *err);
+
+
 typedef struct {
        gboolean manual;
        guint32 set_count;
@@ -152,7 +159,7 @@ mono_w32event_create (gboolean manual, gboolean initial)
        gpointer handle;
        gint32 error;
 
-       handle = ves_icall_System_Threading_Events_CreateEvent_internal (manual, initial, NULL, &error);
+       handle = mono_w32event_create_full (manual, initial, NULL, &error);
        if (error != ERROR_SUCCESS)
                g_assert (!handle);
 
@@ -213,10 +220,9 @@ static gpointer event_create (gboolean manual, gboolean initial)
        return event_handle_create (&event_handle, MONO_W32HANDLE_EVENT, manual, initial);
 }
 
-static gpointer namedevent_create (gboolean manual, gboolean initial, const gunichar2 *name G_GNUC_UNUSED)
+static gpointer namedevent_create (gboolean manual, gboolean initial, const gchar *utf8_name G_GNUC_UNUSED)
 {
        gpointer handle;
-       gchar *utf8_name;
 
        mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: creating %s handle",
                __func__, mono_w32handle_get_typename (MONO_W32HANDLE_NAMEDEVENT));
@@ -224,8 +230,7 @@ static gpointer namedevent_create (gboolean manual, gboolean initial, const guni
        /* w32 seems to guarantee that opening named objects can't race each other */
        mono_w32handle_namespace_lock ();
 
-       glong utf8_len = 0;
-       utf8_name = g_utf16_to_utf8 (name, -1, NULL, &utf8_len, NULL);
+       glong utf8_len = strlen (utf8_name);
 
        handle = mono_w32handle_namespace_search_handle (MONO_W32HANDLE_NAMEDEVENT, utf8_name);
        if (handle == INVALID_HANDLE_VALUE) {
@@ -248,15 +253,13 @@ static gpointer namedevent_create (gboolean manual, gboolean initial, const guni
                handle = event_handle_create ((MonoW32HandleEvent*) &namedevent_handle, MONO_W32HANDLE_NAMEDEVENT, manual, initial);
        }
 
-       g_free (utf8_name);
-
        mono_w32handle_namespace_unlock ();
 
        return handle;
 }
 
 gpointer
-ves_icall_System_Threading_Events_CreateEvent_internal (MonoBoolean manual, MonoBoolean initial, MonoString *name, gint32 *error)
+mono_w32event_create_full (MonoBoolean manual, MonoBoolean initial, const gchar *name, gint32 *error)
 {
        gpointer event;
 
@@ -265,13 +268,24 @@ ves_icall_System_Threading_Events_CreateEvent_internal (MonoBoolean manual, Mono
         * was freshly created */
        mono_w32error_set_last (ERROR_SUCCESS);
 
-       event = name ? namedevent_create (manual, initial, mono_string_chars (name)) : event_create (manual, initial);
+       event = name ? namedevent_create (manual, initial, name) : event_create (manual, initial);
 
        *error = mono_w32error_get_last ();
 
        return event;
 }
 
+gpointer
+ves_icall_System_Threading_Events_CreateEvent_internal (MonoBoolean manual, MonoBoolean initial, MonoStringHandle name, gint32 *err, MonoError *error)
+{
+       error_init (error);
+       gchar *utf8_name = mono_string_handle_to_utf8 (name, error);
+       return_val_if_nok (error, NULL);
+       gpointer result = mono_w32event_create_full (manual, initial, utf8_name, err);
+       g_free (utf8_name);
+       return result;
+}
+
 gboolean
 ves_icall_System_Threading_Events_SetEvent_internal (gpointer handle)
 {
index 792735b02687d3046fd65878a6e37f2ab09714af..c0c9df3e71b81fac213f254a973e7d0a48979f88 100644 (file)
@@ -12,6 +12,8 @@
 
 #include <windows.h>
 #include <winbase.h>
+#include <mono/metadata/handle.h>
+#include <mono/utils/mono-error-internals.h>
 
 void
 mono_w32event_init (void)
@@ -43,13 +45,22 @@ mono_w32event_reset (gpointer handle)
 }
 
 gpointer
-ves_icall_System_Threading_Events_CreateEvent_internal (MonoBoolean manual, MonoBoolean initial, MonoString *name, gint32 *error)
+ves_icall_System_Threading_Events_CreateEvent_internal (MonoBoolean manual, MonoBoolean initial, MonoStringHandle name, gint32 *err, MonoError *error)
 {
        gpointer event;
 
-       event = CreateEvent (NULL, manual, initial, name ? mono_string_chars (name) : NULL);
-
-       *error = GetLastError ();
+       error_init (error);
+       
+       uint32_t gchandle = 0;
+       gunichar2 *uniname = NULL;
+       if (!MONO_HANDLE_IS_NULL (name))
+               uniname = mono_string_handle_pin_chars (name, &gchandle);
+       MONO_ENTER_GC_SAFE;
+       event = CreateEvent (NULL, manual, initial, uniname);
+       *err = GetLastError ();
+       MONO_EXIT_GC_SAFE;
+       if (gchandle)
+               mono_gchandle_free (gchandle);
 
        return event;
 }
index 3e8d65de06ea8f608c00b39c4d91097d73de0dac..f9847d8b1972583ef7b3e1ff104b68aba7095be2 100644 (file)
@@ -9,6 +9,7 @@
 #include <glib.h>
 
 #include "object.h"
+#include "object-internals.h"
 #include "w32handle-namespace.h"
 
 void
@@ -27,7 +28,7 @@ void
 mono_w32event_reset (gpointer handle);
 
 gpointer
-ves_icall_System_Threading_Events_CreateEvent_internal (MonoBoolean manual, MonoBoolean initial, MonoString *name, gint32 *error);
+ves_icall_System_Threading_Events_CreateEvent_internal (MonoBoolean manual, MonoBoolean initial, MonoStringHandle name, gint32 *err, MonoError *error);
 
 gboolean
 ves_icall_System_Threading_Events_SetEvent_internal (gpointer handle);