context.h \
error.h \
events.h \
- handles.h \
io.h \
io-trace.h \
io-layer.h \
events.c \
events.h \
event-private.h \
- handles.c \
- handles.h \
- handles-private.h \
io.c \
io.h \
io-portability.c \
#include <pthread.h>
#include "wapi-private.h"
-#include "handles-private.h"
struct _WapiHandle_event
{
#include <mono/io-layer/wapi.h>
#include <mono/io-layer/wapi-private.h>
-#include <mono/io-layer/handles-private.h>
#include <mono/io-layer/event-private.h>
#include <mono/io-layer/io-trace.h>
#include <mono/utils/mono-once.h>
#include <mono/utils/mono-logger-internals.h>
+#include <mono/utils/w32handle.h>
static void event_signal(gpointer handle);
static gboolean event_own (gpointer handle);
static const gchar* namedevent_typename (void);
static gsize namedevent_typesize (void);
-static WapiHandleOps _wapi_event_ops = {
+static MonoW32HandleOps _wapi_event_ops = {
NULL, /* close */
event_signal, /* signal */
event_own, /* own */
event_typesize, /* typesize */
};
-static WapiHandleOps _wapi_namedevent_ops = {
+static MonoW32HandleOps _wapi_namedevent_ops = {
NULL, /* close */
namedevent_signal, /* signal */
namedevent_own, /* own */
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);
+ mono_w32handle_register_ops (MONO_W32HANDLE_EVENT, &_wapi_event_ops);
+ mono_w32handle_register_ops (MONO_W32HANDLE_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,
- (WapiHandleCapability)(WAPI_HANDLE_CAP_WAIT | WAPI_HANDLE_CAP_SIGNAL));
+ mono_w32handle_register_capabilities (MONO_W32HANDLE_EVENT,
+ (MonoW32HandleCapability)(MONO_W32HANDLE_CAP_WAIT | MONO_W32HANDLE_CAP_SIGNAL));
+ mono_w32handle_register_capabilities (MONO_W32HANDLE_NAMEDEVENT,
+ (MonoW32HandleCapability)(MONO_W32HANDLE_CAP_WAIT | MONO_W32HANDLE_CAP_SIGNAL));
}
-static const char* event_handle_type_to_string (WapiHandleType type)
+static const char* event_handle_type_to_string (MonoW32HandleType type)
{
switch (type) {
- case WAPI_HANDLE_EVENT: return "event";
- case WAPI_HANDLE_NAMEDEVENT: return "named event";
+ case MONO_W32HANDLE_EVENT: return "event";
+ case MONO_W32HANDLE_NAMEDEVENT: return "named event";
default:
g_assert_not_reached ();
}
}
-static gboolean event_handle_own (gpointer handle, WapiHandleType type)
+static gboolean event_handle_own (gpointer handle, MonoW32HandleType type)
{
struct _WapiHandle_event *event_handle;
gboolean ok;
- ok = _wapi_lookup_handle (handle, type, (gpointer *)&event_handle);
+ ok = mono_w32handle_lookup (handle, type, (gpointer *)&event_handle);
if (!ok) {
g_warning ("%s: error looking up %s handle %p",
__func__, event_handle_type_to_string (type), handle);
event_handle->set_count --;
if (event_handle->set_count == 0)
- _wapi_handle_set_signal_state (handle, FALSE, FALSE);
+ mono_w32handle_set_signal_state (handle, FALSE, FALSE);
}
return TRUE;
static gboolean event_own (gpointer handle)
{
- return event_handle_own (handle, WAPI_HANDLE_EVENT);
+ return event_handle_own (handle, MONO_W32HANDLE_EVENT);
}
static void namedevent_signal (gpointer handle)
/* NB, always called with the shared handle lock held */
static gboolean namedevent_own (gpointer handle)
{
- return event_handle_own (handle, WAPI_HANDLE_NAMEDEVENT);
+ return event_handle_own (handle, MONO_W32HANDLE_NAMEDEVENT);
}
static void event_details (gpointer data)
return sizeof (struct _WapiHandle_namedevent);
}
-static gpointer event_handle_create (struct _WapiHandle_event *event_handle, WapiHandleType type, gboolean manual, gboolean initial)
+static gpointer event_handle_create (struct _WapiHandle_event *event_handle, MonoW32HandleType type, gboolean manual, gboolean initial)
{
gpointer handle;
int thr_ret;
event_handle->manual = manual;
event_handle->set_count = (initial && !manual) ? 1 : 0;
- handle = _wapi_handle_new (type, event_handle);
+ handle = mono_w32handle_new (type, event_handle);
if (handle == INVALID_HANDLE_VALUE) {
g_warning ("%s: error creating %s handle",
__func__, event_handle_type_to_string (type));
return NULL;
}
- thr_ret = _wapi_handle_lock_handle (handle);
+ thr_ret = mono_w32handle_lock_handle (handle);
g_assert (thr_ret == 0);
if (initial)
- _wapi_handle_set_signal_state (handle, TRUE, FALSE);
+ mono_w32handle_set_signal_state (handle, TRUE, FALSE);
- thr_ret = _wapi_handle_unlock_handle (handle);
+ thr_ret = mono_w32handle_unlock_handle (handle);
g_assert (thr_ret == 0);
MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: created %s handle %p",
{
struct _WapiHandle_event event_handle;
MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: creating %s handle",
- __func__, event_handle_type_to_string (WAPI_HANDLE_EVENT));
- return event_handle_create (&event_handle, WAPI_HANDLE_EVENT, manual, initial);
+ __func__, event_handle_type_to_string (MONO_W32HANDLE_EVENT));
+ 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)
int thr_ret;
MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: creating %s handle",
- __func__, event_handle_type_to_string (WAPI_HANDLE_NAMEDEVENT));
+ __func__, event_handle_type_to_string (MONO_W32HANDLE_NAMEDEVENT));
/* w32 seems to guarantee that opening named objects can't race each other */
thr_ret = _wapi_namespace_lock ();
utf8_name = g_utf16_to_utf8 (name, -1, NULL, NULL, NULL);
- handle = _wapi_search_handle_namespace (WAPI_HANDLE_NAMEDEVENT, utf8_name);
+ handle = _wapi_search_handle_namespace (MONO_W32HANDLE_NAMEDEVENT, utf8_name);
if (handle == INVALID_HANDLE_VALUE) {
/* The name has already been used for a different object. */
handle = NULL;
SetLastError (ERROR_ALREADY_EXISTS);
/* this is used as creating a new handle */
- _wapi_handle_ref (handle);
+ mono_w32handle_ref (handle);
} else {
/* A new named event */
struct _WapiHandle_namedevent namedevent_handle;
strncpy (&namedevent_handle.sharedns.name [0], utf8_name, MAX_PATH);
namedevent_handle.sharedns.name [MAX_PATH] = '\0';
- handle = event_handle_create ((struct _WapiHandle_event*) &namedevent_handle, WAPI_HANDLE_NAMEDEVENT, manual, initial);
+ handle = event_handle_create ((struct _WapiHandle_event*) &namedevent_handle, MONO_W32HANDLE_NAMEDEVENT, manual, initial);
}
g_free (utf8_name);
*/
gboolean PulseEvent(gpointer handle)
{
- WapiHandleType type;
+ MonoW32HandleType type;
struct _WapiHandle_event *event_handle;
int thr_ret;
return(FALSE);
}
- switch (type = _wapi_handle_type (handle)) {
- case WAPI_HANDLE_EVENT:
- case WAPI_HANDLE_NAMEDEVENT:
+ switch (type = mono_w32handle_get_type (handle)) {
+ case MONO_W32HANDLE_EVENT:
+ case MONO_W32HANDLE_NAMEDEVENT:
break;
default:
SetLastError (ERROR_INVALID_HANDLE);
return FALSE;
}
- if (!_wapi_lookup_handle (handle, type, (gpointer *)&event_handle)) {
+ if (!mono_w32handle_lookup (handle, type, (gpointer *)&event_handle)) {
g_warning ("%s: error looking up %s handle %p",
__func__, event_handle_type_to_string (type), handle);
return FALSE;
MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: pulsing %s handle %p",
__func__, event_handle_type_to_string (type), handle);
- thr_ret = _wapi_handle_lock_handle (handle);
+ thr_ret = mono_w32handle_lock_handle (handle);
g_assert (thr_ret == 0);
if (!event_handle->manual) {
event_handle->set_count = 1;
- _wapi_handle_set_signal_state (handle, TRUE, FALSE);
+ mono_w32handle_set_signal_state (handle, TRUE, FALSE);
} else {
- _wapi_handle_set_signal_state (handle, TRUE, TRUE);
+ mono_w32handle_set_signal_state (handle, TRUE, TRUE);
- thr_ret = _wapi_handle_unlock_handle (handle);
+ thr_ret = mono_w32handle_unlock_handle (handle);
g_assert (thr_ret == 0);
/* For a manual-reset event, we're about to try and get the handle
* that all threads waiting on the event have proceeded. Currently
* we rely on broadcasting a condition. */
- thr_ret = _wapi_handle_lock_handle (handle);
+ thr_ret = mono_w32handle_lock_handle (handle);
g_assert (thr_ret == 0);
- _wapi_handle_set_signal_state (handle, FALSE, FALSE);
+ mono_w32handle_set_signal_state (handle, FALSE, FALSE);
}
- thr_ret = _wapi_handle_unlock_handle (handle);
+ thr_ret = mono_w32handle_unlock_handle (handle);
g_assert (thr_ret == 0);
return TRUE;
*/
gboolean ResetEvent(gpointer handle)
{
- WapiHandleType type;
+ MonoW32HandleType type;
struct _WapiHandle_event *event_handle;
int thr_ret;
return(FALSE);
}
- switch (type = _wapi_handle_type (handle)) {
- case WAPI_HANDLE_EVENT:
- case WAPI_HANDLE_NAMEDEVENT:
+ switch (type = mono_w32handle_get_type (handle)) {
+ case MONO_W32HANDLE_EVENT:
+ case MONO_W32HANDLE_NAMEDEVENT:
break;
default:
SetLastError (ERROR_INVALID_HANDLE);
return FALSE;
}
- if (!_wapi_lookup_handle (handle, type, (gpointer *)&event_handle)) {
+ if (!mono_w32handle_lookup (handle, type, (gpointer *)&event_handle)) {
g_warning ("%s: error looking up %s handle %p",
__func__, event_handle_type_to_string (type), handle);
return FALSE;
MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: resetting %s handle %p",
__func__, event_handle_type_to_string (type), handle);
- thr_ret = _wapi_handle_lock_handle (handle);
+ thr_ret = mono_w32handle_lock_handle (handle);
g_assert (thr_ret == 0);
- if (!_wapi_handle_issignalled (handle)) {
+ if (!mono_w32handle_issignalled (handle)) {
MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: no need to reset %s handle %p",
__func__, event_handle_type_to_string (type), handle);
} else {
MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: obtained write lock on %s handle %p",
__func__, event_handle_type_to_string (type), handle);
- _wapi_handle_set_signal_state (handle, FALSE, FALSE);
+ mono_w32handle_set_signal_state (handle, FALSE, FALSE);
}
event_handle->set_count = 0;
- thr_ret = _wapi_handle_unlock_handle (handle);
+ thr_ret = mono_w32handle_unlock_handle (handle);
g_assert (thr_ret == 0);
return TRUE;
*/
gboolean SetEvent(gpointer handle)
{
- WapiHandleType type;
+ MonoW32HandleType type;
struct _WapiHandle_event *event_handle;
int thr_ret;
return(FALSE);
}
- switch (type = _wapi_handle_type (handle)) {
- case WAPI_HANDLE_EVENT:
- case WAPI_HANDLE_NAMEDEVENT:
+ switch (type = mono_w32handle_get_type (handle)) {
+ case MONO_W32HANDLE_EVENT:
+ case MONO_W32HANDLE_NAMEDEVENT:
break;
default:
SetLastError (ERROR_INVALID_HANDLE);
return FALSE;
}
- if (!_wapi_lookup_handle (handle, type, (gpointer *)&event_handle)) {
+ if (!mono_w32handle_lookup (handle, type, (gpointer *)&event_handle)) {
g_warning ("%s: error looking up %s handle %p",
__func__, event_handle_type_to_string (type), handle);
return FALSE;
MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: setting %s handle %p",
__func__, event_handle_type_to_string (type), handle);
- thr_ret = _wapi_handle_lock_handle (handle);
+ thr_ret = mono_w32handle_lock_handle (handle);
g_assert (thr_ret == 0);
if (!event_handle->manual) {
event_handle->set_count = 1;
- _wapi_handle_set_signal_state (handle, TRUE, FALSE);
+ mono_w32handle_set_signal_state (handle, TRUE, FALSE);
} else {
- _wapi_handle_set_signal_state (handle, TRUE, TRUE);
+ mono_w32handle_set_signal_state (handle, TRUE, TRUE);
}
- thr_ret = _wapi_handle_unlock_handle (handle);
+ thr_ret = mono_w32handle_unlock_handle (handle);
g_assert (thr_ret == 0);
return TRUE;
MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Opening named event [%s]", __func__, utf8_name);
- handle = _wapi_search_handle_namespace (WAPI_HANDLE_NAMEDEVENT,
+ handle = _wapi_search_handle_namespace (MONO_W32HANDLE_NAMEDEVENT,
utf8_name);
if (handle == INVALID_HANDLE_VALUE) {
/* The name has already been used for a different
+++ /dev/null
-/*
- * handles-private.h: Internal operations on handles
- *
- * Author:
- * Dick Porter (dick@ximian.com)
- *
- * (C) 2002-2006 Novell, Inc.
- */
-
-#ifndef _WAPI_HANDLES_PRIVATE_H_
-#define _WAPI_HANDLES_PRIVATE_H_
-
-#include <config.h>
-#include <glib.h>
-#include <errno.h>
-#include <string.h>
-#include <sys/types.h>
-#include <time.h>
-
-#include <mono/utils/atomic.h>
-
-#undef DEBUG
-
-typedef enum {
- WAPI_HANDLE_UNUSED=0,
- WAPI_HANDLE_FILE,
- WAPI_HANDLE_CONSOLE,
- WAPI_HANDLE_THREAD,
- WAPI_HANDLE_SEM,
- WAPI_HANDLE_MUTEX,
- WAPI_HANDLE_EVENT,
- WAPI_HANDLE_SOCKET,
- WAPI_HANDLE_FIND,
- WAPI_HANDLE_PROCESS,
- WAPI_HANDLE_PIPE,
- WAPI_HANDLE_NAMEDMUTEX,
- WAPI_HANDLE_NAMEDSEM,
- WAPI_HANDLE_NAMEDEVENT,
- WAPI_HANDLE_COUNT
-} WapiHandleType;
-
-typedef struct
-{
- void (*close)(gpointer handle, gpointer data);
-
- /* SignalObjectAndWait */
- void (*signal)(gpointer signal);
-
- /* Called by WaitForSingleObject and WaitForMultipleObjects,
- * with the handle locked (shared handles aren't locked.)
- * Returns TRUE if ownership was established, false otherwise.
- */
- gboolean (*own_handle)(gpointer handle);
-
- /* Called by WaitForSingleObject and WaitForMultipleObjects, if the
- * handle in question is "ownable" (ie mutexes), to see if the current
- * thread already owns this handle
- */
- gboolean (*is_owned)(gpointer handle);
-
- /* Called by WaitForSingleObject and WaitForMultipleObjects,
- * if the handle in question needs a special wait function
- * instead of using the normal handle signal mechanism.
- * Returns the WaitForSingleObject return code.
- */
- guint32 (*special_wait)(gpointer handle, guint32 timeout, gboolean alertable);
-
- /* Called by WaitForSingleObject and WaitForMultipleObjects,
- * if the handle in question needs some preprocessing before the
- * signal wait.
- */
- void (*prewait)(gpointer handle);
-
- /* Called when dumping the handles */
- void (*details)(gpointer data);
-
- /* Called to get the name of the handle type */
- const gchar* (*typename) (void);
-
- /* Called to get the size of the handle type */
- gsize (*typesize) (void);
-} WapiHandleOps;
-
-typedef enum {
- WAPI_HANDLE_CAP_WAIT = 0x01,
- WAPI_HANDLE_CAP_SIGNAL = 0x02,
- WAPI_HANDLE_CAP_OWN = 0x04,
- WAPI_HANDLE_CAP_SPECIAL_WAIT = 0x08,
-} WapiHandleCapability;
-
-extern guint32 _wapi_fd_reserve;
-
-void
-_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,
- gpointer handle_specific);
-extern gboolean _wapi_lookup_handle (gpointer handle, WapiHandleType type,
- gpointer *handle_specific);
-extern gpointer _wapi_search_handle (WapiHandleType type,
- gboolean (*check)(gpointer, gpointer),
- gpointer user_data,
- gpointer *handle_specific,
- gboolean search_shared);
-extern void _wapi_handle_ref (gpointer handle);
-extern void _wapi_handle_unref (gpointer handle);
-extern void _wapi_handle_register_capabilities (WapiHandleType type,
- WapiHandleCapability caps);
-extern gboolean _wapi_handle_test_capabilities (gpointer handle,
- WapiHandleCapability caps);
-extern void _wapi_handle_ops_close (gpointer handle, gpointer data);
-extern void _wapi_handle_ops_signal (gpointer handle);
-extern gboolean _wapi_handle_ops_own (gpointer handle);
-extern gboolean _wapi_handle_ops_isowned (gpointer handle);
-extern guint32 _wapi_handle_ops_special_wait (gpointer handle,
- guint32 timeout,
- gboolean alertable);
-extern void _wapi_handle_ops_prewait (gpointer handle);
-extern void _wapi_handle_ops_details (WapiHandleType type, gpointer data);
-extern const gchar* _wapi_handle_ops_typename (WapiHandleType type);
-extern gsize _wapi_handle_ops_typesize (WapiHandleType type);
-
-extern gboolean _wapi_handle_count_signalled_handles (guint32 numhandles,
- gpointer *handles,
- gboolean waitall,
- guint32 *retcount,
- guint32 *lowest);
-extern void _wapi_handle_unlock_handles (guint32 numhandles,
- gpointer *handles);
-extern int _wapi_handle_timedwait_signal_handle (gpointer handle, guint32 timeout, gboolean poll, gboolean *alerted);
-extern int _wapi_handle_timedwait_signal (guint32 timeout, gboolean poll, gboolean *alerted);
-extern void _wapi_handle_dump (void);
-extern void _wapi_handle_foreach (gboolean (*on_each)(gpointer handle, gpointer data, gpointer user_data), gpointer user_data);
-
-WapiHandleType
-_wapi_handle_type (gpointer handle);
-
-void
-_wapi_handle_set_signal_state (gpointer handle, gboolean state, gboolean broadcast);
-
-gboolean
-_wapi_handle_issignalled (gpointer handle);
-
-int
-_wapi_handle_lock_signal_mutex (void);
-
-int
-_wapi_handle_unlock_signal_mutex (void);
-
-int
-_wapi_handle_lock_handle (gpointer handle);
-
-int
-_wapi_handle_trylock_handle (gpointer handle);
-
-int
-_wapi_handle_unlock_handle (gpointer handle);
-
-static gboolean
-_WAPI_SHARED_NAMESPACE (WapiHandleType type)
-{
- switch (type) {
- case WAPI_HANDLE_NAMEDMUTEX:
- case WAPI_HANDLE_NAMEDSEM:
- case WAPI_HANDLE_NAMEDEVENT:
- return TRUE;
- default:
- return FALSE;
- }
-}
-
-static gboolean
-_WAPI_FD_HANDLE (WapiHandleType type)
-{
- switch (type) {
- case WAPI_HANDLE_FILE:
- case WAPI_HANDLE_CONSOLE:
- case WAPI_HANDLE_SOCKET:
- case WAPI_HANDLE_PIPE:
- return TRUE;
- default:
- return FALSE;
- }
-}
-
-#endif /* _WAPI_HANDLES_PRIVATE_H_ */
+++ /dev/null
-/*
- * handles.c: Generic and internal operations on handles
- *
- * Author:
- * Dick Porter (dick@ximian.com)
- *
- * (C) 2002-2011 Novell, Inc.
- * Copyright 2011 Xamarin Inc
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
- */
-
-#include <config.h>
-#include <glib.h>
-#include <pthread.h>
-#include <errno.h>
-#include <unistd.h>
-#ifdef HAVE_SIGNAL_H
-#include <signal.h>
-#endif
-#include <string.h>
-#include <sys/types.h>
-#ifdef HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif
-#ifdef HAVE_SYS_UN_H
-# include <sys/un.h>
-#endif
-#ifdef HAVE_SYS_MMAN_H
-# include <sys/mman.h>
-#endif
-#ifdef HAVE_DIRENT_H
-# include <dirent.h>
-#endif
-#include <sys/stat.h>
-#ifdef HAVE_SYS_RESOURCE_H
-# include <sys/resource.h>
-#endif
-
-#include <mono/io-layer/handles-private.h>
-#include <mono/io-layer/io-trace.h>
-
-#include <mono/utils/mono-os-mutex.h>
-#include <mono/utils/mono-proclib.h>
-#include <mono/utils/mono-threads.h>
-#include <mono/utils/mono-once.h>
-#include <mono/utils/mono-logger-internals.h>
-#undef DEBUG_REFS
-
-#define _WAPI_PRIVATE_MAX_SLOTS (1024 * 16)
-
-/* must be a power of 2 */
-#define _WAPI_HANDLE_INITIAL_COUNT (256)
-
-typedef struct {
- WapiHandleType type;
- guint ref;
- gboolean signalled;
- mono_mutex_t signal_mutex;
- mono_cond_t signal_cond;
- gpointer data;
-} WapiHandleBase;
-
-static void (*_wapi_handle_ops_get_close_func (WapiHandleType type))(gpointer, gpointer);
-
-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.
- * If 4M handles are not enough... Oh, well... we will crash.
- */
-#define SLOT_INDEX(x) (x / _WAPI_HANDLE_INITIAL_COUNT)
-#define SLOT_OFFSET(x) (x % _WAPI_HANDLE_INITIAL_COUNT)
-
-WapiHandleBase *_wapi_private_handles [_WAPI_PRIVATE_MAX_SLOTS];
-static guint32 _wapi_private_handle_count = 0;
-static guint32 _wapi_private_handle_slot_count = 0;
-
-guint32 _wapi_fd_reserve;
-
-/*
- * This is an internal handle which is used for handling waiting for multiple handles.
- * Threads which wait for multiple handles wait on this one handle, and when a handle
- * is signalled, this handle is signalled too.
- */
-static mono_mutex_t _wapi_global_signal_mutex;
-static mono_cond_t _wapi_global_signal_cond;
-
-static gboolean shutting_down = FALSE;
-
-static void _wapi_handle_unref_full (gpointer handle, gboolean ignore_private_busy_handles);
-
-
-static mono_mutex_t scan_mutex;
-
-static gboolean
-_wapi_handle_lookup_data (gpointer handle, WapiHandleBase **handle_data)
-{
- gsize index, offset;
-
- g_assert (handle_data);
-
- index = SLOT_INDEX ((gsize) handle);
- if (index >= _WAPI_PRIVATE_MAX_SLOTS)
- return FALSE;
- if (!_wapi_private_handles [index])
- return FALSE;
-
- offset = SLOT_OFFSET ((gsize) handle);
- if (_wapi_private_handles [index][offset].type == WAPI_HANDLE_UNUSED)
- return FALSE;
-
- *handle_data = &_wapi_private_handles [index][offset];
- return TRUE;
-}
-
-WapiHandleType
-_wapi_handle_type (gpointer handle)
-{
- WapiHandleBase *handle_data;
-
- if (!_wapi_handle_lookup_data (handle, &handle_data))
- return WAPI_HANDLE_UNUSED; /* An impossible type */
-
- return handle_data->type;
-}
-
-void
-_wapi_handle_set_signal_state (gpointer handle, gboolean state, gboolean broadcast)
-{
- WapiHandleBase *handle_data;
- int thr_ret;
-
- if (!_wapi_handle_lookup_data (handle, &handle_data)) {
- return;
- }
-
-#ifdef DEBUG
- g_message ("%s: setting state of %p to %s (broadcast %s)", __func__,
- handle, state?"TRUE":"FALSE", broadcast?"TRUE":"FALSE");
-#endif
-
- if (state == TRUE) {
- /* Tell everyone blocking on a single handle */
-
- /* The condition the global signal cond is waiting on is the signalling of
- * _any_ handle. So lock it before setting the signalled state.
- */
- thr_ret = mono_os_mutex_lock (&_wapi_global_signal_mutex);
- if (thr_ret != 0)
- g_warning ("Bad call to mono_os_mutex_lock result %d for global signal mutex", thr_ret);
- g_assert (thr_ret == 0);
-
- /* This function _must_ be called with
- * handle->signal_mutex locked
- */
- handle_data->signalled=state;
-
- if (broadcast == TRUE) {
- thr_ret = mono_os_cond_broadcast (&handle_data->signal_cond);
- if (thr_ret != 0)
- g_warning ("Bad call to mono_os_cond_broadcast result %d for handle %p", thr_ret, handle);
- g_assert (thr_ret == 0);
- } else {
- thr_ret = mono_os_cond_signal (&handle_data->signal_cond);
- if (thr_ret != 0)
- g_warning ("Bad call to mono_os_cond_signal result %d for handle %p", thr_ret, handle);
- g_assert (thr_ret == 0);
- }
-
- /* Tell everyone blocking on multiple handles that something
- * was signalled
- */
- thr_ret = mono_os_cond_broadcast (&_wapi_global_signal_cond);
- if (thr_ret != 0)
- g_warning ("Bad call to mono_os_cond_broadcast result %d for handle %p", thr_ret, handle);
- g_assert (thr_ret == 0);
-
- thr_ret = mono_os_mutex_unlock (&_wapi_global_signal_mutex);
- if (thr_ret != 0)
- g_warning ("Bad call to mono_os_mutex_unlock result %d for global signal mutex", thr_ret);
- g_assert (thr_ret == 0);
- } else {
- handle_data->signalled=state;
- }
-}
-
-gboolean
-_wapi_handle_issignalled (gpointer handle)
-{
- WapiHandleBase *handle_data;
-
- if (!_wapi_handle_lookup_data (handle, &handle_data)) {
- return(FALSE);
- }
-
- return handle_data->signalled;
-}
-
-int
-_wapi_handle_lock_signal_mutex (void)
-{
-#ifdef DEBUG
- g_message ("%s: lock global signal mutex", __func__);
-#endif
-
- return(mono_os_mutex_lock (&_wapi_global_signal_mutex));
-}
-
-int
-_wapi_handle_unlock_signal_mutex (void)
-{
-#ifdef DEBUG
- g_message ("%s: unlock global signal mutex", __func__);
-#endif
-
- return(mono_os_mutex_unlock (&_wapi_global_signal_mutex));
-}
-
-int
-_wapi_handle_lock_handle (gpointer handle)
-{
- WapiHandleBase *handle_data;
-
-#ifdef DEBUG
- g_message ("%s: locking handle %p", __func__, handle);
-#endif
-
- if (!_wapi_handle_lookup_data (handle, &handle_data)) {
- return(0);
- }
-
- _wapi_handle_ref (handle);
-
- return(mono_os_mutex_lock (&handle_data->signal_mutex));
-}
-
-int
-_wapi_handle_trylock_handle (gpointer handle)
-{
- WapiHandleBase *handle_data;
- int ret;
-
-#ifdef DEBUG
- g_message ("%s: locking handle %p", __func__, handle);
-#endif
-
- if (!_wapi_handle_lookup_data (handle, &handle_data)) {
- return(0);
- }
-
- _wapi_handle_ref (handle);
-
- ret = mono_os_mutex_trylock (&handle_data->signal_mutex);
- if (ret != 0) {
- _wapi_handle_unref (handle);
- }
-
- return(ret);
-}
-
-int
-_wapi_handle_unlock_handle (gpointer handle)
-{
- WapiHandleBase *handle_data;
- int ret;
-
-#ifdef DEBUG
- g_message ("%s: unlocking handle %p", __func__, handle);
-#endif
-
- if (!_wapi_handle_lookup_data (handle, &handle_data)) {
- return(0);
- }
-
- ret = mono_os_mutex_unlock (&handle_data->signal_mutex);
-
- _wapi_handle_unref (handle);
-
- return(ret);
-}
-
-/*
- * wapi_init:
- *
- * Initialize the io-layer.
- */
-void
-_wapi_handle_init (void)
-{
- g_assert ((sizeof (handle_ops) / sizeof (handle_ops[0]))
- == WAPI_HANDLE_COUNT);
-
- _wapi_fd_reserve = eg_getdtablesize ();
-
- /* This is needed by the code in _wapi_handle_new_internal */
- _wapi_fd_reserve = (_wapi_fd_reserve + (_WAPI_HANDLE_INITIAL_COUNT - 1)) & ~(_WAPI_HANDLE_INITIAL_COUNT - 1);
-
- do {
- /*
- * The entries in _wapi_private_handles reserved for fds are allocated lazily to
- * save memory.
- */
-
- _wapi_private_handle_count += _WAPI_HANDLE_INITIAL_COUNT;
- _wapi_private_handle_slot_count ++;
- } while(_wapi_fd_reserve > _wapi_private_handle_count);
-
- mono_os_mutex_init (&scan_mutex);
-
- mono_os_cond_init (&_wapi_global_signal_cond);
- mono_os_mutex_init (&_wapi_global_signal_mutex);
-}
-
-void
-_wapi_handle_cleanup (void)
-{
- int i, j, k;
-
- g_assert (!shutting_down);
- shutting_down = TRUE;
-
- /* Every shared handle we were using ought really to be closed
- * by now, but to make sure just blow them all away. The
- * exiting finalizer thread in particular races us to the
- * program exit and doesn't always win, so it can be left
- * cluttering up the shared file. Anything else left over is
- * really a bug.
- */
- for(i = SLOT_INDEX (0); _wapi_private_handles[i] != NULL; i++) {
- for(j = SLOT_OFFSET (0); j < _WAPI_HANDLE_INITIAL_COUNT; j++) {
- WapiHandleBase *handle_data = &_wapi_private_handles[i][j];
- gpointer handle = GINT_TO_POINTER (i*_WAPI_HANDLE_INITIAL_COUNT+j);
-
- for(k = handle_data->ref; k > 0; k--) {
- _wapi_handle_unref_full (handle, TRUE);
- }
- }
- }
-
- for (i = 0; i < _WAPI_PRIVATE_MAX_SLOTS; ++i)
- g_free (_wapi_private_handles [i]);
-}
-
-static void _wapi_handle_init_handle (WapiHandleBase *handle,
- WapiHandleType type, gpointer handle_specific)
-{
- int thr_ret;
-
- g_assert (!shutting_down);
-
- handle->type = type;
- handle->signalled = FALSE;
- handle->ref = 1;
-
- thr_ret = mono_os_cond_init (&handle->signal_cond);
- g_assert (thr_ret == 0);
-
- thr_ret = mono_os_mutex_init (&handle->signal_mutex);
- g_assert (thr_ret == 0);
-
- if (handle_specific != NULL)
- handle->data = g_memdup (handle_specific, _wapi_handle_ops_typesize (type));
-}
-
-/*
- * _wapi_handle_new_internal:
- * @type: Init handle to this type
- *
- * Search for a free handle and initialize it. Return the handle on
- * success and 0 on failure. This is only called from
- * _wapi_handle_new, and scan_mutex must be held.
- */
-static guint32 _wapi_handle_new_internal (WapiHandleType type,
- gpointer handle_specific)
-{
- guint32 i, k, count;
- static guint32 last = 0;
- gboolean retry = FALSE;
-
- g_assert (!shutting_down);
-
- /* A linear scan should be fast enough. Start from the last
- * allocation, assuming that handles are allocated more often
- * than they're freed. Leave the space reserved for file
- * descriptors
- */
-
- if (last < _wapi_fd_reserve) {
- last = _wapi_fd_reserve;
- } else {
- retry = TRUE;
- }
-
-again:
- count = last;
- for(i = SLOT_INDEX (count); i < _wapi_private_handle_slot_count; i++) {
- if (_wapi_private_handles [i]) {
- for (k = SLOT_OFFSET (count); k < _WAPI_HANDLE_INITIAL_COUNT; k++) {
- WapiHandleBase *handle = &_wapi_private_handles [i][k];
-
- if(handle->type == WAPI_HANDLE_UNUSED) {
- last = count + 1;
-
- _wapi_handle_init_handle (handle, type, handle_specific);
- return (count);
- }
- count++;
- }
- }
- }
-
- if(retry && last > _wapi_fd_reserve) {
- /* Try again from the beginning */
- last = _wapi_fd_reserve;
- goto again;
- }
-
- /* Will need to expand the array. The caller will sort it out */
-
- return(0);
-}
-
-gpointer
-_wapi_handle_new (WapiHandleType type, gpointer handle_specific)
-{
- guint32 handle_idx = 0;
- gpointer handle;
- int thr_ret;
-
- g_assert (!shutting_down);
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Creating new handle of type %s", __func__,
- _wapi_handle_ops_typename (type));
-
- g_assert(!_WAPI_FD_HANDLE(type));
-
- thr_ret = mono_os_mutex_lock (&scan_mutex);
- g_assert (thr_ret == 0);
-
- while ((handle_idx = _wapi_handle_new_internal (type, handle_specific)) == 0) {
- /* Try and expand the array, and have another go */
- int idx = SLOT_INDEX (_wapi_private_handle_count);
- if (idx >= _WAPI_PRIVATE_MAX_SLOTS) {
- break;
- }
-
- _wapi_private_handles [idx] = g_new0 (WapiHandleBase, _WAPI_HANDLE_INITIAL_COUNT);
-
- _wapi_private_handle_count += _WAPI_HANDLE_INITIAL_COUNT;
- _wapi_private_handle_slot_count ++;
- }
-
- thr_ret = mono_os_mutex_unlock (&scan_mutex);
- g_assert (thr_ret == 0);
-
- if (handle_idx == 0) {
- /* We ran out of slots */
- handle = INVALID_HANDLE_VALUE;
- goto done;
- }
-
- /* Make sure we left the space for fd mappings */
- g_assert (handle_idx >= _wapi_fd_reserve);
-
- handle = GUINT_TO_POINTER (handle_idx);
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Allocated new handle %p", __func__, handle);
-
-done:
- return(handle);
-}
-
-gpointer _wapi_handle_new_fd (WapiHandleType type, int fd,
- gpointer handle_specific)
-{
- WapiHandleBase *handle_data;
- int fd_index, fd_offset;
- int thr_ret;
-
- g_assert (!shutting_down);
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Creating new handle of type %s", __func__,
- _wapi_handle_ops_typename (type));
-
- g_assert(_WAPI_FD_HANDLE(type));
-
- if (fd >= _wapi_fd_reserve) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d is too big", __func__, fd);
-
- return(GUINT_TO_POINTER (INVALID_HANDLE_VALUE));
- }
-
- fd_index = SLOT_INDEX (fd);
- fd_offset = SLOT_OFFSET (fd);
-
- /* Initialize the array entries on demand */
- if (!_wapi_private_handles [fd_index]) {
- thr_ret = mono_os_mutex_lock (&scan_mutex);
- g_assert (thr_ret == 0);
-
- if (!_wapi_private_handles [fd_index])
- _wapi_private_handles [fd_index] = g_new0 (WapiHandleBase, _WAPI_HANDLE_INITIAL_COUNT);
-
- thr_ret = mono_os_mutex_unlock (&scan_mutex);
- g_assert (thr_ret == 0);
- }
-
- handle_data = &_wapi_private_handles [fd_index][fd_offset];
-
- if (handle_data->type != WAPI_HANDLE_UNUSED) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d is already in use!", __func__, fd);
- /* FIXME: clean up this handle? We can't do anything
- * with the fd, cos thats the new one
- */
- }
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Assigning new fd handle %p", __func__, (gpointer)(gsize)fd);
-
- _wapi_handle_init_handle (handle_data, type, handle_specific);
-
- return(GUINT_TO_POINTER(fd));
-}
-
-gboolean
-_wapi_lookup_handle (gpointer handle, WapiHandleType type,
- gpointer *handle_specific)
-{
- WapiHandleBase *handle_data;
-
- if (!_wapi_handle_lookup_data (handle, &handle_data)) {
- return(FALSE);
- }
-
- if (handle_data->type != type) {
- return(FALSE);
- }
-
- if (handle_specific == NULL) {
- return(FALSE);
- }
-
- *handle_specific = handle_data->data;
-
- return(TRUE);
-}
-
-void
-_wapi_handle_foreach (gboolean (*on_each)(gpointer handle, gpointer data, gpointer user_data), gpointer user_data)
-{
- WapiHandleBase *handle_data = NULL;
- gpointer handle;
- guint32 i, k;
- int thr_ret;
-
- thr_ret = mono_os_mutex_lock (&scan_mutex);
- g_assert (thr_ret == 0);
-
- for (i = SLOT_INDEX (0); i < _wapi_private_handle_slot_count; i++) {
- if (_wapi_private_handles [i]) {
- for (k = SLOT_OFFSET (0); k < _WAPI_HANDLE_INITIAL_COUNT; k++) {
- handle_data = &_wapi_private_handles [i][k];
- if (handle_data->type == WAPI_HANDLE_UNUSED)
- continue;
- handle = GUINT_TO_POINTER (i * _WAPI_HANDLE_INITIAL_COUNT + k);
- if (on_each (handle, handle_data->data, user_data) == TRUE)
- goto done;
- }
- }
- }
-
-done:
- thr_ret = mono_os_mutex_unlock (&scan_mutex);
- g_assert (thr_ret == 0);
-}
-
-/* This might list some shared handles twice if they are already
- * opened by this process, and the check function returns FALSE the
- * first time. Shared handles that are created during the search are
- * unreffed if the check function returns FALSE, so callers must not
- * rely on the handle persisting (unless the check function returns
- * TRUE)
- * The caller owns the returned handle.
- */
-gpointer _wapi_search_handle (WapiHandleType type,
- gboolean (*check)(gpointer test, gpointer user),
- gpointer user_data,
- gpointer *handle_specific,
- gboolean search_shared)
-{
- WapiHandleBase *handle_data = NULL;
- gpointer ret = NULL;
- guint32 i, k;
- gboolean found = FALSE;
- int thr_ret;
-
- thr_ret = mono_os_mutex_lock (&scan_mutex);
- g_assert (thr_ret == 0);
-
- for (i = SLOT_INDEX (0); !found && i < _wapi_private_handle_slot_count; i++) {
- if (_wapi_private_handles [i]) {
- for (k = SLOT_OFFSET (0); k < _WAPI_HANDLE_INITIAL_COUNT; k++) {
- handle_data = &_wapi_private_handles [i][k];
-
- if (handle_data->type == type) {
- ret = GUINT_TO_POINTER (i * _WAPI_HANDLE_INITIAL_COUNT + k);
- if (check (ret, user_data) == TRUE) {
- _wapi_handle_ref (ret);
- found = TRUE;
- break;
- }
- }
- }
- }
- }
-
- thr_ret = mono_os_mutex_unlock (&scan_mutex);
- g_assert (thr_ret == 0);
-
- if (!found) {
- ret = NULL;
- goto done;
- }
-
- if(handle_specific != NULL) {
- *handle_specific = handle_data->data;
- }
-
-done:
- return(ret);
-}
-
-void _wapi_handle_ref (gpointer handle)
-{
- WapiHandleBase *handle_data;
-
- if (!_wapi_handle_lookup_data (handle, &handle_data)) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Attempting to ref invalid private handle %p", __func__, handle);
- return;
- }
-
- InterlockedIncrement ((gint32 *)&handle_data->ref);
-
-#ifdef DEBUG_REFS
- g_message ("%s: %s handle %p ref now %d",
- __func__, _wapi_handle_ops_typename (handle_data->type), handle, handle_data->ref);
-#endif
-}
-
-/* The handle must not be locked on entry to this function */
-static void _wapi_handle_unref_full (gpointer handle, gboolean ignore_private_busy_handles)
-{
- WapiHandleBase *handle_data;
- gboolean destroy = FALSE, early_exit = FALSE;
- int thr_ret;
-
- if (!_wapi_handle_lookup_data (handle, &handle_data)) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Attempting to unref invalid private handle %p",
- __func__, handle);
- return;
- }
-
- /* Possible race condition here if another thread refs the
- * handle between here and setting the type to UNUSED. I
- * could lock a mutex, but I'm not sure that allowing a handle
- * reference to reach 0 isn't an application bug anyway.
- */
- destroy = (InterlockedDecrement ((gint32 *)&handle_data->ref) ==0);
-
-#ifdef DEBUG_REFS
- g_message ("%s: %s handle %p ref now %d (destroy %s)",
- __func__, _wapi_handle_ops_typename (handle_data->type), handle, handle_data->ref, destroy?"TRUE":"FALSE");
-#endif
-
- if(destroy==TRUE) {
- /* Need to copy the handle info, reset the slot in the
- * array, and _only then_ call the close function to
- * avoid race conditions (eg file descriptors being
- * closed, and another file being opened getting the
- * same fd racing the memset())
- */
- WapiHandleType type;
- gpointer data;
- void (*close_func)(gpointer, gpointer);
-
- type = handle_data->type;
- data = handle_data->data;
-
- thr_ret = mono_os_mutex_lock (&scan_mutex);
- g_assert (thr_ret == 0);
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Destroying handle %p", __func__, handle);
-
- /* Destroy the mutex and cond var. We hope nobody
- * tried to grab them between the handle unlock and
- * now, but pthreads doesn't have a
- * "unlock_and_destroy" atomic function.
- */
- thr_ret = mono_os_mutex_destroy (&handle_data->signal_mutex);
- /*WARNING gross hack to make cleanup not crash when exiting without the whole runtime teardown.*/
- if (thr_ret == EBUSY && ignore_private_busy_handles) {
- early_exit = TRUE;
- } else {
- if (thr_ret != 0)
- g_error ("Error destroying handle %p mutex due to %d\n", handle, thr_ret);
-
- thr_ret = mono_os_cond_destroy (&handle_data->signal_cond);
- if (thr_ret == EBUSY && ignore_private_busy_handles)
- early_exit = TRUE;
- else if (thr_ret != 0)
- g_error ("Error destroying handle %p cond var due to %d\n", handle, thr_ret);
- }
-
- memset (handle_data, 0, sizeof (WapiHandleBase));
-
- thr_ret = mono_os_mutex_unlock (&scan_mutex);
- g_assert (thr_ret == 0);
-
- if (early_exit)
- return;
-
- close_func = _wapi_handle_ops_get_close_func (type);
- if (close_func != NULL) {
- close_func (handle, data);
- }
-
- g_free (data);
- }
-}
-
-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)
-{
- handle_caps[type] = caps;
-}
-
-gboolean _wapi_handle_test_capabilities (gpointer handle,
- WapiHandleCapability caps)
-{
- WapiHandleBase *handle_data;
- WapiHandleType type;
-
- if (!_wapi_handle_lookup_data (handle, &handle_data)) {
- return(FALSE);
- }
-
- type = handle_data->type;
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: testing 0x%x against 0x%x (%d)", __func__,
- handle_caps[type], caps, handle_caps[type] & caps);
-
- return((handle_caps[type] & caps) != 0);
-}
-
-static void (*_wapi_handle_ops_get_close_func (WapiHandleType type))(gpointer, gpointer)
-{
- if (handle_ops[type] != NULL &&
- handle_ops[type]->close != NULL) {
- return (handle_ops[type]->close);
- }
-
- return (NULL);
-}
-
-void _wapi_handle_ops_close (gpointer handle, gpointer data)
-{
- WapiHandleBase *handle_data;
- WapiHandleType type;
-
- if (!_wapi_handle_lookup_data (handle, &handle_data)) {
- return;
- }
-
- type = handle_data->type;
-
- if (handle_ops[type] != NULL &&
- handle_ops[type]->close != NULL) {
- handle_ops[type]->close (handle, data);
- }
-}
-
-void _wapi_handle_ops_details (WapiHandleType type, gpointer data)
-{
- if (handle_ops[type] != NULL &&
- handle_ops[type]->details != NULL) {
- handle_ops[type]->details (data);
- }
-}
-
-const gchar* _wapi_handle_ops_typename (WapiHandleType type)
-{
- g_assert (handle_ops [type]);
- g_assert (handle_ops [type]->typename);
- return handle_ops [type]->typename ();
-}
-
-gsize _wapi_handle_ops_typesize (WapiHandleType type)
-{
- g_assert (handle_ops [type]);
- g_assert (handle_ops [type]->typesize);
- return handle_ops [type]->typesize ();
-}
-
-void _wapi_handle_ops_signal (gpointer handle)
-{
- WapiHandleBase *handle_data;
- WapiHandleType type;
-
- if (!_wapi_handle_lookup_data (handle, &handle_data)) {
- return;
- }
-
- type = handle_data->type;
-
- if (handle_ops[type] != NULL && handle_ops[type]->signal != NULL) {
- handle_ops[type]->signal (handle);
- }
-}
-
-gboolean _wapi_handle_ops_own (gpointer handle)
-{
- WapiHandleBase *handle_data;
- WapiHandleType type;
-
- if (!_wapi_handle_lookup_data (handle, &handle_data)) {
- return(FALSE);
- }
-
- type = handle_data->type;
-
- if (handle_ops[type] != NULL && handle_ops[type]->own_handle != NULL) {
- return(handle_ops[type]->own_handle (handle));
- } else {
- return(FALSE);
- }
-}
-
-gboolean _wapi_handle_ops_isowned (gpointer handle)
-{
- WapiHandleBase *handle_data;
- WapiHandleType type;
-
- if (!_wapi_handle_lookup_data (handle, &handle_data)) {
- return(FALSE);
- }
-
- type = handle_data->type;
-
- if (handle_ops[type] != NULL && handle_ops[type]->is_owned != NULL) {
- return(handle_ops[type]->is_owned (handle));
- } else {
- return(FALSE);
- }
-}
-
-guint32 _wapi_handle_ops_special_wait (gpointer handle, guint32 timeout, gboolean alertable)
-{
- WapiHandleBase *handle_data;
- WapiHandleType type;
-
- if (!_wapi_handle_lookup_data (handle, &handle_data)) {
- return(WAIT_FAILED);
- }
-
- type = handle_data->type;
-
- if (handle_ops[type] != NULL &&
- handle_ops[type]->special_wait != NULL) {
- return(handle_ops[type]->special_wait (handle, timeout, alertable));
- } else {
- return(WAIT_FAILED);
- }
-}
-
-void _wapi_handle_ops_prewait (gpointer handle)
-{
- WapiHandleBase *handle_data;
- WapiHandleType type;
-
- if (!_wapi_handle_lookup_data (handle, &handle_data)) {
- return;
- }
-
- type = handle_data->type;
-
- if (handle_ops[type] != NULL &&
- handle_ops[type]->prewait != NULL) {
- handle_ops[type]->prewait (handle);
- }
-}
-
-static void
-spin (guint32 ms)
-{
- struct timespec sleepytime;
-
- g_assert (ms < 1000);
-
- sleepytime.tv_sec = 0;
- sleepytime.tv_nsec = ms * 1000000;
- nanosleep (&sleepytime, NULL);
-}
-
-gboolean _wapi_handle_count_signalled_handles (guint32 numhandles,
- gpointer *handles,
- gboolean waitall,
- guint32 *retcount,
- guint32 *lowest)
-{
- guint32 count, i, iter=0;
- gboolean ret;
- int thr_ret;
-
- /* Lock all the handles, with backoff */
-again:
- for(i=0; i<numhandles; i++) {
- gpointer handle = handles[i];
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: attempting to lock %p", __func__, handle);
-
- thr_ret = _wapi_handle_trylock_handle (handle);
-
- if (thr_ret != 0) {
- /* Bummer */
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: attempt failed for %p: %s", __func__,
- handle, strerror (thr_ret));
-
- while (i--) {
- handle = handles[i];
-
- thr_ret = _wapi_handle_unlock_handle (handle);
- g_assert (thr_ret == 0);
- }
-
- /* If iter ever reaches 100 the nanosleep will
- * return EINVAL immediately, but we have a
- * design flaw if that happens.
- */
- iter++;
- if(iter==100) {
- g_warning ("%s: iteration overflow!",
- __func__);
- iter=1;
- }
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Backing off for %d ms", __func__,
- iter*10);
- spin (10 * iter);
-
- goto again;
- }
- }
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Locked all handles", __func__);
-
- count=0;
- *lowest=numhandles;
-
- for(i=0; i<numhandles; i++) {
- gpointer handle = handles[i];
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Checking handle %p", __func__, handle);
-
- if(((_wapi_handle_test_capabilities (handle, WAPI_HANDLE_CAP_OWN)==TRUE) &&
- (_wapi_handle_ops_isowned (handle) == TRUE)) ||
- (_wapi_handle_issignalled (handle))) {
- count++;
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Handle %p signalled", __func__,
- handle);
- if(*lowest>i) {
- *lowest=i;
- }
- }
- }
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: %d event handles signalled", __func__, count);
-
- if ((waitall == TRUE && count == numhandles) ||
- (waitall == FALSE && count > 0)) {
- ret=TRUE;
- } else {
- ret=FALSE;
- }
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Returning %d", __func__, ret);
-
- *retcount=count;
-
- return(ret);
-}
-
-void _wapi_handle_unlock_handles (guint32 numhandles, gpointer *handles)
-{
- guint32 i;
- int thr_ret;
-
- for(i=0; i<numhandles; i++) {
- gpointer handle = handles[i];
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unlocking handle %p", __func__, handle);
-
- thr_ret = _wapi_handle_unlock_handle (handle);
- g_assert (thr_ret == 0);
- }
-}
-
-static int
-_wapi_handle_timedwait_signal_naked (mono_cond_t *cond, mono_mutex_t *mutex, guint32 timeout, gboolean poll, gboolean *alerted)
-{
- int res;
-
- if (!poll) {
- res = mono_os_cond_timedwait (cond, mutex, timeout);
- } else {
- /* This is needed when waiting for process handles */
- if (!alerted) {
- /*
- * pthread_cond_(timed)wait() can return 0 even if the condition was not
- * signalled. This happens at least on Darwin. We surface this, i.e., we
- * get spurious wake-ups.
- *
- * http://pubs.opengroup.org/onlinepubs/007908775/xsh/pthread_cond_wait.html
- */
- res = mono_os_cond_timedwait (cond, mutex, timeout);
- } else {
- if (timeout < 100) {
- /* Real timeout is less than 100ms time */
- res = mono_os_cond_timedwait (cond, mutex, timeout);
- } else {
- res = mono_os_cond_timedwait (cond, mutex, 100);
-
- /* Mask the fake timeout, this will cause
- * another poll if the cond was not really signaled
- */
- if (res == ETIMEDOUT)
- res = 0;
- }
- }
- }
-
- return res;
-}
-
-static void
-signal_global (gpointer unused)
-{
- /* If we reach here, then interrupt token is set to the flag value, which
- * means that the target thread is either
- * - before the first CAS in timedwait, which means it won't enter the wait.
- * - it is after the first CAS, so it is already waiting, or it will enter
- * the wait, and it will be interrupted by the broadcast. */
- mono_os_mutex_lock (&_wapi_global_signal_mutex);
- mono_os_cond_broadcast (&_wapi_global_signal_cond);
- mono_os_mutex_unlock (&_wapi_global_signal_mutex);
-}
-
-int
-_wapi_handle_timedwait_signal (guint32 timeout, gboolean poll, gboolean *alerted)
-{
- int res;
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: waiting for global", __func__);
-
- if (alerted)
- *alerted = FALSE;
-
- if (alerted) {
- mono_thread_info_install_interrupt (signal_global, NULL, alerted);
- if (*alerted)
- return 0;
- }
-
- res = _wapi_handle_timedwait_signal_naked (&_wapi_global_signal_cond, &_wapi_global_signal_mutex, timeout, poll, alerted);
-
- if (alerted)
- mono_thread_info_uninstall_interrupt (alerted);
-
- return res;
-}
-
-static void
-signal_handle_and_unref (gpointer handle)
-{
- WapiHandleBase *handle_data;
- mono_cond_t *cond;
- mono_mutex_t *mutex;
-
- if (!_wapi_handle_lookup_data (handle, &handle_data))
- g_error ("cannot signal unknown handle %p", handle);
-
- /* If we reach here, then interrupt token is set to the flag value, which
- * means that the target thread is either
- * - before the first CAS in timedwait, which means it won't enter the wait.
- * - it is after the first CAS, so it is already waiting, or it will enter
- * the wait, and it will be interrupted by the broadcast. */
- cond = &handle_data->signal_cond;
- mutex = &handle_data->signal_mutex;
-
- mono_os_mutex_lock (mutex);
- mono_os_cond_broadcast (cond);
- mono_os_mutex_unlock (mutex);
-
- _wapi_handle_unref (handle);
-}
-
-int
-_wapi_handle_timedwait_signal_handle (gpointer handle, guint32 timeout, gboolean poll, gboolean *alerted)
-{
- WapiHandleBase *handle_data;
- int res;
-
- if (!_wapi_handle_lookup_data (handle, &handle_data))
- g_error ("cannot wait on unknown handle %p", handle);
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: waiting for %p (type %s)", __func__, handle,
- _wapi_handle_ops_typename (_wapi_handle_type (handle)));
-
- if (alerted)
- *alerted = FALSE;
-
- if (alerted) {
- mono_thread_info_install_interrupt (signal_handle_and_unref, handle, alerted);
- if (*alerted)
- return 0;
- _wapi_handle_ref (handle);
- }
-
- res = _wapi_handle_timedwait_signal_naked (&handle_data->signal_cond, &handle_data->signal_mutex, timeout, poll, alerted);
-
- if (alerted) {
- mono_thread_info_uninstall_interrupt (alerted);
- if (!*alerted) {
- /* if it is alerted, then the handle is unref in the interrupt callback */
- _wapi_handle_unref (handle);
- }
- }
-
- return res;
-}
-
-void _wapi_handle_dump (void)
-{
- WapiHandleBase *handle_data;
- guint32 i, k;
- int thr_ret;
-
- thr_ret = mono_os_mutex_lock (&scan_mutex);
- g_assert (thr_ret == 0);
-
- for(i = SLOT_INDEX (0); i < _wapi_private_handle_slot_count; i++) {
- if (_wapi_private_handles [i]) {
- for (k = SLOT_OFFSET (0); k < _WAPI_HANDLE_INITIAL_COUNT; k++) {
- handle_data = &_wapi_private_handles [i][k];
-
- if (handle_data->type == WAPI_HANDLE_UNUSED) {
- continue;
- }
-
- g_print ("%3x [%7s] %s %d ",
- i * _WAPI_HANDLE_INITIAL_COUNT + k,
- _wapi_handle_ops_typename (handle_data->type),
- handle_data->signalled?"Sg":"Un",
- handle_data->ref);
- _wapi_handle_ops_details (handle_data->type, handle_data->data);
- g_print ("\n");
- }
- }
- }
-
- thr_ret = mono_os_mutex_unlock (&scan_mutex);
- g_assert (thr_ret == 0);
-}
+++ /dev/null
-/*
- * handles.h: Generic operations on handles
- *
- * Author:
- * Dick Porter (dick@ximian.com)
- *
- * (C) 2002 Ximian, Inc.
- */
-
-#ifndef _WAPI_HANDLES_H_
-#define _WAPI_HANDLES_H_
-
-#define INVALID_HANDLE_VALUE (gpointer)-1
-
-#endif /* _WAPI_HANDLES_H_ */
#include <mono/io-layer/io.h>
#include <mono/io-layer/wapi-private.h>
-#include "handles-private.h"
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);
#include <mono/io-layer/wapi.h>
#include <mono/io-layer/wapi-private.h>
-#include <mono/io-layer/handles-private.h>
#include <mono/io-layer/io-private.h>
#include <mono/io-layer/timefuncs-private.h>
#include <mono/io-layer/thread-private.h>
#include <mono/utils/strenc.h>
#include <mono/utils/mono-once.h>
#include <mono/utils/mono-logger-internals.h>
+#include <mono/utils/w32handle.h>
/*
* If SHM is disabled, this will point to a hash of _WapiFileShare structures, otherwise
static guint32 GetDriveTypeFromPath (const gchar *utf8_root_path_name);
/* File handle is only signalled for overlapped IO */
-static WapiHandleOps _wapi_file_ops = {
+static MonoW32HandleOps _wapi_file_ops = {
file_close, /* close */
NULL, /* signal */
NULL, /* own */
/* Console is mostly the same as file, except it can block waiting for
* input or output
*/
-static WapiHandleOps _wapi_console_ops = {
+static MonoW32HandleOps _wapi_console_ops = {
console_close, /* close */
NULL, /* signal */
NULL, /* own */
static const gchar* find_typename (void);
static gsize find_typesize (void);
-static WapiHandleOps _wapi_find_ops = {
+static MonoW32HandleOps _wapi_find_ops = {
NULL, /* close */
NULL, /* signal */
NULL, /* own */
/* Pipe handles
*/
-static WapiHandleOps _wapi_pipe_ops = {
+static MonoW32HandleOps _wapi_pipe_ops = {
pipe_close, /* close */
NULL, /* signal */
NULL, /* own */
const WapiFileTime *create_time,
const WapiFileTime *last_access,
const WapiFileTime *last_write);
-} io_ops[WAPI_HANDLE_COUNT]={
+} io_ops[MONO_W32HANDLE_COUNT]={
{NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
/* file */
{file_getfiletype,
gboolean ok;
int fd, ret;
- ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FILE,
+ ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
(gpointer *)&file_handle);
if(ok==FALSE) {
g_warning ("%s: error looking up file handle %p", __func__,
int ret, fd;
off_t current_pos = 0;
- ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FILE,
+ ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
(gpointer *)&file_handle);
if(ok==FALSE) {
g_warning ("%s: error looking up file handle %p", __func__,
gboolean ok;
int ret, fd;
- ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FILE,
+ ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
(gpointer *)&file_handle);
if(ok==FALSE) {
g_warning ("%s: error looking up file handle %p", __func__,
int whence, fd;
guint32 ret;
- ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FILE,
+ ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
(gpointer *)&file_handle);
if(ok==FALSE) {
g_warning ("%s: error looking up file handle %p", __func__,
off_t pos;
int ret, fd;
- ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FILE,
+ ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
(gpointer *)&file_handle);
if(ok==FALSE) {
g_warning ("%s: error looking up file handle %p", __func__,
int ret;
int fd;
- ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FILE,
+ ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
(gpointer *)&file_handle);
if(ok==FALSE) {
g_warning ("%s: error looking up file handle %p", __func__,
guint64 create_ticks, access_ticks, write_ticks;
int ret, fd;
- ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FILE,
+ ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
(gpointer *)&file_handle);
if(ok==FALSE) {
g_warning ("%s: error looking up file handle %p", __func__,
guint64 access_ticks, write_ticks;
int ret, fd;
- ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FILE,
+ ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
(gpointer *)&file_handle);
if(ok==FALSE) {
g_warning ("%s: error looking up file handle %p", __func__,
gboolean ok;
int ret, fd;
- ok=_wapi_lookup_handle (handle, WAPI_HANDLE_CONSOLE,
+ ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_CONSOLE,
(gpointer *)&console_handle);
if(ok==FALSE) {
g_warning ("%s: error looking up console handle %p", __func__,
gboolean ok;
int ret, fd;
- ok=_wapi_lookup_handle (handle, WAPI_HANDLE_CONSOLE,
+ ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_CONSOLE,
(gpointer *)&console_handle);
if(ok==FALSE) {
g_warning ("%s: error looking up console handle %p", __func__,
gboolean ok;
int ret, fd;
- ok=_wapi_lookup_handle (handle, WAPI_HANDLE_PIPE,
+ ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_PIPE,
(gpointer *)&pipe_handle);
if(ok==FALSE) {
g_warning ("%s: error looking up pipe handle %p", __func__,
gboolean ok;
int ret, fd;
- ok=_wapi_lookup_handle (handle, WAPI_HANDLE_PIPE,
+ ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_PIPE,
(gpointer *)&pipe_handle);
if(ok==FALSE) {
g_warning ("%s: error looking up pipe handle %p", __func__,
mode_t perms=0666;
gchar *filename;
int fd, ret;
- WapiHandleType handle_type;
+ MonoW32HandleType handle_type;
struct stat statbuf;
if (attrs & FILE_ATTRIBUTE_TEMPORARY)
return(INVALID_HANDLE_VALUE);
}
- if (fd >= _wapi_fd_reserve) {
+ if (fd >= mono_w32handle_fd_reserve) {
MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: File descriptor is too big", __func__);
SetLastError (ERROR_TOO_MANY_OPEN_FILES);
#define S_ISFIFO(m) ((m & S_IFIFO) != 0)
#endif
if (S_ISFIFO (statbuf.st_mode)) {
- handle_type = WAPI_HANDLE_PIPE;
+ handle_type = MONO_W32HANDLE_PIPE;
/* maintain invariant that pipes have no filename */
file_handle.filename = NULL;
g_free (filename);
filename = NULL;
} else if (S_ISCHR (statbuf.st_mode)) {
- handle_type = WAPI_HANDLE_CONSOLE;
+ handle_type = MONO_W32HANDLE_CONSOLE;
} else {
- handle_type = WAPI_HANDLE_FILE;
+ handle_type = MONO_W32HANDLE_FILE;
}
- handle = _wapi_handle_new_fd (handle_type, fd, &file_handle);
+ handle = mono_w32handle_new_fd (handle_type, fd, &file_handle);
if (handle == INVALID_HANDLE_VALUE) {
g_warning ("%s: error creating file handle", __func__);
g_free (filename);
thr_ret = mono_os_mutex_lock (&stdhandle_mutex);
g_assert (thr_ret == 0);
- ok = _wapi_lookup_handle (handle, WAPI_HANDLE_CONSOLE,
+ ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_CONSOLE,
(gpointer *)&file_handle);
if (ok == FALSE) {
/* Need to create this console handle */
}
} else {
/* Add a reference to this handle */
- _wapi_handle_ref (handle);
+ mono_w32handle_ref (handle);
}
done:
gboolean ReadFile(gpointer handle, gpointer buffer, guint32 numbytes,
guint32 *bytesread, WapiOverlapped *overlapped)
{
- WapiHandleType type;
+ MonoW32HandleType type;
- type = _wapi_handle_type (handle);
+ type = mono_w32handle_get_type (handle);
if(io_ops[type].readfile==NULL) {
SetLastError (ERROR_INVALID_HANDLE);
gboolean WriteFile(gpointer handle, gconstpointer buffer, guint32 numbytes,
guint32 *byteswritten, WapiOverlapped *overlapped)
{
- WapiHandleType type;
+ MonoW32HandleType type;
- type = _wapi_handle_type (handle);
+ type = mono_w32handle_get_type (handle);
if(io_ops[type].writefile==NULL) {
SetLastError (ERROR_INVALID_HANDLE);
*/
gboolean FlushFileBuffers(gpointer handle)
{
- WapiHandleType type;
+ MonoW32HandleType type;
- type = _wapi_handle_type (handle);
+ type = mono_w32handle_get_type (handle);
if(io_ops[type].flushfile==NULL) {
SetLastError (ERROR_INVALID_HANDLE);
*/
gboolean SetEndOfFile(gpointer handle)
{
- WapiHandleType type;
+ MonoW32HandleType type;
- type = _wapi_handle_type (handle);
+ type = mono_w32handle_get_type (handle);
if (io_ops[type].setendoffile == NULL) {
SetLastError (ERROR_INVALID_HANDLE);
guint32 SetFilePointer(gpointer handle, gint32 movedistance,
gint32 *highmovedistance, WapiSeekMethod method)
{
- WapiHandleType type;
+ MonoW32HandleType type;
- type = _wapi_handle_type (handle);
+ type = mono_w32handle_get_type (handle);
if (io_ops[type].seek == NULL) {
SetLastError (ERROR_INVALID_HANDLE);
*/
WapiFileType GetFileType(gpointer handle)
{
- WapiHandleType type;
+ MonoW32HandleType type;
- type = _wapi_handle_type (handle);
+ type = mono_w32handle_get_type (handle);
if (io_ops[type].getfiletype == NULL) {
SetLastError (ERROR_INVALID_HANDLE);
*/
guint32 GetFileSize(gpointer handle, guint32 *highsize)
{
- WapiHandleType type;
+ MonoW32HandleType type;
- type = _wapi_handle_type (handle);
+ type = mono_w32handle_get_type (handle);
if (io_ops[type].getfilesize == NULL) {
SetLastError (ERROR_INVALID_HANDLE);
gboolean GetFileTime(gpointer handle, WapiFileTime *create_time,
WapiFileTime *last_access, WapiFileTime *last_write)
{
- WapiHandleType type;
+ MonoW32HandleType type;
- type = _wapi_handle_type (handle);
+ type = mono_w32handle_get_type (handle);
if (io_ops[type].getfiletime == NULL) {
SetLastError (ERROR_INVALID_HANDLE);
const WapiFileTime *last_access,
const WapiFileTime *last_write)
{
- WapiHandleType type;
+ MonoW32HandleType type;
- type = _wapi_handle_type (handle);
+ type = mono_w32handle_get_type (handle);
if (io_ops[type].setfiletime == NULL) {
SetLastError (ERROR_INVALID_HANDLE);
find_handle.num = result;
find_handle.count = 0;
- handle = _wapi_handle_new (WAPI_HANDLE_FIND, &find_handle);
+ handle = mono_w32handle_new (MONO_W32HANDLE_FIND, &find_handle);
if (handle == INVALID_HANDLE_VALUE) {
g_warning ("%s: error creating find handle", __func__);
g_free (dir_part);
int thr_ret;
gboolean ret = FALSE;
- ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FIND,
+ ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FIND,
(gpointer *)&find_handle);
if(ok==FALSE) {
g_warning ("%s: error looking up find handle %p", __func__,
return(FALSE);
}
- thr_ret = _wapi_handle_lock_handle (handle);
+ thr_ret = mono_w32handle_lock_handle (handle);
g_assert (thr_ret == 0);
retry:
g_free (utf16_basename);
cleanup:
- thr_ret = _wapi_handle_unlock_handle (handle);
+ thr_ret = mono_w32handle_unlock_handle (handle);
g_assert (thr_ret == 0);
return(ret);
return(FALSE);
}
- ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FIND,
+ ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FIND,
(gpointer *)&find_handle);
if(ok==FALSE) {
g_warning ("%s: error looking up find handle %p", __func__,
return(FALSE);
}
- thr_ret = _wapi_handle_lock_handle (handle);
+ thr_ret = mono_w32handle_lock_handle (handle);
g_assert (thr_ret == 0);
g_strfreev (find_handle->namelist);
g_free (find_handle->dir_part);
- thr_ret = _wapi_handle_unlock_handle (handle);
+ thr_ret = mono_w32handle_unlock_handle (handle);
g_assert (thr_ret == 0);
- _wapi_handle_unref (handle);
+ mono_w32handle_unref (handle);
return(TRUE);
}
return(FALSE);
}
- if (filedes[0] >= _wapi_fd_reserve ||
- filedes[1] >= _wapi_fd_reserve) {
+ if (filedes[0] >= mono_w32handle_fd_reserve ||
+ filedes[1] >= mono_w32handle_fd_reserve) {
MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: File descriptor is too big", __func__);
SetLastError (ERROR_TOO_MANY_OPEN_FILES);
pipe_read_handle.fd = filedes [0];
pipe_read_handle.fileaccess = GENERIC_READ;
- read_handle = _wapi_handle_new_fd (WAPI_HANDLE_PIPE, filedes[0],
+ read_handle = mono_w32handle_new_fd (MONO_W32HANDLE_PIPE, filedes[0],
&pipe_read_handle);
if (read_handle == INVALID_HANDLE_VALUE) {
g_warning ("%s: error creating pipe read handle", __func__);
pipe_write_handle.fd = filedes [1];
pipe_write_handle.fileaccess = GENERIC_WRITE;
- write_handle = _wapi_handle_new_fd (WAPI_HANDLE_PIPE, filedes[1],
+ write_handle = mono_w32handle_new_fd (MONO_W32HANDLE_PIPE, filedes[1],
&pipe_write_handle);
if (write_handle == INVALID_HANDLE_VALUE) {
g_warning ("%s: error creating pipe write handle", __func__);
- _wapi_handle_unref (read_handle);
+ mono_w32handle_unref (read_handle);
close (filedes[0]);
close (filedes[1]);
{
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);
+ mono_w32handle_register_ops (MONO_W32HANDLE_FILE, &_wapi_file_ops);
+ mono_w32handle_register_ops (MONO_W32HANDLE_CONSOLE, &_wapi_console_ops);
+ mono_w32handle_register_ops (MONO_W32HANDLE_FIND, &_wapi_find_ops);
+ mono_w32handle_register_ops (MONO_W32HANDLE_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); */
+/* mono_w32handle_register_capabilities (MONO_W32HANDLE_FILE, */
+/* MONO_W32HANDLE_CAP_WAIT); */
+/* mono_w32handle_register_capabilities (MONO_W32HANDLE_CONSOLE, */
+/* MONO_W32HANDLE_CAP_WAIT); */
if (g_getenv ("MONO_STRICT_IO_EMULATION"))
lock_while_writing = TRUE;
#include <errno.h>
#include <mono/io-layer/wapi.h>
#include <mono/io-layer/wapi-private.h>
-#include <mono/io-layer/handles-private.h>
#include <mono/io-layer/io-private.h>
#include <mono/io-layer/io-trace.h>
#include <mono/utils/mono-logger-internals.h>
+#include <mono/utils/w32handle.h>
gboolean
_wapi_lock_file_region (int fd, off_t offset, off_t length)
off_t offset, length;
int fd = GPOINTER_TO_UINT(handle);
- ok = _wapi_lookup_handle (handle, WAPI_HANDLE_FILE,
+ ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
(gpointer *)&file_handle);
if (ok == FALSE) {
g_warning ("%s: error looking up file handle %p", __func__,
off_t offset, length;
int fd = GPOINTER_TO_UINT(handle);
- ok = _wapi_lookup_handle (handle, WAPI_HANDLE_FILE,
+ ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
(gpointer *)&file_handle);
if (ok == FALSE) {
g_warning ("%s: error looking up file handle %p", __func__,
#include <sys/types.h>
#include "wapi-private.h"
-#include "handles-private.h"
struct _WapiHandle_mutex
{
#include <mono/io-layer/wapi.h>
#include <mono/io-layer/wapi-private.h>
-#include <mono/io-layer/handles-private.h>
#include <mono/io-layer/mutex-private.h>
#include <mono/io-layer/io-trace.h>
#include <mono/utils/mono-once.h>
#include <mono/utils/mono-logger-internals.h>
+#include <mono/utils/w32handle.h>
static void mutex_signal(gpointer handle);
static gboolean mutex_own (gpointer handle);
static const gchar* namedmutex_typename (void);
static gsize namedmutex_typesize (void);
-static WapiHandleOps _wapi_mutex_ops = {
+static MonoW32HandleOps _wapi_mutex_ops = {
NULL, /* close */
mutex_signal, /* signal */
mutex_own, /* own */
mutex_typesize, /* typesize */
};
-static WapiHandleOps _wapi_namedmutex_ops = {
+static MonoW32HandleOps _wapi_namedmutex_ops = {
NULL, /* close */
namedmutex_signal, /* signal */
namedmutex_own, /* own */
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);
+ mono_w32handle_register_ops (MONO_W32HANDLE_MUTEX, &_wapi_mutex_ops);
+ mono_w32handle_register_ops (MONO_W32HANDLE_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,
- (WapiHandleCapability)(WAPI_HANDLE_CAP_WAIT | WAPI_HANDLE_CAP_SIGNAL | WAPI_HANDLE_CAP_OWN));
+ mono_w32handle_register_capabilities (MONO_W32HANDLE_MUTEX,
+ (MonoW32HandleCapability)(MONO_W32HANDLE_CAP_WAIT | MONO_W32HANDLE_CAP_SIGNAL | MONO_W32HANDLE_CAP_OWN));
+ mono_w32handle_register_capabilities (MONO_W32HANDLE_NAMEDMUTEX,
+ (MonoW32HandleCapability)(MONO_W32HANDLE_CAP_WAIT | MONO_W32HANDLE_CAP_SIGNAL | MONO_W32HANDLE_CAP_OWN));
}
-static const char* mutex_handle_type_to_string (WapiHandleType type)
+static const char* mutex_handle_type_to_string (MonoW32HandleType type)
{
switch (type) {
- case WAPI_HANDLE_MUTEX: return "mutex";
- case WAPI_HANDLE_NAMEDMUTEX: return "named mutex";
+ case MONO_W32HANDLE_MUTEX: return "mutex";
+ case MONO_W32HANDLE_NAMEDMUTEX: return "named mutex";
default:
g_assert_not_reached ();
}
}
static gboolean
-mutex_handle_own (gpointer handle, WapiHandleType type)
+mutex_handle_own (gpointer handle, MonoW32HandleType type)
{
struct _WapiHandle_mutex *mutex_handle;
- if (!_wapi_lookup_handle (handle, type, (gpointer *)&mutex_handle)) {
+ if (!mono_w32handle_lookup (handle, type, (gpointer *)&mutex_handle)) {
g_warning ("%s: error looking up %s handle %p", __func__, mutex_handle_type_to_string (type), handle);
return FALSE;
}
mutex_handle->tid = pthread_self ();
mutex_handle->recursion++;
- _wapi_handle_set_signal_state (handle, FALSE, FALSE);
+ mono_w32handle_set_signal_state (handle, FALSE, FALSE);
return TRUE;
}
static gboolean
-mutex_handle_is_owned (gpointer handle, WapiHandleType type)
+mutex_handle_is_owned (gpointer handle, MonoW32HandleType type)
{
struct _WapiHandle_mutex *mutex_handle;
- if (!_wapi_lookup_handle (handle, type, (gpointer *)&mutex_handle)) {
+ if (!mono_w32handle_lookup (handle, type, (gpointer *)&mutex_handle)) {
g_warning ("%s: error looking up %s handle %p", __func__, mutex_handle_type_to_string (type), handle);
return FALSE;
}
static gboolean mutex_own (gpointer handle)
{
- return mutex_handle_own (handle, WAPI_HANDLE_MUTEX);
+ return mutex_handle_own (handle, MONO_W32HANDLE_MUTEX);
}
static gboolean mutex_is_owned (gpointer handle)
{
- return mutex_handle_is_owned (handle, WAPI_HANDLE_MUTEX);
+ return mutex_handle_is_owned (handle, MONO_W32HANDLE_MUTEX);
}
static void namedmutex_signal (gpointer handle)
/* NB, always called with the shared handle lock held */
static gboolean namedmutex_own (gpointer handle)
{
- return mutex_handle_own (handle, WAPI_HANDLE_NAMEDMUTEX);
+ return mutex_handle_own (handle, MONO_W32HANDLE_NAMEDMUTEX);
}
static gboolean namedmutex_is_owned (gpointer handle)
{
- return mutex_handle_is_owned (handle, WAPI_HANDLE_NAMEDMUTEX);
+ return mutex_handle_is_owned (handle, MONO_W32HANDLE_NAMEDMUTEX);
}
-static void mutex_handle_prewait (gpointer handle, WapiHandleType type)
+static void mutex_handle_prewait (gpointer handle, MonoW32HandleType type)
{
/* If the mutex is not currently owned, do nothing and let the
* usual wait carry on. If it is owned, check that the owner
*/
struct _WapiHandle_mutex *mutex_handle;
- if (!_wapi_lookup_handle (handle, type, (gpointer *)&mutex_handle)) {
+ if (!mono_w32handle_lookup (handle, type, (gpointer *)&mutex_handle)) {
g_warning ("%s: error looking up %s handle %p",
__func__, mutex_handle_type_to_string (type), handle);
return;
/* The shared state is not locked when prewait methods are called */
static void mutex_prewait (gpointer handle)
{
- mutex_handle_prewait (handle, WAPI_HANDLE_MUTEX);
+ mutex_handle_prewait (handle, MONO_W32HANDLE_MUTEX);
}
/* The shared state is not locked when prewait methods are called */
static void namedmutex_prewait (gpointer handle)
{
- mutex_handle_prewait (handle, WAPI_HANDLE_NAMEDMUTEX);
+ mutex_handle_prewait (handle, MONO_W32HANDLE_NAMEDMUTEX);
}
static void mutex_details (gpointer data)
/* When a thread exits, any mutexes it still holds need to be signalled. */
void _wapi_mutex_abandon (gpointer handle, pid_t pid, pthread_t tid)
{
- WapiHandleType type;
+ MonoW32HandleType type;
struct _WapiHandle_mutex *mutex_handle;
int thr_ret;
- switch (type = _wapi_handle_type (handle)) {
- case WAPI_HANDLE_MUTEX:
- case WAPI_HANDLE_NAMEDMUTEX:
+ switch (type = mono_w32handle_get_type (handle)) {
+ case MONO_W32HANDLE_MUTEX:
+ case MONO_W32HANDLE_NAMEDMUTEX:
break;
default:
g_assert_not_reached ();
}
- if (!_wapi_lookup_handle (handle, type, (gpointer *)&mutex_handle)) {
+ if (!mono_w32handle_lookup (handle, type, (gpointer *)&mutex_handle)) {
g_warning ("%s: error looking up %s handle %p",
__func__, mutex_handle_type_to_string (type), handle);
return;
MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: abandon %s handle %p",
__func__, mutex_handle_type_to_string (type), handle);
- thr_ret = _wapi_handle_lock_handle (handle);
+ thr_ret = mono_w32handle_lock_handle (handle);
g_assert (thr_ret == 0);
if (pthread_equal (mutex_handle->tid, tid)) {
mutex_handle->recursion = 0;
mutex_handle->tid = 0;
- _wapi_handle_set_signal_state (handle, TRUE, FALSE);
+ mono_w32handle_set_signal_state (handle, TRUE, FALSE);
MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: abandoned %s handle %p",
__func__, mutex_handle_type_to_string (type), handle);
}
- thr_ret = _wapi_handle_unlock_handle (handle);
+ thr_ret = mono_w32handle_unlock_handle (handle);
g_assert (thr_ret == 0);
}
-static gpointer mutex_handle_create (struct _WapiHandle_mutex *mutex_handle, WapiHandleType type, gboolean owned)
+static gpointer mutex_handle_create (struct _WapiHandle_mutex *mutex_handle, MonoW32HandleType type, gboolean owned)
{
gpointer handle;
int thr_ret;
mutex_handle->tid = 0;
mutex_handle->recursion = 0;
- handle = _wapi_handle_new (type, mutex_handle);
+ handle = mono_w32handle_new (type, mutex_handle);
if (handle == INVALID_HANDLE_VALUE) {
g_warning ("%s: error creating %s handle",
__func__, mutex_handle_type_to_string (type));
return NULL;
}
- thr_ret = _wapi_handle_lock_handle (handle);
+ thr_ret = mono_w32handle_lock_handle (handle);
g_assert (thr_ret == 0);
if (owned)
mutex_handle_own (handle, type);
else
- _wapi_handle_set_signal_state (handle, TRUE, FALSE);
+ mono_w32handle_set_signal_state (handle, TRUE, FALSE);
- thr_ret = _wapi_handle_unlock_handle (handle);
+ thr_ret = mono_w32handle_unlock_handle (handle);
g_assert (thr_ret == 0);
MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: created %s handle %p",
{
struct _WapiHandle_mutex mutex_handle;
MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: creating %s handle",
- __func__, mutex_handle_type_to_string (WAPI_HANDLE_MUTEX));
- return mutex_handle_create (&mutex_handle, WAPI_HANDLE_MUTEX, owned);
+ __func__, mutex_handle_type_to_string (MONO_W32HANDLE_MUTEX));
+ return mutex_handle_create (&mutex_handle, MONO_W32HANDLE_MUTEX, owned);
}
static gpointer namedmutex_create (gboolean owned, const gunichar2 *name)
int thr_ret;
MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: creating %s handle",
- __func__, mutex_handle_type_to_string (WAPI_HANDLE_NAMEDMUTEX));
+ __func__, mutex_handle_type_to_string (MONO_W32HANDLE_NAMEDMUTEX));
/* w32 seems to guarantee that opening named objects can't race each other */
thr_ret = _wapi_namespace_lock ();
utf8_name = g_utf16_to_utf8 (name, -1, NULL, NULL, NULL);
- handle = _wapi_search_handle_namespace (WAPI_HANDLE_NAMEDMUTEX, utf8_name);
+ handle = _wapi_search_handle_namespace (MONO_W32HANDLE_NAMEDMUTEX, utf8_name);
if (handle == INVALID_HANDLE_VALUE) {
/* The name has already been used for a different object. */
handle = NULL;
SetLastError (ERROR_ALREADY_EXISTS);
/* this is used as creating a new handle */
- _wapi_handle_ref (handle);
+ mono_w32handle_ref (handle);
} else {
/* A new named mutex */
struct _WapiHandle_namedmutex namedmutex_handle;
strncpy (&namedmutex_handle.sharedns.name [0], utf8_name, MAX_PATH);
namedmutex_handle.sharedns.name [MAX_PATH] = '\0';
- handle = mutex_handle_create ((struct _WapiHandle_mutex*) &namedmutex_handle, WAPI_HANDLE_NAMEDMUTEX, owned);
+ handle = mutex_handle_create ((struct _WapiHandle_mutex*) &namedmutex_handle, MONO_W32HANDLE_NAMEDMUTEX, owned);
}
g_free (utf8_name);
*/
gboolean ReleaseMutex(gpointer handle)
{
- WapiHandleType type;
+ MonoW32HandleType type;
struct _WapiHandle_mutex *mutex_handle;
pthread_t tid;
int thr_ret;
return FALSE;
}
- switch (type = _wapi_handle_type (handle)) {
- case WAPI_HANDLE_MUTEX:
- case WAPI_HANDLE_NAMEDMUTEX:
+ switch (type = mono_w32handle_get_type (handle)) {
+ case MONO_W32HANDLE_MUTEX:
+ case MONO_W32HANDLE_NAMEDMUTEX:
break;
default:
SetLastError (ERROR_INVALID_HANDLE);
return FALSE;
}
- if (!_wapi_lookup_handle (handle, type, (gpointer *)&mutex_handle)) {
+ if (!mono_w32handle_lookup (handle, type, (gpointer *)&mutex_handle)) {
g_warning ("%s: error looking up %s handle %p",
__func__, mutex_handle_type_to_string (type), handle);
return FALSE;
MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: releasing %s handle %p",
__func__, mutex_handle_type_to_string (type), handle);
- thr_ret = _wapi_handle_lock_handle (handle);
+ thr_ret = mono_w32handle_lock_handle (handle);
g_assert (thr_ret == 0);
tid = pthread_self ();
__func__, mutex_handle_type_to_string (type), handle);
mutex_handle->tid = 0;
- _wapi_handle_set_signal_state (handle, TRUE, FALSE);
+ mono_w32handle_set_signal_state (handle, TRUE, FALSE);
}
}
- thr_ret = _wapi_handle_unlock_handle (handle);
+ thr_ret = mono_w32handle_unlock_handle (handle);
g_assert (thr_ret == 0);
return ret;
MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Opening named mutex [%s]", __func__, utf8_name);
- handle = _wapi_search_handle_namespace (WAPI_HANDLE_NAMEDMUTEX,
+ handle = _wapi_search_handle_namespace (MONO_W32HANDLE_NAMEDMUTEX,
utf8_name);
if (handle == INVALID_HANDLE_VALUE) {
/* The name has already been used for a different
#include <mono/io-layer/wapi.h>
#include <mono/io-layer/wapi-private.h>
-#include <mono/io-layer/handles-private.h>
#include <mono/io-layer/io-private.h>
#include <mono/io-layer/io-trace.h>
#include <mono/utils/mono-logger-internals.h>
+#include <mono/utils/w32handle.h>
static guint32
convert_from_flags(int flags)
file_handle.sharemode=0;
file_handle.attrs=0;
- handle = _wapi_handle_new_fd (WAPI_HANDLE_CONSOLE, fd, &file_handle);
+ handle = mono_w32handle_new_fd (MONO_W32HANDLE_CONSOLE, fd, &file_handle);
if (handle == INVALID_HANDLE_VALUE) {
g_warning ("%s: error creating file handle", __func__);
SetLastError (ERROR_GEN_FAILURE);
#include <mono/io-layer/wapi.h>
#include <mono/io-layer/wapi-private.h>
-#include <mono/io-layer/handles-private.h>
#include <mono/io-layer/process-private.h>
#include <mono/io-layer/threads.h>
#include <mono/io-layer/io-trace.h>
#include <mono/utils/mono-proclib.h>
#include <mono/utils/mono-once.h>
#include <mono/utils/mono-logger-internals.h>
+#include <mono/utils/w32handle.h>
/* The process' environment strings */
#if defined(__APPLE__)
open_process_map (int pid, const char *mode);
#endif
-static WapiHandleOps _wapi_process_ops = {
+static MonoW32HandleOps _wapi_process_ops = {
process_close, /* close_shared */
NULL, /* signal */
NULL, /* own */
WapiHandle_process *process_data;
gboolean ret;
- ret = _wapi_lookup_handle (handle, WAPI_HANDLE_PROCESS,
+ ret = mono_w32handle_lookup (handle, MONO_W32HANDLE_PROCESS,
(gpointer *)&process_data);
if (!ret)
return NULL;
process_set_defaults (&process_handle);
- handle = _wapi_handle_new (WAPI_HANDLE_PROCESS, &process_handle);
+ handle = mono_w32handle_new (MONO_W32HANDLE_PROCESS, &process_handle);
if (handle == INVALID_HANDLE_VALUE) {
g_warning ("%s: error creating process handle", __func__);
}
/* Close all file descriptors */
- for (i = _wapi_fd_reserve - 1; i > 2; i--)
+ for (i = mono_w32handle_fd_reserve - 1; i > 2; i--)
close (i);
#ifdef DEBUG_ENABLED
process_handle_data = lookup_process_handle (handle);
if (!process_handle_data) {
g_warning ("%s: error looking up process handle %p", __func__, handle);
- _wapi_handle_unref (handle);
+ mono_w32handle_unref (handle);
} else {
process_handle_data->id = pid;
} else {
/* Keep the process handle artificially alive until the process
* exits so that the information in the handle isn't lost. */
- _wapi_handle_ref (handle);
+ mono_w32handle_ref (handle);
mono_process->handle = handle;
process_handle_data->mono_process = mono_process;
}
if (fork_failed)
- _wapi_handle_unref (handle);
+ mono_w32handle_unref (handle);
if (startup_pipe [1] != -1) {
/* Write 1 byte, doesn't matter what */
pid_t pid = _wapi_getpid ();
WapiHandle_process process_handle = {0};
- _wapi_handle_register_ops (WAPI_HANDLE_PROCESS, &_wapi_process_ops);
+ mono_w32handle_register_ops (MONO_W32HANDLE_PROCESS, &_wapi_process_ops);
- _wapi_handle_register_capabilities (WAPI_HANDLE_PROCESS,
- (WapiHandleCapability)(WAPI_HANDLE_CAP_WAIT | WAPI_HANDLE_CAP_SPECIAL_WAIT));
+ mono_w32handle_register_capabilities (MONO_W32HANDLE_PROCESS,
+ (MonoW32HandleCapability)(MONO_W32HANDLE_CAP_WAIT | MONO_W32HANDLE_CAP_SPECIAL_WAIT));
process_handle.id = pid;
process_set_defaults (&process_handle);
process_set_name (&process_handle);
- current_process = _wapi_handle_new (WAPI_HANDLE_PROCESS,
+ current_process = mono_w32handle_new (MONO_W32HANDLE_PROCESS,
&process_handle);
g_assert (current_process);
gpointer
_wapi_process_duplicate (void)
{
- _wapi_handle_ref (current_process);
+ mono_w32handle_ref (current_process);
return current_process;
}
* unsignalled
*/
if (checking_pid == wanted_pid &&
- !_wapi_handle_issignalled (handle)) {
+ !mono_w32handle_issignalled (handle)) {
/* If the handle is blown away in the window between
- * returning TRUE here and _wapi_search_handle pinging
+ * returning TRUE here and mono_w32handle_search pinging
* the timestamp, the search will continue
*/
return TRUE;
MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: looking for process %d", __func__, pid);
- handle = _wapi_search_handle (WAPI_HANDLE_PROCESS,
+ handle = mono_w32handle_search (MONO_W32HANDLE_PROCESS,
process_open_compare,
GUINT_TO_POINTER (pid), NULL, TRUE);
if (handle == 0) {
}
}
- /* _wapi_search_handle () already added a ref */
+ /* mono_w32handle_search () already added a ref */
return handle;
}
*/
process_wait (process, 0, TRUE);
- if (_wapi_handle_issignalled (process))
+ if (mono_w32handle_issignalled (process))
*code = process_handle->exitstatus;
else
*code = STILL_ACTIVE;
/* A process handle is only signalled if the process has
* exited. Otherwise exit_time isn't set
*/
- if (_wapi_handle_issignalled (process))
+ if (mono_w32handle_issignalled (process))
*exit_time = process_handle->exit_time;
#ifdef HAVE_GETRUSAGE
mp->handle = NULL;
mono_os_mutex_unlock (&mono_processes_mutex);
if (unref_handle)
- _wapi_handle_unref (unref_handle);
+ mono_w32handle_unref (unref_handle);
}
}
MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): Setting pid %d signalled, exit status %d",
__func__, handle, timeout, process_handle->id, process_handle->exitstatus);
- _wapi_handle_set_signal_state (handle, TRUE, TRUE);
+ mono_w32handle_set_signal_state (handle, TRUE, TRUE);
return WAIT_OBJECT_0;
}
#endif
#include <glib.h>
-#include <mono/io-layer/handles.h>
#include <mono/io-layer/access.h>
#include <mono/io-layer/versioninfo.h>
#include <glib.h>
#include "wapi-private.h"
-#include "handles-private.h"
/* emulate sem_t, so that we can prod the internal state more easily */
struct _WapiHandle_sem
#include <mono/io-layer/wapi.h>
#include <mono/io-layer/wapi-private.h>
-#include <mono/io-layer/handles-private.h>
#include <mono/io-layer/semaphore-private.h>
#include <mono/io-layer/io-trace.h>
#include <mono/utils/mono-once.h>
#include <mono/utils/mono-logger-internals.h>
+#include <mono/utils/w32handle.h>
static void sema_signal(gpointer handle);
static gboolean sema_own (gpointer handle);
static const gchar* namedsema_typename (void);
static gsize namedsema_typesize (void);
-static WapiHandleOps _wapi_sem_ops = {
+static MonoW32HandleOps _wapi_sem_ops = {
NULL, /* close */
sema_signal, /* signal */
sema_own, /* own */
sema_typesize, /* typesize */
};
-static WapiHandleOps _wapi_namedsem_ops = {
+static MonoW32HandleOps _wapi_namedsem_ops = {
NULL, /* close */
namedsema_signal, /* signal */
namedsema_own, /* own */
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);
+ mono_w32handle_register_ops (MONO_W32HANDLE_SEM, &_wapi_sem_ops);
+ mono_w32handle_register_ops (MONO_W32HANDLE_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,
- (WapiHandleCapability)(WAPI_HANDLE_CAP_WAIT | WAPI_HANDLE_CAP_SIGNAL));
+ mono_w32handle_register_capabilities (MONO_W32HANDLE_SEM,
+ (MonoW32HandleCapability)(MONO_W32HANDLE_CAP_WAIT | MONO_W32HANDLE_CAP_SIGNAL));
+ mono_w32handle_register_capabilities (MONO_W32HANDLE_NAMEDSEM,
+ (MonoW32HandleCapability)(MONO_W32HANDLE_CAP_WAIT | MONO_W32HANDLE_CAP_SIGNAL));
}
-static const char* sem_handle_type_to_string (WapiHandleType type)
+static const char* sem_handle_type_to_string (MonoW32HandleType type)
{
switch (type) {
- case WAPI_HANDLE_SEM: return "sem";
- case WAPI_HANDLE_NAMEDSEM: return "named sem";
+ case MONO_W32HANDLE_SEM: return "sem";
+ case MONO_W32HANDLE_NAMEDSEM: return "named sem";
default:
g_assert_not_reached ();
}
}
-static gboolean sem_handle_own (gpointer handle, WapiHandleType type)
+static gboolean sem_handle_own (gpointer handle, MonoW32HandleType type)
{
struct _WapiHandle_sem *sem_handle;
- if (!_wapi_lookup_handle (handle, type, (gpointer *)&sem_handle)) {
+ if (!mono_w32handle_lookup (handle, type, (gpointer *)&sem_handle)) {
g_warning ("%s: error looking up %s handle %p",
__func__, sem_handle_type_to_string (type), handle);
return FALSE;
sem_handle->val--;
if (sem_handle->val == 0)
- _wapi_handle_set_signal_state (handle, FALSE, FALSE);
+ mono_w32handle_set_signal_state (handle, FALSE, FALSE);
return TRUE;
}
static gboolean sema_own (gpointer handle)
{
- return sem_handle_own (handle, WAPI_HANDLE_SEM);
+ return sem_handle_own (handle, MONO_W32HANDLE_SEM);
}
static void namedsema_signal (gpointer handle)
/* NB, always called with the shared handle lock held */
static gboolean namedsema_own (gpointer handle)
{
- return sem_handle_own (handle, WAPI_HANDLE_NAMEDSEM);
+ return sem_handle_own (handle, MONO_W32HANDLE_NAMEDSEM);
}
static void sema_details (gpointer data)
return sizeof (struct _WapiHandle_namedsem);
}
-static gpointer sem_handle_create (struct _WapiHandle_sem *sem_handle, WapiHandleType type, gint32 initial, gint32 max)
+static gpointer sem_handle_create (struct _WapiHandle_sem *sem_handle, MonoW32HandleType type, gint32 initial, gint32 max)
{
gpointer handle;
int thr_ret;
sem_handle->val = initial;
sem_handle->max = max;
- handle = _wapi_handle_new (type, sem_handle);
+ handle = mono_w32handle_new (type, sem_handle);
if (handle == INVALID_HANDLE_VALUE) {
g_warning ("%s: error creating %s handle",
__func__, sem_handle_type_to_string (type));
return NULL;
}
- thr_ret = _wapi_handle_lock_handle (handle);
+ thr_ret = mono_w32handle_lock_handle (handle);
g_assert (thr_ret == 0);
if (initial != 0)
- _wapi_handle_set_signal_state (handle, TRUE, FALSE);
+ mono_w32handle_set_signal_state (handle, TRUE, FALSE);
- thr_ret = _wapi_handle_unlock_handle (handle);
+ thr_ret = mono_w32handle_unlock_handle (handle);
g_assert (thr_ret == 0);
MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: created %s handle %p",
{
struct _WapiHandle_sem sem_handle;
MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: creating %s handle, initial %d max %d",
- __func__, sem_handle_type_to_string (WAPI_HANDLE_SEM), initial, max);
- return sem_handle_create (&sem_handle, WAPI_HANDLE_SEM, initial, max);
+ __func__, sem_handle_type_to_string (MONO_W32HANDLE_SEM), initial, max);
+ return sem_handle_create (&sem_handle, MONO_W32HANDLE_SEM, initial, max);
}
static gpointer namedsem_create (gint32 initial, gint32 max, const gunichar2 *name)
int thr_ret;
MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: creating %s handle, initial %d max %d name \"%s\"",
- __func__, sem_handle_type_to_string (WAPI_HANDLE_NAMEDSEM), initial, max, name);
+ __func__, sem_handle_type_to_string (MONO_W32HANDLE_NAMEDSEM), initial, max, name);
/* w32 seems to guarantee that opening named objects can't race each other */
thr_ret = _wapi_namespace_lock ();
MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Creating named sem name [%s] initial %d max %d", __func__, utf8_name, initial, max);
- handle = _wapi_search_handle_namespace (WAPI_HANDLE_NAMEDSEM, utf8_name);
+ handle = _wapi_search_handle_namespace (MONO_W32HANDLE_NAMEDSEM, utf8_name);
if (handle == INVALID_HANDLE_VALUE) {
/* The name has already been used for a different object. */
handle = NULL;
SetLastError (ERROR_ALREADY_EXISTS);
/* this is used as creating a new handle */
- _wapi_handle_ref (handle);
+ mono_w32handle_ref (handle);
} else {
/* A new named semaphore */
struct _WapiHandle_namedsem namedsem_handle;
strncpy (&namedsem_handle.sharedns.name [0], utf8_name, MAX_PATH);
namedsem_handle.sharedns.name [MAX_PATH] = '\0';
- handle = sem_handle_create ((struct _WapiHandle_sem*) &namedsem_handle, WAPI_HANDLE_NAMEDSEM, initial, max);
+ handle = sem_handle_create ((struct _WapiHandle_sem*) &namedsem_handle, MONO_W32HANDLE_NAMEDSEM, initial, max);
}
g_free (utf8_name);
*/
gboolean ReleaseSemaphore(gpointer handle, gint32 count, gint32 *prevcount)
{
- WapiHandleType type;
+ MonoW32HandleType type;
struct _WapiHandle_sem *sem_handle;
int thr_ret;
gboolean ret;
return FALSE;
}
- switch (type = _wapi_handle_type (handle)) {
- case WAPI_HANDLE_SEM:
- case WAPI_HANDLE_NAMEDSEM:
+ switch (type = mono_w32handle_get_type (handle)) {
+ case MONO_W32HANDLE_SEM:
+ case MONO_W32HANDLE_NAMEDSEM:
break;
default:
SetLastError (ERROR_INVALID_HANDLE);
return FALSE;
}
- if (!_wapi_lookup_handle (handle, type, (gpointer *)&sem_handle)) {
+ if (!mono_w32handle_lookup (handle, type, (gpointer *)&sem_handle)) {
g_warning ("%s: error looking up sem handle %p", __func__, handle);
return FALSE;
}
MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: releasing %s handle %p",
__func__, sem_handle_type_to_string (type), handle);
- thr_ret = _wapi_handle_lock_handle (handle);
+ thr_ret = mono_w32handle_lock_handle (handle);
g_assert (thr_ret == 0);
/* Do this before checking for count overflow, because overflowing
__func__, sem_handle_type_to_string (type), handle, sem_handle->val, count, sem_handle->max, count);
sem_handle->val += count;
- _wapi_handle_set_signal_state (handle, TRUE, TRUE);
+ mono_w32handle_set_signal_state (handle, TRUE, TRUE);
ret = TRUE;
}
- thr_ret = _wapi_handle_unlock_handle (handle);
+ thr_ret = mono_w32handle_unlock_handle (handle);
g_assert (thr_ret == 0);
return ret;
MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Opening named sem [%s]", __func__, utf8_name);
- handle = _wapi_search_handle_namespace (WAPI_HANDLE_NAMEDSEM,
+ handle = _wapi_search_handle_namespace (MONO_W32HANDLE_NAMEDSEM,
utf8_name);
if (handle == INVALID_HANDLE_VALUE) {
/* The name has already been used for a different
#include <glib.h>
#include "wapi-private.h"
-#include "handles-private.h"
struct _WapiHandle_socket
{
#include <mono/io-layer/wapi.h>
#include <mono/io-layer/wapi-private.h>
#include <mono/io-layer/socket-private.h>
-#include <mono/io-layer/handles-private.h>
#include <mono/io-layer/socket-wrappers.h>
#include <mono/io-layer/io-trace.h>
#include <mono/utils/mono-poll.h>
#include <mono/utils/mono-once.h>
#include <mono/utils/mono-logger-internals.h>
+#include <mono/utils/w32handle.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
static const gchar* socket_typename (void);
static gsize socket_typesize (void);
-static WapiHandleOps _wapi_socket_ops = {
+static MonoW32HandleOps _wapi_socket_ops = {
socket_close, /* close */
NULL, /* signal */
NULL, /* own */
void
_wapi_socket_init (void)
{
- _wapi_handle_register_ops (WAPI_HANDLE_SOCKET, &_wapi_socket_ops);
+ mono_w32handle_register_ops (MONO_W32HANDLE_SOCKET, &_wapi_socket_ops);
}
static void socket_close (gpointer handle, gpointer data)
static gboolean
cleanup_close (gpointer handle, gpointer data, gpointer user_data)
{
- if (_wapi_handle_type (handle) == WAPI_HANDLE_SOCKET)
- _wapi_handle_ops_close (handle, data);
+ if (mono_w32handle_get_type (handle) == MONO_W32HANDLE_SOCKET)
+ mono_w32handle_ops_close (handle, data);
return FALSE;
}
MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: cleaning up", __func__);
in_cleanup = 1;
- _wapi_handle_foreach (cleanup_close, NULL);
+ mono_w32handle_foreach (cleanup_close, NULL);
in_cleanup = 0;
}
{
gpointer handle = GUINT_TO_POINTER (fd);
- if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+ if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
WSASetLastError (WSAENOTSOCK);
return(0);
}
- _wapi_handle_unref (handle);
+ mono_w32handle_unref (handle);
return(0);
}
return(INVALID_SOCKET);
}
- if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+ if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
WSASetLastError (WSAENOTSOCK);
return(INVALID_SOCKET);
}
- ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
+ ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET,
(gpointer *)&socket_handle);
if (ok == FALSE) {
g_warning ("%s: error looking up socket handle %p",
return(INVALID_SOCKET);
}
- if (new_fd >= _wapi_fd_reserve) {
+ if (new_fd >= mono_w32handle_fd_reserve) {
MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: File descriptor is too big", __func__);
WSASetLastError (WSASYSCALLFAILURE);
new_socket_handle.protocol = socket_handle->protocol;
new_socket_handle.still_readable = 1;
- new_handle = _wapi_handle_new_fd (WAPI_HANDLE_SOCKET, new_fd,
+ new_handle = mono_w32handle_new_fd (MONO_W32HANDLE_SOCKET, new_fd,
&new_socket_handle);
if(new_handle == INVALID_HANDLE_VALUE) {
g_warning ("%s: error creating socket handle", __func__);
gpointer handle = GUINT_TO_POINTER (fd);
int ret;
- if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+ if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
WSASetLastError (WSAENOTSOCK);
return(SOCKET_ERROR);
}
gboolean ok;
gint errnum;
- if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+ if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
WSASetLastError (WSAENOTSOCK);
return(SOCKET_ERROR);
}
* But don't do this for EWOULDBLOCK (bug 317315)
*/
if (errnum != WSAEWOULDBLOCK) {
- ok = _wapi_lookup_handle (handle,
- WAPI_HANDLE_SOCKET,
+ ok = mono_w32handle_lookup (handle,
+ MONO_W32HANDLE_SOCKET,
(gpointer *)&socket_handle);
if (ok == FALSE) {
/* ECONNRESET means the socket was closed by another thread */
errnum = errno_to_WSA (so_error, __func__);
/* Need to save this socket error */
- ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
+ ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET,
(gpointer *)&socket_handle);
if (ok == FALSE) {
g_warning ("%s: error looking up socket handle %p", __func__, handle);
gpointer handle = GUINT_TO_POINTER (fd);
int ret;
- if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+ if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
WSASetLastError (WSAENOTSOCK);
return(SOCKET_ERROR);
}
gpointer handle = GUINT_TO_POINTER (fd);
int ret;
- if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+ if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
WSASetLastError (WSAENOTSOCK);
return(SOCKET_ERROR);
}
struct _WapiHandle_socket *socket_handle;
gboolean ok;
- if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+ if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
WSASetLastError (WSAENOTSOCK);
return(SOCKET_ERROR);
}
}
if (optname == SO_ERROR) {
- ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
+ ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET,
(gpointer *)&socket_handle);
if (ok == FALSE) {
g_warning ("%s: error looking up socket handle %p",
gpointer handle = GUINT_TO_POINTER (fd);
int ret;
- if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+ if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
WSASetLastError (WSAENOTSOCK);
return(SOCKET_ERROR);
}
gboolean ok;
int ret;
- if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+ if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
WSASetLastError (WSAENOTSOCK);
return(SOCKET_ERROR);
}
* still_readable != 1 then shutdown
* (SHUT_RD|SHUT_RDWR) has been called locally.
*/
- ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
+ ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET,
(gpointer *)&socket_handle);
if (ok == FALSE || socket_handle->still_readable != 1) {
ret = -1;
gboolean ok;
int ret;
- if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+ if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
WSASetLastError (WSAENOTSOCK);
return(SOCKET_ERROR);
}
if (ret == 0) {
/* see _wapi_recvfrom */
- ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
+ ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET,
(gpointer *)&socket_handle);
if (ok == FALSE || socket_handle->still_readable != 1) {
ret = -1;
gpointer handle = GUINT_TO_POINTER (fd);
int ret;
- if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+ if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
WSASetLastError (WSAENOTSOCK);
return(SOCKET_ERROR);
}
gpointer handle = GUINT_TO_POINTER (fd);
int ret;
- if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+ if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
WSASetLastError (WSAENOTSOCK);
return(SOCKET_ERROR);
}
gpointer handle = GUINT_TO_POINTER (fd);
int ret;
- if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+ if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
WSASetLastError (WSAENOTSOCK);
return(SOCKET_ERROR);
}
#endif
struct timeval tv;
- if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+ if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
WSASetLastError (WSAENOTSOCK);
return(SOCKET_ERROR);
}
gpointer handle = GUINT_TO_POINTER (fd);
int ret;
- if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+ if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
WSASetLastError (WSAENOTSOCK);
return(SOCKET_ERROR);
}
if (how == SHUT_RD ||
how == SHUT_RDWR) {
- ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
+ ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET,
(gpointer *)&socket_handle);
if (ok == FALSE) {
g_warning ("%s: error looking up socket handle %p",
return(INVALID_SOCKET);
}
- if (fd >= _wapi_fd_reserve) {
+ if (fd >= mono_w32handle_fd_reserve) {
MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: File descriptor is too big (%d >= %d)",
- __func__, fd, _wapi_fd_reserve);
+ __func__, fd, mono_w32handle_fd_reserve);
WSASetLastError (WSASYSCALLFAILURE);
close (fd);
}
- handle = _wapi_handle_new_fd (WAPI_HANDLE_SOCKET, fd, &socket_handle);
+ handle = mono_w32handle_new_fd (MONO_W32HANDLE_SOCKET, fd, &socket_handle);
if (handle == INVALID_HANDLE_VALUE) {
g_warning ("%s: error creating socket handle", __func__);
WSASetLastError (WSASYSCALLFAILURE);
gpointer handle = GUINT_TO_POINTER (fd);
int newsock, ret;
- ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
+ ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET,
(gpointer *)&socket_handle);
if (ok == FALSE) {
g_warning ("%s: error looking up socket handle %p", __func__,
gpointer sock = GUINT_TO_POINTER (socket);
gint ret;
- if (_wapi_handle_type (sock) != WAPI_HANDLE_SOCKET) {
+ if (mono_w32handle_get_type (sock) != MONO_W32HANDLE_SOCKET) {
WSASetLastError (WSAENOTSOCK);
return FALSE;
}
int ret;
gchar *buffer = NULL;
- if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+ if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
WSASetLastError (WSAENOTSOCK);
return SOCKET_ERROR;
}
gpointer handle = GUINT_TO_POINTER (fd);
int ret;
- if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+ if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
WSASetLastError (WSAENOTSOCK);
return(SOCKET_ERROR);
}
return;
}
- if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+ if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
WSASetLastError (WSAENOTSOCK);
return;
}
return(0);
}
- if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+ if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
WSASetLastError (WSAENOTSOCK);
return(0);
}
return;
}
- if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+ if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
WSASetLastError (WSAENOTSOCK);
return;
}
#include <pthread.h>
#include "wapi-private.h"
-#include "handles-private.h"
/* There doesn't seem to be a defined symbol for this */
#define _WAPI_THREAD_CURRENT (gpointer)0xFFFFFFFE
#include <glib.h>
-#include <mono/io-layer/handles.h>
#include <mono/io-layer/io.h>
#include <mono/io-layer/status.h>
#include <mono/io-layer/processes.h>
#include <errno.h>
#include <mono/io-layer/wapi.h>
-#include <mono/io-layer/handles-private.h>
#include <mono/io-layer/wapi-private.h>
#include <mono/io-layer/io-trace.h>
#include <mono/utils/mono-logger-internals.h>
#include <mono/utils/mono-time.h>
+#include <mono/utils/w32handle.h>
static gboolean own_if_signalled(gpointer handle)
{
gboolean ret = FALSE;
- if (_wapi_handle_issignalled (handle)) {
- _wapi_handle_ops_own (handle);
+ if (mono_w32handle_issignalled (handle)) {
+ mono_w32handle_ops_own (handle);
ret = TRUE;
}
{
gboolean ret = FALSE;
- if (_wapi_handle_ops_isowned (handle)) {
- _wapi_handle_ops_own (handle);
+ if (mono_w32handle_ops_isowned (handle)) {
+ mono_w32handle_ops_own (handle);
ret = TRUE;
}
return(WAIT_FAILED);
}
- if (_wapi_handle_test_capabilities (handle,
- WAPI_HANDLE_CAP_WAIT) == FALSE) {
+ if (mono_w32handle_test_capabilities (handle,
+ MONO_W32HANDLE_CAP_WAIT) == FALSE) {
MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p can't be waited for", __func__,
handle);
return(WAIT_FAILED);
}
- _wapi_handle_ops_prewait (handle);
+ mono_w32handle_ops_prewait (handle);
- if (_wapi_handle_test_capabilities (handle, WAPI_HANDLE_CAP_SPECIAL_WAIT) == TRUE) {
+ if (mono_w32handle_test_capabilities (handle, MONO_W32HANDLE_CAP_SPECIAL_WAIT) == TRUE) {
MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p has special wait", __func__, handle);
- ret = _wapi_handle_ops_special_wait (handle, timeout, alertable);
+ ret = mono_w32handle_ops_specialwait (handle, timeout, alertable);
if (alertable && _wapi_thread_cur_apc_pending ())
ret = WAIT_IO_COMPLETION;
MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: locking handle %p", __func__, handle);
- thr_ret = _wapi_handle_lock_handle (handle);
+ thr_ret = mono_w32handle_lock_handle (handle);
g_assert (thr_ret == 0);
- if (_wapi_handle_test_capabilities (handle,
- WAPI_HANDLE_CAP_OWN) == TRUE) {
+ if (mono_w32handle_test_capabilities (handle,
+ MONO_W32HANDLE_CAP_OWN) == TRUE) {
if (own_if_owned (handle) == TRUE) {
MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p already owned", __func__,
handle);
do {
/* Check before waiting on the condition, just in case
*/
- _wapi_handle_ops_prewait (handle);
+ mono_w32handle_ops_prewait (handle);
if (own_if_signalled (handle)) {
MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p signalled", __func__,
}
if (timeout == INFINITE) {
- waited = _wapi_handle_timedwait_signal_handle (handle, INFINITE, FALSE, alertable ? &apc_pending : NULL);
+ waited = mono_w32handle_timedwait_signal_handle (handle, INFINITE, FALSE, alertable ? &apc_pending : NULL);
} else {
now = mono_100ns_ticks ();
if (end < now) {
goto done;
}
- waited = _wapi_handle_timedwait_signal_handle (handle, (end - now) / 10 / 1000, FALSE, alertable ? &apc_pending : NULL);
+ waited = mono_w32handle_timedwait_signal_handle (handle, (end - now) / 10 / 1000, FALSE, alertable ? &apc_pending : NULL);
}
if(waited==0 && !apc_pending) {
MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unlocking handle %p", __func__, handle);
- thr_ret = _wapi_handle_unlock_handle (handle);
+ thr_ret = mono_w32handle_unlock_handle (handle);
g_assert (thr_ret == 0);
return(ret);
return(WAIT_FAILED);
}
- if (_wapi_handle_test_capabilities (signal_handle,
- WAPI_HANDLE_CAP_SIGNAL)==FALSE) {
+ if (mono_w32handle_test_capabilities (signal_handle,
+ MONO_W32HANDLE_CAP_SIGNAL)==FALSE) {
return(WAIT_FAILED);
}
- if (_wapi_handle_test_capabilities (wait,
- WAPI_HANDLE_CAP_WAIT)==FALSE) {
+ if (mono_w32handle_test_capabilities (wait,
+ MONO_W32HANDLE_CAP_WAIT)==FALSE) {
return(WAIT_FAILED);
}
- _wapi_handle_ops_prewait (wait);
+ mono_w32handle_ops_prewait (wait);
- if (_wapi_handle_test_capabilities (wait, WAPI_HANDLE_CAP_SPECIAL_WAIT) == TRUE) {
+ if (mono_w32handle_test_capabilities (wait, MONO_W32HANDLE_CAP_SPECIAL_WAIT) == TRUE) {
g_warning ("%s: handle %p has special wait, implement me!!",
__func__, wait);
MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: locking handle %p", __func__, wait);
- thr_ret = _wapi_handle_lock_handle (wait);
+ thr_ret = mono_w32handle_lock_handle (wait);
g_assert (thr_ret == 0);
- _wapi_handle_ops_signal (signal_handle);
+ mono_w32handle_ops_signal (signal_handle);
- if (_wapi_handle_test_capabilities (wait, WAPI_HANDLE_CAP_OWN)==TRUE) {
+ if (mono_w32handle_test_capabilities (wait, MONO_W32HANDLE_CAP_OWN)==TRUE) {
if (own_if_owned (wait)) {
MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p already owned", __func__,
wait);
do {
/* Check before waiting on the condition, just in case
*/
- _wapi_handle_ops_prewait (wait);
+ mono_w32handle_ops_prewait (wait);
if (own_if_signalled (wait)) {
MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p signalled", __func__, wait);
}
if (timeout == INFINITE) {
- waited = _wapi_handle_timedwait_signal_handle (wait, INFINITE, FALSE, alertable ? &apc_pending : NULL);
+ waited = mono_w32handle_timedwait_signal_handle (wait, INFINITE, FALSE, alertable ? &apc_pending : NULL);
} else {
now = mono_100ns_ticks ();
if (end < now) {
goto done;
}
- waited = _wapi_handle_timedwait_signal_handle (wait, (end - now) / 10 / 1000, FALSE, alertable ? &apc_pending : NULL);
+ waited = mono_w32handle_timedwait_signal_handle (wait, (end - now) / 10 / 1000, FALSE, alertable ? &apc_pending : NULL);
}
if (waited==0 && !apc_pending) {
MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unlocking handle %p", __func__, wait);
- thr_ret = _wapi_handle_unlock_handle (wait);
+ thr_ret = mono_w32handle_unlock_handle (wait);
g_assert (thr_ret == 0);
return(ret);
MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: locking handles", __func__);
- done = _wapi_handle_count_signalled_handles (numobjects, handles,
+ done = mono_w32handle_count_signalled_handles (numobjects, handles,
waitall, count, lowest);
if (done == TRUE) {
if (waitall == TRUE) {
MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unlocking handles", __func__);
- _wapi_handle_unlock_handles (numobjects, handles);
+ mono_w32handle_unlock_handles (numobjects, handles);
return(done);
}
break;
}
- if (_wapi_handle_test_capabilities (handles[i], WAPI_HANDLE_CAP_WAIT) == FALSE) {
+ if (mono_w32handle_test_capabilities (handles[i], MONO_W32HANDLE_CAP_WAIT) == FALSE) {
MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Handle %p can't be waited for",
__func__, handles[i]);
}
sorted_handles [i] = handles [i];
- _wapi_handle_ops_prewait (handles[i]);
+ mono_w32handle_ops_prewait (handles[i]);
}
qsort (sorted_handles, numobjects, sizeof (gpointer), g_direct_equal);
poll = FALSE;
for (i = 0; i < numobjects; ++i)
- if (_wapi_handle_type (handles [i]) == WAPI_HANDLE_PROCESS)
+ if (mono_w32handle_get_type (handles [i]) == MONO_W32HANDLE_PROCESS)
/* Can't wait for a process handle + another handle without polling */
poll = TRUE;
* disappear from under us while we're waiting in the loop
* (not lock, as we don't want exclusive access here)
*/
- _wapi_handle_ref (handles[i]);
+ mono_w32handle_ref (handles[i]);
}
while(1) {
* special-wait handles that aren't already signalled
*/
for (i = 0; i < numobjects; i++) {
- _wapi_handle_ops_prewait (handles[i]);
+ mono_w32handle_ops_prewait (handles[i]);
- if (_wapi_handle_test_capabilities (handles[i], WAPI_HANDLE_CAP_SPECIAL_WAIT) == TRUE && _wapi_handle_issignalled (handles[i]) == FALSE) {
- _wapi_handle_ops_special_wait (handles[i], 0, alertable);
+ if (mono_w32handle_test_capabilities (handles[i], MONO_W32HANDLE_CAP_SPECIAL_WAIT) == TRUE && mono_w32handle_issignalled (handles[i]) == FALSE) {
+ mono_w32handle_ops_specialwait (handles[i], 0, alertable);
}
}
MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: locking signal mutex", __func__);
- thr_ret = _wapi_handle_lock_signal_mutex ();
+ thr_ret = mono_w32handle_lock_signal_mutex ();
g_assert (thr_ret == 0);
/* Check the signalled state of handles inside the critical section */
if (waitall) {
done = TRUE;
for (i = 0; i < numobjects; i++)
- if (!_wapi_handle_issignalled (handles [i]))
+ if (!mono_w32handle_issignalled (handles [i]))
done = FALSE;
} else {
done = FALSE;
for (i = 0; i < numobjects; i++)
- if (_wapi_handle_issignalled (handles [i]))
+ if (mono_w32handle_issignalled (handles [i]))
done = TRUE;
}
if (!done) {
/* Enter the wait */
if (timeout == INFINITE) {
- ret = _wapi_handle_timedwait_signal (INFINITE, poll, &apc_pending);
+ ret = mono_w32handle_timedwait_signal (INFINITE, poll, &apc_pending);
} else {
now = mono_100ns_ticks ();
if (end < now) {
ret = WAIT_TIMEOUT;
} else {
- ret = _wapi_handle_timedwait_signal ((end - now) / 10 / 1000, poll, &apc_pending);
+ ret = mono_w32handle_timedwait_signal ((end - now) / 10 / 1000, poll, &apc_pending);
}
}
} else {
MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unlocking signal mutex", __func__);
- thr_ret = _wapi_handle_unlock_signal_mutex ();
+ thr_ret = mono_w32handle_unlock_signal_mutex ();
g_assert (thr_ret == 0);
if (alertable && apc_pending) {
for (i = 0; i < numobjects; i++) {
/* Unref everything we reffed above */
- _wapi_handle_unref (handles[i]);
+ mono_w32handle_unref (handles[i]);
}
return retval;
#include <sys/stat.h>
#include <mono/io-layer/wapi.h>
-#include <mono/io-layer/handles.h>
-#include <mono/io-layer/handles-private.h>
#include <mono/io-layer/io.h>
#include <mono/io-layer/shared.h>
extern gboolean _wapi_has_shut_down;
-extern const char *_wapi_handle_typename[];
-
typedef struct
{
gchar name[MAX_PATH + 1];
#include <mono/io-layer/socket-private.h>
#include <mono/io-layer/thread-private.h>
#include <mono/io-layer/process-private.h>
+#include <mono/utils/w32handle.h>
struct _WapiHandle_shared_ref
{
_wapi_getpid (void);
gpointer
-_wapi_search_handle_namespace (WapiHandleType type, gchar *utf8_name);
+_wapi_search_handle_namespace (MonoW32HandleType type, gchar *utf8_name);
static inline int _wapi_namespace_lock (void)
{
#include "wapi.h"
-#include "handles-private.h"
#include "process-private.h"
#include "thread-private.h"
#include "io-trace.h"
#include "mono/utils/mono-lazy-init.h"
+#include "mono/utils/w32handle.h"
gboolean _wapi_has_shut_down = FALSE;
void
wapi_init (void)
{
- _wapi_handle_init ();
_wapi_shm_semaphores_init ();
_wapi_io_init ();
_wapi_processes_init ();
_wapi_thread_cleanup ();
wapi_processes_cleanup ();
_wapi_io_cleanup ();
- _wapi_handle_cleanup ();
}
/* Use this instead of getpid(), to cope with linuxthreads. It's a
return _wapi_pid;
}
+static gboolean
+_WAPI_SHARED_NAMESPACE (MonoW32HandleType type)
+{
+ switch (type) {
+ case MONO_W32HANDLE_NAMEDMUTEX:
+ case MONO_W32HANDLE_NAMEDSEM:
+ case MONO_W32HANDLE_NAMEDEVENT:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
typedef struct {
gpointer ret;
- WapiHandleType type;
+ MonoW32HandleType type;
gchar *utf8_name;
} _WapiSearchHandleNamespaceData;
-static gboolean _wapi_search_handle_namespace_callback (gpointer handle, gpointer data, gpointer user_data)
+static gboolean mono_w32handle_search_namespace_callback (gpointer handle, gpointer data, gpointer user_data)
{
_WapiSearchHandleNamespaceData *search_data;
- WapiHandleType type;
+ MonoW32HandleType type;
WapiSharedNamespace *sharedns;
- type = _wapi_handle_type (handle);
+ type = mono_w32handle_get_type (handle);
if (!_WAPI_SHARED_NAMESPACE (type))
return FALSE;
search_data = (_WapiSearchHandleNamespaceData*) user_data;
switch (type) {
- case WAPI_HANDLE_NAMEDMUTEX: sharedns = &((struct _WapiHandle_namedmutex*) data)->sharedns; break;
- case WAPI_HANDLE_NAMEDSEM: sharedns = &((struct _WapiHandle_namedsem*) data)->sharedns; break;
- case WAPI_HANDLE_NAMEDEVENT: sharedns = &((struct _WapiHandle_namedevent*) data)->sharedns; break;
+ case MONO_W32HANDLE_NAMEDMUTEX: sharedns = &((struct _WapiHandle_namedmutex*) data)->sharedns; break;
+ case MONO_W32HANDLE_NAMEDSEM: sharedns = &((struct _WapiHandle_namedsem*) data)->sharedns; break;
+ case MONO_W32HANDLE_NAMEDEVENT: sharedns = &((struct _WapiHandle_namedevent*) data)->sharedns; break;
default:
g_assert_not_reached ();
}
if (type != search_data->type) {
/* Its the wrong type, so fail now */
MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p matches name but is wrong type: %s",
- __func__, handle, _wapi_handle_ops_typename (type));
+ __func__, handle, mono_w32handle_ops_typename (type));
search_data->ret = INVALID_HANDLE_VALUE;
} else {
MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p matches name and type",
/* Returns the offset of the metadata array, or INVALID_HANDLE_VALUE on error, or NULL for
* not found
*/
-gpointer _wapi_search_handle_namespace (WapiHandleType type, gchar *utf8_name)
+gpointer _wapi_search_handle_namespace (MonoW32HandleType type, gchar *utf8_name)
{
_WapiSearchHandleNamespaceData search_data;
g_assert(_WAPI_SHARED_NAMESPACE(type));
MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Lookup for handle named [%s] type %s",
- __func__, utf8_name, _wapi_handle_ops_typename (type));
+ __func__, utf8_name, mono_w32handle_ops_typename (type));
search_data.ret = NULL;
search_data.type = type;
search_data.utf8_name = utf8_name;
- _wapi_handle_foreach (_wapi_search_handle_namespace_callback, &search_data);
+ mono_w32handle_foreach (mono_w32handle_search_namespace_callback, &search_data);
return search_data.ret;
}
} else if (src == _WAPI_THREAD_CURRENT) {
g_assert_not_reached ();
} else {
- _wapi_handle_ref (src);
+ mono_w32handle_ref (src);
*target = src;
}
SetLastError (ERROR_INVALID_PARAMETER);
return FALSE;
}
- if (handle == (gpointer)0 && _wapi_handle_type (handle) != WAPI_HANDLE_CONSOLE) {
+ if (handle == (gpointer)0 && mono_w32handle_get_type (handle) != MONO_W32HANDLE_CONSOLE) {
/* Problem: because we map file descriptors to the
* same-numbered handle we can't tell the difference
* between a bogus handle and the handle to stdin.
return FALSE;
}
- _wapi_handle_unref (handle);
+ mono_w32handle_unref (handle);
return TRUE;
}
#include <mono/io-layer/wapi-remap.h>
#include <mono/io-layer/types.h>
#include <mono/io-layer/macros.h>
-#include <mono/io-layer/handles.h>
#include <mono/io-layer/io.h>
#include <mono/io-layer/access.h>
#include <mono/io-layer/context.h>
#include <mono/io-layer/wapi.h>
#include <mono/io-layer/wapi-private.h>
-#include <mono/io-layer/handles-private.h>
#include <mono/io-layer/thread-private.h>
#include <mono/io-layer/mutex-private.h>
#include <mono/io-layer/io-trace.h>
#include <mono/utils/mono-time.h>
#include <mono/utils/mono-once.h>
#include <mono/utils/mono-logger-internals.h>
+#include <mono/utils/w32handle.h>
#ifdef HAVE_VALGRIND_MEMCHECK_H
#include <valgrind/memcheck.h>
static const gchar* thread_typename (void);
static gsize thread_typesize (void);
-static WapiHandleOps _wapi_thread_ops = {
+static MonoW32HandleOps _wapi_thread_ops = {
NULL, /* close */
NULL, /* signal */
NULL, /* own */
void
_wapi_thread_init (void)
{
- _wapi_handle_register_ops (WAPI_HANDLE_THREAD, &_wapi_thread_ops);
+ mono_w32handle_register_ops (MONO_W32HANDLE_THREAD, &_wapi_thread_ops);
- _wapi_handle_register_capabilities (WAPI_HANDLE_THREAD, WAPI_HANDLE_CAP_WAIT);
+ mono_w32handle_register_capabilities (MONO_W32HANDLE_THREAD, MONO_W32HANDLE_CAP_WAIT);
}
static void thread_details (gpointer data)
WapiHandle_thread *thread;
gboolean ok;
- ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
+ ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_THREAD,
(gpointer *)&thread);
g_assert (ok);
return thread;
pid_t pid = _wapi_getpid ();
pthread_t tid = pthread_self ();
- if (_wapi_handle_issignalled (handle) ||
- _wapi_handle_type (handle) == WAPI_HANDLE_UNUSED) {
+ if (mono_w32handle_issignalled (handle) ||
+ mono_w32handle_get_type (handle) == MONO_W32HANDLE_UNUSED) {
/* We must have already deliberately finished with
* this thread, so don't do any more now
*/
}
g_ptr_array_free (thread_handle->owned_mutexes, TRUE);
- thr_ret = _wapi_handle_lock_handle (handle);
+ thr_ret = mono_w32handle_lock_handle (handle);
g_assert (thr_ret == 0);
- _wapi_handle_set_signal_state (handle, TRUE, TRUE);
+ mono_w32handle_set_signal_state (handle, TRUE, TRUE);
- thr_ret = _wapi_handle_unlock_handle (handle);
+ thr_ret = mono_w32handle_unlock_handle (handle);
g_assert (thr_ret == 0);
MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Recording thread handle %p id %ld status as %d",
__func__, handle, thread_handle->id, exitstatus);
/* The thread is no longer active, so unref it */
- _wapi_handle_unref (handle);
+ mono_w32handle_unref (handle);
}
/*
thread_handle.owned_mutexes = g_ptr_array_new ();
- handle = _wapi_handle_new (WAPI_HANDLE_THREAD, &thread_handle);
+ handle = mono_w32handle_new (MONO_W32HANDLE_THREAD, &thread_handle);
if (handle == INVALID_HANDLE_VALUE) {
g_warning ("%s: error creating thread handle", __func__);
SetLastError (ERROR_GEN_FAILURE);
* Hold a reference while the thread is active, because we use
* the handle to store thread exit information
*/
- _wapi_handle_ref (handle);
+ mono_w32handle_ref (handle);
MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: started thread id %ld", __func__, thread->id);
void
wapi_ref_thread_handle (gpointer handle)
{
- _wapi_handle_ref (handle);
+ mono_w32handle_ref (handle);
}
gpointer
thread = get_current_thread ();
- _wapi_handle_ref (mutex);
+ mono_w32handle_ref (mutex);
g_ptr_array_add (thread->owned_mutexes, mutex);
}
thread = get_current_thread ();
- _wapi_handle_unref (mutex);
+ mono_w32handle_unref (mutex);
g_ptr_array_remove (thread->owned_mutexes, mutex);
}
wapi_init_thread_info_priority (gpointer handle, gint32 priority)
{
struct _WapiHandle_thread *thread_handle = NULL;
- gboolean ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
+ gboolean ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_THREAD,
(gpointer *)&thread_handle);
if (ok == TRUE)
struct _WapiHandle_thread *thread_handle = NULL;
int policy;
struct sched_param param;
- gboolean ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
+ gboolean ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_THREAD,
(gpointer *)&thread_handle);
if (ok == FALSE)
posix_priority,
rv;
struct sched_param param;
- gboolean ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
+ gboolean ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_THREAD,
(gpointer *)&thread_handle);
if (ok == FALSE) {
#include <mono/utils/atomic.h>
#include <mono/utils/mono-memory-model.h>
#include <mono/utils/mono-threads.h>
+#include <mono/utils/w32handle.h>
#ifdef HOST_WIN32
#include <direct.h>
#endif
#include <metadata/threads.h>
#include <metadata/profiler-private.h>
#include <mono/metadata/coree.h>
+#include <mono/utils/w32handle.h>
//#define DEBUG_DOMAIN_UNLOAD 1
#endif
#ifndef HOST_WIN32
+ mono_w32handle_init ();
wapi_init ();
#endif
#ifndef HOST_WIN32
wapi_cleanup ();
+ mono_w32handle_cleanup ();
#endif
}
#include <mono/metadata/marshal.h>
#include <mono/utils/strenc.h>
#include <utils/mono-io-portability.h>
+#include <mono/utils/w32handle.h>
#undef DEBUG
#endif
-void _wapi_handle_dump (void);
+void mono_w32handle_dump (void);
void ves_icall_System_IO_MonoIO_DumpHandles (void)
{
#ifndef HOST_WIN32
- _wapi_handle_dump ();
+ mono_w32handle_dump ();
#endif
}
#include <mono/io-layer/io-layer.h>
/* FIXME: fix this code to not depend so much on the internals */
#include <mono/metadata/class-internals.h>
+#include <mono/utils/w32handle.h>
#define LOGDEBUG(...)
/* define LOGDEBUG(...) g_message(__VA_ARGS__) */
#include <mono/utils/mono-threads.h>
#include <mono/utils/mono-memory-model.h>
#include <mono/utils/networking.h>
+#include <mono/utils/w32handle.h>
#include <time.h>
#ifdef HAVE_SYS_TIME_H
parse.c \
parse.h \
checked-build.c \
- checked-build.h
+ checked-build.h \
+ w32handle.c \
+ w32handle.h
arch_sources =
MONO_TRACE_THREADPOOL = (1<<7),
MONO_TRACE_IO_THREADPOOL = (1<<8),
MONO_TRACE_IO_LAYER = (1<<9),
+ MONO_TRACE_W32HANDLE = (1<<10),
MONO_TRACE_ALL = MONO_TRACE_ASSEMBLY |
MONO_TRACE_TYPE |
MONO_TRACE_DLLIMPORT |
MONO_TRACE_SECURITY |
MONO_TRACE_THREADPOOL |
MONO_TRACE_IO_THREADPOOL |
- MONO_TRACE_IO_LAYER
+ MONO_TRACE_IO_LAYER |
+ MONO_TRACE_W32HANDLE
} MonoTraceMask;
extern GLogLevelFlags mono_internal_current_level;
const char *tok;
guint32 flags = 0;
- const char *valid_flags[] = {"asm", "type", "dll", "gc", "cfg", "aot", "security", "threadpool", "io-threadpool", "io-layer", "all", NULL};
+ const char *valid_flags[] = {"asm", "type", "dll", "gc", "cfg", "aot", "security", "threadpool", "io-threadpool", "io-layer", "w32handle", "all", NULL};
const MonoTraceMask valid_masks[] = {MONO_TRACE_ASSEMBLY, MONO_TRACE_TYPE, MONO_TRACE_DLLIMPORT,
MONO_TRACE_GC, MONO_TRACE_CONFIG, MONO_TRACE_AOT, MONO_TRACE_SECURITY,
- MONO_TRACE_THREADPOOL, MONO_TRACE_IO_THREADPOOL, MONO_TRACE_IO_LAYER, MONO_TRACE_ALL };
+ MONO_TRACE_THREADPOOL, MONO_TRACE_IO_THREADPOOL, MONO_TRACE_IO_LAYER,
+ MONO_TRACE_W32HANDLE, MONO_TRACE_ALL };
if(!value)
return;
--- /dev/null
+/*
+ * w32handle.c: Generic and internal operations on handles
+ *
+ * Author:
+ * Dick Porter (dick@ximian.com)
+ * Ludovic Henry (luhenry@microsoft.com)
+ *
+ * (C) 2002-2011 Novell, Inc.
+ * Copyright 2011 Xamarin Inc
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+
+#include <config.h>
+
+#if !defined(HOST_WIN32)
+
+#include <glib.h>
+#include <pthread.h>
+#include <errno.h>
+#include <unistd.h>
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+#include <string.h>
+#include <sys/types.h>
+#ifdef HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
+#ifdef HAVE_SYS_UN_H
+# include <sys/un.h>
+#endif
+#ifdef HAVE_SYS_MMAN_H
+# include <sys/mman.h>
+#endif
+#ifdef HAVE_DIRENT_H
+# include <dirent.h>
+#endif
+#include <sys/stat.h>
+#ifdef HAVE_SYS_RESOURCE_H
+# include <sys/resource.h>
+#endif
+
+#include "w32handle.h"
+
+#include "atomic.h"
+#include "mono-logger-internals.h"
+#include "mono-os-mutex.h"
+#include "mono-proclib.h"
+#include "mono-threads.h"
+
+#undef DEBUG_REFS
+
+#define SLOT_MAX (1024 * 16)
+
+/* must be a power of 2 */
+#define HANDLE_PER_SLOT (256)
+
+typedef struct {
+ MonoW32HandleType type;
+ guint ref;
+ gboolean signalled;
+ mono_mutex_t signal_mutex;
+ mono_cond_t signal_cond;
+ gpointer specific;
+} MonoW32HandleBase;
+
+static MonoW32HandleCapability handle_caps [MONO_W32HANDLE_COUNT];
+static MonoW32HandleOps *handle_ops [MONO_W32HANDLE_COUNT];
+
+/*
+ * We can hold SLOT_MAX * HANDLE_PER_SLOT handles.
+ * If 4M handles are not enough... Oh, well... we will crash.
+ */
+#define SLOT_INDEX(x) (x / HANDLE_PER_SLOT)
+#define SLOT_OFFSET(x) (x % HANDLE_PER_SLOT)
+
+static MonoW32HandleBase *private_handles [SLOT_MAX];
+static guint32 private_handles_count = 0;
+static guint32 private_handles_slots_count = 0;
+
+guint32 mono_w32handle_fd_reserve;
+
+/*
+ * This is an internal handle which is used for handling waiting for multiple handles.
+ * Threads which wait for multiple handles wait on this one handle, and when a handle
+ * is signalled, this handle is signalled too.
+ */
+static mono_mutex_t global_signal_mutex;
+static mono_cond_t global_signal_cond;
+
+static mono_mutex_t scan_mutex;
+
+static gboolean shutting_down = FALSE;
+
+static gboolean
+type_is_fd (MonoW32HandleType type)
+{
+ switch (type) {
+ case MONO_W32HANDLE_FILE:
+ case MONO_W32HANDLE_CONSOLE:
+ case MONO_W32HANDLE_SOCKET:
+ case MONO_W32HANDLE_PIPE:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+static gboolean
+mono_w32handle_lookup_data (gpointer handle, MonoW32HandleBase **handle_data)
+{
+ gsize index, offset;
+
+ g_assert (handle_data);
+
+ index = SLOT_INDEX ((gsize) handle);
+ if (index >= SLOT_MAX)
+ return FALSE;
+ if (!private_handles [index])
+ return FALSE;
+
+ offset = SLOT_OFFSET ((gsize) handle);
+ if (private_handles [index][offset].type == MONO_W32HANDLE_UNUSED)
+ return FALSE;
+
+ *handle_data = &private_handles [index][offset];
+ return TRUE;
+}
+
+MonoW32HandleType
+mono_w32handle_get_type (gpointer handle)
+{
+ MonoW32HandleBase *handle_data;
+
+ if (!mono_w32handle_lookup_data (handle, &handle_data))
+ return MONO_W32HANDLE_UNUSED; /* An impossible type */
+
+ return handle_data->type;
+}
+
+void
+mono_w32handle_set_signal_state (gpointer handle, gboolean state, gboolean broadcast)
+{
+ MonoW32HandleBase *handle_data;
+ int thr_ret;
+
+ if (!mono_w32handle_lookup_data (handle, &handle_data)) {
+ return;
+ }
+
+#ifdef DEBUG
+ g_message ("%s: setting state of %p to %s (broadcast %s)", __func__,
+ handle, state?"TRUE":"FALSE", broadcast?"TRUE":"FALSE");
+#endif
+
+ if (state == TRUE) {
+ /* Tell everyone blocking on a single handle */
+
+ /* The condition the global signal cond is waiting on is the signalling of
+ * _any_ handle. So lock it before setting the signalled state.
+ */
+ thr_ret = mono_os_mutex_lock (&global_signal_mutex);
+ if (thr_ret != 0)
+ g_warning ("Bad call to mono_os_mutex_lock result %d for global signal mutex", thr_ret);
+ g_assert (thr_ret == 0);
+
+ /* This function _must_ be called with
+ * handle->signal_mutex locked
+ */
+ handle_data->signalled=state;
+
+ if (broadcast == TRUE) {
+ thr_ret = mono_os_cond_broadcast (&handle_data->signal_cond);
+ if (thr_ret != 0)
+ g_warning ("Bad call to mono_os_cond_broadcast result %d for handle %p", thr_ret, handle);
+ g_assert (thr_ret == 0);
+ } else {
+ thr_ret = mono_os_cond_signal (&handle_data->signal_cond);
+ if (thr_ret != 0)
+ g_warning ("Bad call to mono_os_cond_signal result %d for handle %p", thr_ret, handle);
+ g_assert (thr_ret == 0);
+ }
+
+ /* Tell everyone blocking on multiple handles that something
+ * was signalled
+ */
+ thr_ret = mono_os_cond_broadcast (&global_signal_cond);
+ if (thr_ret != 0)
+ g_warning ("Bad call to mono_os_cond_broadcast result %d for handle %p", thr_ret, handle);
+ g_assert (thr_ret == 0);
+
+ thr_ret = mono_os_mutex_unlock (&global_signal_mutex);
+ if (thr_ret != 0)
+ g_warning ("Bad call to mono_os_mutex_unlock result %d for global signal mutex", thr_ret);
+ g_assert (thr_ret == 0);
+ } else {
+ handle_data->signalled=state;
+ }
+}
+
+gboolean
+mono_w32handle_issignalled (gpointer handle)
+{
+ MonoW32HandleBase *handle_data;
+
+ if (!mono_w32handle_lookup_data (handle, &handle_data)) {
+ return(FALSE);
+ }
+
+ return handle_data->signalled;
+}
+
+int
+mono_w32handle_lock_signal_mutex (void)
+{
+#ifdef DEBUG
+ g_message ("%s: lock global signal mutex", __func__);
+#endif
+
+ return(mono_os_mutex_lock (&global_signal_mutex));
+}
+
+int
+mono_w32handle_unlock_signal_mutex (void)
+{
+#ifdef DEBUG
+ g_message ("%s: unlock global signal mutex", __func__);
+#endif
+
+ return(mono_os_mutex_unlock (&global_signal_mutex));
+}
+
+int
+mono_w32handle_lock_handle (gpointer handle)
+{
+ MonoW32HandleBase *handle_data;
+
+#ifdef DEBUG
+ g_message ("%s: locking handle %p", __func__, handle);
+#endif
+
+ if (!mono_w32handle_lookup_data (handle, &handle_data)) {
+ return(0);
+ }
+
+ mono_w32handle_ref (handle);
+
+ return(mono_os_mutex_lock (&handle_data->signal_mutex));
+}
+
+int
+mono_w32handle_trylock_handle (gpointer handle)
+{
+ MonoW32HandleBase *handle_data;
+ int ret;
+
+#ifdef DEBUG
+ g_message ("%s: locking handle %p", __func__, handle);
+#endif
+
+ if (!mono_w32handle_lookup_data (handle, &handle_data)) {
+ return(0);
+ }
+
+ mono_w32handle_ref (handle);
+
+ ret = mono_os_mutex_trylock (&handle_data->signal_mutex);
+ if (ret != 0) {
+ mono_w32handle_unref (handle);
+ }
+
+ return(ret);
+}
+
+int
+mono_w32handle_unlock_handle (gpointer handle)
+{
+ MonoW32HandleBase *handle_data;
+ int ret;
+
+#ifdef DEBUG
+ g_message ("%s: unlocking handle %p", __func__, handle);
+#endif
+
+ if (!mono_w32handle_lookup_data (handle, &handle_data)) {
+ return(0);
+ }
+
+ ret = mono_os_mutex_unlock (&handle_data->signal_mutex);
+
+ mono_w32handle_unref (handle);
+
+ return(ret);
+}
+
+/*
+ * wapi_init:
+ *
+ * Initialize the io-layer.
+ */
+void
+mono_w32handle_init (void)
+{
+ g_assert ((sizeof (handle_ops) / sizeof (handle_ops[0]))
+ == MONO_W32HANDLE_COUNT);
+
+ /* This is needed by the code in mono_w32handle_new_internal */
+ mono_w32handle_fd_reserve = (eg_getdtablesize () + (HANDLE_PER_SLOT - 1)) & ~(HANDLE_PER_SLOT - 1);
+
+ do {
+ /*
+ * The entries in private_handles reserved for fds are allocated lazily to
+ * save memory.
+ */
+
+ private_handles_count += HANDLE_PER_SLOT;
+ private_handles_slots_count ++;
+ } while(mono_w32handle_fd_reserve > private_handles_count);
+
+ mono_os_mutex_init (&scan_mutex);
+
+ mono_os_cond_init (&global_signal_cond);
+ mono_os_mutex_init (&global_signal_mutex);
+}
+
+static void mono_w32handle_unref_full (gpointer handle, gboolean ignore_private_busy_handles);
+
+void
+mono_w32handle_cleanup (void)
+{
+ int i, j, k;
+
+ g_assert (!shutting_down);
+ shutting_down = TRUE;
+
+ /* Every shared handle we were using ought really to be closed
+ * by now, but to make sure just blow them all away. The
+ * exiting finalizer thread in particular races us to the
+ * program exit and doesn't always win, so it can be left
+ * cluttering up the shared file. Anything else left over is
+ * really a bug.
+ */
+ for(i = SLOT_INDEX (0); private_handles[i] != NULL; i++) {
+ for(j = SLOT_OFFSET (0); j < HANDLE_PER_SLOT; j++) {
+ MonoW32HandleBase *handle_data = &private_handles[i][j];
+ gpointer handle = GINT_TO_POINTER (i*HANDLE_PER_SLOT+j);
+
+ for(k = handle_data->ref; k > 0; k--) {
+ mono_w32handle_unref_full (handle, TRUE);
+ }
+ }
+ }
+
+ for (i = 0; i < SLOT_MAX; ++i)
+ g_free (private_handles [i]);
+}
+
+static void mono_w32handle_init_handle (MonoW32HandleBase *handle,
+ MonoW32HandleType type, gpointer handle_specific)
+{
+ int thr_ret;
+
+ g_assert (!shutting_down);
+
+ handle->type = type;
+ handle->signalled = FALSE;
+ handle->ref = 1;
+
+ thr_ret = mono_os_cond_init (&handle->signal_cond);
+ g_assert (thr_ret == 0);
+
+ thr_ret = mono_os_mutex_init (&handle->signal_mutex);
+ g_assert (thr_ret == 0);
+
+ if (handle_specific)
+ handle->specific = g_memdup (handle_specific, mono_w32handle_ops_typesize (type));
+}
+
+/*
+ * mono_w32handle_new_internal:
+ * @type: Init handle to this type
+ *
+ * Search for a free handle and initialize it. Return the handle on
+ * success and 0 on failure. This is only called from
+ * mono_w32handle_new, and scan_mutex must be held.
+ */
+static guint32 mono_w32handle_new_internal (MonoW32HandleType type,
+ gpointer handle_specific)
+{
+ guint32 i, k, count;
+ static guint32 last = 0;
+ gboolean retry = FALSE;
+
+ g_assert (!shutting_down);
+
+ /* A linear scan should be fast enough. Start from the last
+ * allocation, assuming that handles are allocated more often
+ * than they're freed. Leave the space reserved for file
+ * descriptors
+ */
+
+ if (last < mono_w32handle_fd_reserve) {
+ last = mono_w32handle_fd_reserve;
+ } else {
+ retry = TRUE;
+ }
+
+again:
+ count = last;
+ for(i = SLOT_INDEX (count); i < private_handles_slots_count; i++) {
+ if (private_handles [i]) {
+ for (k = SLOT_OFFSET (count); k < HANDLE_PER_SLOT; k++) {
+ MonoW32HandleBase *handle = &private_handles [i][k];
+
+ if(handle->type == MONO_W32HANDLE_UNUSED) {
+ last = count + 1;
+
+ mono_w32handle_init_handle (handle, type, handle_specific);
+ return (count);
+ }
+ count++;
+ }
+ }
+ }
+
+ if(retry && last > mono_w32handle_fd_reserve) {
+ /* Try again from the beginning */
+ last = mono_w32handle_fd_reserve;
+ goto again;
+ }
+
+ /* Will need to expand the array. The caller will sort it out */
+
+ return(0);
+}
+
+gpointer
+mono_w32handle_new (MonoW32HandleType type, gpointer handle_specific)
+{
+ guint32 handle_idx = 0;
+ gpointer handle;
+ int thr_ret;
+
+ g_assert (!shutting_down);
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: Creating new handle of type %s", __func__,
+ mono_w32handle_ops_typename (type));
+
+ g_assert(!type_is_fd(type));
+
+ thr_ret = mono_os_mutex_lock (&scan_mutex);
+ g_assert (thr_ret == 0);
+
+ while ((handle_idx = mono_w32handle_new_internal (type, handle_specific)) == 0) {
+ /* Try and expand the array, and have another go */
+ int idx = SLOT_INDEX (private_handles_count);
+ if (idx >= SLOT_MAX) {
+ break;
+ }
+
+ private_handles [idx] = g_new0 (MonoW32HandleBase, HANDLE_PER_SLOT);
+
+ private_handles_count += HANDLE_PER_SLOT;
+ private_handles_slots_count ++;
+ }
+
+ thr_ret = mono_os_mutex_unlock (&scan_mutex);
+ g_assert (thr_ret == 0);
+
+ if (handle_idx == 0) {
+ /* We ran out of slots */
+ handle = INVALID_HANDLE_VALUE;
+ goto done;
+ }
+
+ /* Make sure we left the space for fd mappings */
+ g_assert (handle_idx >= mono_w32handle_fd_reserve);
+
+ handle = GUINT_TO_POINTER (handle_idx);
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: Allocated new handle %p", __func__, handle);
+
+done:
+ return(handle);
+}
+
+gpointer mono_w32handle_new_fd (MonoW32HandleType type, int fd,
+ gpointer handle_specific)
+{
+ MonoW32HandleBase *handle_data;
+ int fd_index, fd_offset;
+ int thr_ret;
+
+ g_assert (!shutting_down);
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: Creating new handle of type %s", __func__,
+ mono_w32handle_ops_typename (type));
+
+ g_assert(type_is_fd(type));
+
+ if (fd >= mono_w32handle_fd_reserve) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: fd %d is too big", __func__, fd);
+
+ return(GUINT_TO_POINTER (INVALID_HANDLE_VALUE));
+ }
+
+ fd_index = SLOT_INDEX (fd);
+ fd_offset = SLOT_OFFSET (fd);
+
+ /* Initialize the array entries on demand */
+ if (!private_handles [fd_index]) {
+ thr_ret = mono_os_mutex_lock (&scan_mutex);
+ g_assert (thr_ret == 0);
+
+ if (!private_handles [fd_index])
+ private_handles [fd_index] = g_new0 (MonoW32HandleBase, HANDLE_PER_SLOT);
+
+ thr_ret = mono_os_mutex_unlock (&scan_mutex);
+ g_assert (thr_ret == 0);
+ }
+
+ handle_data = &private_handles [fd_index][fd_offset];
+
+ if (handle_data->type != MONO_W32HANDLE_UNUSED) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: fd %d is already in use!", __func__, fd);
+ /* FIXME: clean up this handle? We can't do anything
+ * with the fd, cos thats the new one
+ */
+ }
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: Assigning new fd handle %p", __func__, (gpointer)(gsize)fd);
+
+ mono_w32handle_init_handle (handle_data, type, handle_specific);
+
+ return(GUINT_TO_POINTER(fd));
+}
+
+gboolean
+mono_w32handle_lookup (gpointer handle, MonoW32HandleType type,
+ gpointer *handle_specific)
+{
+ MonoW32HandleBase *handle_data;
+
+ g_assert (handle_specific);
+
+ if (!mono_w32handle_lookup_data (handle, &handle_data)) {
+ return(FALSE);
+ }
+
+ if (handle_data->type != type) {
+ return(FALSE);
+ }
+
+ *handle_specific = handle_data->specific;
+
+ return(TRUE);
+}
+
+void
+mono_w32handle_foreach (gboolean (*on_each)(gpointer handle, gpointer data, gpointer user_data), gpointer user_data)
+{
+ MonoW32HandleBase *handle_data = NULL;
+ gpointer handle;
+ guint32 i, k;
+ int thr_ret;
+
+ thr_ret = mono_os_mutex_lock (&scan_mutex);
+ g_assert (thr_ret == 0);
+
+ for (i = SLOT_INDEX (0); i < private_handles_slots_count; i++) {
+ if (private_handles [i]) {
+ for (k = SLOT_OFFSET (0); k < HANDLE_PER_SLOT; k++) {
+ handle_data = &private_handles [i][k];
+ if (handle_data->type == MONO_W32HANDLE_UNUSED)
+ continue;
+ handle = GUINT_TO_POINTER (i * HANDLE_PER_SLOT + k);
+ if (on_each (handle, handle_data->specific, user_data) == TRUE)
+ goto done;
+ }
+ }
+ }
+
+done:
+ thr_ret = mono_os_mutex_unlock (&scan_mutex);
+ g_assert (thr_ret == 0);
+}
+
+/* This might list some shared handles twice if they are already
+ * opened by this process, and the check function returns FALSE the
+ * first time. Shared handles that are created during the search are
+ * unreffed if the check function returns FALSE, so callers must not
+ * rely on the handle persisting (unless the check function returns
+ * TRUE)
+ * The caller owns the returned handle.
+ */
+gpointer mono_w32handle_search (MonoW32HandleType type,
+ gboolean (*check)(gpointer test, gpointer user),
+ gpointer user_data,
+ gpointer *handle_specific,
+ gboolean search_shared)
+{
+ MonoW32HandleBase *handle_data = NULL;
+ gpointer ret = NULL;
+ guint32 i, k;
+ gboolean found = FALSE;
+ int thr_ret;
+
+ thr_ret = mono_os_mutex_lock (&scan_mutex);
+ g_assert (thr_ret == 0);
+
+ for (i = SLOT_INDEX (0); !found && i < private_handles_slots_count; i++) {
+ if (private_handles [i]) {
+ for (k = SLOT_OFFSET (0); k < HANDLE_PER_SLOT; k++) {
+ handle_data = &private_handles [i][k];
+
+ if (handle_data->type == type) {
+ ret = GUINT_TO_POINTER (i * HANDLE_PER_SLOT + k);
+ if (check (ret, user_data) == TRUE) {
+ mono_w32handle_ref (ret);
+ found = TRUE;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ thr_ret = mono_os_mutex_unlock (&scan_mutex);
+ g_assert (thr_ret == 0);
+
+ if (!found) {
+ ret = NULL;
+ goto done;
+ }
+
+ if(handle_specific != NULL) {
+ *handle_specific = handle_data->specific;
+ }
+
+done:
+ return(ret);
+}
+
+void mono_w32handle_ref (gpointer handle)
+{
+ MonoW32HandleBase *handle_data;
+
+ if (!mono_w32handle_lookup_data (handle, &handle_data)) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: Attempting to ref invalid private handle %p", __func__, handle);
+ return;
+ }
+
+ InterlockedIncrement ((gint32 *)&handle_data->ref);
+
+#ifdef DEBUG_REFS
+ g_message ("%s: %s handle %p ref now %d",
+ __func__, mono_w32handle_ops_typename (handle_data->type), handle, handle_data->ref);
+#endif
+}
+
+static void (*_wapi_handle_ops_get_close_func (MonoW32HandleType type))(gpointer, gpointer);
+
+/* The handle must not be locked on entry to this function */
+static void mono_w32handle_unref_full (gpointer handle, gboolean ignore_private_busy_handles)
+{
+ MonoW32HandleBase *handle_data;
+ gboolean destroy = FALSE, early_exit = FALSE;
+ int thr_ret;
+
+ if (!mono_w32handle_lookup_data (handle, &handle_data)) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: Attempting to unref invalid private handle %p",
+ __func__, handle);
+ return;
+ }
+
+ /* Possible race condition here if another thread refs the
+ * handle between here and setting the type to UNUSED. I
+ * could lock a mutex, but I'm not sure that allowing a handle
+ * reference to reach 0 isn't an application bug anyway.
+ */
+ destroy = (InterlockedDecrement ((gint32 *)&handle_data->ref) ==0);
+
+#ifdef DEBUG_REFS
+ g_message ("%s: %s handle %p ref now %d (destroy %s)",
+ __func__, mono_w32handle_ops_typename (handle_data->type), handle, handle_data->ref, destroy?"TRUE":"FALSE");
+#endif
+
+ if(destroy==TRUE) {
+ /* Need to copy the handle info, reset the slot in the
+ * array, and _only then_ call the close function to
+ * avoid race conditions (eg file descriptors being
+ * closed, and another file being opened getting the
+ * same fd racing the memset())
+ */
+ MonoW32HandleType type;
+ gpointer handle_specific;
+ void (*close_func)(gpointer, gpointer);
+
+ type = handle_data->type;
+ handle_specific = handle_data->specific;
+
+ thr_ret = mono_os_mutex_lock (&scan_mutex);
+ g_assert (thr_ret == 0);
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: Destroying handle %p", __func__, handle);
+
+ /* Destroy the mutex and cond var. We hope nobody
+ * tried to grab them between the handle unlock and
+ * now, but pthreads doesn't have a
+ * "unlock_and_destroy" atomic function.
+ */
+ thr_ret = mono_os_mutex_destroy (&handle_data->signal_mutex);
+ /*WARNING gross hack to make cleanup not crash when exiting without the whole runtime teardown.*/
+ if (thr_ret == EBUSY && ignore_private_busy_handles) {
+ early_exit = TRUE;
+ } else {
+ if (thr_ret != 0)
+ g_error ("Error destroying handle %p mutex due to %d\n", handle, thr_ret);
+
+ thr_ret = mono_os_cond_destroy (&handle_data->signal_cond);
+ if (thr_ret == EBUSY && ignore_private_busy_handles)
+ early_exit = TRUE;
+ else if (thr_ret != 0)
+ g_error ("Error destroying handle %p cond var due to %d\n", handle, thr_ret);
+ }
+
+ memset (handle_data, 0, sizeof (MonoW32HandleBase));
+
+ thr_ret = mono_os_mutex_unlock (&scan_mutex);
+ g_assert (thr_ret == 0);
+
+ if (early_exit)
+ return;
+
+ close_func = _wapi_handle_ops_get_close_func (type);
+ if (close_func != NULL) {
+ close_func (handle, handle_specific);
+ }
+
+ g_free (handle_specific);
+ }
+}
+
+void mono_w32handle_unref (gpointer handle)
+{
+ mono_w32handle_unref_full (handle, FALSE);
+}
+
+void
+mono_w32handle_register_ops (MonoW32HandleType type, MonoW32HandleOps *ops)
+{
+ handle_ops [type] = ops;
+}
+
+void mono_w32handle_register_capabilities (MonoW32HandleType type,
+ MonoW32HandleCapability caps)
+{
+ handle_caps[type] = caps;
+}
+
+gboolean mono_w32handle_test_capabilities (gpointer handle,
+ MonoW32HandleCapability caps)
+{
+ MonoW32HandleBase *handle_data;
+ MonoW32HandleType type;
+
+ if (!mono_w32handle_lookup_data (handle, &handle_data)) {
+ return(FALSE);
+ }
+
+ type = handle_data->type;
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: testing 0x%x against 0x%x (%d)", __func__,
+ handle_caps[type], caps, handle_caps[type] & caps);
+
+ return((handle_caps[type] & caps) != 0);
+}
+
+static void (*_wapi_handle_ops_get_close_func (MonoW32HandleType type))(gpointer, gpointer)
+{
+ if (handle_ops[type] != NULL &&
+ handle_ops[type]->close != NULL) {
+ return (handle_ops[type]->close);
+ }
+
+ return (NULL);
+}
+
+void mono_w32handle_ops_close (gpointer handle, gpointer data)
+{
+ MonoW32HandleBase *handle_data;
+ MonoW32HandleType type;
+
+ if (!mono_w32handle_lookup_data (handle, &handle_data)) {
+ return;
+ }
+
+ type = handle_data->type;
+
+ if (handle_ops[type] != NULL &&
+ handle_ops[type]->close != NULL) {
+ handle_ops[type]->close (handle, data);
+ }
+}
+
+void mono_w32handle_ops_details (MonoW32HandleType type, gpointer data)
+{
+ if (handle_ops[type] != NULL &&
+ handle_ops[type]->details != NULL) {
+ handle_ops[type]->details (data);
+ }
+}
+
+const gchar* mono_w32handle_ops_typename (MonoW32HandleType type)
+{
+ g_assert (handle_ops [type]);
+ g_assert (handle_ops [type]->typename);
+ return handle_ops [type]->typename ();
+}
+
+gsize mono_w32handle_ops_typesize (MonoW32HandleType type)
+{
+ g_assert (handle_ops [type]);
+ g_assert (handle_ops [type]->typesize);
+ return handle_ops [type]->typesize ();
+}
+
+void mono_w32handle_ops_signal (gpointer handle)
+{
+ MonoW32HandleBase *handle_data;
+ MonoW32HandleType type;
+
+ if (!mono_w32handle_lookup_data (handle, &handle_data)) {
+ return;
+ }
+
+ type = handle_data->type;
+
+ if (handle_ops[type] != NULL && handle_ops[type]->signal != NULL) {
+ handle_ops[type]->signal (handle);
+ }
+}
+
+gboolean mono_w32handle_ops_own (gpointer handle)
+{
+ MonoW32HandleBase *handle_data;
+ MonoW32HandleType type;
+
+ if (!mono_w32handle_lookup_data (handle, &handle_data)) {
+ return(FALSE);
+ }
+
+ type = handle_data->type;
+
+ if (handle_ops[type] != NULL && handle_ops[type]->own_handle != NULL) {
+ return(handle_ops[type]->own_handle (handle));
+ } else {
+ return(FALSE);
+ }
+}
+
+gboolean mono_w32handle_ops_isowned (gpointer handle)
+{
+ MonoW32HandleBase *handle_data;
+ MonoW32HandleType type;
+
+ if (!mono_w32handle_lookup_data (handle, &handle_data)) {
+ return(FALSE);
+ }
+
+ type = handle_data->type;
+
+ if (handle_ops[type] != NULL && handle_ops[type]->is_owned != NULL) {
+ return(handle_ops[type]->is_owned (handle));
+ } else {
+ return(FALSE);
+ }
+}
+
+guint32 mono_w32handle_ops_specialwait (gpointer handle, guint32 timeout, gboolean alertable)
+{
+ MonoW32HandleBase *handle_data;
+ MonoW32HandleType type;
+
+ if (!mono_w32handle_lookup_data (handle, &handle_data)) {
+ return(WAIT_FAILED);
+ }
+
+ type = handle_data->type;
+
+ if (handle_ops[type] != NULL &&
+ handle_ops[type]->special_wait != NULL) {
+ return(handle_ops[type]->special_wait (handle, timeout, alertable));
+ } else {
+ return(WAIT_FAILED);
+ }
+}
+
+void mono_w32handle_ops_prewait (gpointer handle)
+{
+ MonoW32HandleBase *handle_data;
+ MonoW32HandleType type;
+
+ if (!mono_w32handle_lookup_data (handle, &handle_data)) {
+ return;
+ }
+
+ type = handle_data->type;
+
+ if (handle_ops[type] != NULL &&
+ handle_ops[type]->prewait != NULL) {
+ handle_ops[type]->prewait (handle);
+ }
+}
+
+static void
+spin (guint32 ms)
+{
+ struct timespec sleepytime;
+
+ g_assert (ms < 1000);
+
+ sleepytime.tv_sec = 0;
+ sleepytime.tv_nsec = ms * 1000000;
+ nanosleep (&sleepytime, NULL);
+}
+
+gboolean
+mono_w32handle_count_signalled_handles (guint32 numhandles, gpointer *handles,
+ gboolean waitall, guint32 *retcount, guint32 *lowest)
+{
+ guint32 count, i, iter=0;
+ gboolean ret;
+ int thr_ret;
+
+ /* Lock all the handles, with backoff */
+again:
+ for(i=0; i<numhandles; i++) {
+ gpointer handle = handles[i];
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: attempting to lock %p", __func__, handle);
+
+ thr_ret = mono_w32handle_trylock_handle (handle);
+
+ if (thr_ret != 0) {
+ /* Bummer */
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: attempt failed for %p: %s", __func__,
+ handle, strerror (thr_ret));
+
+ while (i--) {
+ handle = handles[i];
+
+ thr_ret = mono_w32handle_unlock_handle (handle);
+ g_assert (thr_ret == 0);
+ }
+
+ /* If iter ever reaches 100 the nanosleep will
+ * return EINVAL immediately, but we have a
+ * design flaw if that happens.
+ */
+ iter++;
+ if(iter==100) {
+ g_warning ("%s: iteration overflow!",
+ __func__);
+ iter=1;
+ }
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: Backing off for %d ms", __func__,
+ iter*10);
+ spin (10 * iter);
+
+ goto again;
+ }
+ }
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: Locked all handles", __func__);
+
+ count=0;
+ *lowest=numhandles;
+
+ for(i=0; i<numhandles; i++) {
+ gpointer handle = handles[i];
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: Checking handle %p", __func__, handle);
+
+ if(((mono_w32handle_test_capabilities (handle, MONO_W32HANDLE_CAP_OWN)==TRUE) &&
+ (mono_w32handle_ops_isowned (handle) == TRUE)) ||
+ (mono_w32handle_issignalled (handle))) {
+ count++;
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: Handle %p signalled", __func__,
+ handle);
+ if(*lowest>i) {
+ *lowest=i;
+ }
+ }
+ }
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: %d event handles signalled", __func__, count);
+
+ if ((waitall == TRUE && count == numhandles) ||
+ (waitall == FALSE && count > 0)) {
+ ret=TRUE;
+ } else {
+ ret=FALSE;
+ }
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: Returning %d", __func__, ret);
+
+ *retcount=count;
+
+ return(ret);
+}
+
+void mono_w32handle_unlock_handles (guint32 numhandles, gpointer *handles)
+{
+ guint32 i;
+ int thr_ret;
+
+ for(i=0; i<numhandles; i++) {
+ gpointer handle = handles[i];
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: unlocking handle %p", __func__, handle);
+
+ thr_ret = mono_w32handle_unlock_handle (handle);
+ g_assert (thr_ret == 0);
+ }
+}
+
+static int
+mono_w32handle_timedwait_signal_naked (mono_cond_t *cond, mono_mutex_t *mutex, guint32 timeout, gboolean poll, gboolean *alerted)
+{
+ int res;
+
+ if (!poll) {
+ res = mono_os_cond_timedwait (cond, mutex, timeout);
+ } else {
+ /* This is needed when waiting for process handles */
+ if (!alerted) {
+ /*
+ * pthread_cond_(timed)wait() can return 0 even if the condition was not
+ * signalled. This happens at least on Darwin. We surface this, i.e., we
+ * get spurious wake-ups.
+ *
+ * http://pubs.opengroup.org/onlinepubs/007908775/xsh/pthread_cond_wait.html
+ */
+ res = mono_os_cond_timedwait (cond, mutex, timeout);
+ } else {
+ if (timeout < 100) {
+ /* Real timeout is less than 100ms time */
+ res = mono_os_cond_timedwait (cond, mutex, timeout);
+ } else {
+ res = mono_os_cond_timedwait (cond, mutex, 100);
+
+ /* Mask the fake timeout, this will cause
+ * another poll if the cond was not really signaled
+ */
+ if (res == ETIMEDOUT)
+ res = 0;
+ }
+ }
+ }
+
+ return res;
+}
+
+static void
+signal_global (gpointer unused)
+{
+ /* If we reach here, then interrupt token is set to the flag value, which
+ * means that the target thread is either
+ * - before the first CAS in timedwait, which means it won't enter the wait.
+ * - it is after the first CAS, so it is already waiting, or it will enter
+ * the wait, and it will be interrupted by the broadcast. */
+ mono_os_mutex_lock (&global_signal_mutex);
+ mono_os_cond_broadcast (&global_signal_cond);
+ mono_os_mutex_unlock (&global_signal_mutex);
+}
+
+int
+mono_w32handle_timedwait_signal (guint32 timeout, gboolean poll, gboolean *alerted)
+{
+ int res;
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: waiting for global", __func__);
+
+ if (alerted)
+ *alerted = FALSE;
+
+ if (alerted) {
+ mono_thread_info_install_interrupt (signal_global, NULL, alerted);
+ if (*alerted)
+ return 0;
+ }
+
+ res = mono_w32handle_timedwait_signal_naked (&global_signal_cond, &global_signal_mutex, timeout, poll, alerted);
+
+ if (alerted)
+ mono_thread_info_uninstall_interrupt (alerted);
+
+ return res;
+}
+
+static void
+signal_handle_and_unref (gpointer handle)
+{
+ MonoW32HandleBase *handle_data;
+ mono_cond_t *cond;
+ mono_mutex_t *mutex;
+
+ if (!mono_w32handle_lookup_data (handle, &handle_data))
+ g_error ("cannot signal unknown handle %p", handle);
+
+ /* If we reach here, then interrupt token is set to the flag value, which
+ * means that the target thread is either
+ * - before the first CAS in timedwait, which means it won't enter the wait.
+ * - it is after the first CAS, so it is already waiting, or it will enter
+ * the wait, and it will be interrupted by the broadcast. */
+ cond = &handle_data->signal_cond;
+ mutex = &handle_data->signal_mutex;
+
+ mono_os_mutex_lock (mutex);
+ mono_os_cond_broadcast (cond);
+ mono_os_mutex_unlock (mutex);
+
+ mono_w32handle_unref (handle);
+}
+
+int
+mono_w32handle_timedwait_signal_handle (gpointer handle, guint32 timeout, gboolean poll, gboolean *alerted)
+{
+ MonoW32HandleBase *handle_data;
+ int res;
+
+ if (!mono_w32handle_lookup_data (handle, &handle_data))
+ g_error ("cannot wait on unknown handle %p", handle);
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: waiting for %p (type %s)", __func__, handle,
+ mono_w32handle_ops_typename (mono_w32handle_get_type (handle)));
+
+ if (alerted)
+ *alerted = FALSE;
+
+ if (alerted) {
+ mono_thread_info_install_interrupt (signal_handle_and_unref, handle, alerted);
+ if (*alerted)
+ return 0;
+ mono_w32handle_ref (handle);
+ }
+
+ res = mono_w32handle_timedwait_signal_naked (&handle_data->signal_cond, &handle_data->signal_mutex, timeout, poll, alerted);
+
+ if (alerted) {
+ mono_thread_info_uninstall_interrupt (alerted);
+ if (!*alerted) {
+ /* if it is alerted, then the handle is unref in the interrupt callback */
+ mono_w32handle_unref (handle);
+ }
+ }
+
+ return res;
+}
+
+void mono_w32handle_dump (void)
+{
+ MonoW32HandleBase *handle_data;
+ guint32 i, k;
+ int thr_ret;
+
+ thr_ret = mono_os_mutex_lock (&scan_mutex);
+ g_assert (thr_ret == 0);
+
+ for(i = SLOT_INDEX (0); i < private_handles_slots_count; i++) {
+ if (private_handles [i]) {
+ for (k = SLOT_OFFSET (0); k < HANDLE_PER_SLOT; k++) {
+ handle_data = &private_handles [i][k];
+
+ if (handle_data->type == MONO_W32HANDLE_UNUSED) {
+ continue;
+ }
+
+ g_print ("%3x [%7s] %s %d ",
+ i * HANDLE_PER_SLOT + k,
+ mono_w32handle_ops_typename (handle_data->type),
+ handle_data->signalled?"Sg":"Un",
+ handle_data->ref);
+ mono_w32handle_ops_details (handle_data->type, handle_data->specific);
+ g_print ("\n");
+ }
+ }
+ }
+
+ thr_ret = mono_os_mutex_unlock (&scan_mutex);
+ g_assert (thr_ret == 0);
+}
+
+#endif /* !defined(HOST_WIN32) */
--- /dev/null
+
+#ifndef _MONO_UTILS_W32HANDLE_H_
+#define _MONO_UTILS_W32HANDLE_H_
+
+#include <config.h>
+
+#if !defined(HOST_WIN32)
+
+#include <glib.h>
+
+#define INVALID_HANDLE_VALUE (gpointer)-1
+
+typedef enum {
+ MONO_W32HANDLE_UNUSED = 0,
+ MONO_W32HANDLE_FILE,
+ MONO_W32HANDLE_CONSOLE,
+ MONO_W32HANDLE_THREAD,
+ MONO_W32HANDLE_SEM,
+ MONO_W32HANDLE_MUTEX,
+ MONO_W32HANDLE_EVENT,
+ MONO_W32HANDLE_SOCKET,
+ MONO_W32HANDLE_FIND,
+ MONO_W32HANDLE_PROCESS,
+ MONO_W32HANDLE_PIPE,
+ MONO_W32HANDLE_NAMEDMUTEX,
+ MONO_W32HANDLE_NAMEDSEM,
+ MONO_W32HANDLE_NAMEDEVENT,
+ MONO_W32HANDLE_COUNT
+} MonoW32HandleType;
+
+typedef struct
+{
+ void (*close)(gpointer handle, gpointer data);
+
+ /* SignalObjectAndWait */
+ void (*signal)(gpointer signal);
+
+ /* Called by WaitForSingleObject and WaitForMultipleObjects,
+ * with the handle locked (shared handles aren't locked.)
+ * Returns TRUE if ownership was established, false otherwise.
+ */
+ gboolean (*own_handle)(gpointer handle);
+
+ /* Called by WaitForSingleObject and WaitForMultipleObjects, if the
+ * handle in question is "ownable" (ie mutexes), to see if the current
+ * thread already owns this handle
+ */
+ gboolean (*is_owned)(gpointer handle);
+
+ /* Called by WaitForSingleObject and WaitForMultipleObjects,
+ * if the handle in question needs a special wait function
+ * instead of using the normal handle signal mechanism.
+ * Returns the WaitForSingleObject return code.
+ */
+ guint32 (*special_wait)(gpointer handle, guint32 timeout, gboolean alertable);
+
+ /* Called by WaitForSingleObject and WaitForMultipleObjects,
+ * if the handle in question needs some preprocessing before the
+ * signal wait.
+ */
+ void (*prewait)(gpointer handle);
+
+ /* Called when dumping the handles */
+ void (*details)(gpointer data);
+
+ /* Called to get the name of the handle type */
+ const gchar* (*typename) (void);
+
+ /* Called to get the size of the handle type */
+ gsize (*typesize) (void);
+} MonoW32HandleOps;
+
+typedef enum {
+ MONO_W32HANDLE_CAP_WAIT = 0x01,
+ MONO_W32HANDLE_CAP_SIGNAL = 0x02,
+ MONO_W32HANDLE_CAP_OWN = 0x04,
+ MONO_W32HANDLE_CAP_SPECIAL_WAIT = 0x08,
+} MonoW32HandleCapability;
+
+extern guint32 mono_w32handle_fd_reserve;
+
+void
+mono_w32handle_init (void);
+
+void
+mono_w32handle_cleanup (void);
+
+void
+mono_w32handle_register_ops (MonoW32HandleType type, MonoW32HandleOps *ops);
+
+gpointer
+mono_w32handle_new (MonoW32HandleType type, gpointer handle_specific);
+
+gpointer
+mono_w32handle_new_fd (MonoW32HandleType type, int fd, gpointer handle_specific);
+
+MonoW32HandleType
+mono_w32handle_get_type (gpointer handle);
+
+gboolean
+mono_w32handle_lookup (gpointer handle, MonoW32HandleType type, gpointer *handle_specific);
+
+gpointer
+mono_w32handle_search (MonoW32HandleType type, gboolean (*check)(gpointer, gpointer), gpointer user_data, gpointer *handle_specific, gboolean search_shared);
+
+void
+mono_w32handle_foreach (gboolean (*on_each)(gpointer handle, gpointer data, gpointer user_data), gpointer user_data);
+
+void
+mono_w32handle_dump (void);
+
+void
+mono_w32handle_ref (gpointer handle);
+
+void
+mono_w32handle_unref (gpointer handle);
+
+void
+mono_w32handle_register_capabilities (MonoW32HandleType type, MonoW32HandleCapability caps);
+
+gboolean
+mono_w32handle_test_capabilities (gpointer handle, MonoW32HandleCapability caps);
+
+void
+mono_w32handle_ops_close (gpointer handle, gpointer data);
+
+void
+mono_w32handle_ops_signal (gpointer handle);
+
+gboolean
+mono_w32handle_ops_own (gpointer handle);
+
+gboolean
+mono_w32handle_ops_isowned (gpointer handle);
+
+guint32
+mono_w32handle_ops_specialwait (gpointer handle, guint32 timeout, gboolean alertable);
+
+void
+mono_w32handle_ops_prewait (gpointer handle);
+
+void
+mono_w32handle_ops_details (MonoW32HandleType type, gpointer data);
+
+const gchar*
+mono_w32handle_ops_typename (MonoW32HandleType type);
+
+gsize
+mono_w32handle_ops_typesize (MonoW32HandleType type);
+
+gboolean
+mono_w32handle_count_signalled_handles (guint32 numhandles, gpointer *handles, gboolean waitall, guint32 *retcount, guint32 *lowest);
+
+void
+mono_w32handle_unlock_handles (guint32 numhandles, gpointer *handles);
+
+int
+mono_w32handle_timedwait_signal_handle (gpointer handle, guint32 timeout, gboolean poll, gboolean *alerted);
+
+int
+mono_w32handle_timedwait_signal (guint32 timeout, gboolean poll, gboolean *alerted);
+
+void
+mono_w32handle_set_signal_state (gpointer handle, gboolean state, gboolean broadcast);
+
+gboolean
+mono_w32handle_issignalled (gpointer handle);
+
+int
+mono_w32handle_lock_handle (gpointer handle);
+
+int
+mono_w32handle_trylock_handle (gpointer handle);
+
+int
+mono_w32handle_unlock_handle (gpointer handle);
+
+int
+mono_w32handle_lock_signal_mutex (void);
+
+int
+mono_w32handle_unlock_signal_mutex (void);
+
+#endif /* !defined(HOST_WIN32) */
+
+#endif /* _MONO_UTILS_W32HANDLE_H_ */