#include <mono/utils/mono-error-internals.h>
#include <mono/utils/w32handle.h>
#include <mono/metadata/w32event.h>
+#include <mono/metadata/w32mutex.h>
#include <mono/metadata/gc-internals.h>
#include <mono/metadata/reflection-internals.h>
#include <signal.h>
#endif
+#if defined(HOST_WIN32)
+#include <objbase.h>
+#endif
+
#if defined(PLATFORM_ANDROID) && !defined(TARGET_ARM64) && !defined(TARGET_AMD64)
#define USE_TKILL_ON_ANDROID 1
#endif
THREAD_DEBUG (g_message ("%s: mono_thread_detach for %p (%"G_GSIZE_FORMAT")", __func__, thread, (gsize)thread->tid));
+#ifndef HOST_WIN32
+ mono_w32mutex_abandon ();
+#endif
+
thread_cleanup (thread);
SET_CURRENT_OBJECT (NULL);
return;
for(i=0; i<wait->num; i++) {
- gsize tid = wait->threads[i]->tid;
+ MonoInternalThread *internal;
- /*
- * On !win32, when the thread handle becomes signalled, it just means the thread has exited user code,
- * it can still run io-layer etc. code. So wait for it to really exit.
- * FIXME: This won't join threads which are not in the joinable_hash yet.
- */
- mono_thread_join ((gpointer)tid);
+ internal = wait->threads [i];
mono_threads_lock ();
- if(mono_g_hash_table_lookup (threads, (gpointer)tid)!=NULL) {
- /* This thread must have been killed, because
- * it hasn't cleaned itself up. (It's just
- * possible that the thread exited before the
- * parent thread had a chance to store the
- * handle, and now there is another pointer to
- * the already-exited thread stored. In this
- * case, we'll just get two
- * mono_profiler_thread_end() calls for the
- * same thread.)
- */
-
- mono_threads_unlock ();
- THREAD_DEBUG (g_message ("%s: cleaning up after thread %p (%"G_GSIZE_FORMAT")", __func__, wait->threads[i], tid));
- thread_cleanup (wait->threads[i]);
- } else {
- mono_threads_unlock ();
- }
+ if (mono_g_hash_table_lookup (threads, (gpointer) internal->tid) == internal)
+ g_error ("%s: failed to call mono_thread_detach_internal on thread %p, InternalThread: %p", __func__, internal->tid, internal);
+ mono_threads_unlock ();
}
}
return;
if (ret < wait->num) {
- gsize tid = wait->threads[ret]->tid;
+ MonoInternalThread *internal;
+
+ internal = wait->threads [ret];
+
mono_threads_lock ();
- if (mono_g_hash_table_lookup (threads, (gpointer)tid)!=NULL) {
- /* See comment in wait_for_tids about thread cleanup */
- mono_threads_unlock ();
- THREAD_DEBUG (g_message ("%s: cleaning up after thread %"G_GSIZE_FORMAT, __func__, tid));
- thread_cleanup (wait->threads [ret]);
- } else
- mono_threads_unlock ();
+ if (mono_g_hash_table_lookup (threads, (gpointer) internal->tid) == internal)
+ g_error ("%s: failed to call mono_thread_detach_internal on thread %p, InternalThread: %p", __func__, internal->tid, internal);
+ mono_threads_unlock ();
}
}
void
mono_thread_internal_describe (MonoInternalThread *internal, GString *text)
{
- MonoThreadInfo *info;
-
g_string_append_printf (text, ", thread handle : %p", internal->handle);
- info = (MonoThreadInfo*) internal->thread_info;
- if (!info)
- return;
-
- g_string_append (text, ", state : ");
- mono_thread_info_describe_interrupt_token (info, text);
+ if (internal->thread_info) {
+ g_string_append (text, ", state : ");
+ mono_thread_info_describe_interrupt_token ((MonoThreadInfo*) internal->thread_info, text);
+ }
- if (info->owned_mutexes) {
+ if (internal->owned_mutexes) {
int i;
g_string_append (text, ", owns : [");
- for (i = 0; i < info->owned_mutexes->len; i++)
- g_string_append_printf (text, i == 0 ? "%p" : ", %p", g_ptr_array_index (info->owned_mutexes, i));
+ for (i = 0; i < internal->owned_mutexes->len; i++)
+ g_string_append_printf (text, i == 0 ? "%p" : ", %p", g_ptr_array_index (internal->owned_mutexes, i));
g_string_append (text, "]");
}
}
+
+gboolean
+mono_thread_internal_is_current (MonoInternalThread *internal)
+{
+ g_assert (internal);
+ return mono_native_thread_id_equals (mono_native_thread_id_get (), MONO_UINT_TO_NATIVE_THREAD_ID (internal->tid));
+}