#include <mono/metadata/threadpool.h>
#include <mono/metadata/threadpool-internals.h>
#include <mono/metadata/threads-types.h>
+#include <mono/metadata/sgen-conf.h>
#include <mono/utils/mono-logger-internal.h>
#include <mono/metadata/gc-internal.h>
#include <mono/metadata/marshal.h> /* for mono_delegate_free_ftnptr () */
static gboolean finalizing_root_domain = FALSE;
-#define mono_finalizer_lock() EnterCriticalSection (&finalizer_mutex)
-#define mono_finalizer_unlock() LeaveCriticalSection (&finalizer_mutex)
-static CRITICAL_SECTION finalizer_mutex;
-static CRITICAL_SECTION reference_queue_mutex;
+#define mono_finalizer_lock() mono_mutex_lock (&finalizer_mutex)
+#define mono_finalizer_unlock() mono_mutex_unlock (&finalizer_mutex)
+static mono_mutex_t finalizer_mutex;
+static mono_mutex_t reference_queue_mutex;
static GSList *domains_to_finalize= NULL;
static MonoMList *threads_to_finalize = NULL;
return mono_domain_get ()->ephemeron_tombstone;
}
-#define mono_allocator_lock() EnterCriticalSection (&allocator_section)
-#define mono_allocator_unlock() LeaveCriticalSection (&allocator_section)
-static CRITICAL_SECTION allocator_section;
-static CRITICAL_SECTION handle_section;
+#define mono_allocator_lock() mono_mutex_lock (&allocator_section)
+#define mono_allocator_unlock() mono_mutex_unlock (&allocator_section)
+static mono_mutex_t allocator_section;
+static mono_mutex_t handle_section;
typedef enum {
HANDLE_WEAK,
{NULL, NULL, 0, HANDLE_PINNED, 0}
};
-#define lock_handles(handles) EnterCriticalSection (&handle_section)
-#define unlock_handles(handles) LeaveCriticalSection (&handle_section)
+#define lock_handles(handles) mono_mutex_lock (&handle_section)
+#define unlock_handles(handles) mono_mutex_unlock (&handle_section)
static int
find_first_unset (guint32 bitmap)
static guint32
finalizer_thread (gpointer unused)
{
+ gboolean wait = TRUE;
+
while (!finished) {
/* Wait to be notified that there's at least one
* finaliser to run
g_assert (mono_domain_get () == mono_get_root_domain ());
+ if (wait) {
/* An alertable wait is required so this thread can be suspended on windows */
#ifdef MONO_HAS_SEMAPHORES
- MONO_SEM_WAIT_ALERTABLE (&finalizer_sem, TRUE);
+ MONO_SEM_WAIT_ALERTABLE (&finalizer_sem, TRUE);
#else
- WaitForSingleObjectEx (finalizer_event, INFINITE, TRUE);
+ WaitForSingleObjectEx (finalizer_event, INFINITE, TRUE);
#endif
+ }
+ wait = TRUE;
mono_threads_perform_thread_dump ();
reference_queue_proccess_all ();
- SetEvent (pending_done_event);
+#ifdef MONO_HAS_SEMAPHORES
+ /* Avoid posting the pending done event until there are pending finalizers */
+ if (MONO_SEM_TIMEDWAIT (&finalizer_sem, 0) == 0)
+ /* Don't wait again at the start of the loop */
+ wait = FALSE;
+ else
+ SetEvent (pending_done_event);
+#else
+ SetEvent (pending_done_event);
+#endif
}
SetEvent (shutdown_event);
void
mono_gc_init (void)
{
- InitializeCriticalSection (&handle_section);
- InitializeCriticalSection (&allocator_section);
+ mono_mutex_init_recursive (&handle_section);
+ mono_mutex_init_recursive (&allocator_section);
- InitializeCriticalSection (&finalizer_mutex);
- InitializeCriticalSection (&reference_queue_mutex);
+ mono_mutex_init_recursive (&finalizer_mutex);
+ mono_mutex_init_recursive (&reference_queue_mutex);
MONO_GC_REGISTER_ROOT_FIXED (gc_handles [HANDLE_NORMAL].entries);
MONO_GC_REGISTER_ROOT_FIXED (gc_handles [HANDLE_PINNED].entries);
- mono_counters_register ("Created object count", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &mono_stats.new_object_count);
- mono_counters_register ("Minor GC collections", MONO_COUNTER_GC | MONO_COUNTER_INT, &gc_stats.minor_gc_count);
- mono_counters_register ("Major GC collections", MONO_COUNTER_GC | MONO_COUNTER_INT, &gc_stats.major_gc_count);
- mono_counters_register ("Minor GC time", MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &gc_stats.minor_gc_time_usecs);
- mono_counters_register ("Major GC time", MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &gc_stats.major_gc_time_usecs);
+ mono_counters_register ("Minor GC collections", MONO_COUNTER_GC | MONO_COUNTER_UINT, &gc_stats.minor_gc_count);
+ mono_counters_register ("Major GC collections", MONO_COUNTER_GC | MONO_COUNTER_UINT, &gc_stats.major_gc_count);
+ mono_counters_register ("Minor GC time", MONO_COUNTER_GC | MONO_COUNTER_ULONG | MONO_COUNTER_TIME, &gc_stats.minor_gc_time);
+ mono_counters_register ("Major GC time", MONO_COUNTER_GC | MONO_COUNTER_ULONG | MONO_COUNTER_TIME, &gc_stats.major_gc_time);
+ mono_counters_register ("Major GC time concurrent", MONO_COUNTER_GC | MONO_COUNTER_ULONG | MONO_COUNTER_TIME, &gc_stats.major_gc_time_concurrent);
mono_gc_base_init ();
ret = WaitForSingleObjectEx (gc_thread->handle, INFINITE, TRUE);
g_assert (ret == WAIT_OBJECT_0);
- mono_thread_join ((gpointer)gc_thread->tid);
+ mono_thread_join (GUINT_TO_POINTER (gc_thread->tid));
}
}
gc_thread = NULL;
mono_reference_queue_cleanup ();
- DeleteCriticalSection (&handle_section);
- DeleteCriticalSection (&allocator_section);
- DeleteCriticalSection (&finalizer_mutex);
- DeleteCriticalSection (&reference_queue_mutex);
+ mono_mutex_destroy (&handle_section);
+ mono_mutex_destroy (&allocator_section);
+ mono_mutex_destroy (&finalizer_mutex);
+ mono_mutex_destroy (&reference_queue_mutex);
}
#else
void mono_gc_init (void)
{
- InitializeCriticalSection (&handle_section);
+ mono_mutex_init_recursive (&handle_section);
}
void mono_gc_cleanup (void)
reference_queue_proccess (queue);
restart:
- EnterCriticalSection (&reference_queue_mutex);
+ mono_mutex_lock (&reference_queue_mutex);
for (iter = &ref_queues; *iter;) {
queue = *iter;
if (!queue->should_be_deleted) {
continue;
}
if (queue->queue) {
- LeaveCriticalSection (&reference_queue_mutex);
+ mono_mutex_unlock (&reference_queue_mutex);
reference_queue_proccess (queue);
goto restart;
}
*iter = queue->next;
g_free (queue);
}
- LeaveCriticalSection (&reference_queue_mutex);
+ mono_mutex_unlock (&reference_queue_mutex);
}
static void
MonoReferenceQueue *res = g_new0 (MonoReferenceQueue, 1);
res->callback = callback;
- EnterCriticalSection (&reference_queue_mutex);
+ mono_mutex_lock (&reference_queue_mutex);
res->next = ref_queues;
ref_queues = res;
- LeaveCriticalSection (&reference_queue_mutex);
+ mono_mutex_unlock (&reference_queue_mutex);
return res;
}