void mono_w32mutex_abandon (MonoInternalThread *internal_raw) { HANDLE_FUNCTION_ENTER () MONO_HANDLE_DCL (MonoInternalThread, internal); g_assert (mono_thread_internal_is_current_handle (internal)); if (!MONO_HANDLE_GETVAL (internal, owned_mutexes)) goto exit; while (MONO_HANDLE_GETVAL (internal, owned_mutexes)->len) { MonoW32Handle *handle_data; MonoW32HandleMutex *mutex_handle; MonoNativeThreadId tid; gpointer handle; handle = g_ptr_array_index (MONO_HANDLE_GETVAL (internal, owned_mutexes), 0); if (!mono_w32handle_lookup_and_ref (handle, &handle_data)) g_error ("%s: unkown handle %p", __func__, handle); if (handle_data->type != MONO_W32TYPE_MUTEX && handle_data->type != MONO_W32TYPE_NAMEDMUTEX) g_error ("%s: unkown mutex handle %p", __func__, handle); mutex_handle = (MonoW32HandleMutex*) handle_data->specific; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_MUTEX, "%s: abandoning %s handle %p", __func__, mono_w32handle_get_typename (handle_data->type), handle); tid = MONO_UINT_TO_NATIVE_THREAD_ID (MONO_HANDLE_GETVAL (internal, tid)); if (!pthread_equal (mutex_handle->tid, tid)) g_error ("%s: trying to release mutex %p acquired by thread %p from thread %p", __func__, handle, (gpointer) mutex_handle->tid, (gpointer) tid); mono_w32handle_lock (handle_data); mutex_handle->recursion = 0; mutex_handle->tid = 0; mutex_handle->abandoned = TRUE; mono_w32handle_set_signal_state (handle_data, TRUE, FALSE); thread_disown_mutex (internal, handle); mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_MUTEX, "%s: abandoned %s handle %p", __func__, mono_w32handle_get_typename (handle_data->type), handle); mono_w32handle_unlock (handle_data); mono_w32handle_unref (handle_data); } g_ptr_array_free (MONO_HANDLE_GETVAL (internal, owned_mutexes), TRUE); MONO_HANDLE_SETVAL(internal, owned_mutexes, GPtrArray*, NULL); exit: HANDLE_FUNCTION_RETURN (); }
static gpointer sem_handle_create (MonoW32HandleSemaphore *sem_handle, MonoW32HandleType type, gint32 initial, gint32 max) { gpointer handle; 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_get_typename (type)); SetLastError (ERROR_GEN_FAILURE); return NULL; } mono_w32handle_lock_handle (handle); if (initial != 0) mono_w32handle_set_signal_state (handle, TRUE, FALSE); mono_w32handle_unlock_handle (handle); mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: created %s handle %p", __func__, mono_w32handle_get_typename (type), handle); return handle; }
static gboolean mutex_handle_own (gpointer handle, MonoW32HandleType type, gboolean *abandoned) { MonoW32HandleMutex *mutex_handle; *abandoned = FALSE; if (!mono_w32handle_lookup (handle, type, (gpointer *)&mutex_handle)) { g_warning ("%s: error looking up %s handle %p", __func__, mono_w32handle_get_typename (type), handle); return FALSE; } mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: owning %s handle %p, before: [tid: %p, recursion: %d], after: [tid: %p, recursion: %d], abandoned: %s", __func__, mono_w32handle_get_typename (type), handle, (gpointer) mutex_handle->tid, mutex_handle->recursion, (gpointer) pthread_self (), mutex_handle->recursion + 1, mutex_handle->abandoned ? "true" : "false"); if (mutex_handle->recursion != 0) { g_assert (pthread_equal (pthread_self (), mutex_handle->tid)); mutex_handle->recursion++; } else { mutex_handle->tid = pthread_self (); mutex_handle->recursion = 1; thread_own_mutex (mono_thread_internal_current (), handle); } if (mutex_handle->abandoned) { mutex_handle->abandoned = FALSE; *abandoned = TRUE; } mono_w32handle_set_signal_state (handle, FALSE, FALSE); return TRUE; }
static void mutex_handle_signal (MonoW32Handle *handle_data) { MonoW32HandleMutex *mutex_handle; pthread_t tid; mutex_handle = (MonoW32HandleMutex*) handle_data->specific; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_MUTEX, "%s: signalling %s handle %p, tid: %p recursion: %d", __func__, mono_w32handle_get_typename (handle_data->type), handle_data, (gpointer) mutex_handle->tid, mutex_handle->recursion); tid = pthread_self (); if (mutex_handle->abandoned) { mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_MUTEX, "%s: %s handle %p is abandoned", __func__, mono_w32handle_get_typename (handle_data->type), handle_data); } else if (!pthread_equal (mutex_handle->tid, tid)) { mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_MUTEX, "%s: we don't own %s handle %p (owned by %ld, me %ld)", __func__, mono_w32handle_get_typename (handle_data->type), handle_data, (long)mutex_handle->tid, (long)tid); } else { /* OK, we own this mutex */ mutex_handle->recursion--; if (mutex_handle->recursion == 0) { thread_disown_mutex (mono_thread_internal_current (), handle_data); mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_MUTEX, "%s: unlocking %s handle %p, tid: %p recusion : %d", __func__, mono_w32handle_get_typename (handle_data->type), handle_data, (gpointer) mutex_handle->tid, mutex_handle->recursion); mutex_handle->tid = 0; mono_w32handle_set_signal_state (handle_data, TRUE, FALSE); } } }
MonoBoolean ves_icall_System_Threading_Mutex_ReleaseMutex_internal (gpointer handle) { MonoW32Handle *handle_data; MonoW32HandleMutex *mutex_handle; pthread_t tid; gboolean ret; if (!mono_w32handle_lookup_and_ref (handle, &handle_data)) { g_warning ("%s: unkown handle %p", __func__, handle); mono_w32error_set_last (ERROR_INVALID_HANDLE); return FALSE; } if (handle_data->type != MONO_W32TYPE_MUTEX && handle_data->type != MONO_W32TYPE_NAMEDMUTEX) { g_warning ("%s: unknown mutex handle %p", __func__, handle); mono_w32error_set_last (ERROR_INVALID_HANDLE); mono_w32handle_unref (handle_data); return FALSE; } mutex_handle = (MonoW32HandleMutex*) handle_data->specific; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_MUTEX, "%s: releasing %s handle %p, tid: %p recursion: %d", __func__, mono_w32handle_get_typename (handle_data->type), handle, (gpointer) mutex_handle->tid, mutex_handle->recursion); mono_w32handle_lock (handle_data); tid = pthread_self (); if (mutex_handle->abandoned) { // The Win32 ReleaseMutex() function returns TRUE for abandoned mutexes ret = TRUE; } else if (!pthread_equal (mutex_handle->tid, tid)) { ret = FALSE; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_MUTEX, "%s: we don't own %s handle %p (owned by %ld, me %ld)", __func__, mono_w32handle_get_typename (handle_data->type), handle, (long)mutex_handle->tid, (long)tid); } else { ret = TRUE; /* OK, we own this mutex */ mutex_handle->recursion--; if (mutex_handle->recursion == 0) { thread_disown_mutex (mono_thread_internal_current_handle (), handle); mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_MUTEX, "%s: unlocking %s handle %p, tid: %p recusion : %d", __func__, mono_w32handle_get_typename (handle_data->type), handle, (gpointer) mutex_handle->tid, mutex_handle->recursion); mutex_handle->tid = 0; mono_w32handle_set_signal_state (handle_data, TRUE, FALSE); } } mono_w32handle_unlock (handle_data); mono_w32handle_unref (handle_data); return ret; }
static gpointer mutex_handle_create (MonoW32HandleMutex *mutex_handle, MonoW32HandleType type, gboolean owned) { gpointer handle; gboolean abandoned; mutex_handle->tid = 0; mutex_handle->recursion = 0; mutex_handle->abandoned = FALSE; handle = mono_w32handle_new (type, mutex_handle); if (handle == INVALID_HANDLE_VALUE) { g_warning ("%s: error creating %s handle", __func__, mono_w32handle_get_typename (type)); mono_w32error_set_last (ERROR_GEN_FAILURE); return NULL; } mono_w32handle_lock_handle (handle); if (owned) mutex_handle_own (handle, type, &abandoned); else mono_w32handle_set_signal_state (handle, TRUE, FALSE); mono_w32handle_unlock_handle (handle); mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: created %s handle %p", __func__, mono_w32handle_get_typename (type), handle); return handle; }
MonoBoolean ves_icall_System_Threading_Semaphore_ReleaseSemaphore_internal (gpointer handle, gint32 releaseCount, gint32 *prevcount) { MonoW32HandleType type; MonoW32HandleSemaphore *sem_handle; 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_get_typename (type), handle); mono_w32handle_lock_handle (handle); /* 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_get_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_get_typename (type), handle, sem_handle->val, releaseCount, sem_handle->max); sem_handle->val += releaseCount; mono_w32handle_set_signal_state (handle, TRUE, TRUE); ret = TRUE; } mono_w32handle_unlock_handle (handle); return ret; }
void mono_w32mutex_abandon (MonoInternalThread *internal) { g_assert (mono_thread_internal_is_current (internal)); if (!internal->owned_mutexes) return; while (internal->owned_mutexes->len) { MonoW32Handle *handle_data; MonoW32HandleMutex *mutex_handle; MonoNativeThreadId tid; gpointer handle; handle = g_ptr_array_index (internal->owned_mutexes, 0); if (!mono_w32handle_lookup_and_ref (handle, &handle_data)) g_error ("%s: unkown handle %p", __func__, handle); if (handle_data->type != MONO_W32TYPE_MUTEX && handle_data->type != MONO_W32TYPE_NAMEDMUTEX) g_error ("%s: unkown mutex handle %p", __func__, handle); mutex_handle = (MonoW32HandleMutex*) handle_data->specific; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_MUTEX, "%s: abandoning %s handle %p", __func__, mono_w32handle_get_typename (handle_data->type), handle); tid = MONO_UINT_TO_NATIVE_THREAD_ID (internal->tid); if (!pthread_equal (mutex_handle->tid, tid)) g_error ("%s: trying to release mutex %p acquired by thread %p from thread %p", __func__, handle, (gpointer) mutex_handle->tid, (gpointer) tid); mono_w32handle_lock (handle_data); mutex_handle->recursion = 0; mutex_handle->tid = 0; mutex_handle->abandoned = TRUE; mono_w32handle_set_signal_state (handle_data, TRUE, FALSE); thread_disown_mutex (internal, handle); mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_MUTEX, "%s: abandoned %s handle %p", __func__, mono_w32handle_get_typename (handle_data->type), handle); mono_w32handle_unlock (handle_data); mono_w32handle_unref (handle_data); } g_ptr_array_free (internal->owned_mutexes, TRUE); internal->owned_mutexes = NULL; }
static gpointer event_create (gboolean manual, gboolean initial) { MonoW32HandleEvent event_handle; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_EVENT, "%s: creating %s handle", __func__, mono_w32handle_get_typename (MONO_W32TYPE_EVENT)); return event_handle_create (&event_handle, MONO_W32TYPE_EVENT, manual, initial); }
static gboolean mutex_handle_own (MonoW32Handle *handle_data, gboolean *abandoned) { HANDLE_FUNCTION_ENTER (); MonoW32HandleMutex *mutex_handle; *abandoned = FALSE; mutex_handle = (MonoW32HandleMutex*) handle_data->specific; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_MUTEX, "%s: owning %s handle %p, before: [tid: %p, recursion: %d], after: [tid: %p, recursion: %d], abandoned: %s", __func__, mono_w32handle_get_typename (handle_data->type), handle_data, (gpointer) mutex_handle->tid, mutex_handle->recursion, (gpointer) pthread_self (), mutex_handle->recursion + 1, mutex_handle->abandoned ? "true" : "false"); if (mutex_handle->recursion != 0) { g_assert (pthread_equal (pthread_self (), mutex_handle->tid)); mutex_handle->recursion++; } else { mutex_handle->tid = pthread_self (); mutex_handle->recursion = 1; thread_own_mutex (mono_thread_internal_current_handle (), handle_data, handle_data); } if (mutex_handle->abandoned) { mutex_handle->abandoned = FALSE; *abandoned = TRUE; } mono_w32handle_set_signal_state (handle_data, FALSE, FALSE); HANDLE_FUNCTION_RETURN_VAL (TRUE); }
static gpointer mutex_create (gboolean owned) { MonoW32HandleMutex mutex_handle; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_MUTEX, "%s: creating %s handle", __func__, mono_w32handle_get_typename (MONO_W32TYPE_MUTEX)); return mutex_handle_create (&mutex_handle, MONO_W32TYPE_MUTEX, owned); }
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_get_typename (MONO_W32HANDLE_SEM), initial, max); return sem_handle_create (&sem_handle, MONO_W32HANDLE_SEM, initial, max); }
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_get_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_get_typename (type), handle, mutex_handle->recursion != 0 ? "true" : "false"); }
static gboolean mutex_handle_is_owned (MonoW32Handle *handle_data) { MonoW32HandleMutex *mutex_handle; mutex_handle = (MonoW32HandleMutex*) handle_data->specific; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_MUTEX, "%s: testing ownership %s handle %p", __func__, mono_w32handle_get_typename (handle_data->type), handle_data); if (mutex_handle->recursion > 0 && pthread_equal (mutex_handle->tid, pthread_self ())) { mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_MUTEX, "%s: %s handle %p owned by %p", __func__, mono_w32handle_get_typename (handle_data->type), handle_data, (gpointer) pthread_self ()); return TRUE; } else { mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_MUTEX, "%s: %s handle %p not owned by %p, tid: %p recursion: %d", __func__, mono_w32handle_get_typename (handle_data->type), handle_data, (gpointer) pthread_self (), (gpointer) mutex_handle->tid, mutex_handle->recursion); return FALSE; } }
static gpointer mutex_handle_create (MonoW32HandleMutex *mutex_handle, MonoW32Type type, gboolean owned) { MonoW32Handle *handle_data; gpointer handle; gboolean abandoned; mutex_handle->tid = 0; mutex_handle->recursion = 0; mutex_handle->abandoned = FALSE; handle = mono_w32handle_new (type, mutex_handle); if (handle == INVALID_HANDLE_VALUE) { g_warning ("%s: error creating %s handle", __func__, mono_w32handle_get_typename (type)); mono_w32error_set_last (ERROR_GEN_FAILURE); return NULL; } if (!mono_w32handle_lookup_and_ref (handle, &handle_data)) g_error ("%s: unkown handle %p", __func__, handle); if (handle_data->type != type) g_error ("%s: unknown mutex handle %p", __func__, handle); mono_w32handle_lock (handle_data); if (owned) mutex_handle_own (handle_data, &abandoned); else mono_w32handle_set_signal_state (handle_data, TRUE, FALSE); mono_w32handle_unlock (handle_data); /* Balance mono_w32handle_lookup_and_ref */ mono_w32handle_unref (handle_data); mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_MUTEX, "%s: created %s handle %p", __func__, mono_w32handle_get_typename (type), handle); return handle; }
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_get_typename (type), handle); return FALSE; } mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: owning %s handle %p", __func__, mono_w32handle_get_typename (type), handle); sem_handle->val--; if (sem_handle->val == 0) 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_get_typename (type), handle); return FALSE; } mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: testing ownership %s handle %p", __func__, mono_w32handle_get_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_get_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, tid: %p recursion: %d", __func__, mono_w32handle_get_typename (type), handle, (gpointer) pthread_self (), (gpointer) mutex_handle->tid, mutex_handle->recursion); return FALSE; } }
static void mutex_handle_prewait (MonoW32Handle *handle_data) { /* 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; mutex_handle = (MonoW32HandleMutex*) handle_data->specific; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_MUTEX, "%s: pre-waiting %s handle %p, owned? %s", __func__, mono_w32handle_get_typename (handle_data->type), handle_data, mutex_handle->recursion != 0 ? "true" : "false"); }
static gpointer event_handle_create (MonoW32HandleEvent *event_handle, MonoW32Type type, gboolean manual, gboolean initial) { MonoW32Handle *handle_data; gpointer handle; 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_get_typename (type)); mono_w32error_set_last (ERROR_GEN_FAILURE); return NULL; } if (!mono_w32handle_lookup_and_ref (handle, &handle_data)) g_error ("%s: unkown handle %p", __func__, handle); if (handle_data->type != type) g_error ("%s: unknown event handle %p", __func__, handle); mono_w32handle_lock (handle_data); if (initial) mono_w32handle_set_signal_state (handle_data, TRUE, FALSE); mono_w32handle_unlock (handle_data); mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_EVENT, "%s: created %s handle %p", __func__, mono_w32handle_get_typename (type), handle); mono_w32handle_unref (handle_data); return handle; }
static void event_handle_signal (MonoW32Handle *handle_data) { MonoW32HandleEvent *event_handle; event_handle = (MonoW32HandleEvent*) handle_data->specific; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_EVENT, "%s: signalling %s handle %p", __func__, mono_w32handle_get_typename (handle_data->type), handle_data); if (!event_handle->manual) { event_handle->set_count = 1; mono_w32handle_set_signal_state (handle_data, TRUE, FALSE); } else { mono_w32handle_set_signal_state (handle_data, TRUE, TRUE); } }
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_get_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; }
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_get_typename (MONO_W32HANDLE_NAMEDSEM), initial, max, (const char*)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; }
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_get_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); /* we do not want the handle to be destroyed before we return it */ mono_w32handle_ref (handle); search_data->ret = handle; } return TRUE; } return FALSE; }
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_get_typename (MONO_W32HANDLE_NAMEDMUTEX)); /* w32 seems to guarantee that opening named objects can't race each other */ mono_w32handle_namespace_lock (); glong utf8_len = 0; utf8_name = g_utf16_to_utf8 (name, -1, NULL, &utf8_len, 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; mono_w32error_set_last (ERROR_INVALID_HANDLE); } else if (handle) { /* Not an error, but this is how the caller is informed that the mutex wasn't freshly created */ mono_w32error_set_last (ERROR_ALREADY_EXISTS); /* mono_w32handle_namespace_search_handle already adds a ref to the handle */ } else { /* A new named mutex */ MonoW32HandleNamedMutex namedmutex_handle; size_t len = utf8_len < MAX_PATH ? utf8_len : MAX_PATH; memcpy (&namedmutex_handle.sharedns.name [0], utf8_name, len); namedmutex_handle.sharedns.name [len] = '\0'; handle = mutex_handle_create ((MonoW32HandleMutex*) &namedmutex_handle, MONO_W32HANDLE_NAMEDMUTEX, owned); } g_free (utf8_name); mono_w32handle_namespace_unlock (); return handle; }
static gboolean event_handle_own (MonoW32Handle *handle_data, gboolean *abandoned) { MonoW32HandleEvent *event_handle; *abandoned = FALSE; event_handle = (MonoW32HandleEvent*) handle_data->specific; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_EVENT, "%s: owning %s handle %p", __func__, mono_w32handle_get_typename (handle_data->type), handle_data); 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_data, FALSE, FALSE); } return TRUE; }
} static gpointer event_create (gboolean manual, gboolean initial) { MonoW32HandleEvent event_handle; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_EVENT, "%s: creating %s handle", __func__, mono_w32handle_get_typename (MONO_W32TYPE_EVENT)); return event_handle_create (&event_handle, MONO_W32TYPE_EVENT, manual, initial); } static gpointer namedevent_create (gboolean manual, gboolean initial, const gchar *utf8_name G_GNUC_UNUSED) { gpointer handle; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_EVENT, "%s: creating %s handle", __func__, mono_w32handle_get_typename (MONO_W32TYPE_NAMEDEVENT)); /* w32 seems to guarantee that opening named objects can't race each other */ mono_w32handle_namespace_lock (); glong utf8_len = strlen (utf8_name); handle = mono_w32handle_namespace_search_handle (MONO_W32TYPE_NAMEDEVENT, utf8_name); if (handle == INVALID_HANDLE_VALUE) { /* The name has already been used for a different object. */ handle = NULL; mono_w32error_set_last (ERROR_INVALID_HANDLE); } else if (handle) { /* Not an error, but this is how the caller is informed that the event wasn't freshly created */ mono_w32error_set_last (ERROR_ALREADY_EXISTS);
void mono_w32mutex_abandon (void) { MonoInternalThread *internal; g_assert (mono_thread_internal_current_is_attached ()); internal = mono_thread_internal_current (); g_assert (internal); if (!internal->owned_mutexes) return; while (internal->owned_mutexes->len) { MonoW32HandleType type; MonoW32HandleMutex *mutex_handle; MonoNativeThreadId tid; gpointer handle; handle = g_ptr_array_index (internal->owned_mutexes, 0); 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_error ("%s: error looking up %s handle %p", __func__, mono_w32handle_get_typename (type), handle); } mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: abandoning %s handle %p", __func__, mono_w32handle_get_typename (type), handle); tid = MONO_UINT_TO_NATIVE_THREAD_ID (internal->tid); if (!pthread_equal (mutex_handle->tid, tid)) g_error ("%s: trying to release mutex %p acquired by thread %p from thread %p", __func__, handle, (gpointer) mutex_handle->tid, (gpointer) tid); mono_w32handle_lock_handle (handle); mutex_handle->recursion = 0; mutex_handle->tid = 0; mutex_handle->abandoned = TRUE; mono_w32handle_set_signal_state (handle, TRUE, FALSE); thread_disown_mutex (internal, handle); mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: abandoned %s handle %p", __func__, mono_w32handle_get_typename (type), handle); mono_w32handle_unlock_handle (handle); } g_ptr_array_free (internal->owned_mutexes, TRUE); internal->owned_mutexes = NULL; }
MonoBoolean ves_icall_System_Threading_Mutex_ReleaseMutex_internal (gpointer handle) { MonoW32HandleType type; MonoW32HandleMutex *mutex_handle; pthread_t tid; gboolean ret; if (handle == NULL) { mono_w32error_set_last (ERROR_INVALID_HANDLE); return FALSE; } switch (type = mono_w32handle_get_type (handle)) { case MONO_W32HANDLE_MUTEX: case MONO_W32HANDLE_NAMEDMUTEX: break; default: mono_w32error_set_last (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_get_typename (type), handle); return FALSE; } mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: releasing %s handle %p, tid: %p recursion: %d", __func__, mono_w32handle_get_typename (type), handle, (gpointer) mutex_handle->tid, mutex_handle->recursion); mono_w32handle_lock_handle (handle); tid = pthread_self (); if (mutex_handle->abandoned) { // The Win32 ReleaseMutex() function returns TRUE for abandoned mutexes ret = TRUE; } else 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_get_typename (type), handle, (long)mutex_handle->tid, (long)tid); } else { ret = TRUE; /* OK, we own this mutex */ mutex_handle->recursion--; if (mutex_handle->recursion == 0) { thread_disown_mutex (mono_thread_internal_current (), handle); mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unlocking %s handle %p, tid: %p recusion : %d", __func__, mono_w32handle_get_typename (type), handle, (gpointer) mutex_handle->tid, mutex_handle->recursion); mutex_handle->tid = 0; mono_w32handle_set_signal_state (handle, TRUE, FALSE); } } mono_w32handle_unlock_handle (handle); return ret; }