[io-layer] Register WapiHandleOps dynamically
authorLudovic Henry <ludovic@xamarin.com>
Thu, 30 Jun 2016 16:05:33 +0000 (18:05 +0200)
committerLudovic Henry <ludovic@xamarin.com>
Tue, 12 Jul 2016 12:53:23 +0000 (14:53 +0200)
17 files changed:
mono/io-layer/event-private.h
mono/io-layer/events.c
mono/io-layer/handles-private.h
mono/io-layer/handles.c
mono/io-layer/io-private.h
mono/io-layer/io.c
mono/io-layer/mutex-private.h
mono/io-layer/mutexes.c
mono/io-layer/process-private.h
mono/io-layer/processes.c
mono/io-layer/semaphore-private.h
mono/io-layer/semaphores.c
mono/io-layer/socket-private.h
mono/io-layer/sockets.c
mono/io-layer/thread-private.h
mono/io-layer/wapi.c
mono/io-layer/wthreads.c

index bf67bbb6d24376e0784261aa6bf14041438281c6..2808635a59fae559cee29c15bdf4f1979fc0c398 100644 (file)
@@ -17,9 +17,6 @@
 #include "wapi-private.h"
 #include "handles-private.h"
 
-extern WapiHandleOps _wapi_event_ops;
-extern WapiHandleOps _wapi_namedevent_ops;
-
 struct _WapiHandle_event
 {
        gboolean manual;
@@ -32,4 +29,7 @@ struct _WapiHandle_namedevent
        WapiSharedNamespace sharedns;
 };
 
+void
+_wapi_event_init (void);
+
 #endif /* _WAPI_EVENT_PRIVATE_H_ */
index 3839a16d7e3bd9527c31bffcb2d047de0cdbc98e..21195e07462e5947ebd8799c87cf3e44690e2be1 100644 (file)
@@ -32,7 +32,7 @@ static void namedevent_details (gpointer data);
 static const gchar* namedevent_typename (void);
 static gsize namedevent_typesize (void);
 
-WapiHandleOps _wapi_event_ops = {
+static WapiHandleOps _wapi_event_ops = {
        NULL,                   /* close */
        event_signal,           /* signal */
        event_own,              /* own */
@@ -44,7 +44,7 @@ WapiHandleOps _wapi_event_ops = {
        event_typesize, /* typesize */
 };
 
-WapiHandleOps _wapi_namedevent_ops = {
+static WapiHandleOps _wapi_namedevent_ops = {
        NULL,                   /* close */
        namedevent_signal,      /* signal */
        namedevent_own,         /* own */
@@ -56,10 +56,12 @@ WapiHandleOps _wapi_namedevent_ops = {
        namedevent_typesize, /* typesize */
 };
 
-static mono_once_t event_ops_once=MONO_ONCE_INIT;
-
-static void event_ops_init (void)
+void
+_wapi_event_init (void)
 {
+       _wapi_handle_register_ops (WAPI_HANDLE_EVENT,      &_wapi_event_ops);
+       _wapi_handle_register_ops (WAPI_HANDLE_NAMEDEVENT, &_wapi_namedevent_ops);
+
        _wapi_handle_register_capabilities (WAPI_HANDLE_EVENT,
                (WapiHandleCapability)(WAPI_HANDLE_CAP_WAIT | WAPI_HANDLE_CAP_SIGNAL));
        _wapi_handle_register_capabilities (WAPI_HANDLE_NAMEDEVENT,
@@ -265,8 +267,6 @@ gpointer CreateEvent(WapiSecurityAttributes *security G_GNUC_UNUSED,
                     gboolean manual, gboolean initial,
                     const gunichar2 *name G_GNUC_UNUSED)
 {
-       mono_once (&event_ops_once, event_ops_init);
-
        /* Need to blow away any old errors here, because code tests
         * for ERROR_ALREADY_EXISTS on success (!) to see if an event
         * was freshly created
@@ -479,8 +479,6 @@ gpointer OpenEvent (guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED
        gpointer handle;
        gchar *utf8_name;
        int thr_ret;
-       
-       mono_once (&event_ops_once, event_ops_init);
 
        /* w32 seems to guarantee that opening named objects can't
         * race each other
index 2046f097718f7a77e11c4c0b067bb0c8465857d3..fe4bf7b634b2cce173930d70d1eda7010d35fcc0 100644 (file)
@@ -96,6 +96,9 @@ _wapi_handle_init (void);
 void
 _wapi_handle_cleanup (void);
 
+void
+_wapi_handle_register_ops (WapiHandleType type, WapiHandleOps *ops);
+
 extern gpointer _wapi_handle_new (WapiHandleType type,
                                  gpointer handle_specific);
 extern gpointer _wapi_handle_new_fd (WapiHandleType type, int fd,
index edcdb6eafd2726d5920f4bc08cf81700c88b4b3b..e7930c93acee2b60db4778b1bc886682dbb896ef 100644 (file)
@@ -86,25 +86,8 @@ struct _WapiHandleUnshared
 
 static void (*_wapi_handle_ops_get_close_func (WapiHandleType type))(gpointer, gpointer);
 
-static WapiHandleCapability handle_caps[WAPI_HANDLE_COUNT] = { (WapiHandleCapability)0 };
-static WapiHandleOps *handle_ops[WAPI_HANDLE_COUNT]={
-       NULL,
-       &_wapi_file_ops,
-       &_wapi_console_ops,
-       &_wapi_thread_ops,
-       &_wapi_sem_ops,
-       &_wapi_mutex_ops,
-       &_wapi_event_ops,
-#ifndef DISABLE_SOCKETS
-       &_wapi_socket_ops,
-#endif
-       &_wapi_find_ops,
-       &_wapi_process_ops,
-       &_wapi_pipe_ops,
-       &_wapi_namedmutex_ops,
-       &_wapi_namedsem_ops,
-       &_wapi_namedevent_ops,
-};
+static WapiHandleCapability handle_caps [WAPI_HANDLE_COUNT];
+static WapiHandleOps *handle_ops [WAPI_HANDLE_COUNT];
 
 /*
  * We can hold _WAPI_PRIVATE_MAX_SLOTS * _WAPI_HANDLE_INITIAL_COUNT handles.
@@ -818,6 +801,12 @@ void _wapi_handle_unref (gpointer handle)
        _wapi_handle_unref_full (handle, FALSE);
 }
 
+void
+_wapi_handle_register_ops (WapiHandleType type, WapiHandleOps *ops)
+{
+       handle_ops [type] = ops;
+}
+
 void _wapi_handle_register_capabilities (WapiHandleType type,
                                         WapiHandleCapability caps)
 {
index bb32a6158b5493fea0842c512b65b49ed4921317..1e0237cee89deffd55a33e91d4d65ee7b300f1f9 100644 (file)
 #include <mono/io-layer/wapi-private.h>
 #include "handles-private.h"
 
-extern WapiHandleOps _wapi_file_ops;
-extern WapiHandleOps _wapi_console_ops;
-extern WapiHandleOps _wapi_find_ops;
-extern WapiHandleOps _wapi_pipe_ops;
-
 extern gboolean _wapi_lock_file_region (int fd, off_t offset, off_t length);
 extern gboolean _wapi_unlock_file_region (int fd, off_t offset, off_t length);
 extern gpointer _wapi_stdhandle_create (int fd, const gchar *name);
index 5712f671d45a16c091638460fb1f36045d27cb43..23268f1cfa63e3fabd6161662dfe029464e9a418 100644 (file)
@@ -182,7 +182,7 @@ static gboolean file_setfiletime(gpointer handle,
 static guint32 GetDriveTypeFromPath (const gchar *utf8_root_path_name);
 
 /* File handle is only signalled for overlapped IO */
-WapiHandleOps _wapi_file_ops = {
+static WapiHandleOps _wapi_file_ops = {
        file_close,             /* close */
        NULL,                   /* signal */
        NULL,                   /* own */
@@ -209,7 +209,7 @@ static gboolean console_write(gpointer handle, gconstpointer buffer,
 /* Console is mostly the same as file, except it can block waiting for
  * input or output
  */
-WapiHandleOps _wapi_console_ops = {
+static WapiHandleOps _wapi_console_ops = {
        console_close,          /* close */
        NULL,                   /* signal */
        NULL,                   /* own */
@@ -224,7 +224,7 @@ WapiHandleOps _wapi_console_ops = {
 static const gchar* find_typename (void);
 static gsize find_typesize (void);
 
-WapiHandleOps _wapi_find_ops = {
+static WapiHandleOps _wapi_find_ops = {
        NULL,                   /* close */
        NULL,                   /* signal */
        NULL,                   /* own */
@@ -249,7 +249,7 @@ static gboolean pipe_write (gpointer handle, gconstpointer buffer,
 
 /* Pipe handles
  */
-WapiHandleOps _wapi_pipe_ops = {
+static WapiHandleOps _wapi_pipe_ops = {
        pipe_close,             /* close */
        NULL,                   /* signal */
        NULL,                   /* own */
@@ -322,21 +322,8 @@ static const struct {
         NULL, NULL, NULL, NULL, NULL, NULL},
 };
 
-static mono_once_t io_ops_once=MONO_ONCE_INIT;
 static gboolean lock_while_writing = FALSE;
 
-static void io_ops_init (void)
-{
-/*     _wapi_handle_register_capabilities (WAPI_HANDLE_FILE, */
-/*                                         WAPI_HANDLE_CAP_WAIT); */
-/*     _wapi_handle_register_capabilities (WAPI_HANDLE_CONSOLE, */
-/*                                         WAPI_HANDLE_CAP_WAIT); */
-
-       if (g_getenv ("MONO_STRICT_IO_EMULATION") != NULL) {
-               lock_while_writing = TRUE;
-       }
-}
-
 /* Some utility functions.
  */
 
@@ -1669,8 +1656,6 @@ gpointer CreateFile(const gunichar2 *name, guint32 fileaccess,
        int fd, ret;
        WapiHandleType handle_type;
        struct stat statbuf;
-       
-       mono_once (&io_ops_once, io_ops_init);
 
        if (attrs & FILE_ATTRIBUTE_TEMPORARY)
                perms = 0600;
@@ -3511,8 +3496,6 @@ gboolean CreatePipe (gpointer *readpipe, gpointer *writepipe,
        int filedes[2];
        int ret;
        
-       mono_once (&io_ops_once, io_ops_init);
-       
        MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Creating pipe", __func__);
 
        ret=pipe (filedes);
@@ -4438,11 +4421,23 @@ GetVolumeInformation (const gunichar2 *path, gunichar2 *volumename, int volumesi
 }
 #endif
 
-
 void
 _wapi_io_init (void)
 {
        mono_os_mutex_init (&stdhandle_mutex);
+
+       _wapi_handle_register_ops (WAPI_HANDLE_FILE,    &_wapi_file_ops);
+       _wapi_handle_register_ops (WAPI_HANDLE_CONSOLE, &_wapi_console_ops);
+       _wapi_handle_register_ops (WAPI_HANDLE_FIND,    &_wapi_find_ops);
+       _wapi_handle_register_ops (WAPI_HANDLE_PIPE,    &_wapi_pipe_ops);
+
+/*     _wapi_handle_register_capabilities (WAPI_HANDLE_FILE, */
+/*                                         WAPI_HANDLE_CAP_WAIT); */
+/*     _wapi_handle_register_capabilities (WAPI_HANDLE_CONSOLE, */
+/*                                         WAPI_HANDLE_CAP_WAIT); */
+
+       if (g_getenv ("MONO_STRICT_IO_EMULATION"))
+               lock_while_writing = TRUE;
 }
 
 void
index e0066b09aca94af4f7616ca756a4873be9266b8c..032c0a013ffb6259ddd8126eb469dbbc3414b0d1 100644 (file)
@@ -18,9 +18,6 @@
 #include "wapi-private.h"
 #include "handles-private.h"
 
-extern WapiHandleOps _wapi_mutex_ops;
-extern WapiHandleOps _wapi_namedmutex_ops;
-
 struct _WapiHandle_mutex
 {
        pthread_t tid;
@@ -33,6 +30,9 @@ struct _WapiHandle_namedmutex
        WapiSharedNamespace sharedns;
 };
 
+void
+_wapi_mutex_init (void);
+
 extern void _wapi_mutex_abandon (gpointer data, pid_t pid, pthread_t tid);
 
 #endif /* _WAPI_MUTEX_PRIVATE_H_ */
index 3bbe40714cfc6d5226eeb5d96f48e1b5a71adb97..dccbfb96f51e962c8b6414b8a72bc6a9e4060673 100644 (file)
@@ -37,7 +37,7 @@ static void namedmutex_details (gpointer data);
 static const gchar* namedmutex_typename (void);
 static gsize namedmutex_typesize (void);
 
-WapiHandleOps _wapi_mutex_ops = {
+static WapiHandleOps _wapi_mutex_ops = {
        NULL,                   /* close */
        mutex_signal,           /* signal */
        mutex_own,              /* own */
@@ -49,7 +49,7 @@ WapiHandleOps _wapi_mutex_ops = {
        mutex_typesize, /* typesize */
 };
 
-WapiHandleOps _wapi_namedmutex_ops = {
+static WapiHandleOps _wapi_namedmutex_ops = {
        NULL,                   /* close */
        namedmutex_signal,      /* signal */
        namedmutex_own,         /* own */
@@ -61,10 +61,12 @@ WapiHandleOps _wapi_namedmutex_ops = {
        namedmutex_typesize,    /* typesize */
 };
 
-static mono_once_t mutex_ops_once=MONO_ONCE_INIT;
-
-static void mutex_ops_init (void)
+void
+_wapi_mutex_init (void)
 {
+       _wapi_handle_register_ops (WAPI_HANDLE_MUTEX,      &_wapi_mutex_ops);
+       _wapi_handle_register_ops (WAPI_HANDLE_NAMEDMUTEX, &_wapi_namedmutex_ops);
+
        _wapi_handle_register_capabilities (WAPI_HANDLE_MUTEX,
                (WapiHandleCapability)(WAPI_HANDLE_CAP_WAIT | WAPI_HANDLE_CAP_SIGNAL | WAPI_HANDLE_CAP_OWN));
        _wapi_handle_register_capabilities (WAPI_HANDLE_NAMEDMUTEX,
@@ -383,8 +385,6 @@ static gpointer namedmutex_create (gboolean owned, const gunichar2 *name)
  */
 gpointer CreateMutex(WapiSecurityAttributes *security G_GNUC_UNUSED, gboolean owned, const gunichar2 *name)
 {
-       mono_once (&mutex_ops_once, mutex_ops_init);
-
        /* Need to blow away any old errors here, because code tests
         * for ERROR_ALREADY_EXISTS on success (!) to see if a mutex
         * was freshly created */
@@ -472,8 +472,6 @@ gpointer OpenMutex (guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED
        gchar *utf8_name;
        int thr_ret;
 
-       mono_once (&mutex_ops_once, mutex_ops_init);
-
        /* w32 seems to guarantee that opening named objects can't
         * race each other
         */
index 0816e1d8227e59d00f4b8b38ccebccfe4ff61d8b..a17de8a3adb607fd5e6f3ad509033ffcbf6f9271 100644 (file)
 #define WAPI_PID_TO_HANDLE(pid) GINT_TO_POINTER (_WAPI_PROCESS_UNHANDLED + (pid))
 #define WAPI_HANDLE_TO_PID(handle) (GPOINTER_TO_UINT ((handle)) - _WAPI_PROCESS_UNHANDLED)
 
-void wapi_processes_init (void);
+void _wapi_processes_init (void);
 extern gpointer _wapi_process_duplicate (void);
 extern void wapi_processes_cleanup (void);
 
-extern WapiHandleOps _wapi_process_ops;
-
 /*
  * MonoProcess describes processes we create.
  * It contains a semaphore that can be waited on in order to wait
index 10821f7195fad272afb30ebdd9add3129b317158..ad297b017e08087ed0835473313b3df947d1bb9e 100644 (file)
@@ -139,7 +139,7 @@ static FILE *
 open_process_map (int pid, const char *mode);
 #endif
 
-WapiHandleOps _wapi_process_ops = {
+static WapiHandleOps _wapi_process_ops = {
        process_close,          /* close_shared */
        NULL,                           /* signal */
        NULL,                           /* own */
@@ -1136,11 +1136,13 @@ process_set_name (WapiHandle_process *process_handle)
 }
 
 void
-wapi_processes_init (void)
+_wapi_processes_init (void)
 {
        pid_t pid = _wapi_getpid ();
        WapiHandle_process process_handle = {0};
 
+       _wapi_handle_register_ops (WAPI_HANDLE_PROCESS, &_wapi_process_ops);
+
        _wapi_handle_register_capabilities (WAPI_HANDLE_PROCESS,
                (WapiHandleCapability)(WAPI_HANDLE_CAP_WAIT | WAPI_HANDLE_CAP_SPECIAL_WAIT));
        
index aee3adf44845e39dd45c228d49ec9cc351a46efb..c5ff5df07f1768e49e45772d8171e5906563bf1e 100644 (file)
@@ -16,9 +16,6 @@
 #include "wapi-private.h"
 #include "handles-private.h"
 
-extern WapiHandleOps _wapi_sem_ops;
-extern WapiHandleOps _wapi_namedsem_ops;
-
 /* emulate sem_t, so that we can prod the internal state more easily */
 struct _WapiHandle_sem
 {
@@ -32,4 +29,7 @@ struct _WapiHandle_namedsem
        WapiSharedNamespace sharedns;
 };
 
+void
+_wapi_semaphore_init (void);
+
 #endif /* _WAPI_SEMAPHORE_PRIVATE_H_ */
index 1bee0d9161fd835dca89426be2cff30c5e63207a..e9375a820ef295e477ea9b547c015b55e6a13257 100644 (file)
@@ -37,7 +37,7 @@ static void namedsema_details (gpointer data);
 static const gchar* namedsema_typename (void);
 static gsize namedsema_typesize (void);
 
-WapiHandleOps _wapi_sem_ops = {
+static WapiHandleOps _wapi_sem_ops = {
        NULL,                   /* close */
        sema_signal,            /* signal */
        sema_own,               /* own */
@@ -49,7 +49,7 @@ WapiHandleOps _wapi_sem_ops = {
        sema_typesize,  /* typesize */
 };
 
-WapiHandleOps _wapi_namedsem_ops = {
+static WapiHandleOps _wapi_namedsem_ops = {
        NULL,                   /* close */
        namedsema_signal,       /* signal */
        namedsema_own,          /* own */
@@ -61,10 +61,12 @@ WapiHandleOps _wapi_namedsem_ops = {
        namedsema_typesize,     /* typesize */
 };
 
-static mono_once_t sem_ops_once=MONO_ONCE_INIT;
-
-static void sem_ops_init (void)
+void
+_wapi_semaphore_init (void)
 {
+       _wapi_handle_register_ops (WAPI_HANDLE_SEM,      &_wapi_sem_ops);
+       _wapi_handle_register_ops (WAPI_HANDLE_NAMEDSEM, &_wapi_namedsem_ops);
+
        _wapi_handle_register_capabilities (WAPI_HANDLE_SEM,
                (WapiHandleCapability)(WAPI_HANDLE_CAP_WAIT | WAPI_HANDLE_CAP_SIGNAL));
        _wapi_handle_register_capabilities (WAPI_HANDLE_NAMEDSEM,
@@ -261,8 +263,6 @@ static gpointer namedsem_create (gint32 initial, gint32 max, const gunichar2 *na
  */
 gpointer CreateSemaphore(WapiSecurityAttributes *security G_GNUC_UNUSED, gint32 initial, gint32 max, const gunichar2 *name)
 {
-       mono_once (&sem_ops_once, sem_ops_init);
-       
        if (max <= 0) {
                MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: max <= 0", __func__);
 
@@ -364,8 +364,6 @@ gpointer OpenSemaphore (guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UN
        gchar *utf8_name;
        int thr_ret;
 
-       mono_once (&sem_ops_once, sem_ops_init);
-       
        /* w32 seems to guarantee that opening named objects can't
         * race each other
         */
index dbc27fbb6aa30b7881875b045246374a785b16ca..e60178dd02017d07ed62d2618b1b05cf01bf8ca6 100644 (file)
@@ -16,8 +16,6 @@
 #include "wapi-private.h"
 #include "handles-private.h"
 
-extern WapiHandleOps _wapi_socket_ops;
-
 struct _WapiHandle_socket
 {
        int domain;
@@ -27,4 +25,7 @@ struct _WapiHandle_socket
        int still_readable;
 };
 
+void
+_wapi_socket_init (void);
+
 #endif /* _WAPI_SOCKET_PRIVATE_H_ */
index 8dceaf5f7f9730c8bc9ef3f4230e48d08b464189..d4aabc44fa7dc6ccea6367929e03bd2c6583a068 100644 (file)
@@ -63,7 +63,7 @@ static void socket_details (gpointer data);
 static const gchar* socket_typename (void);
 static gsize socket_typesize (void);
 
-WapiHandleOps _wapi_socket_ops = {
+static WapiHandleOps _wapi_socket_ops = {
        socket_close,           /* close */
        NULL,                   /* signal */
        NULL,                   /* own */
@@ -75,11 +75,10 @@ WapiHandleOps _wapi_socket_ops = {
        socket_typesize,        /* typesize */
 };
 
-static mono_once_t socket_ops_once=MONO_ONCE_INIT;
-
-static void socket_ops_init (void)
+void
+_wapi_socket_init (void)
 {
-       /* No capabilities to register */
+       _wapi_handle_register_ops (WAPI_HANDLE_SOCKET, &_wapi_socket_ops);
 }
 
 static void socket_close (gpointer handle, gpointer data)
@@ -879,8 +878,6 @@ guint32 _wapi_socket(int domain, int type, int protocol, void *unused,
        }
        
        
-       mono_once (&socket_ops_once, socket_ops_init);
-       
        handle = _wapi_handle_new_fd (WAPI_HANDLE_SOCKET, fd, &socket_handle);
        if (handle == _WAPI_HANDLE_INVALID) {
                g_warning ("%s: error creating socket handle", __func__);
index 2f130d5de73926b2b0db9b31b5d78917e72c5a2b..9d337521d984526d8ddd678a9a6ad6903e2c608d 100644 (file)
@@ -20,8 +20,6 @@
 /* There doesn't seem to be a defined symbol for this */
 #define _WAPI_THREAD_CURRENT (gpointer)0xFFFFFFFE
 
-extern WapiHandleOps _wapi_thread_ops;
-
 struct _WapiHandle_thread
 {
        pthread_t id;
@@ -31,6 +29,9 @@ struct _WapiHandle_thread
 
 typedef struct _WapiHandle_thread WapiHandle_thread;
 
+void
+_wapi_thread_init (void);
+
 extern gboolean _wapi_thread_cur_apc_pending (void);
 extern void _wapi_thread_own_mutex (gpointer mutex);
 extern void _wapi_thread_disown_mutex (gpointer mutex);
index 96be5c36000c38751444ee9a69879b4ef9f33fc0..e5e21f7836436a1b37a6e18f01fa867f5dd4a8ce 100644 (file)
@@ -16,7 +16,12 @@ wapi_init (void)
        _wapi_handle_init ();
        _wapi_shm_semaphores_init ();
        _wapi_io_init ();
-       wapi_processes_init ();
+       _wapi_processes_init ();
+       _wapi_thread_init ();
+       _wapi_semaphore_init ();
+       _wapi_mutex_init ();
+       _wapi_event_init ();
+       _wapi_socket_init ();
 }
 
 void
index 0fe5e5f0086ec922e9e6671eb48537b1069edda2..6c847e59e61774798bf7e05e953c901b39bbadf2 100644 (file)
@@ -42,7 +42,7 @@ static void thread_details (gpointer data);
 static const gchar* thread_typename (void);
 static gsize thread_typesize (void);
 
-WapiHandleOps _wapi_thread_ops = {
+static WapiHandleOps _wapi_thread_ops = {
        NULL,                           /* close */
        NULL,                           /* signal */
        NULL,                           /* own */
@@ -54,13 +54,12 @@ WapiHandleOps _wapi_thread_ops = {
        thread_typesize,        /* typesize */
 };
 
-static mono_once_t thread_ops_once = MONO_ONCE_INIT;
-
-static void
-thread_ops_init (void)
+void
+_wapi_thread_init (void)
 {
-       _wapi_handle_register_capabilities (WAPI_HANDLE_THREAD,
-                                           WAPI_HANDLE_CAP_WAIT);
+       _wapi_handle_register_ops (WAPI_HANDLE_THREAD, &_wapi_thread_ops);
+
+       _wapi_handle_register_capabilities (WAPI_HANDLE_THREAD, WAPI_HANDLE_CAP_WAIT);
 }
 
 static void thread_details (gpointer data)
@@ -173,8 +172,6 @@ wapi_create_thread_handle (void)
        WapiHandle_thread thread_handle = {0}, *thread;
        gpointer handle;
 
-       mono_once (&thread_ops_once, thread_ops_init);
-
        thread_handle.owned_mutexes = g_ptr_array_new ();
 
        handle = _wapi_handle_new (WAPI_HANDLE_THREAD, &thread_handle);