#include <mono/io-layer/wapi.h>
#include <mono/io-layer/wapi-private.h>
-#include <mono/io-layer/handles-private.h>
#include <mono/io-layer/semaphore-private.h>
+#include <mono/io-layer/io-trace.h>
#include <mono/utils/mono-once.h>
-
-#if 0
-#define DEBUG(...) g_message(__VA_ARGS__)
-#else
-#define DEBUG(...)
-#endif
+#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);
-struct _WapiHandleOps _wapi_sem_ops = {
+static MonoW32HandleOps _wapi_sem_ops = {
NULL, /* close */
sema_signal, /* signal */
sema_own, /* own */
NULL, /* is_owned */
NULL, /* special_wait */
- NULL /* prewait */
+ NULL, /* prewait */
+ sema_details, /* details */
+ sema_typename, /* typename */
+ sema_typesize, /* typesize */
};
-void _wapi_sem_details (gpointer handle_info)
-{
- struct _WapiHandle_sem *sem = (struct _WapiHandle_sem *)handle_info;
-
- g_print ("val: %5u, max: %5d", sem->val, sem->max);
-}
-
-struct _WapiHandleOps _wapi_namedsem_ops = {
+static MonoW32HandleOps _wapi_namedsem_ops = {
NULL, /* close */
namedsema_signal, /* signal */
namedsema_own, /* own */
NULL, /* is_owned */
NULL, /* special_wait */
- NULL /* prewait */
+ NULL, /* prewait */
+ namedsema_details, /* details */
+ namedsema_typename, /* typename */
+ namedsema_typesize, /* typesize */
};
-static gboolean sem_release (gpointer handle, gint32 count, gint32 *prev);
-static gboolean namedsem_release (gpointer handle, gint32 count, gint32 *prev);
-
-static struct
+void
+_wapi_semaphore_init (void)
{
- gboolean (*release)(gpointer handle, gint32 count, gint32 *prev);
-} sem_ops[WAPI_HANDLE_COUNT] = {
- {NULL},
- {NULL},
- {NULL},
- {NULL},
- {sem_release},
- {NULL},
- {NULL},
- {NULL},
- {NULL},
- {NULL},
- {NULL},
- {NULL},
- {namedsem_release},
-};
-
-static mono_once_t sem_ops_once=MONO_ONCE_INIT;
+ mono_w32handle_register_ops (MONO_W32HANDLE_SEM, &_wapi_sem_ops);
+ mono_w32handle_register_ops (MONO_W32HANDLE_NAMEDSEM, &_wapi_namedsem_ops);
-static void sem_ops_init (void)
-{
- _wapi_handle_register_capabilities (WAPI_HANDLE_SEM,
- (WapiHandleCapability)(WAPI_HANDLE_CAP_WAIT | WAPI_HANDLE_CAP_SIGNAL));
- _wapi_handle_register_capabilities (WAPI_HANDLE_NAMEDSEM,
- (WapiHandleCapability)(WAPI_HANDLE_CAP_WAIT | WAPI_HANDLE_CAP_SIGNAL));
+ mono_w32handle_register_capabilities (MONO_W32HANDLE_SEM,
+ (MonoW32HandleCapability)(MONO_W32HANDLE_CAP_WAIT | MONO_W32HANDLE_CAP_SIGNAL));
+ mono_w32handle_register_capabilities (MONO_W32HANDLE_NAMEDSEM,
+ (MonoW32HandleCapability)(MONO_W32HANDLE_CAP_WAIT | MONO_W32HANDLE_CAP_SIGNAL));
}
-static void sema_signal(gpointer handle)
+static const char* sem_handle_type_to_string (MonoW32HandleType type)
{
- ReleaseSemaphore(handle, 1, NULL);
+ switch (type) {
+ case MONO_W32HANDLE_SEM: return "sem";
+ case MONO_W32HANDLE_NAMEDSEM: return "named sem";
+ default:
+ g_assert_not_reached ();
+ }
}
-static gboolean sema_own (gpointer handle)
+static gboolean sem_handle_own (gpointer handle, MonoW32HandleType type)
{
struct _WapiHandle_sem *sem_handle;
- gboolean ok;
-
- ok=_wapi_lookup_handle (handle, WAPI_HANDLE_SEM,
- (gpointer *)&sem_handle);
- if(ok==FALSE) {
- g_warning ("%s: error looking up sem handle %p", __func__,
- handle);
- return(FALSE);
+
+ 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;
}
-
- DEBUG("%s: owning sem handle %p", __func__, handle);
+
+ 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--;
-
- DEBUG ("%s: sem %p val now %d", __func__, handle, sem_handle->val);
- if(sem_handle->val==0) {
- _wapi_handle_set_signal_state (handle, FALSE, FALSE);
- }
+ 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);
+}
- return(TRUE);
+static gboolean sema_own (gpointer handle)
+{
+ return sem_handle_own (handle, MONO_W32HANDLE_SEM);
}
static void namedsema_signal (gpointer handle)
/* NB, always called with the shared handle lock held */
static gboolean namedsema_own (gpointer handle)
{
- struct _WapiHandle_namedsem *namedsem_handle;
- gboolean ok;
-
- DEBUG ("%s: owning named sem handle %p", __func__, handle);
-
- ok = _wapi_lookup_handle (handle, WAPI_HANDLE_NAMEDSEM,
- (gpointer *)&namedsem_handle);
- if (ok == FALSE) {
- g_warning ("%s: error looking up named sem handle %p",
- __func__, handle);
- return (FALSE);
- }
-
- namedsem_handle->val--;
-
- DEBUG ("%s: named sem %p val now %d", __func__, handle,
- namedsem_handle->val);
+ return sem_handle_own (handle, MONO_W32HANDLE_NAMEDSEM);
+}
- if (namedsem_handle->val == 0) {
- _wapi_shared_handle_set_signal_state (handle, FALSE);
- }
-
- return (TRUE);
+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 gpointer sem_create (WapiSecurityAttributes *security G_GNUC_UNUSED,
- gint32 initial, gint32 max)
+
+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)
{
- struct _WapiHandle_sem sem_handle = {0};
gpointer handle;
int thr_ret;
-
- /* 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);
-
- sem_handle.val = initial;
- sem_handle.max = max;
- handle = _wapi_handle_new (WAPI_HANDLE_SEM, &sem_handle);
- if (handle == _WAPI_HANDLE_INVALID) {
- g_warning ("%s: error creating semaphore handle", __func__);
+ 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);
+ return NULL;
}
- thr_ret = _wapi_handle_lock_handle (handle);
+ thr_ret = mono_w32handle_lock_handle (handle);
g_assert (thr_ret == 0);
-
- if (initial != 0) {
- _wapi_handle_set_signal_state (handle, TRUE, FALSE);
- }
- DEBUG ("%s: Created semaphore handle %p initial %d max %d",
- __func__, handle, initial, max);
+ if (initial != 0)
+ mono_w32handle_set_signal_state (handle, TRUE, FALSE);
- thr_ret = _wapi_handle_unlock_handle (handle);
+ thr_ret = mono_w32handle_unlock_handle (handle);
g_assert (thr_ret == 0);
- return(handle);
+ 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 (WapiSecurityAttributes *security G_GNUC_UNUSED, gint32 initial, gint32 max, const gunichar2 *name G_GNUC_UNUSED)
+static gpointer namedsem_create (gint32 initial, gint32 max, const gunichar2 *name)
{
- struct _WapiHandle_namedsem namedsem_handle = {{{0}}, 0};
gpointer handle;
gchar *utf8_name;
int thr_ret;
- gpointer ret = NULL;
- guint32 namelen;
- gint32 offset;
-
- /* w32 seems to guarantee that opening named objects can't
- * race each other
- */
+
+ 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);
-
- /* 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);
utf8_name = g_utf16_to_utf8 (name, -1, NULL, NULL, NULL);
-
- DEBUG ("%s: Creating named sem [%s]", __func__, utf8_name);
- offset = _wapi_search_handle_namespace (WAPI_HANDLE_NAMEDSEM,
- utf8_name);
- if (offset == -1) {
- /* The name has already been used for a different
- * object.
- */
+ 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);
- goto cleanup;
- } else if (offset != 0) {
- /* Not an error, but this is how the caller is
- * informed that the semaphore wasn't freshly created
- */
+ } 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);
- }
- /* Fall through to create the semaphore handle */
-
- if (offset == 0) {
- /* A new named semaphore, so create both the private
- * and shared parts
- */
- if (strlen (utf8_name) < MAX_PATH) {
- namelen = strlen (utf8_name);
- } else {
- namelen = MAX_PATH;
- }
-
- memcpy (&namedsem_handle.sharedns.name, utf8_name, namelen);
-
- namedsem_handle.val = initial;
- namedsem_handle.max = max;
- handle = _wapi_handle_new (WAPI_HANDLE_NAMEDSEM,
- &namedsem_handle);
+ /* this is used as creating a new handle */
+ mono_w32handle_ref (handle);
} else {
- /* A new reference to an existing named semaphore, so
- * just create the private part
- */
- handle = _wapi_handle_new_from_offset (WAPI_HANDLE_NAMEDSEM,
- offset, TRUE);
- }
-
- if (handle == _WAPI_HANDLE_INVALID) {
- g_warning ("%s: error creating named sem handle", __func__);
- SetLastError (ERROR_GEN_FAILURE);
- goto cleanup;
- }
- ret = handle;
-
- if (offset == 0) {
- /* Set the initial state, as this is a completely new
- * handle
- */
- thr_ret = _wapi_handle_lock_shared_handles ();
- g_assert (thr_ret == 0);
-
- if (initial != 0) {
- _wapi_shared_handle_set_signal_state (handle, TRUE);
- }
-
- _wapi_handle_unlock_shared_handles ();
+ /* 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);
}
-
- DEBUG ("%s: returning named sem handle %p", __func__, handle);
-cleanup:
g_free (utf8_name);
-
- _wapi_namespace_unlock (NULL);
-
- return (ret);
+
+ thr_ret = _wapi_namespace_unlock (NULL);
+ g_assert (thr_ret == 0);
+
+ return handle;
}
*/
gpointer CreateSemaphore(WapiSecurityAttributes *security G_GNUC_UNUSED, gint32 initial, gint32 max, const gunichar2 *name)
{
- mono_once (&sem_ops_once, sem_ops_init);
-
if (max <= 0) {
- DEBUG ("%s: max <= 0", __func__);
+ 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) {
- DEBUG ("%s: initial>max or < 0", __func__);
+ MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: initial>max or < 0", __func__);
SetLastError (ERROR_INVALID_PARAMETER);
return(NULL);
}
- if (name == NULL) {
- return (sem_create (security, initial, max));
- } else {
- return (namedsem_create (security, initial, max, name));
- }
-}
-
-static gboolean sem_release (gpointer handle, gint32 count, gint32 *prevcount)
-{
- struct _WapiHandle_sem *sem_handle;
- gboolean ok;
- gboolean ret=FALSE;
- int thr_ret;
-
- ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SEM,
- (gpointer *)&sem_handle);
- if (ok == FALSE) {
- g_warning ("%s: error looking up sem handle %p", __func__,
- handle);
- return(FALSE);
- }
-
- thr_ret = _wapi_handle_lock_handle (handle);
- g_assert (thr_ret == 0);
-
- DEBUG ("%s: sem %p val %d count %d", __func__, handle,
- sem_handle->val, count);
-
- /* Do this before checking for count overflow, because overflowing max
- * is a listed technique for finding the current value
- */
- if (prevcount != NULL) {
- *prevcount = sem_handle->val;
- }
-
- /* No idea why max is signed, but thats the spec :-( */
- if (sem_handle->val + count > (guint32)sem_handle->max) {
- DEBUG ("%s: sem %p max value would be exceeded: max %d current %d count %d", __func__, handle, sem_handle->max, sem_handle->val, count);
-
- goto end;
- }
-
- sem_handle->val += count;
- _wapi_handle_set_signal_state (handle, TRUE, TRUE);
-
- ret = TRUE;
-
- DEBUG ("%s: sem %p val now %d", __func__, handle, sem_handle->val);
-
-end:
- thr_ret = _wapi_handle_unlock_handle (handle);
- g_assert (thr_ret == 0);
-
- return(ret);
-}
-
-static gboolean namedsem_release (gpointer handle, gint32 count,
- gint32 *prevcount)
-{
- struct _WapiHandle_namedsem *sem_handle;
- gboolean ok;
- gboolean ret=FALSE;
- int thr_ret;
-
- ok = _wapi_lookup_handle (handle, WAPI_HANDLE_NAMEDSEM,
- (gpointer *)&sem_handle);
- if (ok == FALSE) {
- g_warning ("%s: error looking up sem handle %p", __func__,
- handle);
- return(FALSE);
- }
-
- thr_ret = _wapi_handle_lock_shared_handles ();
- g_assert (thr_ret == 0);
-
- DEBUG("%s: named sem %p val %d count %d", __func__, handle,
- sem_handle->val, count);
-
- /* Do this before checking for count overflow, because overflowing max
- * is a listed technique for finding the current value
+ /* 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
*/
- if (prevcount != NULL) {
- *prevcount = sem_handle->val;
- }
-
- /* No idea why max is signed, but thats the spec :-( */
- if (sem_handle->val + count > (guint32)sem_handle->max) {
- DEBUG ("%s: named sem %p max value would be exceeded: max %d current %d count %d", __func__, handle, sem_handle->max, sem_handle->val, count);
-
- goto end;
- }
-
- sem_handle->val += count;
- _wapi_shared_handle_set_signal_state (handle, TRUE);
-
- ret = TRUE;
-
- DEBUG("%s: named sem %p val now %d", __func__, handle,
- sem_handle->val);
-
-end:
- _wapi_handle_unlock_shared_handles ();
+ SetLastError (ERROR_SUCCESS);
- return(ret);
+ return name ? namedsem_create (initial, max, name) : sem_create (initial, max);
}
/**
*/
gboolean ReleaseSemaphore(gpointer handle, gint32 count, gint32 *prevcount)
{
- WapiHandleType type;
-
- if (handle == NULL) {
+ MonoW32HandleType type;
+ struct _WapiHandle_sem *sem_handle;
+ int thr_ret;
+ gboolean ret;
+
+ if (!handle) {
SetLastError (ERROR_INVALID_HANDLE);
- return (FALSE);
+ return FALSE;
}
-
- type = _wapi_handle_type (handle);
-
- if (sem_ops[type].release == NULL) {
+
+ switch (type = mono_w32handle_get_type (handle)) {
+ case MONO_W32HANDLE_SEM:
+ case MONO_W32HANDLE_NAMEDSEM:
+ break;
+ default:
SetLastError (ERROR_INVALID_HANDLE);
- return (FALSE);
+ return FALSE;
}
-
- return (sem_ops[type].release (handle, count, prevcount));
+
+ 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,
gpointer handle;
gchar *utf8_name;
int thr_ret;
- gpointer ret = NULL;
- gint32 offset;
- mono_once (&sem_ops_once, sem_ops_init);
-
/* w32 seems to guarantee that opening named objects can't
* race each other
*/
utf8_name = g_utf16_to_utf8 (name, -1, NULL, NULL, NULL);
- DEBUG ("%s: Opening named sem [%s]", __func__, utf8_name);
+ MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Opening named sem [%s]", __func__, utf8_name);
- offset = _wapi_search_handle_namespace (WAPI_HANDLE_NAMEDSEM,
+ handle = _wapi_search_handle_namespace (MONO_W32HANDLE_NAMEDSEM,
utf8_name);
- if (offset == -1) {
+ if (handle == INVALID_HANDLE_VALUE) {
/* The name has already been used for a different
* object.
*/
SetLastError (ERROR_INVALID_HANDLE);
goto cleanup;
- } else if (offset == 0) {
+ } else if (!handle) {
/* This name doesn't exist */
SetLastError (ERROR_FILE_NOT_FOUND); /* yes, really */
goto cleanup;
}
- /* A new reference to an existing named semaphore, so just
- * create the private part
- */
- handle = _wapi_handle_new_from_offset (WAPI_HANDLE_NAMEDSEM, offset,
- TRUE);
-
- if (handle == _WAPI_HANDLE_INVALID) {
- g_warning ("%s: error opening named sem handle", __func__);
- SetLastError (ERROR_GEN_FAILURE);
- goto cleanup;
- }
- ret = handle;
-
- DEBUG ("%s: returning named sem handle %p", __func__, handle);
+ 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 (ret);
+ return handle;
}