access.h \
context.h \
error.h \
- events.h \
io.h \
io-trace.h \
io-layer.h \
io-portability.h \
macros.h \
messages.h \
- mutexes.h \
processes.h \
security.h \
- semaphores.h \
sockets.h \
status.h \
timefuncs.h \
context.h \
error.c \
error.h \
- events.c \
- events.h \
- event-private.h \
io.c \
io.h \
io-portability.c \
macros.h \
messages.c \
messages.h \
- mutexes.c \
- mutexes.h \
- mutex-private.h \
posix.c \
processes.c \
processes.h \
process-private.h \
security.c \
security.h \
- semaphores.c \
- semaphores.h \
- semaphore-private.h \
- shared.c \
- shared.h \
sockets.c \
sockets.h \
socket-private.h \
+++ /dev/null
-/*
- * event-private.h: Private definitions for event handles
- *
- * Author:
- * Dick Porter (dick@ximian.com)
- *
- * (C) 2002 Ximian, Inc.
- */
-
-#ifndef _WAPI_EVENT_PRIVATE_H_
-#define _WAPI_EVENT_PRIVATE_H_
-
-#include <config.h>
-#include <glib.h>
-#include <pthread.h>
-
-#include "wapi-private.h"
-
-struct _WapiHandle_event
-{
- gboolean manual;
- guint32 set_count;
-};
-
-struct _WapiHandle_namedevent
-{
- struct _WapiHandle_event e;
- WapiSharedNamespace sharedns;
-};
-
-void
-_wapi_event_init (void);
-
-#endif /* _WAPI_EVENT_PRIVATE_H_ */
+++ /dev/null
-/*
- * events.c: Event handles
- *
- * Author:
- * Dick Porter (dick@ximian.com)
- *
- * (C) 2002 Ximian, Inc.
- */
-
-#include <config.h>
-#include <glib.h>
-#include <pthread.h>
-#include <string.h>
-
-#include <mono/io-layer/wapi.h>
-#include <mono/io-layer/wapi-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 void event_details (gpointer data);
-static const gchar* event_typename (void);
-static gsize event_typesize (void);
-
-static void namedevent_signal (gpointer handle);
-static gboolean namedevent_own (gpointer handle);
-static void namedevent_details (gpointer data);
-static const gchar* namedevent_typename (void);
-static gsize namedevent_typesize (void);
-
-static MonoW32HandleOps _wapi_event_ops = {
- NULL, /* close */
- event_signal, /* signal */
- event_own, /* own */
- NULL, /* is_owned */
- NULL, /* special_wait */
- NULL, /* prewait */
- event_details, /* details */
- event_typename, /* typename */
- event_typesize, /* typesize */
-};
-
-static MonoW32HandleOps _wapi_namedevent_ops = {
- NULL, /* close */
- namedevent_signal, /* signal */
- namedevent_own, /* own */
- NULL, /* is_owned */
- NULL, /* special_wait */
- NULL, /* prewait */
- namedevent_details, /* details */
- namedevent_typename, /* typename */
- namedevent_typesize, /* typesize */
-};
-
-void
-_wapi_event_init (void)
-{
- mono_w32handle_register_ops (MONO_W32HANDLE_EVENT, &_wapi_event_ops);
- mono_w32handle_register_ops (MONO_W32HANDLE_NAMEDEVENT, &_wapi_namedevent_ops);
-
- 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 (MonoW32HandleType type)
-{
- switch (type) {
- 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, MonoW32HandleType type)
-{
- struct _WapiHandle_event *event_handle;
- gboolean ok;
-
- 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);
- return FALSE;
- }
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: owning %s handle %p",
- __func__, event_handle_type_to_string (type), handle);
-
- if (!event_handle->manual) {
- g_assert (event_handle->set_count > 0);
- event_handle->set_count --;
-
- if (event_handle->set_count == 0)
- mono_w32handle_set_signal_state (handle, FALSE, FALSE);
- }
-
- return TRUE;
-}
-
-static void event_signal(gpointer handle)
-{
- SetEvent(handle);
-}
-
-static gboolean event_own (gpointer handle)
-{
- return event_handle_own (handle, MONO_W32HANDLE_EVENT);
-}
-
-static void namedevent_signal (gpointer handle)
-{
- SetEvent (handle);
-}
-
-/* NB, always called with the shared handle lock held */
-static gboolean namedevent_own (gpointer handle)
-{
- return event_handle_own (handle, MONO_W32HANDLE_NAMEDEVENT);
-}
-
-static void event_details (gpointer data)
-{
- struct _WapiHandle_event *event = (struct _WapiHandle_event *)data;
- g_print ("manual: %s, set_count: %d",
- event->manual ? "TRUE" : "FALSE", event->set_count);
-}
-
-static void namedevent_details (gpointer data)
-{
- struct _WapiHandle_namedevent *namedevent = (struct _WapiHandle_namedevent *)data;
- g_print ("manual: %s, set_count: %d, name: \"%s\"",
- namedevent->e.manual ? "TRUE" : "FALSE", namedevent->e.set_count, namedevent->sharedns.name);
-}
-
-static const gchar* event_typename (void)
-{
- return "Event";
-}
-
-static gsize event_typesize (void)
-{
- return sizeof (struct _WapiHandle_event);
-}
-
-static const gchar* namedevent_typename (void)
-{
- return "N.Event";
-}
-
-static gsize namedevent_typesize (void)
-{
- return sizeof (struct _WapiHandle_namedevent);
-}
-
-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 = 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));
- SetLastError (ERROR_GEN_FAILURE);
- return NULL;
- }
-
- thr_ret = mono_w32handle_lock_handle (handle);
- g_assert (thr_ret == 0);
-
- if (initial)
- mono_w32handle_set_signal_state (handle, TRUE, FALSE);
-
- 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",
- __func__, event_handle_type_to_string (type), handle);
-
- return handle;
-}
-
-static gpointer event_create (gboolean manual, gboolean initial)
-{
- 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 (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)
-{
- gpointer handle;
- gchar *utf8_name;
- int thr_ret;
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: creating %s handle",
- __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 ();
- g_assert (thr_ret == 0);
-
- utf8_name = g_utf16_to_utf8 (name, -1, NULL, NULL, NULL);
-
- 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_INVALID_HANDLE);
- } else if (handle) {
- /* Not an error, but this is how the caller is informed that the event wasn't freshly created */
- SetLastError (ERROR_ALREADY_EXISTS);
-
- /* this is used as creating a new 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, MONO_W32HANDLE_NAMEDEVENT, manual, initial);
- }
-
- g_free (utf8_name);
-
- thr_ret = _wapi_namespace_unlock (NULL);
- g_assert (thr_ret == 0);
-
- return handle;
-}
-
-
-/**
- * CreateEvent:
- * @security: Ignored for now.
- * @manual: Specifies whether the new event handle has manual or auto
- * reset behaviour.
- * @initial: Specifies whether the new event handle is initially
- * signalled or not.
- * @name:Pointer to a string specifying the name of this name, or
- * %NULL. Currently ignored.
- *
- * Creates a new event handle.
- *
- * An event handle is signalled with SetEvent(). If the new handle is
- * a manual reset event handle, it remains signalled until it is reset
- * with ResetEvent(). An auto reset event remains signalled until a
- * single thread has waited for it, at which time the event handle is
- * automatically reset to unsignalled.
- *
- * Return value: A new handle, or %NULL on error.
- */
-gpointer CreateEvent(WapiSecurityAttributes *security G_GNUC_UNUSED,
- gboolean manual, gboolean initial,
- const gunichar2 *name G_GNUC_UNUSED)
-{
- /* Need to blow away any old errors here, because code tests
- * for ERROR_ALREADY_EXISTS on success (!) to see if an event
- * was freshly created
- */
- SetLastError (ERROR_SUCCESS);
-
- return name ? namedevent_create (manual, initial, name) : event_create (manual, initial);
-}
-
-/**
- * PulseEvent:
- * @handle: The event handle.
- *
- * Sets the event handle @handle to the signalled state, and then
- * resets it to unsignalled after informing any waiting threads.
- *
- * If @handle is a manual reset event, all waiting threads that can be
- * released immediately are released. @handle is then reset. If
- * @handle is an auto reset event, one waiting thread is released even
- * if multiple threads are waiting.
- *
- * Return value: %TRUE on success, %FALSE otherwise. (Currently only
- * ever returns %TRUE).
- */
-gboolean PulseEvent(gpointer handle)
-{
- MonoW32HandleType type;
- struct _WapiHandle_event *event_handle;
- int thr_ret;
-
- if (handle == NULL) {
- SetLastError (ERROR_INVALID_HANDLE);
- return(FALSE);
- }
-
- switch (type = mono_w32handle_get_type (handle)) {
- case MONO_W32HANDLE_EVENT:
- case MONO_W32HANDLE_NAMEDEVENT:
- break;
- default:
- SetLastError (ERROR_INVALID_HANDLE);
- return FALSE;
- }
-
- 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 = mono_w32handle_lock_handle (handle);
- g_assert (thr_ret == 0);
-
- if (!event_handle->manual) {
- event_handle->set_count = 1;
- mono_w32handle_set_signal_state (handle, TRUE, FALSE);
- } else {
- mono_w32handle_set_signal_state (handle, TRUE, TRUE);
-
- 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
- * lock again, so give other threads a chance */
- sched_yield ();
-
- /* Reset the handle signal state */
-
- /* I'm not sure whether or not we need a barrier here to make sure
- * that all threads waiting on the event have proceeded. Currently
- * we rely on broadcasting a condition. */
-
- thr_ret = mono_w32handle_lock_handle (handle);
- g_assert (thr_ret == 0);
-
- mono_w32handle_set_signal_state (handle, FALSE, FALSE);
- }
-
- thr_ret = mono_w32handle_unlock_handle (handle);
- g_assert (thr_ret == 0);
-
- return TRUE;
-}
-
-/**
- * ResetEvent:
- * @handle: The event handle.
- *
- * Resets the event handle @handle to the unsignalled state.
- *
- * Return value: %TRUE on success, %FALSE otherwise. (Currently only
- * ever returns %TRUE).
- */
-gboolean ResetEvent(gpointer handle)
-{
- MonoW32HandleType type;
- struct _WapiHandle_event *event_handle;
- int thr_ret;
-
- SetLastError (ERROR_SUCCESS);
-
- if (handle == NULL) {
- SetLastError (ERROR_INVALID_HANDLE);
- return(FALSE);
- }
-
- switch (type = mono_w32handle_get_type (handle)) {
- case MONO_W32HANDLE_EVENT:
- case MONO_W32HANDLE_NAMEDEVENT:
- break;
- default:
- SetLastError (ERROR_INVALID_HANDLE);
- return FALSE;
- }
-
- 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 = mono_w32handle_lock_handle (handle);
- g_assert (thr_ret == 0);
-
- 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);
-
- mono_w32handle_set_signal_state (handle, FALSE, FALSE);
- }
-
- event_handle->set_count = 0;
-
- thr_ret = mono_w32handle_unlock_handle (handle);
- g_assert (thr_ret == 0);
-
- return TRUE;
-}
-
-/**
- * SetEvent:
- * @handle: The event handle
- *
- * Sets the event handle @handle to the signalled state.
- *
- * If @handle is a manual reset event, it remains signalled until it
- * is reset with ResetEvent(). An auto reset event remains signalled
- * until a single thread has waited for it, at which time @handle is
- * automatically reset to unsignalled.
- *
- * Return value: %TRUE on success, %FALSE otherwise. (Currently only
- * ever returns %TRUE).
- */
-gboolean SetEvent(gpointer handle)
-{
- MonoW32HandleType type;
- struct _WapiHandle_event *event_handle;
- int thr_ret;
-
- if (handle == NULL) {
- SetLastError (ERROR_INVALID_HANDLE);
- return(FALSE);
- }
-
- switch (type = mono_w32handle_get_type (handle)) {
- case MONO_W32HANDLE_EVENT:
- case MONO_W32HANDLE_NAMEDEVENT:
- break;
- default:
- SetLastError (ERROR_INVALID_HANDLE);
- return FALSE;
- }
-
- 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 = mono_w32handle_lock_handle (handle);
- g_assert (thr_ret == 0);
-
- if (!event_handle->manual) {
- event_handle->set_count = 1;
- mono_w32handle_set_signal_state (handle, TRUE, FALSE);
- } else {
- mono_w32handle_set_signal_state (handle, TRUE, TRUE);
- }
-
- thr_ret = mono_w32handle_unlock_handle (handle);
- g_assert (thr_ret == 0);
-
- return TRUE;
-}
-
-gpointer OpenEvent (guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED, const gunichar2 *name)
-{
- gpointer handle;
- gchar *utf8_name;
- int thr_ret;
-
- /* w32 seems to guarantee that opening named objects can't
- * race each other
- */
- thr_ret = _wapi_namespace_lock ();
- g_assert (thr_ret == 0);
-
- utf8_name = g_utf16_to_utf8 (name, -1, NULL, NULL, NULL);
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Opening named event [%s]", __func__, 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.
- */
- SetLastError (ERROR_INVALID_HANDLE);
- goto cleanup;
- } else if (!handle) {
- /* This name doesn't exist */
- SetLastError (ERROR_FILE_NOT_FOUND); /* yes, really */
- goto cleanup;
- }
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning named event handle %p", __func__, handle);
-
-cleanup:
- g_free (utf8_name);
-
- _wapi_namespace_unlock (NULL);
-
- return handle;
-
-}
+++ /dev/null
-/*
- * events.h: Event handles
- *
- * Author:
- * Dick Porter (dick@ximian.com)
- *
- * (C) 2002 Ximian, Inc.
- */
-
-#ifndef _WAPI_EVENTS_H_
-#define _WAPI_EVENTS_H_
-
-#include <glib.h>
-
-G_BEGIN_DECLS
-
-extern gpointer CreateEvent (WapiSecurityAttributes *security, gboolean manual,
- gboolean initial, const gunichar2 *name);
-extern gboolean PulseEvent (gpointer handle);
-extern gboolean ResetEvent (gpointer handle);
-extern gboolean SetEvent (gpointer handle);
-extern gpointer OpenEvent (guint32 access, gboolean inherit,
- const gunichar2 *name);
-
-G_END_DECLS
-
-#endif /* _WAPI_EVENTS_H_ */
* 4MB array.
*/
static GHashTable *file_share_hash;
-static mono_mutex_t file_share_hash_mutex;
-
-#define file_share_hash_lock() mono_os_mutex_lock (&file_share_hash_mutex)
-#define file_share_hash_unlock() mono_os_mutex_unlock (&file_share_hash_mutex)
+static mono_mutex_t file_share_mutex;
static void
_wapi_handle_share_release (_WapiFileShare *share_info)
{
- int thr_ret;
+ /* Prevent new entries racing with us */
+ mono_os_mutex_lock (&file_share_mutex);
g_assert (share_info->handle_refs > 0);
-
- /* Prevent new entries racing with us */
- thr_ret = _wapi_shm_sem_lock (_WAPI_SHARED_SEM_FILESHARE);
- g_assert(thr_ret == 0);
+ share_info->handle_refs -= 1;
- if (InterlockedDecrement ((gint32 *)&share_info->handle_refs) == 0) {
- file_share_hash_lock ();
+ if (share_info->handle_refs == 0)
g_hash_table_remove (file_share_hash, share_info);
- file_share_hash_unlock ();
- }
- thr_ret = _wapi_shm_sem_unlock (_WAPI_SHARED_SEM_FILESHARE);
- g_assert (thr_ret == 0);
+ mono_os_mutex_unlock (&file_share_mutex);
}
static gint
guint32 *old_sharemode, guint32 *old_access, struct _WapiFileShare **share_info)
{
struct _WapiFileShare *file_share;
- int thr_ret;
gboolean exists = FALSE;
/* Prevent new entries racing with us */
- thr_ret = _wapi_shm_sem_lock (_WAPI_SHARED_SEM_FILESHARE);
- g_assert (thr_ret == 0);
+ mono_os_mutex_lock (&file_share_mutex);
_WapiFileShare tmp;
* info. This is needed even if SHM is disabled, to track sharing inside
* the current process.
*/
- if (!file_share_hash) {
+ if (!file_share_hash)
file_share_hash = g_hash_table_new_full (wapi_share_info_hash, wapi_share_info_equal, NULL, g_free);
- mono_os_mutex_init_recursive (&file_share_hash_mutex);
- }
tmp.device = device;
tmp.inode = inode;
- file_share_hash_lock ();
-
file_share = (_WapiFileShare *)g_hash_table_lookup (file_share_hash, &tmp);
if (file_share) {
*old_sharemode = file_share->sharemode;
*old_access = file_share->access;
*share_info = file_share;
- InterlockedIncrement ((gint32 *)&file_share->handle_refs);
+ g_assert (file_share->handle_refs > 0);
+ file_share->handle_refs += 1;
+
exists = TRUE;
} else {
file_share = g_new0 (_WapiFileShare, 1);
g_hash_table_insert (file_share_hash, file_share, file_share);
}
- file_share_hash_unlock ();
-
- thr_ret = _wapi_shm_sem_unlock (_WAPI_SHARED_SEM_FILESHARE);
- g_assert (thr_ret == 0);
+ mono_os_mutex_unlock (&file_share_mutex);
return(exists);
}
_wapi_io_init (void)
{
mono_os_mutex_init (&stdhandle_mutex);
+ mono_os_mutex_init (&file_share_mutex);
mono_w32handle_register_ops (MONO_W32HANDLE_FILE, &_wapi_file_ops);
mono_w32handle_register_ops (MONO_W32HANDLE_CONSOLE, &_wapi_console_ops);
void
_wapi_io_cleanup (void)
{
- if (file_share_hash) {
+ mono_os_mutex_destroy (&file_share_mutex);
+
+ if (file_share_hash)
g_hash_table_destroy (file_share_hash);
- mono_os_mutex_destroy (&file_share_hash_mutex);
- }
}
+++ /dev/null
-/*
- * mutex-private.h: Private definitions for mutex handles
- *
- * Author:
- * Dick Porter (dick@ximian.com)
- *
- * (C) 2002 Ximian, Inc.
- */
-
-#ifndef _WAPI_MUTEX_PRIVATE_H_
-#define _WAPI_MUTEX_PRIVATE_H_
-
-#include <config.h>
-#include <glib.h>
-#include <pthread.h>
-#include <sys/types.h>
-
-#include "wapi-private.h"
-
-struct _WapiHandle_mutex
-{
- pthread_t tid;
- guint32 recursion;
-};
-
-struct _WapiHandle_namedmutex
-{
- struct _WapiHandle_mutex m;
- WapiSharedNamespace sharedns;
-};
-
-void
-_wapi_mutex_init (void);
-
-#endif /* _WAPI_MUTEX_PRIVATE_H_ */
+++ /dev/null
-/*
- * mutexes.c: Mutex handles
- *
- * Author:
- * Dick Porter (dick@ximian.com)
- *
- * (C) 2002-2006 Ximian, Inc.
- */
-
-#include <config.h>
-#include <glib.h>
-#include <pthread.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <mono/io-layer/wapi.h>
-#include <mono/io-layer/wapi-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 gboolean mutex_is_owned (gpointer handle);
-static void mutex_prewait (gpointer handle);
-static void mutex_details (gpointer data);
-static const gchar* mutex_typename (void);
-static gsize mutex_typesize (void);
-
-static void namedmutex_signal (gpointer handle);
-static gboolean namedmutex_own (gpointer handle);
-static gboolean namedmutex_is_owned (gpointer handle);
-static void namedmutex_prewait (gpointer handle);
-static void namedmutex_details (gpointer data);
-static const gchar* namedmutex_typename (void);
-static gsize namedmutex_typesize (void);
-
-static MonoW32HandleOps _wapi_mutex_ops = {
- NULL, /* close */
- mutex_signal, /* signal */
- mutex_own, /* own */
- mutex_is_owned, /* is_owned */
- NULL, /* special_wait */
- mutex_prewait, /* prewait */
- mutex_details, /* details */
- mutex_typename, /* typename */
- mutex_typesize, /* typesize */
-};
-
-static MonoW32HandleOps _wapi_namedmutex_ops = {
- NULL, /* close */
- namedmutex_signal, /* signal */
- namedmutex_own, /* own */
- namedmutex_is_owned, /* is_owned */
- NULL, /* special_wait */
- namedmutex_prewait, /* prewait */
- namedmutex_details, /* details */
- namedmutex_typename, /* typename */
- namedmutex_typesize, /* typesize */
-};
-
-void
-_wapi_mutex_init (void)
-{
- mono_w32handle_register_ops (MONO_W32HANDLE_MUTEX, &_wapi_mutex_ops);
- mono_w32handle_register_ops (MONO_W32HANDLE_NAMEDMUTEX, &_wapi_namedmutex_ops);
-
- 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 (MonoW32HandleType type)
-{
- switch (type) {
- 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, MonoW32HandleType type)
-{
- struct _WapiHandle_mutex *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: owning %s handle %p, tid %p, recursion %u",
- __func__, mutex_handle_type_to_string (type), handle, (gpointer) mutex_handle->tid, mutex_handle->recursion);
-
- mono_thread_info_own_mutex (mono_thread_info_current (), handle);
-
- mutex_handle->tid = pthread_self ();
- mutex_handle->recursion++;
-
- mono_w32handle_set_signal_state (handle, FALSE, FALSE);
-
- return TRUE;
-}
-
-static gboolean
-mutex_handle_is_owned (gpointer handle, MonoW32HandleType type)
-{
- struct _WapiHandle_mutex *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: testing ownership %s handle %p",
- __func__, mutex_handle_type_to_string (type), handle);
-
- if (mutex_handle->recursion > 0 && pthread_equal (mutex_handle->tid, pthread_self ())) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: %s handle %p owned by %p",
- __func__, mutex_handle_type_to_string (type), handle, (gpointer) pthread_self ());
- return TRUE;
- } else {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: %s handle %p not owned by %p, but locked %d times by %p",
- __func__, mutex_handle_type_to_string (type), handle, (gpointer) pthread_self (), mutex_handle->recursion, (gpointer) mutex_handle->tid);
- return FALSE;
- }
-}
-
-static void mutex_signal(gpointer handle)
-{
- ReleaseMutex(handle);
-}
-
-static gboolean mutex_own (gpointer handle)
-{
- return mutex_handle_own (handle, MONO_W32HANDLE_MUTEX);
-}
-
-static gboolean mutex_is_owned (gpointer handle)
-{
-
- return mutex_handle_is_owned (handle, MONO_W32HANDLE_MUTEX);
-}
-
-static void namedmutex_signal (gpointer handle)
-{
- ReleaseMutex(handle);
-}
-
-/* NB, always called with the shared handle lock held */
-static gboolean namedmutex_own (gpointer handle)
-{
- return mutex_handle_own (handle, MONO_W32HANDLE_NAMEDMUTEX);
-}
-
-static gboolean namedmutex_is_owned (gpointer handle)
-{
- return mutex_handle_is_owned (handle, MONO_W32HANDLE_NAMEDMUTEX);
-}
-
-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
- * is still alive; if it isn't we override the previous owner
- * and assume that process exited abnormally and failed to
- * clean up.
- */
- struct _WapiHandle_mutex *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: pre-waiting %s handle %p, owned? %s",
- __func__, mutex_handle_type_to_string (type), handle, mutex_handle->recursion != 0 ? "true" : "false");
-}
-
-/* The shared state is not locked when prewait methods are called */
-static void mutex_prewait (gpointer handle)
-{
- 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, MONO_W32HANDLE_NAMEDMUTEX);
-}
-
-static void mutex_details (gpointer data)
-{
- struct _WapiHandle_mutex *mut = (struct _WapiHandle_mutex *)data;
-
-#ifdef PTHREAD_POINTER_ID
- g_print ("own: %5p, count: %5u", mut->tid, mut->recursion);
-#else
- g_print ("own: %5ld, count: %5u", mut->tid, mut->recursion);
-#endif
-}
-
-static void namedmutex_details (gpointer data)
-{
- struct _WapiHandle_namedmutex *namedmut = (struct _WapiHandle_namedmutex *)data;
-
-#ifdef PTHREAD_POINTER_ID
- g_print ("own: %5p, count: %5u, name: \"%s\"",
- namedmut->m.tid, namedmut->m.recursion, namedmut->sharedns.name);
-#else
- g_print ("own: %5ld, count: %5u, name: \"%s\"",
- namedmut->m.tid, namedmut->m.recursion, namedmut->sharedns.name);
-#endif
-}
-
-static const gchar* mutex_typename (void)
-{
- return "Mutex";
-}
-
-static gsize mutex_typesize (void)
-{
- return sizeof (struct _WapiHandle_mutex);
-}
-
-static const gchar* namedmutex_typename (void)
-{
- return "N.Mutex";
-}
-
-static gsize namedmutex_typesize (void)
-{
- return sizeof (struct _WapiHandle_namedmutex);
-}
-
-/* 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)
-{
- MonoW32HandleType type;
- struct _WapiHandle_mutex *mutex_handle;
- int thr_ret;
-
- switch (type = mono_w32handle_get_type (handle)) {
- case MONO_W32HANDLE_MUTEX:
- case MONO_W32HANDLE_NAMEDMUTEX:
- break;
- default:
- g_assert_not_reached ();
- }
-
- 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 = 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;
-
- 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 = mono_w32handle_unlock_handle (handle);
- g_assert (thr_ret == 0);
-}
-
-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 = 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));
- SetLastError (ERROR_GEN_FAILURE);
- return NULL;
- }
-
- thr_ret = mono_w32handle_lock_handle (handle);
- g_assert (thr_ret == 0);
-
- if (owned)
- mutex_handle_own (handle, type);
- else
- mono_w32handle_set_signal_state (handle, TRUE, FALSE);
-
- 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",
- __func__, mutex_handle_type_to_string (type), handle);
-
- return handle;
-}
-
-static gpointer mutex_create (gboolean owned)
-{
- 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 (MONO_W32HANDLE_MUTEX));
- return mutex_handle_create (&mutex_handle, MONO_W32HANDLE_MUTEX, owned);
-}
-
-static gpointer namedmutex_create (gboolean owned, const gunichar2 *name)
-{
- gpointer handle;
- gchar *utf8_name;
- int thr_ret;
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: creating %s handle",
- __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 ();
- g_assert (thr_ret == 0);
-
- utf8_name = g_utf16_to_utf8 (name, -1, NULL, NULL, NULL);
-
- 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_INVALID_HANDLE);
- } else if (handle) {
- /* Not an error, but this is how the caller is informed that the mutex wasn't freshly created */
- SetLastError (ERROR_ALREADY_EXISTS);
-
- /* this is used as creating a new 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, MONO_W32HANDLE_NAMEDMUTEX, owned);
- }
-
- g_free (utf8_name);
-
- thr_ret = _wapi_namespace_unlock (NULL);
- g_assert (thr_ret == 0);
-
- return handle;
-}
-
-/**
- * CreateMutex:
- * @security: Ignored for now.
- * @owned: If %TRUE, the mutex is created with the calling thread
- * already owning the mutex.
- * @name:Pointer to a string specifying the name of this mutex, or
- * %NULL.
- *
- * Creates a new mutex handle. A mutex is signalled when no thread
- * owns it. A thread acquires ownership of the mutex by waiting for
- * it with WaitForSingleObject() or WaitForMultipleObjects(). A
- * thread relinquishes ownership with ReleaseMutex().
- *
- * A thread that owns a mutex can specify the same mutex in repeated
- * wait function calls without blocking. The thread must call
- * ReleaseMutex() an equal number of times to release the mutex.
- *
- * Return value: A new handle, or %NULL on error.
- */
-gpointer CreateMutex(WapiSecurityAttributes *security G_GNUC_UNUSED, gboolean owned, const gunichar2 *name)
-{
- /* Need to blow away any old errors here, because code tests
- * for ERROR_ALREADY_EXISTS on success (!) to see if a mutex
- * was freshly created */
- SetLastError (ERROR_SUCCESS);
-
- return name ? namedmutex_create (owned, name) : mutex_create (owned);
-}
-
-/**
- * ReleaseMutex:
- * @handle: The mutex handle.
- *
- * Releases ownership if the mutex handle @handle.
- *
- * Return value: %TRUE on success, %FALSE otherwise. This function
- * fails if the calling thread does not own the mutex @handle.
- */
-gboolean ReleaseMutex(gpointer handle)
-{
- MonoW32HandleType type;
- struct _WapiHandle_mutex *mutex_handle;
- pthread_t tid;
- int thr_ret;
- gboolean ret;
-
- if (handle == NULL) {
- SetLastError (ERROR_INVALID_HANDLE);
- return FALSE;
- }
-
- switch (type = mono_w32handle_get_type (handle)) {
- case MONO_W32HANDLE_MUTEX:
- case MONO_W32HANDLE_NAMEDMUTEX:
- break;
- default:
- SetLastError (ERROR_INVALID_HANDLE);
- return FALSE;
- }
-
- 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 = mono_w32handle_lock_handle (handle);
- g_assert (thr_ret == 0);
-
- tid = pthread_self ();
-
- if (!pthread_equal (mutex_handle->tid, tid)) {
- ret = FALSE;
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: we don't own %s handle %p (owned by %ld, me %ld)",
- __func__, mutex_handle_type_to_string (type), handle, mutex_handle->tid, tid);
- } else {
- ret = TRUE;
-
- /* OK, we own this mutex */
- mutex_handle->recursion--;
-
- if (mutex_handle->recursion == 0) {
- mono_thread_info_disown_mutex (mono_thread_info_current (), handle);
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unlocking %s handle %p",
- __func__, mutex_handle_type_to_string (type), handle);
-
- mutex_handle->tid = 0;
- mono_w32handle_set_signal_state (handle, TRUE, FALSE);
- }
- }
-
- thr_ret = mono_w32handle_unlock_handle (handle);
- g_assert (thr_ret == 0);
-
- return ret;
-}
-
-gpointer OpenMutex (guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED, const gunichar2 *name)
-{
- gpointer handle;
- gchar *utf8_name;
- int thr_ret;
-
- /* w32 seems to guarantee that opening named objects can't
- * race each other
- */
- thr_ret = _wapi_namespace_lock ();
- g_assert (thr_ret == 0);
-
- utf8_name = g_utf16_to_utf8 (name, -1, NULL, NULL, NULL);
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Opening named mutex [%s]", __func__, 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.
- */
- SetLastError (ERROR_INVALID_HANDLE);
- goto cleanup;
- } else if (!handle) {
- /* This name doesn't exist */
- SetLastError (ERROR_FILE_NOT_FOUND); /* yes, really */
- goto cleanup;
- }
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning named mutex handle %p", __func__, handle);
-
-cleanup:
- g_free (utf8_name);
-
- _wapi_namespace_unlock (NULL);
-
- return handle;
-}
+++ /dev/null
-/*
- * mutexes.h: Mutex handles
- *
- * Author:
- * Dick Porter (dick@ximian.com)
- *
- * (C) 2002 Ximian, Inc.
- */
-
-#ifndef _WAPI_MUTEXES_H_
-#define _WAPI_MUTEXES_H_
-
-#include <glib.h>
-
-#include <pthread.h>
-
-G_BEGIN_DECLS
-
-extern gpointer CreateMutex (WapiSecurityAttributes *security, gboolean owned,
- const gunichar2 *name);
-extern gboolean ReleaseMutex (gpointer handle);
-extern gpointer OpenMutex (guint32 access, gboolean inherit,
- const gunichar2 *name);
-
-void
-wapi_mutex_abandon (gpointer data, pid_t pid, pthread_t tid);
-
-G_END_DECLS
-
-#endif /* _WAPI_MUTEXES_H_ */
+++ /dev/null
-/*
- * semaphore-private.h: Private definitions for semaphore handles
- *
- * Author:
- * Dick Porter (dick@ximian.com)
- *
- * (C) 2002 Ximian, Inc.
- */
-
-#ifndef _WAPI_SEMAPHORE_PRIVATE_H_
-#define _WAPI_SEMAPHORE_PRIVATE_H_
-
-#include <config.h>
-#include <glib.h>
-
-#include "wapi-private.h"
-
-/* emulate sem_t, so that we can prod the internal state more easily */
-struct _WapiHandle_sem
-{
- guint32 val;
- gint32 max;
-};
-
-struct _WapiHandle_namedsem
-{
- struct _WapiHandle_sem s;
- WapiSharedNamespace sharedns;
-};
-
-void
-_wapi_semaphore_init (void);
-
-#endif /* _WAPI_SEMAPHORE_PRIVATE_H_ */
+++ /dev/null
-/*
- * semaphores.c: Semaphore handles
- *
- * Author:
- * Dick Porter (dick@ximian.com)
- *
- * (C) 2002 Ximian, Inc.
- */
-
-#include <config.h>
-#include <glib.h>
-#include <pthread.h>
-#ifdef HAVE_SEMAPHORE_H
-#include <semaphore.h>
-#endif
-#include <errno.h>
-#include <string.h>
-#include <sys/time.h>
-
-#include <mono/io-layer/wapi.h>
-#include <mono/io-layer/wapi-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 void sema_details (gpointer data);
-static const gchar* sema_typename (void);
-static gsize sema_typesize (void);
-
-static void namedsema_signal (gpointer handle);
-static gboolean namedsema_own (gpointer handle);
-static void namedsema_details (gpointer data);
-static const gchar* namedsema_typename (void);
-static gsize namedsema_typesize (void);
-
-static MonoW32HandleOps _wapi_sem_ops = {
- NULL, /* close */
- sema_signal, /* signal */
- sema_own, /* own */
- NULL, /* is_owned */
- NULL, /* special_wait */
- NULL, /* prewait */
- sema_details, /* details */
- sema_typename, /* typename */
- sema_typesize, /* typesize */
-};
-
-static MonoW32HandleOps _wapi_namedsem_ops = {
- NULL, /* close */
- namedsema_signal, /* signal */
- namedsema_own, /* own */
- NULL, /* is_owned */
- NULL, /* special_wait */
- NULL, /* prewait */
- namedsema_details, /* details */
- namedsema_typename, /* typename */
- namedsema_typesize, /* typesize */
-};
-
-void
-_wapi_semaphore_init (void)
-{
- mono_w32handle_register_ops (MONO_W32HANDLE_SEM, &_wapi_sem_ops);
- mono_w32handle_register_ops (MONO_W32HANDLE_NAMEDSEM, &_wapi_namedsem_ops);
-
- 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 (MonoW32HandleType type)
-{
- switch (type) {
- 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, MonoW32HandleType type)
-{
- struct _WapiHandle_sem *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;
- }
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: owning %s handle %p",
- __func__, sem_handle_type_to_string (type), handle);
-
- sem_handle->val--;
-
- if (sem_handle->val == 0)
- mono_w32handle_set_signal_state (handle, FALSE, FALSE);
-
- return TRUE;
-}
-
-static void sema_signal(gpointer handle)
-{
- ReleaseSemaphore(handle, 1, NULL);
-}
-
-static gboolean sema_own (gpointer handle)
-{
- return sem_handle_own (handle, MONO_W32HANDLE_SEM);
-}
-
-static void namedsema_signal (gpointer handle)
-{
- ReleaseSemaphore (handle, 1, NULL);
-}
-
-/* NB, always called with the shared handle lock held */
-static gboolean namedsema_own (gpointer handle)
-{
- return sem_handle_own (handle, MONO_W32HANDLE_NAMEDSEM);
-}
-
-static void sema_details (gpointer data)
-{
- struct _WapiHandle_sem *sem = (struct _WapiHandle_sem *)data;
- g_print ("val: %5u, max: %5d", sem->val, sem->max);
-}
-
-static void namedsema_details (gpointer data)
-{
- struct _WapiHandle_namedsem *namedsem = (struct _WapiHandle_namedsem *)data;
- g_print ("val: %5u, max: %5d, name: \"%s\"", namedsem->s.val, namedsem->s.max, namedsem->sharedns.name);
-}
-
-static const gchar* sema_typename (void)
-{
- return "Semaphore";
-}
-
-static gsize sema_typesize (void)
-{
- return sizeof (struct _WapiHandle_sem);
-}
-
-static const gchar* namedsema_typename (void)
-{
- return "N.Semaphore";
-}
-
-static gsize namedsema_typesize (void)
-{
- return sizeof (struct _WapiHandle_namedsem);
-}
-
-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 = 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));
- SetLastError (ERROR_GEN_FAILURE);
- return NULL;
- }
-
- thr_ret = mono_w32handle_lock_handle (handle);
- g_assert (thr_ret == 0);
-
- if (initial != 0)
- mono_w32handle_set_signal_state (handle, TRUE, FALSE);
-
- 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",
- __func__, sem_handle_type_to_string (type), handle);
-
- return handle;
-}
-
-static gpointer sem_create (gint32 initial, gint32 max)
-{
- 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 (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)
-{
- gpointer handle;
- gchar *utf8_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 (MONO_W32HANDLE_NAMEDSEM), initial, max, name);
-
- /* w32 seems to guarantee that opening named objects can't race each other */
- thr_ret = _wapi_namespace_lock ();
- g_assert (thr_ret == 0);
-
- utf8_name = g_utf16_to_utf8 (name, -1, NULL, NULL, NULL);
-
- 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 (MONO_W32HANDLE_NAMEDSEM, utf8_name);
- if (handle == INVALID_HANDLE_VALUE) {
- /* The name has already been used for a different object. */
- handle = NULL;
- SetLastError (ERROR_INVALID_HANDLE);
- } else if (handle) {
- /* Not an error, but this is how the caller is informed that the semaphore wasn't freshly created */
- SetLastError (ERROR_ALREADY_EXISTS);
-
- /* this is used as creating a new 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, MONO_W32HANDLE_NAMEDSEM, initial, max);
- }
-
- g_free (utf8_name);
-
- thr_ret = _wapi_namespace_unlock (NULL);
- g_assert (thr_ret == 0);
-
- return handle;
-}
-
-
-/**
- * CreateSemaphore:
- * @security: Ignored for now.
- * @initial: The initial count for the semaphore. The value must be
- * greater than or equal to zero, and less than or equal to @max.
- * @max: The maximum count for this semaphore. The value must be
- * greater than zero.
- * @name: Pointer to a string specifying the name of this semaphore,
- * or %NULL. Currently ignored.
- *
- * Creates a new semaphore handle. A semaphore is signalled when its
- * count is greater than zero, and unsignalled otherwise. The count
- * is decreased by one whenever a wait function releases a thread that
- * was waiting for the semaphore. The count is increased by calling
- * ReleaseSemaphore().
- *
- * Return value: a new handle, or NULL
- */
-gpointer CreateSemaphore(WapiSecurityAttributes *security G_GNUC_UNUSED, gint32 initial, gint32 max, const gunichar2 *name)
-{
- if (max <= 0) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: max <= 0", __func__);
-
- SetLastError (ERROR_INVALID_PARAMETER);
- return(NULL);
- }
-
- if (initial > max || initial < 0) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: initial>max or < 0", __func__);
-
- SetLastError (ERROR_INVALID_PARAMETER);
- return(NULL);
- }
-
- /* Need to blow away any old errors here, because code tests
- * for ERROR_ALREADY_EXISTS on success (!) to see if a
- * semaphore was freshly created
- */
- SetLastError (ERROR_SUCCESS);
-
- return name ? namedsem_create (initial, max, name) : sem_create (initial, max);
-}
-
-/**
- * ReleaseSemaphore:
- * @handle: The semaphore handle to release.
- * @count: The amount by which the semaphore's count should be
- * increased.
- * @prevcount: Pointer to a location to store the previous count of
- * the semaphore, or %NULL.
- *
- * Increases the count of semaphore @handle by @count.
- *
- * Return value: %TRUE on success, %FALSE otherwise.
- */
-gboolean ReleaseSemaphore(gpointer handle, gint32 count, gint32 *prevcount)
-{
- MonoW32HandleType type;
- struct _WapiHandle_sem *sem_handle;
- int thr_ret;
- gboolean ret;
-
- if (!handle) {
- SetLastError (ERROR_INVALID_HANDLE);
- return FALSE;
- }
-
- switch (type = mono_w32handle_get_type (handle)) {
- case MONO_W32HANDLE_SEM:
- case MONO_W32HANDLE_NAMEDSEM:
- break;
- default:
- SetLastError (ERROR_INVALID_HANDLE);
- return FALSE;
- }
-
- 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 = mono_w32handle_lock_handle (handle);
- g_assert (thr_ret == 0);
-
- /* Do this before checking for count overflow, because overflowing
- * max is a listed technique for finding the current value */
- if (prevcount)
- *prevcount = sem_handle->val;
-
- /* No idea why max is signed, but thats the spec :-( */
- if (sem_handle->val + count > (guint32)sem_handle->max) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: %s handle %p val %d count %d max %d, max value would be exceeded",
- __func__, sem_handle_type_to_string (type), handle, sem_handle->val, count, sem_handle->max, count);
-
- ret = FALSE;
- } else {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: %s handle %p val %d count %d max %d",
- __func__, sem_handle_type_to_string (type), handle, sem_handle->val, count, sem_handle->max, count);
-
- sem_handle->val += count;
- mono_w32handle_set_signal_state (handle, TRUE, TRUE);
-
- ret = TRUE;
- }
-
- thr_ret = mono_w32handle_unlock_handle (handle);
- g_assert (thr_ret == 0);
-
- return ret;
-}
-
-gpointer OpenSemaphore (guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED,
- const gunichar2 *name)
-{
- gpointer handle;
- gchar *utf8_name;
- int thr_ret;
-
- /* w32 seems to guarantee that opening named objects can't
- * race each other
- */
- thr_ret = _wapi_namespace_lock ();
- g_assert (thr_ret == 0);
-
- utf8_name = g_utf16_to_utf8 (name, -1, NULL, NULL, NULL);
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Opening named sem [%s]", __func__, 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.
- */
- SetLastError (ERROR_INVALID_HANDLE);
- goto cleanup;
- } else if (!handle) {
- /* This name doesn't exist */
- SetLastError (ERROR_FILE_NOT_FOUND); /* yes, really */
- goto cleanup;
- }
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning named sem handle %p", __func__, handle);
-
-cleanup:
- g_free (utf8_name);
-
- _wapi_namespace_unlock (NULL);
-
- return handle;
-}
+++ /dev/null
-/*
- * semaphores.h: Semaphore handles
- *
- * Author:
- * Dick Porter (dick@ximian.com)
- *
- * (C) 2002 Ximian, Inc.
- */
-
-#ifndef _WAPI_SEMAPHORES_H_
-#define _WAPI_SEMAPHORES_H_
-
-#include <glib.h>
-
-G_BEGIN_DECLS
-
-extern gpointer CreateSemaphore(WapiSecurityAttributes *security,
- gint32 initial, gint32 max,
- const gunichar2 *name);
-extern gboolean ReleaseSemaphore(gpointer handle, gint32 count,
- gint32 *prevcount);
-extern gpointer OpenSemaphore (guint32 access, gboolean inherit,
- const gunichar2 *name);
-
-G_END_DECLS
-#endif /* _WAPI_SEMAPHORES_H_ */
+++ /dev/null
-/*
- * shared.c: Shared memory handling, and daemon launching
- *
- * Author:
- * Dick Porter (dick@ximian.com)
- *
- * (C) 2002-2006 Novell, Inc.
- */
-
-#include <config.h>
-#include <glib.h>
-
-#include <mono/io-layer/wapi-private.h>
-#include <mono/io-layer/shared.h>
-#include <mono/utils/mono-os-mutex.h>
-
-#define DEBUGLOG(...)
-//#define DEBUGLOG(...) g_message(__VA_ARGS__);
-
-static mono_mutex_t noshm_sems[_WAPI_SHARED_SEM_COUNT];
-
-void
-_wapi_shm_semaphores_init (void)
-{
- int i;
- for (i = 0; i < _WAPI_SHARED_SEM_COUNT; i++)
- mono_os_mutex_init (&noshm_sems [i]);
-}
-
-int
-_wapi_shm_sem_lock (int sem)
-{
- DEBUGLOG ("%s: locking nosem %d", __func__, sem);
- mono_os_mutex_lock (&noshm_sems[sem]);
- return 0;
-}
-
-int
-_wapi_shm_sem_trylock (int sem)
-{
- DEBUGLOG ("%s: trying to lock nosem %d", __func__, sem);
- return mono_os_mutex_trylock (&noshm_sems[sem]);
-}
-
-int
-_wapi_shm_sem_unlock (int sem)
-{
- DEBUGLOG ("%s: unlocking nosem %d", __func__, sem);
- mono_os_mutex_unlock (&noshm_sems[sem]);
- return 0;
-}
+++ /dev/null
-/*
- * shared.h: Shared memory handle, and daemon launching
- *
- * Author:
- * Dick Porter (dick@ximian.com)
- *
- * (C) 2002-2006 Novell, Inc.
- */
-
-#ifndef _WAPI_SHARED_H_
-#define _WAPI_SHARED_H_
-
-extern void _wapi_shm_semaphores_init (void);
-extern int _wapi_shm_sem_lock (int sem);
-extern int _wapi_shm_sem_trylock (int sem);
-extern int _wapi_shm_sem_unlock (int sem);
-
-#endif /* _WAPI_SHARED_H_ */
#include <mono/io-layer/wapi.h>
#include <mono/io-layer/io.h>
-#include <mono/io-layer/shared.h>
#include <mono/utils/mono-os-mutex.h>
extern gboolean _wapi_has_shut_down;
-typedef struct
-{
- gchar name[MAX_PATH + 1];
-} WapiSharedNamespace;
-
-#include <mono/io-layer/event-private.h>
#include <mono/io-layer/io-private.h>
-#include <mono/io-layer/mutex-private.h>
-#include <mono/io-layer/semaphore-private.h>
#include <mono/io-layer/socket-private.h>
#include <mono/io-layer/process-private.h>
#include <mono/utils/w32handle.h>
guint32 offset;
};
-#define _WAPI_SHARED_SEM_NAMESPACE 0
-/*#define _WAPI_SHARED_SEM_COLLECTION 1*/
-#define _WAPI_SHARED_SEM_FILESHARE 2
-#define _WAPI_SHARED_SEM_PROCESS_COUNT_LOCK 6
-#define _WAPI_SHARED_SEM_PROCESS_COUNT 7
-#define _WAPI_SHARED_SEM_COUNT 8 /* Leave some future expansion space */
-
struct _WapiFileShare
{
#ifdef WAPI_FILE_SHARE_PLATFORM_EXTRA_DATA
typedef struct _WapiFileShare _WapiFileShare;
-gpointer
-_wapi_search_handle_namespace (MonoW32HandleType type, gchar *utf8_name);
-
-static inline int _wapi_namespace_lock (void)
-{
- return(_wapi_shm_sem_lock (_WAPI_SHARED_SEM_NAMESPACE));
-}
-
-/* This signature makes it easier to use in pthread cleanup handlers */
-static inline int _wapi_namespace_unlock (gpointer data G_GNUC_UNUSED)
-{
- return(_wapi_shm_sem_unlock (_WAPI_SHARED_SEM_NAMESPACE));
-}
-
#endif /* _WAPI_PRIVATE_H_ */
#define SetLastError wapi_SetLastError
#define TransmitFile wapi_TransmitFile
#define GetThreadContext wapi_GetThreadContext
-#define CreateEvent wapi_CreateEvent
-#define PulseEvent wapi_PulseEvent
-#define ResetEvent wapi_ResetEvent
-#define SetEvent wapi_SetEvent
-#define OpenEvent wapi_OpenEvent
#define CloseHandle wapi_CloseHandle
#define DuplicateHandle wapi_DuplicateHandle
#define CreateFile wapi_CreateFile
#define UnlockFile wapi_UnlockFile
#define GetVolumeInformation wapi_GetVolumeInformation
#define FormatMessage wapi_FormatMessage
-#define CreateMutex wapi_CreateMutex
-#define ReleaseMutex wapi_ReleaseMutex
-#define OpenMutex wapi_OpenMutex
#define ShellExecuteEx wapi_ShellExecuteEx
#define CreateProcess wapi_CreateProcess
#define CreateProcessWithLogonW wapi_CreateProcessWithLogonW
#define SetPriorityClass wapi_SetPriorityClass
#define ImpersonateLoggedOnUser wapi_ImpersonateLoggedOnUser
#define RevertToSelf wapi_RevertToSelf
-#define CreateSemaphore wapi_CreateSemaphore
-#define ReleaseSemaphore wapi_ReleaseSemaphore
-#define OpenSemaphore wapi_OpenSemaphore
#define WSASetLastError wapi_WSASetLastError
#define WSAGetLastError wapi_WSAGetLastError
#define WSAIoctl wapi_WSAIoctl
#include "wapi.h"
-#include "event-private.h"
#include "io-trace.h"
#include "io.h"
-#include "mutex-private.h"
#include "process-private.h"
-#include "semaphore-private.h"
-#include "shared.h"
#include "socket-private.h"
#include "mono/utils/mono-lazy-init.h"
void
wapi_init (void)
{
- _wapi_shm_semaphores_init ();
_wapi_io_init ();
_wapi_processes_init ();
- _wapi_semaphore_init ();
- _wapi_mutex_init ();
- _wapi_event_init ();
_wapi_socket_init ();
}
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;
- MonoW32HandleType type;
- gchar *utf8_name;
-} _WapiSearchHandleNamespaceData;
-
-static gboolean mono_w32handle_search_namespace_callback (gpointer handle, gpointer data, gpointer user_data)
-{
- _WapiSearchHandleNamespaceData *search_data;
- MonoW32HandleType type;
- WapiSharedNamespace *sharedns;
-
- type = mono_w32handle_get_type (handle);
- if (!_WAPI_SHARED_NAMESPACE (type))
- return FALSE;
-
- search_data = (_WapiSearchHandleNamespaceData*) user_data;
-
- switch (type) {
- 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 (strcmp (sharedns->name, search_data->utf8_name) == 0) {
- 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, 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",
- __func__, handle);
- search_data->ret = handle;
- }
-
- return TRUE;
- }
-
- return FALSE;
-}
-
-/* Returns the offset of the metadata array, or INVALID_HANDLE_VALUE on error, or NULL for
- * not found
- */
-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, mono_w32handle_ops_typename (type));
-
- search_data.ret = NULL;
- search_data.type = type;
- search_data.utf8_name = utf8_name;
- mono_w32handle_foreach (mono_w32handle_search_namespace_callback, &search_data);
- return search_data.ret;
-}
-
/* Lots more to implement here, but this is all we need at the moment */
gboolean
DuplicateHandle (gpointer srcprocess, gpointer src, gpointer targetprocess, gpointer *target,
#include <mono/io-layer/access.h>
#include <mono/io-layer/context.h>
#include <mono/io-layer/error.h>
-#include <mono/io-layer/events.h>
#include <mono/io-layer/messages.h>
-#include <mono/io-layer/mutexes.h>
#include <mono/io-layer/processes.h>
#include <mono/io-layer/security.h>
-#include <mono/io-layer/semaphores.h>
#include <mono/io-layer/sockets.h>
#include <mono/io-layer/status.h>
#include <mono/io-layer/timefuncs.h>
if HOST_WIN32
win32_sources = \
- console-win32.c
+ console-win32.c \
+ w32mutex-win32.c \
+ w32semaphore-win32.c \
+ w32event-win32.c
platform_sources = $(win32_sources)
assembliesdir = $(exec_prefix)/lib
confdir = $(sysconfdir)
unix_sources = \
- console-unix.c
+ console-unix.c \
+ w32mutex-unix.c \
+ w32semaphore-unix.c \
+ w32event-unix.c
platform_sources = $(unix_sources)
endif
seq-points-data.h \
seq-points-data.c \
handle.c \
- handle.h
-
+ handle.h \
+ w32mutex.h \
+ w32semaphore.h \
+ w32event.h \
+ w32handle-namespace.h \
+ w32handle-namespace.c
# These source files have compile time dependencies on GC code
gc_dependent_sources = \
#include <mono/metadata/mono-config.h>
#include <mono/metadata/threads-types.h>
#include <mono/metadata/runtime.h>
+#include <mono/metadata/w32mutex.h>
+#include <mono/metadata/w32semaphore.h>
+#include <mono/metadata/w32event.h>
#include <metadata/threads.h>
#include <metadata/profiler-private.h>
#include <mono/metadata/coree.h>
#ifndef HOST_WIN32
mono_w32handle_init ();
+ mono_w32handle_namespace_init ();
wapi_init ();
#endif
+ mono_w32mutex_init ();
+ mono_w32semaphore_init ();
+ mono_w32event_init ();
+
#ifndef DISABLE_PERFCOUNTERS
mono_perfcounters_init ();
#endif
#include <mono/metadata/file-mmap.h>
#include <mono/metadata/seq-points-data.h>
#include <mono/metadata/handle.h>
+#include <mono/metadata/w32mutex.h>
+#include <mono/metadata/w32semaphore.h>
+#include <mono/metadata/w32event.h>
#include <mono/io-layer/io-layer.h>
#include <mono/utils/monobitset.h>
#include <mono/utils/mono-time.h>
#include <mono/metadata/debug-helpers.h>
#include <mono/metadata/tabledefs.h>
#include <mono/metadata/marshal.h>
+#include <mono/metadata/w32event.h>
#include <mono/utils/mono-threads.h>
#include <mono/metadata/profiler-private.h>
#include <mono/utils/mono-time.h>
if (mon->wait_list != NULL) {
LOCK_DEBUG (g_message ("%s: (%d) signalling and dequeuing handle %p", __func__, mono_thread_info_get_small_id (), mon->wait_list->data));
- SetEvent (mon->wait_list->data);
+ mono_w32event_set (mon->wait_list->data);
mon->wait_list = g_slist_remove (mon->wait_list, mon->wait_list->data);
}
}
while (mon->wait_list != NULL) {
LOCK_DEBUG (g_message ("%s: (%d) signalling and dequeuing handle %p", __func__, mono_thread_info_get_small_id (), mon->wait_list->data));
- SetEvent (mon->wait_list->data);
+ mono_w32event_set (mon->wait_list->data);
mon->wait_list = g_slist_remove (mon->wait_list, mon->wait_list->data);
}
}
if (mono_thread_current_check_pending_interrupt ())
return FALSE;
- event = CreateEvent (NULL, FALSE, FALSE, NULL);
+ event = mono_w32event_create (FALSE, FALSE);
if (event == NULL) {
mono_set_pending_exception (mono_get_exception_synchronization_lock ("Failed to set up wait event"));
return FALSE;
#include <mono/metadata/gc-internals.h>
#include <mono/metadata/verify-internals.h>
#include <mono/metadata/reflection-internals.h>
+#include <mono/metadata/w32event.h>
#include <mono/utils/strenc.h>
#include <mono/utils/mono-counters.h>
#include <mono/utils/mono-error-internals.h>
mono_monitor_exit ((MonoObject*) ares);
if (wait_event != NULL)
- SetEvent (wait_event);
+ mono_w32event_set (wait_event);
mono_error_init (&error); //the else branch would leave it in an undefined state
if (ac->cb_method)
#include <mono/metadata/object-internals.h>
#include <mono/metadata/threadpool-ms.h>
#include <mono/metadata/threadpool-ms-io.h>
+#include <mono/metadata/w32event.h>
#include <mono/utils/atomic.h>
#include <mono/utils/mono-compiler.h>
#include <mono/utils/mono-complex.h>
if (ares->handle) {
wait_event = mono_wait_handle_get_handle ((MonoWaitHandle*) ares->handle);
} else {
- wait_event = CreateEvent (NULL, TRUE, FALSE, NULL);
+ wait_event = mono_w32event_create (TRUE, FALSE);
g_assert(wait_event);
MonoWaitHandle *wait_handle = mono_wait_handle_new (mono_object_domain (ares), wait_event, error);
if (!is_ok (error)) {
void ves_icall_System_Threading_Thread_SetCachedCurrentCulture (MonoThread *this_obj, MonoObject *culture);
MonoObject* ves_icall_System_Threading_Thread_GetCachedCurrentUICulture (MonoInternalThread *this_obj);
void ves_icall_System_Threading_Thread_SetCachedCurrentUICulture (MonoThread *this_obj, MonoObject *culture);
-HANDLE ves_icall_System_Threading_Mutex_CreateMutex_internal(MonoBoolean owned, MonoString *name, MonoBoolean *created);
-MonoBoolean ves_icall_System_Threading_Mutex_ReleaseMutex_internal (HANDLE handle );
-HANDLE ves_icall_System_Threading_Mutex_OpenMutex_internal (MonoString *name, gint32 rights, gint32 *error);
-HANDLE ves_icall_System_Threading_Semaphore_CreateSemaphore_internal (gint32 initialCount, gint32 maximumCount, MonoString *name, gint32 *error);
-MonoBoolean ves_icall_System_Threading_Semaphore_ReleaseSemaphore_internal (HANDLE handle, gint32 releaseCount, gint32 *prevcount);
-HANDLE ves_icall_System_Threading_Semaphore_OpenSemaphore_internal (MonoString *name, gint32 rights, gint32 *error);
-HANDLE ves_icall_System_Threading_Events_CreateEvent_internal (MonoBoolean manual, MonoBoolean initial, MonoString *name, gint32 *error);
-gboolean ves_icall_System_Threading_Events_SetEvent_internal (HANDLE handle);
-gboolean ves_icall_System_Threading_Events_ResetEvent_internal (HANDLE handle);
-void ves_icall_System_Threading_Events_CloseEvent_internal (HANDLE handle);
-HANDLE ves_icall_System_Threading_Events_OpenEvent_internal (MonoString *name, gint32 rights, gint32 *error);
gint32 ves_icall_System_Threading_WaitHandle_WaitAll_internal(MonoArray *mono_handles, gint32 ms);
gint32 ves_icall_System_Threading_WaitHandle_WaitAny_internal(MonoArray *mono_handles, gint32 ms);
#include <mono/utils/mono-threads-coop.h>
#include <mono/utils/mono-error-internals.h>
#include <mono/utils/w32handle.h>
+#include <mono/metadata/w32event.h>
#include <mono/metadata/gc-internals.h>
#include <mono/metadata/reflection-internals.h>
return map_native_wait_result_to_managed (ret);
}
-HANDLE ves_icall_System_Threading_Mutex_CreateMutex_internal (MonoBoolean owned, MonoString *name, MonoBoolean *created)
-{
- HANDLE mutex;
-
- *created = TRUE;
-
- if (name == NULL) {
- mutex = CreateMutex (NULL, owned, NULL);
- } else {
- mutex = CreateMutex (NULL, owned, mono_string_chars (name));
-
- if (GetLastError () == ERROR_ALREADY_EXISTS) {
- *created = FALSE;
- }
- }
-
- return(mutex);
-}
-
-MonoBoolean ves_icall_System_Threading_Mutex_ReleaseMutex_internal (HANDLE handle ) {
- return(ReleaseMutex (handle));
-}
-
-HANDLE ves_icall_System_Threading_Mutex_OpenMutex_internal (MonoString *name,
- gint32 rights,
- gint32 *error)
-{
- HANDLE ret;
-
- *error = ERROR_SUCCESS;
-
- ret = OpenMutex (rights, FALSE, mono_string_chars (name));
- if (ret == NULL) {
- *error = GetLastError ();
- }
-
- return(ret);
-}
-
-
-HANDLE ves_icall_System_Threading_Semaphore_CreateSemaphore_internal (gint32 initialCount, gint32 maximumCount, MonoString *name, gint32 *error)
-{
- HANDLE sem;
-
- if (name == NULL) {
- sem = CreateSemaphore (NULL, initialCount, maximumCount, NULL);
- } else {
- sem = CreateSemaphore (NULL, initialCount, maximumCount,
- mono_string_chars (name));
- }
-
- *error = GetLastError ();
-
- return(sem);
-}
-
-MonoBoolean ves_icall_System_Threading_Semaphore_ReleaseSemaphore_internal (HANDLE handle, gint32 releaseCount, gint32 *prevcount)
-{
- return ReleaseSemaphore (handle, releaseCount, prevcount);
-}
-
-HANDLE ves_icall_System_Threading_Semaphore_OpenSemaphore_internal (MonoString *name, gint32 rights, gint32 *error)
-{
- HANDLE sem;
-
- sem = OpenSemaphore (rights, FALSE, mono_string_chars (name));
-
- *error = GetLastError ();
-
- return(sem);
-}
-
-HANDLE ves_icall_System_Threading_Events_CreateEvent_internal (MonoBoolean manual, MonoBoolean initial, MonoString *name, gint32 *error)
-{
- HANDLE event;
-
- if (name == NULL) {
- event = CreateEvent (NULL, manual, initial, NULL);
- } else {
- event = CreateEvent (NULL, manual, initial,
- mono_string_chars (name));
- }
-
- *error = GetLastError ();
-
- return(event);
-}
-
-gboolean ves_icall_System_Threading_Events_SetEvent_internal (HANDLE handle) {
- return (SetEvent(handle));
-}
-
-gboolean ves_icall_System_Threading_Events_ResetEvent_internal (HANDLE handle) {
- return (ResetEvent(handle));
-}
-
-void
-ves_icall_System_Threading_Events_CloseEvent_internal (HANDLE handle) {
- CloseHandle (handle);
-}
-
-HANDLE ves_icall_System_Threading_Events_OpenEvent_internal (MonoString *name,
- gint32 rights,
- gint32 *error)
-{
- HANDLE ret;
-
- ret = OpenEvent (rights, FALSE, mono_string_chars (name));
- if (ret == NULL) {
- *error = GetLastError ();
- } else {
- *error = ERROR_SUCCESS;
- }
-
- return(ret);
-}
-
gint32 ves_icall_System_Threading_Interlocked_Increment_Int (gint32 *location)
{
return InterlockedIncrement (location);
* be notified, since it has to rebuild the list of threads to
* wait for.
*/
- SetEvent (background_change_event);
+ mono_w32event_set (background_change_event);
}
}
* be notified, since it has to rebuild the list of threads to
* wait for.
*/
- SetEvent (background_change_event);
+ mono_w32event_set (background_change_event);
}
}
mono_os_mutex_init_recursive(&interlocked_mutex);
mono_os_mutex_init_recursive(&joinable_threads_mutex);
- background_change_event = CreateEvent (NULL, TRUE, FALSE, NULL);
+ background_change_event = mono_w32event_create (TRUE, FALSE);
g_assert(background_change_event != NULL);
mono_init_static_data_info (&thread_static_info);
* interrupt the main thread if it is waiting for all
* the other threads.
*/
- SetEvent (background_change_event);
+ mono_w32event_set (background_change_event);
mono_threads_unlock ();
}
THREAD_DEBUG (g_message ("%s: There are %d threads to join", __func__, mono_g_hash_table_size (threads));
mono_g_hash_table_foreach (threads, print_tids, NULL));
- ResetEvent (background_change_event);
+ mono_w32event_reset (background_change_event);
wait->num=0;
/*We must zero all InternalThread pointers to avoid making the GC unhappy.*/
memset (wait->threads, 0, MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS * SIZEOF_VOID_P);
--- /dev/null
+/*
+ * w32event-unix.c: Runtime support for managed Event on Unix
+ *
+ * Author:
+ * Ludovic Henry (luhenry@microsoft.com)
+ *
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+
+#include "w32event.h"
+
+#include "w32handle-namespace.h"
+#include "mono/io-layer/io-layer.h"
+#include "mono/utils/mono-logger-internals.h"
+#include "mono/utils/w32handle.h"
+
+typedef struct {
+ gboolean manual;
+ guint32 set_count;
+} MonoW32HandleEvent;
+
+struct MonoW32HandleNamedEvent {
+ MonoW32HandleEvent e;
+ MonoW32HandleNamespace sharedns;
+};
+
+static gboolean event_handle_own (gpointer handle, MonoW32HandleType type)
+{
+ MonoW32HandleEvent *event_handle;
+ gboolean ok;
+
+ ok = mono_w32handle_lookup (handle, type, (gpointer *)&event_handle);
+ if (!ok) {
+ g_warning ("%s: error looking up %s handle %p",
+ __func__, mono_w32handle_ops_typename (type), handle);
+ return FALSE;
+ }
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: owning %s handle %p",
+ __func__, mono_w32handle_ops_typename (type), handle);
+
+ if (!event_handle->manual) {
+ g_assert (event_handle->set_count > 0);
+ event_handle->set_count --;
+
+ if (event_handle->set_count == 0)
+ mono_w32handle_set_signal_state (handle, FALSE, FALSE);
+ }
+
+ return TRUE;
+}
+
+static void event_signal(gpointer handle)
+{
+ ves_icall_System_Threading_Events_SetEvent_internal (handle);
+}
+
+static gboolean event_own (gpointer handle)
+{
+ return event_handle_own (handle, MONO_W32HANDLE_EVENT);
+}
+
+static void namedevent_signal (gpointer handle)
+{
+ ves_icall_System_Threading_Events_SetEvent_internal (handle);
+}
+
+/* NB, always called with the shared handle lock held */
+static gboolean namedevent_own (gpointer handle)
+{
+ return event_handle_own (handle, MONO_W32HANDLE_NAMEDEVENT);
+}
+
+static void event_details (gpointer data)
+{
+ MonoW32HandleEvent *event = (MonoW32HandleEvent *)data;
+ g_print ("manual: %s, set_count: %d",
+ event->manual ? "TRUE" : "FALSE", event->set_count);
+}
+
+static void namedevent_details (gpointer data)
+{
+ MonoW32HandleNamedEvent *namedevent = (MonoW32HandleNamedEvent *)data;
+ g_print ("manual: %s, set_count: %d, name: \"%s\"",
+ namedevent->e.manual ? "TRUE" : "FALSE", namedevent->e.set_count, namedevent->sharedns.name);
+}
+
+static const gchar* event_typename (void)
+{
+ return "Event";
+}
+
+static gsize event_typesize (void)
+{
+ return sizeof (MonoW32HandleEvent);
+}
+
+static const gchar* namedevent_typename (void)
+{
+ return "N.Event";
+}
+
+static gsize namedevent_typesize (void)
+{
+ return sizeof (MonoW32HandleNamedEvent);
+}
+
+void
+mono_w32event_init (void)
+{
+ static MonoW32HandleOps event_ops = {
+ NULL, /* close */
+ event_signal, /* signal */
+ event_own, /* own */
+ NULL, /* is_owned */
+ NULL, /* special_wait */
+ NULL, /* prewait */
+ event_details, /* details */
+ event_typename, /* typename */
+ event_typesize, /* typesize */
+ };
+
+ static MonoW32HandleOps namedevent_ops = {
+ NULL, /* close */
+ namedevent_signal, /* signal */
+ namedevent_own, /* own */
+ NULL, /* is_owned */
+ NULL, /* special_wait */
+ NULL, /* prewait */
+ namedevent_details, /* details */
+ namedevent_typename, /* typename */
+ namedevent_typesize, /* typesize */
+ };
+
+ mono_w32handle_register_ops (MONO_W32HANDLE_EVENT, &event_ops);
+ mono_w32handle_register_ops (MONO_W32HANDLE_NAMEDEVENT, &namedevent_ops);
+
+ 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));
+}
+
+gpointer
+mono_w32event_create (gboolean manual, gboolean initial)
+{
+ gpointer handle;
+ gint32 error;
+
+ handle = ves_icall_System_Threading_Events_CreateEvent_internal (manual, initial, NULL, &error);
+ if (error != ERROR_SUCCESS)
+ g_assert (!handle);
+
+ return handle;
+}
+
+void
+mono_w32event_set (gpointer handle)
+{
+ ves_icall_System_Threading_Events_SetEvent_internal (handle);
+}
+
+void
+mono_w32event_reset (gpointer handle)
+{
+ ves_icall_System_Threading_Events_ResetEvent_internal (handle);
+}
+
+static gpointer event_handle_create (MonoW32HandleEvent *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 = mono_w32handle_new (type, event_handle);
+ if (handle == INVALID_HANDLE_VALUE) {
+ g_warning ("%s: error creating %s handle",
+ __func__, mono_w32handle_ops_typename (type));
+ SetLastError (ERROR_GEN_FAILURE);
+ return NULL;
+ }
+
+ thr_ret = mono_w32handle_lock_handle (handle);
+ g_assert (thr_ret == 0);
+
+ if (initial)
+ mono_w32handle_set_signal_state (handle, TRUE, FALSE);
+
+ 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",
+ __func__, mono_w32handle_ops_typename (type), handle);
+
+ return handle;
+}
+
+static gpointer event_create (gboolean manual, gboolean initial)
+{
+ MonoW32HandleEvent event_handle;
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: creating %s handle",
+ __func__, mono_w32handle_ops_typename (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)
+{
+ gpointer handle;
+ gchar *utf8_name;
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: creating %s handle",
+ __func__, mono_w32handle_ops_typename (MONO_W32HANDLE_NAMEDEVENT));
+
+ /* w32 seems to guarantee that opening named objects can't race each other */
+ mono_w32handle_namespace_lock ();
+
+ utf8_name = g_utf16_to_utf8 (name, -1, NULL, NULL, NULL);
+
+ handle = mono_w32handle_namespace_search_handle (MONO_W32HANDLE_NAMEDEVENT, utf8_name);
+ if (handle == INVALID_HANDLE_VALUE) {
+ /* The name has already been used for a different object. */
+ handle = NULL;
+ SetLastError (ERROR_INVALID_HANDLE);
+ } else if (handle) {
+ /* Not an error, but this is how the caller is informed that the event wasn't freshly created */
+ SetLastError (ERROR_ALREADY_EXISTS);
+
+ /* this is used as creating a new handle */
+ mono_w32handle_ref (handle);
+ } else {
+ /* A new named event */
+ MonoW32HandleNamedEvent namedevent_handle;
+
+ strncpy (&namedevent_handle.sharedns.name [0], utf8_name, MAX_PATH);
+ namedevent_handle.sharedns.name [MAX_PATH] = '\0';
+
+ handle = event_handle_create ((MonoW32HandleEvent*) &namedevent_handle, MONO_W32HANDLE_NAMEDEVENT, manual, initial);
+ }
+
+ g_free (utf8_name);
+
+ mono_w32handle_namespace_unlock ();
+
+ return handle;
+}
+
+gpointer
+ves_icall_System_Threading_Events_CreateEvent_internal (MonoBoolean manual, MonoBoolean initial, MonoString *name, gint32 *error)
+{
+ gpointer event;
+
+ /* Need to blow away any old errors here, because code tests
+ * for ERROR_ALREADY_EXISTS on success (!) to see if an event
+ * was freshly created */
+ SetLastError (ERROR_SUCCESS);
+
+ event = name ? namedevent_create (manual, initial, mono_string_chars (name)) : event_create (manual, initial);
+
+ *error = GetLastError ();
+
+ return event;
+}
+
+gboolean
+ves_icall_System_Threading_Events_SetEvent_internal (gpointer handle)
+{
+ MonoW32HandleType type;
+ MonoW32HandleEvent *event_handle;
+ int thr_ret;
+
+ if (handle == NULL) {
+ SetLastError (ERROR_INVALID_HANDLE);
+ return(FALSE);
+ }
+
+ switch (type = mono_w32handle_get_type (handle)) {
+ case MONO_W32HANDLE_EVENT:
+ case MONO_W32HANDLE_NAMEDEVENT:
+ break;
+ default:
+ SetLastError (ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
+
+ if (!mono_w32handle_lookup (handle, type, (gpointer *)&event_handle)) {
+ g_warning ("%s: error looking up %s handle %p",
+ __func__, mono_w32handle_ops_typename (type), handle);
+ return FALSE;
+ }
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: setting %s handle %p",
+ __func__, mono_w32handle_ops_typename (type), handle);
+
+ thr_ret = mono_w32handle_lock_handle (handle);
+ g_assert (thr_ret == 0);
+
+ if (!event_handle->manual) {
+ event_handle->set_count = 1;
+ mono_w32handle_set_signal_state (handle, TRUE, FALSE);
+ } else {
+ mono_w32handle_set_signal_state (handle, TRUE, TRUE);
+ }
+
+ thr_ret = mono_w32handle_unlock_handle (handle);
+ g_assert (thr_ret == 0);
+
+ return TRUE;
+}
+
+gboolean
+ves_icall_System_Threading_Events_ResetEvent_internal (gpointer handle)
+{
+ MonoW32HandleType type;
+ MonoW32HandleEvent *event_handle;
+ int thr_ret;
+
+ SetLastError (ERROR_SUCCESS);
+
+ if (handle == NULL) {
+ SetLastError (ERROR_INVALID_HANDLE);
+ return(FALSE);
+ }
+
+ switch (type = mono_w32handle_get_type (handle)) {
+ case MONO_W32HANDLE_EVENT:
+ case MONO_W32HANDLE_NAMEDEVENT:
+ break;
+ default:
+ SetLastError (ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
+
+ if (!mono_w32handle_lookup (handle, type, (gpointer *)&event_handle)) {
+ g_warning ("%s: error looking up %s handle %p",
+ __func__, mono_w32handle_ops_typename (type), handle);
+ return FALSE;
+ }
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: resetting %s handle %p",
+ __func__, mono_w32handle_ops_typename (type), handle);
+
+ thr_ret = mono_w32handle_lock_handle (handle);
+ g_assert (thr_ret == 0);
+
+ if (!mono_w32handle_issignalled (handle)) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: no need to reset %s handle %p",
+ __func__, mono_w32handle_ops_typename (type), handle);
+ } else {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: obtained write lock on %s handle %p",
+ __func__, mono_w32handle_ops_typename (type), handle);
+
+ mono_w32handle_set_signal_state (handle, FALSE, FALSE);
+ }
+
+ event_handle->set_count = 0;
+
+ thr_ret = mono_w32handle_unlock_handle (handle);
+ g_assert (thr_ret == 0);
+
+ return TRUE;
+}
+
+void
+ves_icall_System_Threading_Events_CloseEvent_internal (gpointer handle)
+{
+ CloseHandle (handle);
+}
+
+gpointer
+ves_icall_System_Threading_Events_OpenEvent_internal (MonoString *name, gint32 rights G_GNUC_UNUSED, gint32 *error)
+{
+ gpointer handle;
+ gchar *utf8_name;
+
+ *error = ERROR_SUCCESS;
+
+ /* w32 seems to guarantee that opening named objects can't race each other */
+ mono_w32handle_namespace_lock ();
+
+ utf8_name = g_utf16_to_utf8 (mono_string_chars (name), -1, NULL, NULL, NULL);
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Opening named event [%s]", __func__, utf8_name);
+
+ handle = mono_w32handle_namespace_search_handle (MONO_W32HANDLE_NAMEDEVENT, utf8_name);
+ if (handle == INVALID_HANDLE_VALUE) {
+ /* The name has already been used for a different object. */
+ *error = ERROR_INVALID_HANDLE;
+ goto cleanup;
+ } else if (!handle) {
+ /* This name doesn't exist */
+ *error = ERROR_FILE_NOT_FOUND;
+ goto cleanup;
+ }
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning named event handle %p", __func__, handle);
+
+cleanup:
+ g_free (utf8_name);
+
+ mono_w32handle_namespace_unlock ();
+
+ return handle;
+}
+
+MonoW32HandleNamespace*
+mono_w32event_get_namespace (MonoW32HandleNamedEvent *event)
+{
+ return &event->sharedns;
+}
--- /dev/null
+/*
+ * w32event-win32.c: Runtime support for managed Event on Win32
+ *
+ * Author:
+ * Ludovic Henry (luhenry@microsoft.com)
+ *
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+
+#include "w32event.h"
+
+#include <windows.h>
+#include <winbase.h>
+
+void
+mono_w32event_init (void)
+{
+}
+
+gpointer
+mono_w32event_create (gboolean manual, gboolean initial)
+{
+ return CreateEvent (NULL, manual, initial, NULL);
+}
+
+void
+mono_w32event_set (gpointer handle)
+{
+ SetEvent (handle);
+}
+
+void
+mono_w32event_reset (gpointer handle)
+{
+ ResetEvent (handle);
+}
+
+gpointer
+ves_icall_System_Threading_Events_CreateEvent_internal (MonoBoolean manual, MonoBoolean initial, MonoString *name, gint32 *error)
+{
+ gpointer event;
+
+ event = CreateEvent (NULL, manual, initial, name ? mono_string_chars (name) : NULL);
+
+ *error = GetLastError ();
+
+ return event;
+}
+
+gboolean
+ves_icall_System_Threading_Events_SetEvent_internal (gpointer handle)
+{
+ return SetEvent (handle);
+}
+
+gboolean
+ves_icall_System_Threading_Events_ResetEvent_internal (gpointer handle)
+{
+ return ResetEvent (handle);
+}
+
+void
+ves_icall_System_Threading_Events_CloseEvent_internal (gpointer handle)
+{
+ CloseHandle (handle);
+}
+
+gpointer
+ves_icall_System_Threading_Events_OpenEvent_internal (MonoString *name, gint32 rights, gint32 *error)
+{
+ gpointer handle;
+
+ *error = ERROR_SUCCESS;
+
+ handle = OpenEvent (rights, FALSE, mono_string_chars (name));
+ if (!handle)
+ *error = GetLastError ();
+
+ return handle;
+}
--- /dev/null
+
+#ifndef _MONO_METADATA_W32EVENT_H_
+#define _MONO_METADATA_W32EVENT_H_
+
+#include <config.h>
+#include <glib.h>
+
+#include "object.h"
+#include "w32handle-namespace.h"
+
+void
+mono_w32event_init (void);
+
+gpointer
+mono_w32event_create (gboolean manual, gboolean initial);
+
+void
+mono_w32event_set (gpointer handle);
+
+void
+mono_w32event_reset (gpointer handle);
+
+gpointer
+ves_icall_System_Threading_Events_CreateEvent_internal (MonoBoolean manual, MonoBoolean initial, MonoString *name, gint32 *error);
+
+gboolean
+ves_icall_System_Threading_Events_SetEvent_internal (gpointer handle);
+
+gboolean
+ves_icall_System_Threading_Events_ResetEvent_internal (gpointer handle);
+
+void
+ves_icall_System_Threading_Events_CloseEvent_internal (gpointer handle);
+
+gpointer
+ves_icall_System_Threading_Events_OpenEvent_internal (MonoString *name, gint32 rights, gint32 *error);
+
+typedef struct MonoW32HandleNamedEvent MonoW32HandleNamedEvent;
+
+MonoW32HandleNamespace*
+mono_w32event_get_namespace (MonoW32HandleNamedEvent *event);
+
+#endif /* _MONO_METADATA_W32EVENT_H_ */
--- /dev/null
+/*
+ * w32handle-namespace.c: namespace for w32handles
+ *
+ * Author:
+ * Ludovic Henry (luhenry@microsoft.com)
+ *
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+
+#include <config.h>
+
+#ifndef HOST_WIN32
+
+#include "w32handle-namespace.h"
+
+#include "w32mutex.h"
+#include "w32semaphore.h"
+#include "w32event.h"
+#include "mono/io-layer/io-layer.h"
+#include "mono/utils/mono-logger-internals.h"
+#include "mono/utils/mono-coop-mutex.h"
+
+static MonoCoopMutex lock;
+
+void
+mono_w32handle_namespace_init (void)
+{
+ mono_coop_mutex_init (&lock);
+}
+
+void
+mono_w32handle_namespace_lock (void)
+{
+ mono_coop_mutex_lock (&lock);
+}
+
+void
+mono_w32handle_namespace_unlock (void)
+{
+ mono_coop_mutex_unlock (&lock);
+}
+
+static gboolean
+has_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;
+ MonoW32HandleType type;
+ gchar *name;
+} NamespaceSearchHandleData;
+
+static gboolean
+mono_w32handle_namespace_search_handle_callback (gpointer handle, gpointer data, gpointer user_data)
+{
+ NamespaceSearchHandleData *search_data;
+ MonoW32HandleType type;
+ MonoW32HandleNamespace *sharedns;
+
+ type = mono_w32handle_get_type (handle);
+ if (!has_namespace (type))
+ return FALSE;
+
+ search_data = (NamespaceSearchHandleData*) user_data;
+
+ switch (type) {
+ case MONO_W32HANDLE_NAMEDMUTEX: sharedns = mono_w32mutex_get_namespace ((MonoW32HandleNamedMutex*) data); break;
+ case MONO_W32HANDLE_NAMEDSEM: sharedns = mono_w32semaphore_get_namespace ((MonoW32HandleNamedSemaphore*) data); break;
+ case MONO_W32HANDLE_NAMEDEVENT: sharedns = mono_w32event_get_namespace ((MonoW32HandleNamedEvent*) data); break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ if (strcmp (sharedns->name, search_data->name) == 0) {
+ 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, 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",
+ __func__, handle);
+ search_data->ret = handle;
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+gpointer
+mono_w32handle_namespace_search_handle (MonoW32HandleType type, gchar *name)
+{
+ NamespaceSearchHandleData search_data;
+
+ if (!has_namespace (type))
+ g_error ("%s: type %s does not have a namespace", __func__, type);
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Lookup for handle named [%s] type %s",
+ __func__, name, mono_w32handle_ops_typename (type));
+
+ search_data.ret = NULL;
+ search_data.type = type;
+ search_data.name = name;
+ mono_w32handle_foreach (mono_w32handle_namespace_search_handle_callback, &search_data);
+ return search_data.ret;
+}
+
+#endif
--- /dev/null
+
+#ifndef _MONO_METADATA_W32HANDLE_NAMESPACE_H_
+#define _MONO_METADATA_W32HANDLE_NAMESPACE_H_
+
+#include <config.h>
+#include <glib.h>
+
+#include "mono/utils/w32handle.h"
+
+#define MONO_W32HANDLE_NAMESPACE_MAX_PATH 260
+
+typedef struct {
+ gchar name [MONO_W32HANDLE_NAMESPACE_MAX_PATH + 1];
+} MonoW32HandleNamespace;
+
+void
+mono_w32handle_namespace_init (void);
+
+void
+mono_w32handle_namespace_lock (void);
+
+void
+mono_w32handle_namespace_unlock (void);
+
+gpointer
+mono_w32handle_namespace_search_handle (MonoW32HandleType type, gchar *name);
+
+#endif /* _MONO_METADATA_W32HANDLE_NAMESPACE_H_ */
\ No newline at end of file
--- /dev/null
+/*
+ * w32mutex-unix.c: Runtime support for managed Mutex on Unix
+ *
+ * Author:
+ * Ludovic Henry (luhenry@microsoft.com)
+ *
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+
+#include "w32mutex.h"
+#include "w32mutex-utils.h"
+
+#include <pthread.h>
+
+#include "w32handle-namespace.h"
+#include "mono/io-layer/io-layer.h"
+#include "mono/utils/mono-logger-internals.h"
+#include "mono/utils/mono-threads.h"
+#include "mono/utils/w32handle.h"
+
+typedef struct {
+ MonoNativeThreadId tid;
+ guint32 recursion;
+} MonoW32HandleMutex;
+
+struct MonoW32HandleNamedMutex {
+ MonoW32HandleMutex m;
+ MonoW32HandleNamespace sharedns;
+};
+
+static gboolean
+mutex_handle_own (gpointer handle, MonoW32HandleType type)
+{
+ MonoW32HandleMutex *mutex_handle;
+
+ if (!mono_w32handle_lookup (handle, type, (gpointer *)&mutex_handle)) {
+ g_warning ("%s: error looking up %s handle %p", __func__, mono_w32handle_ops_typename (type), handle);
+ return FALSE;
+ }
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: owning %s handle %p, tid %p, recursion %u",
+ __func__, mono_w32handle_ops_typename (type), handle, (gpointer) mutex_handle->tid, mutex_handle->recursion);
+
+ mono_thread_info_own_mutex (mono_thread_info_current (), handle);
+
+ mutex_handle->tid = pthread_self ();
+ mutex_handle->recursion++;
+
+ mono_w32handle_set_signal_state (handle, FALSE, FALSE);
+
+ return TRUE;
+}
+
+static gboolean
+mutex_handle_is_owned (gpointer handle, MonoW32HandleType type)
+{
+ MonoW32HandleMutex *mutex_handle;
+
+ if (!mono_w32handle_lookup (handle, type, (gpointer *)&mutex_handle)) {
+ g_warning ("%s: error looking up %s handle %p", __func__, mono_w32handle_ops_typename (type), handle);
+ return FALSE;
+ }
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: testing ownership %s handle %p",
+ __func__, mono_w32handle_ops_typename (type), handle);
+
+ if (mutex_handle->recursion > 0 && pthread_equal (mutex_handle->tid, pthread_self ())) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: %s handle %p owned by %p",
+ __func__, mono_w32handle_ops_typename (type), handle, (gpointer) pthread_self ());
+ return TRUE;
+ } else {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: %s handle %p not owned by %p, but locked %d times by %p",
+ __func__, mono_w32handle_ops_typename (type), handle, (gpointer) pthread_self (), mutex_handle->recursion, (gpointer) mutex_handle->tid);
+ return FALSE;
+ }
+}
+
+static void mutex_signal(gpointer handle)
+{
+ ves_icall_System_Threading_Mutex_ReleaseMutex_internal (handle);
+}
+
+static gboolean mutex_own (gpointer handle)
+{
+ return mutex_handle_own (handle, MONO_W32HANDLE_MUTEX);
+}
+
+static gboolean mutex_is_owned (gpointer handle)
+{
+
+ return mutex_handle_is_owned (handle, MONO_W32HANDLE_MUTEX);
+}
+
+static void namedmutex_signal (gpointer handle)
+{
+ ves_icall_System_Threading_Mutex_ReleaseMutex_internal (handle);
+}
+
+/* NB, always called with the shared handle lock held */
+static gboolean namedmutex_own (gpointer handle)
+{
+ return mutex_handle_own (handle, MONO_W32HANDLE_NAMEDMUTEX);
+}
+
+static gboolean namedmutex_is_owned (gpointer handle)
+{
+ return mutex_handle_is_owned (handle, MONO_W32HANDLE_NAMEDMUTEX);
+}
+
+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
+ * is still alive; if it isn't we override the previous owner
+ * and assume that process exited abnormally and failed to
+ * clean up.
+ */
+ MonoW32HandleMutex *mutex_handle;
+
+ if (!mono_w32handle_lookup (handle, type, (gpointer *)&mutex_handle)) {
+ g_warning ("%s: error looking up %s handle %p",
+ __func__, mono_w32handle_ops_typename (type), handle);
+ return;
+ }
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: pre-waiting %s handle %p, owned? %s",
+ __func__, mono_w32handle_ops_typename (type), handle, mutex_handle->recursion != 0 ? "true" : "false");
+}
+
+/* The shared state is not locked when prewait methods are called */
+static void mutex_prewait (gpointer handle)
+{
+ 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, MONO_W32HANDLE_NAMEDMUTEX);
+}
+
+static void mutex_details (gpointer data)
+{
+ MonoW32HandleMutex *mut = (MonoW32HandleMutex *)data;
+
+#ifdef PTHREAD_POINTER_ID
+ g_print ("own: %5p, count: %5u", mut->tid, mut->recursion);
+#else
+ g_print ("own: %5ld, count: %5u", mut->tid, mut->recursion);
+#endif
+}
+
+static void namedmutex_details (gpointer data)
+{
+ MonoW32HandleNamedMutex *namedmut = (MonoW32HandleNamedMutex *)data;
+
+#ifdef PTHREAD_POINTER_ID
+ g_print ("own: %5p, count: %5u, name: \"%s\"",
+ namedmut->m.tid, namedmut->m.recursion, namedmut->sharedns.name);
+#else
+ g_print ("own: %5ld, count: %5u, name: \"%s\"",
+ namedmut->m.tid, namedmut->m.recursion, namedmut->sharedns.name);
+#endif
+}
+
+static const gchar* mutex_typename (void)
+{
+ return "Mutex";
+}
+
+static gsize mutex_typesize (void)
+{
+ return sizeof (MonoW32HandleMutex);
+}
+
+static const gchar* namedmutex_typename (void)
+{
+ return "N.Mutex";
+}
+
+static gsize namedmutex_typesize (void)
+{
+ return sizeof (MonoW32HandleNamedMutex);
+}
+
+void
+mono_w32mutex_init (void)
+{
+ static MonoW32HandleOps mutex_ops = {
+ NULL, /* close */
+ mutex_signal, /* signal */
+ mutex_own, /* own */
+ mutex_is_owned, /* is_owned */
+ NULL, /* special_wait */
+ mutex_prewait, /* prewait */
+ mutex_details, /* details */
+ mutex_typename, /* typename */
+ mutex_typesize, /* typesize */
+ };
+
+ static MonoW32HandleOps namedmutex_ops = {
+ NULL, /* close */
+ namedmutex_signal, /* signal */
+ namedmutex_own, /* own */
+ namedmutex_is_owned, /* is_owned */
+ NULL, /* special_wait */
+ namedmutex_prewait, /* prewait */
+ namedmutex_details, /* details */
+ namedmutex_typename, /* typename */
+ namedmutex_typesize, /* typesize */
+ };
+
+ mono_w32handle_register_ops (MONO_W32HANDLE_MUTEX, &mutex_ops);
+ mono_w32handle_register_ops (MONO_W32HANDLE_NAMEDMUTEX, &namedmutex_ops);
+
+ 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 gpointer mutex_handle_create (MonoW32HandleMutex *mutex_handle, MonoW32HandleType type, gboolean owned)
+{
+ gpointer handle;
+ int thr_ret;
+
+ mutex_handle->tid = 0;
+ mutex_handle->recursion = 0;
+
+ handle = mono_w32handle_new (type, mutex_handle);
+ if (handle == INVALID_HANDLE_VALUE) {
+ g_warning ("%s: error creating %s handle",
+ __func__, mono_w32handle_ops_typename (type));
+ SetLastError (ERROR_GEN_FAILURE);
+ return NULL;
+ }
+
+ thr_ret = mono_w32handle_lock_handle (handle);
+ g_assert (thr_ret == 0);
+
+ if (owned)
+ mutex_handle_own (handle, type);
+ else
+ mono_w32handle_set_signal_state (handle, TRUE, FALSE);
+
+ 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",
+ __func__, mono_w32handle_ops_typename (type), handle);
+
+ return handle;
+}
+
+static gpointer mutex_create (gboolean owned)
+{
+ MonoW32HandleMutex mutex_handle;
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: creating %s handle",
+ __func__, mono_w32handle_ops_typename (MONO_W32HANDLE_MUTEX));
+ return mutex_handle_create (&mutex_handle, MONO_W32HANDLE_MUTEX, owned);
+}
+
+static gpointer namedmutex_create (gboolean owned, const gunichar2 *name)
+{
+ gpointer handle;
+ gchar *utf8_name;
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: creating %s handle",
+ __func__, mono_w32handle_ops_typename (MONO_W32HANDLE_NAMEDMUTEX));
+
+ /* w32 seems to guarantee that opening named objects can't race each other */
+ mono_w32handle_namespace_lock ();
+
+ utf8_name = g_utf16_to_utf8 (name, -1, NULL, NULL, NULL);
+
+ handle = mono_w32handle_namespace_search_handle (MONO_W32HANDLE_NAMEDMUTEX, utf8_name);
+ if (handle == INVALID_HANDLE_VALUE) {
+ /* The name has already been used for a different object. */
+ handle = NULL;
+ SetLastError (ERROR_INVALID_HANDLE);
+ } else if (handle) {
+ /* Not an error, but this is how the caller is informed that the mutex wasn't freshly created */
+ SetLastError (ERROR_ALREADY_EXISTS);
+
+ /* this is used as creating a new handle */
+ mono_w32handle_ref (handle);
+ } else {
+ /* A new named mutex */
+ MonoW32HandleNamedMutex namedmutex_handle;
+
+ strncpy (&namedmutex_handle.sharedns.name [0], utf8_name, MAX_PATH);
+ namedmutex_handle.sharedns.name [MAX_PATH] = '\0';
+
+ handle = mutex_handle_create ((MonoW32HandleMutex*) &namedmutex_handle, MONO_W32HANDLE_NAMEDMUTEX, owned);
+ }
+
+ g_free (utf8_name);
+
+ mono_w32handle_namespace_unlock ();
+
+ return handle;
+}
+
+gpointer
+ves_icall_System_Threading_Mutex_CreateMutex_internal (MonoBoolean owned, MonoString *name, MonoBoolean *created)
+{
+ gpointer mutex;
+
+ *created = TRUE;
+
+ /* Need to blow away any old errors here, because code tests
+ * for ERROR_ALREADY_EXISTS on success (!) to see if a mutex
+ * was freshly created */
+ SetLastError (ERROR_SUCCESS);
+
+ if (!name) {
+ mutex = mutex_create (owned);
+ } else {
+ mutex = namedmutex_create (owned, mono_string_chars (name));
+
+ if (GetLastError () == ERROR_ALREADY_EXISTS)
+ *created = FALSE;
+ }
+
+ return mutex;
+}
+
+MonoBoolean
+ves_icall_System_Threading_Mutex_ReleaseMutex_internal (gpointer handle)
+{
+ MonoW32HandleType type;
+ MonoW32HandleMutex *mutex_handle;
+ pthread_t tid;
+ int thr_ret;
+ gboolean ret;
+
+ if (handle == NULL) {
+ SetLastError (ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
+
+ switch (type = mono_w32handle_get_type (handle)) {
+ case MONO_W32HANDLE_MUTEX:
+ case MONO_W32HANDLE_NAMEDMUTEX:
+ break;
+ default:
+ SetLastError (ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
+
+ if (!mono_w32handle_lookup (handle, type, (gpointer *)&mutex_handle)) {
+ g_warning ("%s: error looking up %s handle %p",
+ __func__, mono_w32handle_ops_typename (type), handle);
+ return FALSE;
+ }
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: releasing %s handle %p",
+ __func__, mono_w32handle_ops_typename (type), handle);
+
+ thr_ret = mono_w32handle_lock_handle (handle);
+ g_assert (thr_ret == 0);
+
+ tid = pthread_self ();
+
+ if (!pthread_equal (mutex_handle->tid, tid)) {
+ ret = FALSE;
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: we don't own %s handle %p (owned by %ld, me %ld)",
+ __func__, mono_w32handle_ops_typename (type), handle, mutex_handle->tid, tid);
+ } else {
+ ret = TRUE;
+
+ /* OK, we own this mutex */
+ mutex_handle->recursion--;
+
+ if (mutex_handle->recursion == 0) {
+ mono_thread_info_disown_mutex (mono_thread_info_current (), handle);
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unlocking %s handle %p",
+ __func__, mono_w32handle_ops_typename (type), handle);
+
+ mutex_handle->tid = 0;
+ mono_w32handle_set_signal_state (handle, TRUE, FALSE);
+ }
+ }
+
+ thr_ret = mono_w32handle_unlock_handle (handle);
+ g_assert (thr_ret == 0);
+
+ return ret;
+}
+
+gpointer
+ves_icall_System_Threading_Mutex_OpenMutex_internal (MonoString *name, gint32 rights G_GNUC_UNUSED, gint32 *error)
+{
+ gpointer handle;
+ gchar *utf8_name;
+
+ *error = ERROR_SUCCESS;
+
+ /* w32 seems to guarantee that opening named objects can't race each other */
+ mono_w32handle_namespace_lock ();
+
+ utf8_name = g_utf16_to_utf8 (mono_string_chars (name), -1, NULL, NULL, NULL);
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Opening named mutex [%s]",
+ __func__, utf8_name);
+
+ handle = mono_w32handle_namespace_search_handle (MONO_W32HANDLE_NAMEDMUTEX, utf8_name);
+ if (handle == INVALID_HANDLE_VALUE) {
+ /* The name has already been used for a different object. */
+ *error = ERROR_INVALID_HANDLE;
+ goto cleanup;
+ } else if (!handle) {
+ /* This name doesn't exist */
+ *error = ERROR_FILE_NOT_FOUND;
+ goto cleanup;
+ }
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning named mutex handle %p",
+ __func__, handle);
+
+cleanup:
+ g_free (utf8_name);
+
+ mono_w32handle_namespace_unlock ();
+
+ return handle;
+}
+
+void
+mono_w32mutex_abandon (gpointer handle, MonoNativeThreadId tid)
+{
+ MonoW32HandleType type;
+ MonoW32HandleMutex *mutex_handle;
+ int thr_ret;
+
+ switch (type = mono_w32handle_get_type (handle)) {
+ case MONO_W32HANDLE_MUTEX:
+ case MONO_W32HANDLE_NAMEDMUTEX:
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ if (!mono_w32handle_lookup (handle, type, (gpointer *)&mutex_handle)) {
+ g_warning ("%s: error looking up %s handle %p",
+ __func__, mono_w32handle_ops_typename (type), handle);
+ return;
+ }
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: abandon %s handle %p",
+ __func__, mono_w32handle_ops_typename (type), 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;
+
+ mono_w32handle_set_signal_state (handle, TRUE, FALSE);
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: abandoned %s handle %p",
+ __func__, mono_w32handle_ops_typename (type), handle);
+ }
+
+ thr_ret = mono_w32handle_unlock_handle (handle);
+ g_assert (thr_ret == 0);
+}
+
+MonoW32HandleNamespace*
+mono_w32mutex_get_namespace (MonoW32HandleNamedMutex *mutex)
+{
+ return &mutex->sharedns;
+}
--- /dev/null
+
+/* This is just a hack so we can call mono_w32mutex_abandon
+ * from mono/utils/mono-threads-posix.c, without importing
+ * the whole object.h
+ * In the best of all world, mutex owning + disowning + abandoning
+ * should be done in metadata/ */
+
+#ifndef _MONO_METADATA_W32MUTEX_UTILS_H_
+#define _MONO_METADATA_W32MUTEX_UTILS_H_
+
+#include <config.h>
+#include <glib.h>
+
+#include "mono/utils/mono-threads.h"
+
+void
+mono_w32mutex_abandon (gpointer handle, MonoNativeThreadId tid);
+
+#endif /* _MONO_METADATA_W32MUTEX_UTILS_H_ */
+
--- /dev/null
+/*
+ * w32mutex-win32.c: Runtime support for managed Mutex on Win32
+ *
+ * Author:
+ * Ludovic Henry (luhenry@microsoft.com)
+ *
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+
+#include "w32mutex.h"
+
+#include <windows.h>
+#include <winbase.h>
+
+void
+mono_w32mutex_init (void)
+{
+}
+
+gpointer
+ves_icall_System_Threading_Mutex_CreateMutex_internal (MonoBoolean owned, MonoString *name, MonoBoolean *created)
+{
+ HANDLE mutex;
+
+ *created = TRUE;
+
+ if (!name) {
+ mutex = CreateMutex (NULL, owned, NULL);
+ } else {
+ mutex = CreateMutex (NULL, owned, mono_string_chars (name));
+
+ if (GetLastError () == ERROR_ALREADY_EXISTS)
+ *created = FALSE;
+ }
+
+ return mutex;
+}
+
+MonoBoolean
+ves_icall_System_Threading_Mutex_ReleaseMutex_internal (gpointer handle)
+{
+ return ReleaseMutex (handle);
+}
+
+gpointer
+ves_icall_System_Threading_Mutex_OpenMutex_internal (MonoString *name, gint32 rights, gint32 *error)
+{
+ HANDLE ret;
+
+ *error = ERROR_SUCCESS;
+
+ ret = OpenMutex (rights, FALSE, mono_string_chars (name));
+ if (!ret)
+ *error = GetLastError ();
+
+ return ret;
+}
--- /dev/null
+
+#ifndef _MONO_METADATA_W32MUTEX_H_
+#define _MONO_METADATA_W32MUTEX_H_
+
+#include <config.h>
+#include <glib.h>
+
+#include "object.h"
+#include "w32handle-namespace.h"
+
+void
+mono_w32mutex_init (void);
+
+gpointer
+ves_icall_System_Threading_Mutex_CreateMutex_internal (MonoBoolean owned, MonoString *name, MonoBoolean *created);
+
+MonoBoolean
+ves_icall_System_Threading_Mutex_ReleaseMutex_internal (gpointer handle);
+
+gpointer
+ves_icall_System_Threading_Mutex_OpenMutex_internal (MonoString *name, gint32 rights, gint32 *error);
+
+typedef struct MonoW32HandleNamedMutex MonoW32HandleNamedMutex;
+
+MonoW32HandleNamespace*
+mono_w32mutex_get_namespace (MonoW32HandleNamedMutex *mutex);
+
+#endif /* _MONO_METADATA_W32MUTEX_H_ */
--- /dev/null
+/*
+ * w32semaphore-unix.c: Runtime support for managed Semaphore on Unix
+ *
+ * Author:
+ * Ludovic Henry (luhenry@microsoft.com)
+ *
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+
+#include "w32semaphore.h"
+
+#include "w32handle-namespace.h"
+#include "mono/io-layer/io-layer.h"
+#include "mono/utils/mono-logger-internals.h"
+#include "mono/utils/w32handle.h"
+
+typedef struct {
+ guint32 val;
+ gint32 max;
+} MonoW32HandleSemaphore;
+
+struct MonoW32HandleNamedSemaphore {
+ MonoW32HandleSemaphore s;
+ MonoW32HandleNamespace sharedns;
+};
+
+static gboolean sem_handle_own (gpointer handle, MonoW32HandleType type)
+{
+ MonoW32HandleSemaphore *sem_handle;
+
+ if (!mono_w32handle_lookup (handle, type, (gpointer *)&sem_handle)) {
+ g_warning ("%s: error looking up %s handle %p",
+ __func__, mono_w32handle_ops_typename (type), handle);
+ return FALSE;
+ }
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: owning %s handle %p",
+ __func__, mono_w32handle_ops_typename (type), handle);
+
+ sem_handle->val--;
+
+ if (sem_handle->val == 0)
+ mono_w32handle_set_signal_state (handle, FALSE, FALSE);
+
+ return TRUE;
+}
+
+static void sema_signal(gpointer handle)
+{
+ ves_icall_System_Threading_Semaphore_ReleaseSemaphore_internal(handle, 1, NULL);
+}
+
+static gboolean sema_own (gpointer handle)
+{
+ return sem_handle_own (handle, MONO_W32HANDLE_SEM);
+}
+
+static void namedsema_signal (gpointer handle)
+{
+ ves_icall_System_Threading_Semaphore_ReleaseSemaphore_internal (handle, 1, NULL);
+}
+
+/* NB, always called with the shared handle lock held */
+static gboolean namedsema_own (gpointer handle)
+{
+ return sem_handle_own (handle, MONO_W32HANDLE_NAMEDSEM);
+}
+
+static void sema_details (gpointer data)
+{
+ MonoW32HandleSemaphore *sem = (MonoW32HandleSemaphore *)data;
+ g_print ("val: %5u, max: %5d", sem->val, sem->max);
+}
+
+static void namedsema_details (gpointer data)
+{
+ MonoW32HandleNamedSemaphore *namedsem = (MonoW32HandleNamedSemaphore *)data;
+ g_print ("val: %5u, max: %5d, name: \"%s\"", namedsem->s.val, namedsem->s.max, namedsem->sharedns.name);
+}
+
+static const gchar* sema_typename (void)
+{
+ return "Semaphore";
+}
+
+static gsize sema_typesize (void)
+{
+ return sizeof (MonoW32HandleSemaphore);
+}
+
+static const gchar* namedsema_typename (void)
+{
+ return "N.Semaphore";
+}
+
+static gsize namedsema_typesize (void)
+{
+ return sizeof (MonoW32HandleNamedSemaphore);
+}
+
+void
+mono_w32semaphore_init (void)
+{
+ static MonoW32HandleOps sem_ops = {
+ NULL, /* close */
+ sema_signal, /* signal */
+ sema_own, /* own */
+ NULL, /* is_owned */
+ NULL, /* special_wait */
+ NULL, /* prewait */
+ sema_details, /* details */
+ sema_typename, /* typename */
+ sema_typesize, /* typesize */
+ };
+
+ static MonoW32HandleOps namedsem_ops = {
+ NULL, /* close */
+ namedsema_signal, /* signal */
+ namedsema_own, /* own */
+ NULL, /* is_owned */
+ NULL, /* special_wait */
+ NULL, /* prewait */
+ namedsema_details, /* details */
+ namedsema_typename, /* typename */
+ namedsema_typesize, /* typesize */
+ };
+
+ mono_w32handle_register_ops (MONO_W32HANDLE_SEM, &sem_ops);
+ mono_w32handle_register_ops (MONO_W32HANDLE_NAMEDSEM, &namedsem_ops);
+
+ 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 gpointer
+sem_handle_create (MonoW32HandleSemaphore *sem_handle, MonoW32HandleType type, gint32 initial, gint32 max)
+{
+ gpointer handle;
+ int thr_ret;
+
+ sem_handle->val = initial;
+ sem_handle->max = max;
+
+ handle = mono_w32handle_new (type, sem_handle);
+ if (handle == INVALID_HANDLE_VALUE) {
+ g_warning ("%s: error creating %s handle",
+ __func__, mono_w32handle_ops_typename (type));
+ SetLastError (ERROR_GEN_FAILURE);
+ return NULL;
+ }
+
+ thr_ret = mono_w32handle_lock_handle (handle);
+ g_assert (thr_ret == 0);
+
+ if (initial != 0)
+ mono_w32handle_set_signal_state (handle, TRUE, FALSE);
+
+ 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",
+ __func__, mono_w32handle_ops_typename (type), handle);
+
+ return handle;
+}
+
+static gpointer
+sem_create (gint32 initial, gint32 max)
+{
+ MonoW32HandleSemaphore sem_handle;
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: creating %s handle, initial %d max %d",
+ __func__, mono_w32handle_ops_typename (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)
+{
+ gpointer handle;
+ gchar *utf8_name;
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: creating %s handle, initial %d max %d name \"%s\"",
+ __func__, mono_w32handle_ops_typename (MONO_W32HANDLE_NAMEDSEM), initial, max, name);
+
+ /* w32 seems to guarantee that opening named objects can't race each other */
+ mono_w32handle_namespace_lock ();
+
+ utf8_name = g_utf16_to_utf8 (name, -1, NULL, NULL, NULL);
+
+ 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 = mono_w32handle_namespace_search_handle (MONO_W32HANDLE_NAMEDSEM, utf8_name);
+ if (handle == INVALID_HANDLE_VALUE) {
+ /* The name has already been used for a different object. */
+ handle = NULL;
+ SetLastError (ERROR_INVALID_HANDLE);
+ } else if (handle) {
+ /* Not an error, but this is how the caller is informed that the semaphore wasn't freshly created */
+ SetLastError (ERROR_ALREADY_EXISTS);
+
+ /* this is used as creating a new handle */
+ mono_w32handle_ref (handle);
+ } else {
+ /* A new named semaphore */
+ MonoW32HandleNamedSemaphore namedsem_handle;
+
+ strncpy (&namedsem_handle.sharedns.name [0], utf8_name, MAX_PATH);
+ namedsem_handle.sharedns.name [MAX_PATH] = '\0';
+
+ handle = sem_handle_create ((MonoW32HandleSemaphore*) &namedsem_handle, MONO_W32HANDLE_NAMEDSEM, initial, max);
+ }
+
+ g_free (utf8_name);
+
+ mono_w32handle_namespace_unlock ();
+
+ return handle;
+}
+
+gpointer
+ves_icall_System_Threading_Semaphore_CreateSemaphore_internal (gint32 initialCount, gint32 maximumCount, MonoString *name, gint32 *error)
+{
+ gpointer sem;
+
+ if (maximumCount <= 0) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: maximumCount <= 0", __func__);
+
+ *error = ERROR_INVALID_PARAMETER;
+ return NULL;
+ }
+
+ if (initialCount > maximumCount || initialCount < 0) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: initialCount > maximumCount or < 0", __func__);
+
+ *error = ERROR_INVALID_PARAMETER;
+ return NULL;
+ }
+
+ /* Need to blow away any old errors here, because code tests
+ * for ERROR_ALREADY_EXISTS on success (!) to see if a
+ * semaphore was freshly created
+ */
+ SetLastError (ERROR_SUCCESS);
+
+ if (!name)
+ sem = sem_create (initialCount, maximumCount);
+ else
+ sem = namedsem_create (initialCount, maximumCount, mono_string_chars (name));
+
+ *error = GetLastError ();
+
+ return sem;
+}
+
+MonoBoolean
+ves_icall_System_Threading_Semaphore_ReleaseSemaphore_internal (gpointer handle, gint32 releaseCount, gint32 *prevcount)
+{
+ MonoW32HandleType type;
+ MonoW32HandleSemaphore *sem_handle;
+ int thr_ret;
+ MonoBoolean ret;
+
+ if (!handle) {
+ SetLastError (ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
+
+ switch (type = mono_w32handle_get_type (handle)) {
+ case MONO_W32HANDLE_SEM:
+ case MONO_W32HANDLE_NAMEDSEM:
+ break;
+ default:
+ SetLastError (ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
+
+ 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__, mono_w32handle_ops_typename (type), handle);
+
+ thr_ret = mono_w32handle_lock_handle (handle);
+ g_assert (thr_ret == 0);
+
+ /* Do this before checking for count overflow, because overflowing
+ * max is a listed technique for finding the current value */
+ if (prevcount)
+ *prevcount = sem_handle->val;
+
+ /* No idea why max is signed, but thats the spec :-( */
+ if (sem_handle->val + releaseCount > (guint32)sem_handle->max) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: %s handle %p val %d count %d max %d, max value would be exceeded",
+ __func__, mono_w32handle_ops_typename (type), handle, sem_handle->val, releaseCount, sem_handle->max);
+
+ ret = FALSE;
+ } else {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: %s handle %p val %d count %d max %d",
+ __func__, mono_w32handle_ops_typename (type), handle, sem_handle->val, releaseCount, sem_handle->max);
+
+ sem_handle->val += releaseCount;
+ mono_w32handle_set_signal_state (handle, TRUE, TRUE);
+
+ ret = TRUE;
+ }
+
+ thr_ret = mono_w32handle_unlock_handle (handle);
+ g_assert (thr_ret == 0);
+
+ return ret;
+}
+
+gpointer
+ves_icall_System_Threading_Semaphore_OpenSemaphore_internal (MonoString *name, gint32 rights, gint32 *error)
+{
+ gpointer handle;
+ gchar *utf8_name;
+
+ *error = ERROR_SUCCESS;
+
+ /* w32 seems to guarantee that opening named objects can't race each other */
+ mono_w32handle_namespace_lock ();
+
+ utf8_name = g_utf16_to_utf8 (mono_string_chars (name), -1, NULL, NULL, NULL);
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Opening named sem [%s]", __func__, utf8_name);
+
+ handle = mono_w32handle_namespace_search_handle (MONO_W32HANDLE_NAMEDSEM, utf8_name);
+ if (handle == INVALID_HANDLE_VALUE) {
+ /* The name has already been used for a different object. */
+ *error = ERROR_INVALID_HANDLE;
+ goto cleanup;
+ } else if (!handle) {
+ /* This name doesn't exist */
+ *error = ERROR_FILE_NOT_FOUND;
+ goto cleanup;
+ }
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning named sem handle %p", __func__, handle);
+
+cleanup:
+ g_free (utf8_name);
+
+ mono_w32handle_namespace_unlock ();
+
+ return handle;
+}
+
+MonoW32HandleNamespace*
+mono_w32semaphore_get_namespace (MonoW32HandleNamedSemaphore *semaphore)
+{
+ return &semaphore->sharedns;
+}
--- /dev/null
+/*
+ * w32semaphore-win32.c: Runtime support for managed Semaphore on Win32
+ *
+ * Author:
+ * Ludovic Henry (luhenry@microsoft.com)
+ *
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+
+#include "w32semaphore.h"
+
+#include <windows.h>
+#include <winbase.h>
+
+void
+mono_w32semaphore_init (void)
+{
+}
+
+gpointer
+ves_icall_System_Threading_Semaphore_CreateSemaphore_internal (gint32 initialCount, gint32 maximumCount, MonoString *name, gint32 *error)
+{
+ HANDLE sem;
+
+ sem = CreateSemaphore (NULL, initialCount, maximumCount, name ? mono_string_chars (name) : NULL);
+
+ *error = GetLastError ();
+
+ return sem;
+}
+
+MonoBoolean
+ves_icall_System_Threading_Semaphore_ReleaseSemaphore_internal (gpointer handle, gint32 releaseCount, gint32 *prevcount)
+{
+ return ReleaseSemaphore (handle, releaseCount, prevcount);
+}
+
+gpointer
+ves_icall_System_Threading_Semaphore_OpenSemaphore_internal (MonoString *name, gint32 rights, gint32 *error)
+{
+ HANDLE sem;
+
+ sem = OpenSemaphore (rights, FALSE, mono_string_chars (name));
+
+ *error = GetLastError ();
+
+ return sem;
+}
\ No newline at end of file
--- /dev/null
+
+#ifndef _MONO_METADATA_W32SEMAPHORE_H_
+#define _MONO_METADATA_W32SEMAPHORE_H_
+
+#include <config.h>
+#include <glib.h>
+
+#include "object.h"
+#include "w32handle-namespace.h"
+
+void
+mono_w32semaphore_init (void);
+
+gpointer
+ves_icall_System_Threading_Semaphore_CreateSemaphore_internal (gint32 initialCount, gint32 maximumCount, MonoString *name, gint32 *error);
+
+MonoBoolean
+ves_icall_System_Threading_Semaphore_ReleaseSemaphore_internal (gpointer handle, gint32 releaseCount, gint32 *prevcount);
+
+gpointer
+ves_icall_System_Threading_Semaphore_OpenSemaphore_internal (MonoString *name, gint32 rights, gint32 *error);
+
+typedef struct MonoW32HandleNamedSemaphore MonoW32HandleNamedSemaphore;
+
+MonoW32HandleNamespace*
+mono_w32semaphore_get_namespace (MonoW32HandleNamedSemaphore *semaphore);
+
+#endif /* _MONO_METADATA_W32SEMAPHORE_H_ */
#include <mono/utils/mono-threads-posix-signals.h>
#include <mono/utils/mono-coop-semaphore.h>
#include <mono/metadata/gc-internals.h>
+#include <mono/metadata/w32mutex-utils.h>
#include <mono/utils/w32handle.h>
#include <errno.h>
{
gpointer mutex_handle;
int i, thr_ret;
- pid_t pid;
pthread_t tid;
g_assert (info->handle);
if (mono_w32handle_get_type (info->handle) == MONO_W32HANDLE_UNUSED)
g_error ("%s: handle %p thread %p has already exited, it's handle type is 'unused'", __func__, info->handle, mono_thread_info_get_tid (info));
- pid = wapi_getpid ();
tid = pthread_self ();
for (i = 0; i < info->owned_mutexes->len; i++) {
mutex_handle = g_ptr_array_index (info->owned_mutexes, i);
- wapi_mutex_abandon (mutex_handle, pid, tid);
+ mono_w32mutex_abandon (mutex_handle, tid);
mono_thread_info_disown_mutex (info, mutex_handle);
}
<ClCompile Include="..\mono\metadata\class.c" />\r
<ClCompile Include="..\mono\metadata\cominterop.c" />\r
<ClCompile Include="..\mono\metadata\console-win32.c" />\r
+ <ClCompile Include="..\mono\metadata\w32mutex-win32.c" />\r
+ <ClCompile Include="..\mono\metadata\w32semaphore-win32.c" />\r
+ <ClCompile Include="..\mono\metadata\w32event-win32.c" />\r
<ClCompile Include="..\mono\metadata\coree.c" />\r
<ClCompile Include="..\mono\metadata\custom-attrs.c" />\r
<ClCompile Include="..\mono\metadata\debug-helpers.c" />\r
<ClCompile Include="..\mono\metadata\console-win32.c">\r
<Filter>Source Files</Filter>\r
</ClCompile>\r
+ <ClCompile Include="..\mono\metadata\w32mutex-win32.c">\r
+ <Filter>Source Files</Filter>\r
+ </ClCompile>\r
+ <ClCompile Include="..\mono\metadata\w32semaphore-win32.c">\r
+ <Filter>Source Files</Filter>\r
+ </ClCompile>\r
+ <ClCompile Include="..\mono\metadata\w32event-win32.c">\r
+ <Filter>Source Files</Filter>\r
+ </ClCompile>\r
<ClCompile Include="..\mono\metadata\coree.c">\r
<Filter>Source Files</Filter>\r
</ClCompile>\r