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 gboolean event_handle_own (gpointer handle, MonoW32HandleType type, guint32 *statuscode) { MonoW32HandleEvent *event_handle; gboolean ok; *statuscode = WAIT_OBJECT_0; 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 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; }
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; }
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 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 gboolean sem_handle_own (gpointer handle, MonoW32HandleType type, guint32 *statuscode) { MonoW32HandleSemaphore *sem_handle; *statuscode = WAIT_OBJECT_0; 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 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); /* mono_w32handle_namespace_search_handle already adds a ref to the 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 mono_w32handle_new_fd (MonoW32HandleType type, int fd, gpointer handle_specific) { MonoW32HandleBase *handle_data; int fd_index, fd_offset; g_assert (!shutting_down); g_assert(type_is_fd(type)); if (fd >= mono_w32handle_fd_reserve) { mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: failed to create %s handle, fd is too big", __func__, mono_w32handle_ops_typename (type)); return(GUINT_TO_POINTER (INVALID_HANDLE_VALUE)); } fd_index = SLOT_INDEX (fd); fd_offset = SLOT_OFFSET (fd); /* Initialize the array entries on demand */ if (!private_handles [fd_index]) { mono_os_mutex_lock (&scan_mutex); if (!private_handles [fd_index]) private_handles [fd_index] = g_new0 (MonoW32HandleBase, HANDLE_PER_SLOT); mono_os_mutex_unlock (&scan_mutex); } handle_data = &private_handles [fd_index][fd_offset]; if (handle_data->type != MONO_W32HANDLE_UNUSED) { mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: failed to create %s handle, fd is already in use", __func__, mono_w32handle_ops_typename (type)); /* FIXME: clean up this handle? We can't do anything * with the fd, cos thats the new one */ return(GUINT_TO_POINTER (INVALID_HANDLE_VALUE)); } mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: create %s handle %p", __func__, mono_w32handle_ops_typename (type), GUINT_TO_POINTER(fd)); mono_w32handle_init_handle (handle_data, type, handle_specific); return(GUINT_TO_POINTER(fd)); }
gpointer mono_w32handle_new (MonoW32HandleType type, gpointer handle_specific) { guint32 handle_idx = 0; gpointer handle; g_assert (!shutting_down); g_assert(!type_is_fd(type)); mono_os_mutex_lock (&scan_mutex); while ((handle_idx = mono_w32handle_new_internal (type, handle_specific)) == 0) { /* Try and expand the array, and have another go */ int idx = SLOT_INDEX (private_handles_count); if (idx >= SLOT_MAX) { break; } private_handles [idx] = g_new0 (MonoW32HandleBase, HANDLE_PER_SLOT); private_handles_count += HANDLE_PER_SLOT; private_handles_slots_count ++; } mono_os_mutex_unlock (&scan_mutex); if (handle_idx == 0) { /* We ran out of slots */ handle = INVALID_HANDLE_VALUE; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: failed to create %s handle", __func__, mono_w32handle_ops_typename (type)); goto done; } /* Make sure we left the space for fd mappings */ g_assert (handle_idx >= mono_w32handle_fd_reserve); handle = GUINT_TO_POINTER (handle_idx); mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: create %s handle %p", __func__, mono_w32handle_ops_typename (type), handle); done: 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);