Merge pull request #2709 from lewurm/jit-phase-typo
authormonojenkins <jo.shields+jenkins@xamarin.com>
Wed, 2 Mar 2016 23:45:34 +0000 (23:45 +0000)
committermonojenkins <jo.shields+jenkins@xamarin.com>
Wed, 2 Mar 2016 23:45:34 +0000 (23:45 +0000)
[jit] remove 'jit_' prefix in two phases in stats output

@monojenkins merge

19 files changed:
mono/metadata/jit-info.c
mono/metadata/sgen-mono.c
mono/metadata/sgen-os-mach.c
mono/metadata/sgen-os-posix.c
mono/metadata/sgen-os-win32.c
mono/metadata/sgen-stw.c
mono/mini/mini-posix.c
mono/sgen/sgen-alloc.c
mono/sgen/sgen-debug.c
mono/unit-tests/test-mono-linked-list-set.c
mono/utils/hazard-pointer.c
mono/utils/hazard-pointer.h
mono/utils/lock-free-alloc.c
mono/utils/lock-free-queue.c
mono/utils/mono-conc-hashtable.c
mono/utils/mono-linked-list-set.c
mono/utils/mono-linked-list-set.h
mono/utils/mono-threads.c
mono/utils/mono-threads.h

index 228ce69bb8f01f6a186975f48dc7c7164ef9203b..2f4be6663ff503b84ec0f3f1983d4587fca2d875 100644 (file)
@@ -613,7 +613,7 @@ jit_info_table_add (MonoDomain *domain, MonoJitInfoTable *volatile *table_ptr, M
                *table_ptr = new_table;
                mono_memory_barrier ();
                domain->num_jit_info_tables++;
-               mono_thread_hazardous_free_or_queue (table, (MonoHazardousFreeFunc)mono_jit_info_table_free, TRUE, FALSE);
+               mono_thread_hazardous_free_or_queue (table, (MonoHazardousFreeFunc)mono_jit_info_table_free, HAZARD_FREE_MAY_LOCK, HAZARD_FREE_SAFE_CTX);
                table = new_table;
 
                goto restart;
@@ -691,7 +691,7 @@ mono_jit_info_free_or_queue (MonoDomain *domain, MonoJitInfo *ji)
        if (domain->num_jit_info_tables <= 1) {
                /* Can it actually happen that we only have one table
                   but ji is still hazardous? */
-               mono_thread_hazardous_free_or_queue (ji, g_free, TRUE, FALSE);
+               mono_thread_hazardous_free_or_queue (ji, g_free, HAZARD_FREE_MAY_LOCK, HAZARD_FREE_SAFE_CTX);
        } else {
                domain->jit_info_free_queue = g_slist_prepend (domain->jit_info_free_queue, ji);
        }
index 34ab667d2c89190bce9802a130041f8ae3cb5368..8421b903ba6f967366bba0f2d7c7b337510ac1ee 100644 (file)
@@ -2342,8 +2342,6 @@ mono_gc_scan_object (void *obj, void *gc_data)
 void
 sgen_client_scan_thread_data (void *start_nursery, void *end_nursery, gboolean precise, ScanCopyContext ctx)
 {
-       SgenThreadInfo *info;
-
        scan_area_arg_start = start_nursery;
        scan_area_arg_end = end_nursery;
 
@@ -2397,7 +2395,7 @@ sgen_client_scan_thread_data (void *start_nursery, void *end_nursery, gboolean p
                                }
                        }
                }
-       } END_FOREACH_THREAD
+       } FOREACH_THREAD_END
 }
 
 /*
index b6d90399bfade433128cd03b218dffe793b19992..666ef3ce8cfb3103bd06720529a1a44424430e58 100644 (file)
@@ -112,12 +112,11 @@ sgen_thread_handshake (BOOL suspend)
 {
        SgenThreadInfo *cur_thread = mono_thread_info_current ();
        kern_return_t ret;
-       SgenThreadInfo *info;
 
        int count = 0;
 
        cur_thread->client_info.suspend_done = TRUE;
-       FOREACH_THREAD_SAFE (info) {
+       FOREACH_THREAD (info) {
                if (info == cur_thread || sgen_thread_pool_is_thread_pool_thread (mono_thread_info_get_tid (info)))
                        continue;
 
@@ -134,7 +133,7 @@ sgen_thread_handshake (BOOL suspend)
                                continue;
                }
                count ++;
-       } END_FOREACH_THREAD_SAFE
+       } FOREACH_THREAD_END
        return count;
 }
 
index 29ce34f917c0bd0b805a7247bddd6d8ad441fec0..37979a497d40939f04fe9a03de7d307f564efbb2 100644 (file)
@@ -197,14 +197,13 @@ int
 sgen_thread_handshake (BOOL suspend)
 {
        int count, result;
-       SgenThreadInfo *info;
        int signum = suspend ? suspend_signal_num : restart_signal_num;
 
        MonoNativeThreadId me = mono_native_thread_id_get ();
 
        count = 0;
        mono_thread_info_current ()->client_info.suspend_done = TRUE;
-       FOREACH_THREAD_SAFE (info) {
+       FOREACH_THREAD (info) {
                if (mono_native_thread_id_equals (mono_thread_info_get_tid (info), me)) {
                        continue;
                }
@@ -219,7 +218,7 @@ sgen_thread_handshake (BOOL suspend)
                } else {
                        info->client_info.skip = 1;
                }
-       } END_FOREACH_THREAD_SAFE
+       } FOREACH_THREAD_END
 
        sgen_wait_for_suspend_ack (count);
 
index f9f699b7601c5b0e93c2979985305b346441359e..3e78396ccd10f536f2bd73be7b41f01c69b76435 100644 (file)
@@ -123,12 +123,11 @@ sgen_wait_for_suspend_ack (int count)
 int
 sgen_thread_handshake (BOOL suspend)
 {
-       SgenThreadInfo *info;
        SgenThreadInfo *current = mono_thread_info_current ();
        int count = 0;
 
        current->client_info.suspend_done = TRUE;
-       FOREACH_THREAD_SAFE (info) {
+       FOREACH_THREAD (info) {
                if (info == current)
                        continue;
                info->client_info.suspend_done = FALSE;
@@ -142,7 +141,7 @@ sgen_thread_handshake (BOOL suspend)
                                continue;
                }
                ++count;
-       } END_FOREACH_THREAD_SAFE
+       } FOREACH_THREAD_END
        return count;
 }
 
index 4b54c8d267251baba139888a2b23f5e6d70b4adc..15eb283ee1343486e706ebcee4f25738d122d518 100644 (file)
@@ -113,7 +113,6 @@ is_ip_in_managed_allocator (MonoDomain *domain, gpointer ip)
 static int
 restart_threads_until_none_in_managed_allocator (void)
 {
-       SgenThreadInfo *info;
        int num_threads_died = 0;
        int sleep_duration = -1;
 
@@ -121,7 +120,7 @@ restart_threads_until_none_in_managed_allocator (void)
                int restart_count = 0, restarted_count = 0;
                /* restart all threads that stopped in the
                   allocator */
-               FOREACH_THREAD_SAFE (info) {
+               FOREACH_THREAD (info) {
                        gboolean result;
                        if (info->client_info.skip || info->client_info.gc_disabled || info->client_info.suspend_done)
                                continue;
@@ -146,7 +145,7 @@ restart_threads_until_none_in_managed_allocator (void)
                                info->client_info.stopped_domain = NULL;
                                info->client_info.suspend_done = TRUE;
                        }
-               } END_FOREACH_THREAD_SAFE
+               } FOREACH_THREAD_END
                /* if no threads were restarted, we're done */
                if (restart_count == 0)
                        break;
@@ -174,7 +173,7 @@ restart_threads_until_none_in_managed_allocator (void)
                        } else {
                                info->client_info.skip = 1;
                        }
-               } END_FOREACH_THREAD
+               } FOREACH_THREAD_END
                /* some threads might have died */
                num_threads_died += restart_count - restarted_count;
                /* wait for the threads to signal their suspension
@@ -251,7 +250,6 @@ sgen_client_stop_world (int generation)
 void
 sgen_client_restart_world (int generation, GGTimingInfo *timing)
 {
-       SgenThreadInfo *info;
        TV_DECLARE (end_sw);
        TV_DECLARE (start_handshake);
        TV_DECLARE (end_bridge);
@@ -269,7 +267,7 @@ sgen_client_restart_world (int generation, GGTimingInfo *timing)
 #else
                memset (&info->client_info.regs, 0, sizeof (info->client_info.regs));
 #endif
-       } END_FOREACH_THREAD
+       } FOREACH_THREAD_END
 
        TV_GETTIME (start_handshake);
 
@@ -387,13 +385,12 @@ static void
 sgen_unified_suspend_stop_world (void)
 {
        int restart_counter;
-       SgenThreadInfo *info;
        int sleep_duration = -1;
 
        mono_threads_begin_global_suspend ();
        THREADS_STW_DEBUG ("[GC-STW-BEGIN] *** BEGIN SUSPEND *** \n");
 
-       FOREACH_THREAD_SAFE (info) {
+       FOREACH_THREAD (info) {
                info->client_info.skip = FALSE;
                info->client_info.suspend_done = FALSE;
                if (sgen_is_thread_in_current_stw (info)) {
@@ -402,14 +399,14 @@ sgen_unified_suspend_stop_world (void)
                } else {
                        THREADS_STW_DEBUG ("[GC-STW-BEGIN-SUSPEND] IGNORE thread %p skip %d\n", mono_thread_info_get_tid (info), info->client_info.skip);
                }
-       } END_FOREACH_THREAD_SAFE
+       } FOREACH_THREAD_END
 
        mono_thread_info_current ()->client_info.suspend_done = TRUE;
        mono_threads_wait_pending_operations ();
 
        for (;;) {
                restart_counter = 0;
-               FOREACH_THREAD_SAFE (info) {
+               FOREACH_THREAD (info) {
                        if (info->client_info.suspend_done || !sgen_is_thread_in_current_stw (info)) {
                                THREADS_STW_DEBUG ("[GC-STW-RESTART] IGNORE thread %p not been processed done %d current %d\n", mono_thread_info_get_tid (info), info->client_info.suspend_done, !sgen_is_thread_in_current_stw (info));
                                continue;
@@ -438,7 +435,7 @@ sgen_unified_suspend_stop_world (void)
                                g_assert (!info->client_info.in_critical_region);
                                info->client_info.suspend_done = TRUE;
                        }
-               } END_FOREACH_THREAD_SAFE
+               } FOREACH_THREAD_END
 
                if (restart_counter == 0)
                        break;
@@ -456,19 +453,19 @@ sgen_unified_suspend_stop_world (void)
                        sleep_duration += 10;
                }
 
-               FOREACH_THREAD_SAFE (info) {
+               FOREACH_THREAD (info) {
                        if (sgen_is_thread_in_current_stw (info) && mono_thread_info_is_running (info)) {
                                gboolean res = mono_thread_info_begin_suspend (info);
                                THREADS_STW_DEBUG ("[GC-STW-RESTART] SUSPEND thread %p skip %d\n", mono_thread_info_get_tid (info), res);
                                if (!res)
                                        info->client_info.skip = TRUE;
                        }
-               } END_FOREACH_THREAD_SAFE
+               } FOREACH_THREAD_END
 
                mono_threads_wait_pending_operations ();
        }
 
-       FOREACH_THREAD_SAFE (info) {
+       FOREACH_THREAD (info) {
                if (sgen_is_thread_in_current_stw (info)) {
                        THREADS_STW_DEBUG ("[GC-STW-SUSPEND-END] thread %p is suspended\n", mono_thread_info_get_tid (info));
                        g_assert (info->client_info.suspend_done);
@@ -476,23 +473,21 @@ sgen_unified_suspend_stop_world (void)
                } else {
                        g_assert (!info->client_info.suspend_done || info == mono_thread_info_current ());
                }
-       } END_FOREACH_THREAD_SAFE
+       } FOREACH_THREAD_END
 }
 
 static void
 sgen_unified_suspend_restart_world (void)
 {
-       SgenThreadInfo *info;
-
        THREADS_STW_DEBUG ("[GC-STW-END] *** BEGIN RESUME ***\n");
-       FOREACH_THREAD_SAFE (info) {
+       FOREACH_THREAD (info) {
                if (sgen_is_thread_in_current_stw (info)) {
                        g_assert (mono_thread_info_begin_resume (info));
                        THREADS_STW_DEBUG ("[GC-STW-RESUME-WORLD] RESUME thread %p\n", mono_thread_info_get_tid (info));
                } else {
                        THREADS_STW_DEBUG ("[GC-STW-RESUME-WORLD] IGNORE thread %p\n", mono_thread_info_get_tid (info));
                }
-       } END_FOREACH_THREAD_SAFE
+       } FOREACH_THREAD_END
 
        mono_threads_wait_pending_operations ();
        mono_threads_end_global_suspend ();
index e8fd88159dd27838af01a87544225c71291a3277..63198d79083cdafc1718a111016e0be15ad63a87 100644 (file)
@@ -326,7 +326,6 @@ per_thread_profiler_hit (void *ctx)
 
 MONO_SIG_HANDLER_FUNC (static, sigprof_signal_handler)
 {
-       MonoThreadInfo *info;
        int old_errno = errno;
        int hp_save_index;
        MONO_SIG_HANDLER_GET_CONTEXT;
@@ -348,7 +347,7 @@ MONO_SIG_HANDLER_FUNC (static, sigprof_signal_handler)
 
                        mono_threads_add_async_job (info, MONO_SERVICE_REQUEST_SAMPLE);
                        mono_threads_pthread_kill (info, profiling_signal_in_use);
-               } END_FOREACH_THREAD_SAFE;
+               } FOREACH_THREAD_SAFE_END
        }
 
        mono_thread_info_set_is_async_context (TRUE);
index 2c69c7d932f24a5109cbc92e289676dcb2fc86ca..9d3f45195e115047b8e3c303c5d0ec1d21fbce6b 100644 (file)
@@ -526,15 +526,13 @@ sgen_init_tlab_info (SgenThreadInfo* info)
 void
 sgen_clear_tlabs (void)
 {
-       SgenThreadInfo *info;
-
        FOREACH_THREAD (info) {
                /* A new TLAB will be allocated when the thread does its first allocation */
                *info->tlab_start_addr = NULL;
                *info->tlab_next_addr = NULL;
                *info->tlab_temp_end_addr = NULL;
                *info->tlab_real_end_addr = NULL;
-       } END_FOREACH_THREAD
+       } FOREACH_THREAD_END
 }
 
 void
index a7f61cc8f4eacc5a7ee0f731b0e4ed434193d3a5..27e8cb0addf54d760ef99b1b351bd011eab5eb73 100644 (file)
@@ -505,7 +505,6 @@ find_pinning_ref_from_thread (char *obj, size_t size)
 {
 #ifndef SGEN_WITHOUT_MONO
        int j;
-       SgenThreadInfo *info;
        char *endobj = obj + size;
 
        FOREACH_THREAD (info) {
@@ -527,8 +526,8 @@ find_pinning_ref_from_thread (char *obj, size_t size)
 
                        if (w >= (mword)obj && w < (mword)obj + size)
                                SGEN_LOG (0, "Object %p referenced in saved reg %d of thread %p (id %p)", obj, j, info, (gpointer)mono_thread_info_get_tid (info));
-               } END_FOREACH_THREAD
-       }
+               }
+       } FOREACH_THREAD_END
 #endif
 }
 
index a5e01ebe09ec6e5f913e1ad936c822596d39ecde..3841581e0bb02fd61fe9f407dbcbef8891a0cea9 100644 (file)
@@ -74,11 +74,11 @@ worker (void *arg)
                        break;
                case STATE_OUT:
                        if (InterlockedCompareExchange (&nodes [i].state, STATE_BUSY, STATE_OUT) == STATE_OUT) {
-                               result = mono_lls_find (&lls, hp, i);
+                               result = mono_lls_find (&lls, hp, i, HAZARD_FREE_SAFE_CTX);
                                assert (!result);
                                mono_hazard_pointer_clear_all (hp, -1);
 
-                               result = mono_lls_insert (&lls, hp, &nodes [i].node);
+                               result = mono_lls_insert (&lls, hp, &nodes [i].node, HAZARD_FREE_SAFE_CTX);
                                mono_hazard_pointer_clear_all (hp, -1);
 
                                assert (nodes [i].state == STATE_BUSY);
@@ -89,12 +89,12 @@ worker (void *arg)
                        break;
                case STATE_IN:
                        if (InterlockedCompareExchange (&nodes [i].state, STATE_BUSY, STATE_IN) == STATE_IN) {
-                               result = mono_lls_find (&lls, hp, i);
+                               result = mono_lls_find (&lls, hp, i, HAZARD_FREE_SAFE_CTX);
                                assert (result);
                                assert (mono_hazard_pointer_get_val (hp, 1) == &nodes [i].node);
                                mono_hazard_pointer_clear_all (hp, -1);
 
-                               result = mono_lls_remove (&lls, hp, &nodes [i].node);
+                               result = mono_lls_remove (&lls, hp, &nodes [i].node, HAZARD_FREE_SAFE_CTX);
                                mono_hazard_pointer_clear_all (hp, -1);
 
                                ++thread_data->num_removes;
@@ -126,7 +126,7 @@ main (int argc, char *argv [])
 
        mono_threads_init (&thread_callbacks, 0);
 
-       mono_lls_init (&lls, free_node);
+       mono_lls_init (&lls, free_node, HAZARD_FREE_NO_LOCK);
 
        for (i = 0; i < N; ++i) {
                nodes [i].node.key = i;
index 89dfe54512f6c085d9872c4d26d0c0fe007ceb55..df1e4cdc8e96744b8aed11c16686b66af0064fdd 100644 (file)
@@ -28,7 +28,7 @@
 typedef struct {
        gpointer p;
        MonoHazardousFreeFunc free_func;
-       gboolean might_lock;
+       HazardFreeLocking locking;
 } DelayedFreeItem;
 
 /* The hazard table */
@@ -286,7 +286,7 @@ mono_hazard_pointer_restore_for_signal_handler (int small_id)
 }
 
 static gboolean
-try_free_delayed_free_item (gboolean lock_free_context)
+try_free_delayed_free_item (HazardFreeContext context)
 {
        DelayedFreeItem item;
        gboolean popped = mono_lock_free_array_queue_pop (&delayed_free_queue, &item);
@@ -294,7 +294,8 @@ try_free_delayed_free_item (gboolean lock_free_context)
        if (!popped)
                return FALSE;
 
-       if ((lock_free_context && item.might_lock) || (is_pointer_hazardous (item.p))) {
+       if ((context == HAZARD_FREE_ASYNC_CTX && item.locking == HAZARD_FREE_MAY_LOCK) ||
+           (is_pointer_hazardous (item.p))) {
                mono_lock_free_array_queue_push (&delayed_free_queue, &item);
                return FALSE;
        }
@@ -306,24 +307,20 @@ try_free_delayed_free_item (gboolean lock_free_context)
 
 void
 mono_thread_hazardous_free_or_queue (gpointer p, MonoHazardousFreeFunc free_func,
-               gboolean free_func_might_lock, gboolean lock_free_context)
+                                     HazardFreeLocking locking, HazardFreeContext context)
 {
        int i;
 
-       if (lock_free_context)
-               g_assert (!free_func_might_lock);
-       if (free_func_might_lock)
-               g_assert (!lock_free_context);
-
        /* First try to free a few entries in the delayed free
           table. */
        for (i = 0; i < 3; ++i)
-               try_free_delayed_free_item (lock_free_context);
+               try_free_delayed_free_item (context);
 
        /* Now see if the pointer we're freeing is hazardous.  If it
           isn't, free it.  Otherwise put it in the delay list. */
-       if (is_pointer_hazardous (p)) {
-               DelayedFreeItem item = { p, free_func, free_func_might_lock };
+       if ((context == HAZARD_FREE_ASYNC_CTX && locking == HAZARD_FREE_MAY_LOCK) ||
+           is_pointer_hazardous (p)) {
+               DelayedFreeItem item = { p, free_func, locking };
 
                ++hazardous_pointer_count;
 
@@ -336,7 +333,7 @@ mono_thread_hazardous_free_or_queue (gpointer p, MonoHazardousFreeFunc free_func
 void
 mono_thread_hazardous_try_free_all (void)
 {
-       while (try_free_delayed_free_item (FALSE))
+       while (try_free_delayed_free_item (HAZARD_FREE_SAFE_CTX))
                ;
 }
 
@@ -345,7 +342,7 @@ mono_thread_hazardous_try_free_some (void)
 {
        int i;
        for (i = 0; i < 10; ++i)
-               try_free_delayed_free_item (FALSE);
+               try_free_delayed_free_item (HAZARD_FREE_SAFE_CTX);
 }
 
 void
index 540f743994c120406e3cf78fe7e7dbf81de1839f..fa70e71bb40d1853f0269b95ada6d32f1262eda7 100644 (file)
@@ -18,8 +18,18 @@ typedef struct {
 
 typedef void (*MonoHazardousFreeFunc) (gpointer p);
 
+typedef enum {
+       HAZARD_FREE_MAY_LOCK,
+       HAZARD_FREE_NO_LOCK,
+} HazardFreeLocking;
+
+typedef enum {
+       HAZARD_FREE_SAFE_CTX,
+       HAZARD_FREE_ASYNC_CTX,
+} HazardFreeContext;
+
 void mono_thread_hazardous_free_or_queue (gpointer p, MonoHazardousFreeFunc free_func,
-               gboolean free_func_might_lock, gboolean lock_free_context);
+                                          HazardFreeLocking locking, HazardFreeContext context);
 void mono_thread_hazardous_try_free_all (void);
 void mono_thread_hazardous_try_free_some (void);
 MonoThreadHazardPointers* mono_hazard_pointer_get (void);
index 308ab12dda8037eed792642c24d7b6fafccb56a2..66cb6ea3f8075fc44c9e6793c6bb86b5a7350844 100644 (file)
@@ -250,7 +250,7 @@ desc_retire (Descriptor *desc)
        g_assert (desc->in_use);
        desc->in_use = FALSE;
        free_sb (desc->sb, desc->block_size);
-       mono_thread_hazardous_free_or_queue (desc, desc_enqueue_avail, FALSE, TRUE);
+       mono_thread_hazardous_free_or_queue (desc, desc_enqueue_avail, HAZARD_FREE_NO_LOCK, HAZARD_FREE_ASYNC_CTX);
 }
 #else
 MonoLockFreeQueue available_descs;
@@ -302,7 +302,7 @@ static void
 list_put_partial (Descriptor *desc)
 {
        g_assert (desc->anchor.data.state != STATE_FULL);
-       mono_thread_hazardous_free_or_queue (desc, desc_put_partial, FALSE, TRUE);
+       mono_thread_hazardous_free_or_queue (desc, desc_put_partial, HAZARD_FREE_NO_LOCK, HAZARD_FREE_ASYNC_CTX);
 }
 
 static void
@@ -321,7 +321,7 @@ list_remove_empty_desc (MonoLockFreeAllocSizeClass *sc)
                        desc_retire (desc);
                } else {
                        g_assert (desc->heap->sc == sc);
-                       mono_thread_hazardous_free_or_queue (desc, desc_put_partial, FALSE, TRUE);
+                       mono_thread_hazardous_free_or_queue (desc, desc_put_partial, HAZARD_FREE_NO_LOCK, HAZARD_FREE_ASYNC_CTX);
                        if (++num_non_empty >= 2)
                                return;
                }
index 99cc8aaaf1622607d854923ca80a87e71218b663..b0076c6d18441ade1e6d345282b60652a5f3c57e 100644 (file)
@@ -286,7 +286,7 @@ mono_lock_free_queue_dequeue (MonoLockFreeQueue *q)
                g_assert (q->has_dummy);
                q->has_dummy = 0;
                mono_memory_write_barrier ();
-               mono_thread_hazardous_free_or_queue (head, free_dummy, FALSE, TRUE);
+               mono_thread_hazardous_free_or_queue (head, free_dummy, HAZARD_FREE_NO_LOCK, HAZARD_FREE_ASYNC_CTX);
                if (try_reenqueue_dummy (q))
                        goto retry;
                return NULL;
index e0b2dcbbb0e36c49e649da110e62f8a6fd87d247..58cf945facf0a0136f920c2f94d72622df4c7ea9 100644 (file)
@@ -56,7 +56,7 @@ conc_table_free (gpointer ptr)
 static void
 conc_table_lf_free (conc_table *table)
 {
-       mono_thread_hazardous_free_or_queue (table, conc_table_free, TRUE, FALSE);
+       mono_thread_hazardous_free_or_queue (table, conc_table_free, HAZARD_FREE_MAY_LOCK, HAZARD_FREE_SAFE_CTX);
 }
 
 
index 95b3cad57b28cdc32a5e64d81293c91d98d592ce..bed9595f84d344e3209521564fc756efcfdb77c9 100644 (file)
@@ -56,27 +56,28 @@ get_hazardous_pointer_with_mask (gpointer volatile *pp, MonoThreadHazardPointers
 /*
 Initialize @list and will use @free_node_func to release memory.
 If @free_node_func is null the caller is responsible for releasing node memory.
-@free_node_func must be lock-free.  That implies that it cannot use malloc/free.
+If @free_node_func may lock, @free_node_func_locking must be
+HAZARD_FREE_MAY_LOCK; otherwise, HAZARD_FREE_NO_LOCK. It is ignored if
+@free_node_func is null.
 */
 void
-mono_lls_init (MonoLinkedListSet *list, void (*free_node_func)(void *))
+mono_lls_init (MonoLinkedListSet *list, void (*free_node_func)(void *), HazardFreeLocking free_node_func_locking)
 {
        list->head = NULL;
        list->free_node_func = free_node_func;
+       list->locking = free_node_func_locking;
 }
 
 /*
 Search @list for element with key @key.
+@context specifies whether the function is being called from a lock-free (i.e.
+signal handler or world stopped) context. It is only relevant if a node free
+function was given.
 The nodes next, cur and prev are returned in @hp.
 Returns true if a node with key @key was found.
-This function cannot be called from a signal nor within interrupt context*.
-XXX A variant that works within interrupted is possible if needed.
-
-* interrupt context is when the current thread is reposible for another thread
-been suspended at an arbritary point. This is a limitation of our SMR implementation.
 */
 gboolean
-mono_lls_find (MonoLinkedListSet *list, MonoThreadHazardPointers *hp, uintptr_t key)
+mono_lls_find (MonoLinkedListSet *list, MonoThreadHazardPointers *hp, uintptr_t key, HazardFreeContext context)
 {
        MonoLinkedListSetNode *cur, *next;
        MonoLinkedListSetNode **prev;
@@ -125,7 +126,7 @@ try_again:
                                mono_memory_write_barrier ();
                                mono_hazard_pointer_clear (hp, 1);
                                if (list->free_node_func)
-                                       mono_thread_hazardous_free_or_queue (cur, list->free_node_func, FALSE, TRUE);
+                                       mono_thread_hazardous_free_or_queue (cur, list->free_node_func, list->locking, context);
                        } else
                                goto try_again;
                }
@@ -136,13 +137,15 @@ try_again:
 
 /*
 Insert @value into @list.
+@context specifies whether the function is being called from a lock-free (i.e.
+signal handler or world stopped) context. It is only relevant if a node free
+function was given.
 The nodes value, cur and prev are returned in @hp.
 Return true if @value was inserted by this call. If it returns FALSE, it's the caller
 resposibility to release memory.
-This function cannot be called from a signal nor with the world stopped.
 */
 gboolean
-mono_lls_insert (MonoLinkedListSet *list, MonoThreadHazardPointers *hp, MonoLinkedListSetNode *value)
+mono_lls_insert (MonoLinkedListSet *list, MonoThreadHazardPointers *hp, MonoLinkedListSetNode *value, HazardFreeContext context)
 {
        MonoLinkedListSetNode *cur, **prev;
        /*We must do a store barrier before inserting 
@@ -150,7 +153,7 @@ mono_lls_insert (MonoLinkedListSet *list, MonoThreadHazardPointers *hp, MonoLink
        mono_memory_barrier ();
 
        while (1) {
-               if (mono_lls_find (list, hp, value->key))
+               if (mono_lls_find (list, hp, value->key, context))
                        return FALSE;
                cur = (MonoLinkedListSetNode *) mono_hazard_pointer_get_val (hp, 1);
                prev = (MonoLinkedListSetNode **) mono_hazard_pointer_get_val (hp, 2);
@@ -165,17 +168,19 @@ mono_lls_insert (MonoLinkedListSet *list, MonoThreadHazardPointers *hp, MonoLink
 }
 
 /*
-Search @list for element with key @key.
+Search @list for element with key @key and remove it.
+@context specifies whether the function is being called from a lock-free (i.e.
+signal handler or world stopped) context. It is only relevant if a node free
+function was given.
 The nodes next, cur and prev are returned in @hp
 Returns true if @value was removed by this call.
-This function cannot be called from a signal nor with the world stopped.
 */
 gboolean
-mono_lls_remove (MonoLinkedListSet *list, MonoThreadHazardPointers *hp, MonoLinkedListSetNode *value)
+mono_lls_remove (MonoLinkedListSet *list, MonoThreadHazardPointers *hp, MonoLinkedListSetNode *value, HazardFreeContext context)
 {
        MonoLinkedListSetNode *cur, **prev, *next;
        while (1) {
-               if (!mono_lls_find (list, hp, value->key))
+               if (!mono_lls_find (list, hp, value->key, context))
                        return FALSE;
 
                next = (MonoLinkedListSetNode *) mono_hazard_pointer_get_val (hp, 0);
@@ -193,9 +198,9 @@ mono_lls_remove (MonoLinkedListSet *list, MonoThreadHazardPointers *hp, MonoLink
                        mono_memory_write_barrier ();
                        mono_hazard_pointer_clear (hp, 1);
                        if (list->free_node_func)
-                               mono_thread_hazardous_free_or_queue (value, list->free_node_func, FALSE, TRUE);
+                               mono_thread_hazardous_free_or_queue (value, list->free_node_func, list->locking, context);
                } else
-                       mono_lls_find (list, hp, value->key);
+                       mono_lls_find (list, hp, value->key, context);
                return TRUE;
        }
 }
index 0abcee98f15730a8d73b7a2f4dec99dc81409b06..6e0d6296fd6b53a04ba05727240d196daab5fb08 100644 (file)
@@ -24,6 +24,7 @@ struct _MonoLinkedListSetNode {
 typedef struct {
        MonoLinkedListSetNode *head;
        void (*free_node_func)(void *);
+       HazardFreeLocking locking;
 } MonoLinkedListSet;
 
 
@@ -45,77 +46,129 @@ You must manually clean the hazard pointer table after using them.
 */
 
 void
-mono_lls_init (MonoLinkedListSet *list, void (*free_node_func)(void *));
+mono_lls_init (MonoLinkedListSet *list, void (*free_node_func)(void *), HazardFreeLocking free_node_func_locking);
 
 gboolean
-mono_lls_find (MonoLinkedListSet *list, MonoThreadHazardPointers *hp, uintptr_t key);
+mono_lls_find (MonoLinkedListSet *list, MonoThreadHazardPointers *hp, uintptr_t key, HazardFreeContext context);
 
 gboolean
-mono_lls_insert (MonoLinkedListSet *list, MonoThreadHazardPointers *hp, MonoLinkedListSetNode *value);
+mono_lls_insert (MonoLinkedListSet *list, MonoThreadHazardPointers *hp, MonoLinkedListSetNode *value, HazardFreeContext context);
 
 gboolean
-mono_lls_remove (MonoLinkedListSet *list, MonoThreadHazardPointers *hp, MonoLinkedListSetNode *value);
+mono_lls_remove (MonoLinkedListSet *list, MonoThreadHazardPointers *hp, MonoLinkedListSetNode *value, HazardFreeContext context);
 
 gpointer
 get_hazardous_pointer_with_mask (gpointer volatile *pp, MonoThreadHazardPointers *hp, int hazard_index);
 
-/*
-Requires the world to be stoped
-*/
-#define MONO_LLS_FOREACH(list, element, type) {\
-       MonoLinkedListSetNode *__cur;   \
-       for (__cur = (list)->head; __cur; __cur = mono_lls_pointer_unmask (__cur->next)) \
-               if (!mono_lls_pointer_get_mark (__cur->next)) { \
-                       (element) = (type)__cur;
-
-
-#define MONO_LLS_FOREACH_FILTERED(list, element, filter_func, type) {\
-       MonoLinkedListSetNode *__cur;   \
-       for (__cur = (list)->head; __cur; __cur = (MonoLinkedListSetNode *)mono_lls_pointer_unmask (__cur->next)) \
-               if (!mono_lls_pointer_get_mark (__cur->next)) { \
-                       (element) = (type)__cur;                        \
-                       if (!filter_func (element)) continue;
-
-#define MONO_LLS_END_FOREACH }}
-
-static inline MonoLinkedListSetNode*
-mono_lls_info_step (MonoLinkedListSetNode *val, MonoThreadHazardPointers *hp)
+static inline gboolean
+mono_lls_filter_accept_all (gpointer elem)
 {
-       val = (MonoLinkedListSetNode *) mono_lls_pointer_unmask (val);
-       mono_hazard_pointer_set (hp, 1, val);
-       return val;
+       return TRUE;
 }
 
 /*
-Provides snapshot iteration
-*/
-#define MONO_LLS_FOREACH_SAFE(list, element, type) {\
-       MonoThreadHazardPointers *__hp = mono_hazard_pointer_get ();    \
-       MonoLinkedListSetNode *__cur, *__next;  \
-       for (__cur = (MonoLinkedListSetNode *) mono_lls_pointer_unmask (get_hazardous_pointer ((gpointer volatile*)&(list)->head, __hp, 1)); \
-               __cur;  \
-               __cur = (MonoLinkedListSetNode *) mono_lls_info_step (__next, __hp)) {  \
-               __next = (MonoLinkedListSetNode *) get_hazardous_pointer_with_mask ((gpointer volatile*)&__cur->next, __hp, 0); \
-               if (!mono_lls_pointer_get_mark (__next)) {      \
-                       (element) = (type)__cur;
-
-#define MONO_LLS_FOREACH_FILTERED_SAFE(list, element, filter_func, type) {\
-       MonoThreadHazardPointers *__hp = mono_hazard_pointer_get ();    \
-       MonoLinkedListSetNode *__cur, *__next;  \
-       for (__cur = (MonoLinkedListSetNode *) mono_lls_pointer_unmask (get_hazardous_pointer ((gpointer volatile*)&(list)->head, __hp, 1)); \
-               __cur;  \
-               __cur = (MonoLinkedListSetNode *) mono_lls_info_step (__next, __hp)) {  \
-               __next = (MonoLinkedListSetNode *) get_hazardous_pointer_with_mask ((gpointer volatile*)&__cur->next, __hp, 0); \
-               if (!mono_lls_pointer_get_mark (__next)) {      \
-                       (element) = (type)__cur;        \
-                       if (!filter_func (element)) continue;
-
-
-#define MONO_LLS_END_FOREACH_SAFE \
+ * These macros assume that no other threads are actively modifying the list.
+ */
+
+#define MONO_LLS_FOREACH_FILTERED(list, type, elem, filter) \
+       do { \
+               MonoLinkedListSet *list__ = (list); \
+               for (MonoLinkedListSetNode *cur__ = list__->head; cur__; cur__ = (MonoLinkedListSetNode *) mono_lls_pointer_unmask (cur__->next)) { \
+                       if (!mono_lls_pointer_get_mark (cur__->next)) { \
+                               type *elem = (type *) cur__; \
+                               if (filter (elem)) {
+
+#define MONO_LLS_FOREACH_END \
+                               } \
+                       } \
                } \
-       }       \
-       mono_hazard_pointer_clear (__hp, 0); \
-       mono_hazard_pointer_clear (__hp, 1); \
-}
+       } while (0);
+
+#define MONO_LLS_FOREACH(list, type, elem) \
+       MONO_LLS_FOREACH_FILTERED ((list), type, elem, mono_lls_filter_accept_all)
+
+/*
+ * These macros can be used while other threads are potentially modifying the
+ * list, but they only provide a snapshot of the list as a result.
+ *
+ * NOTE: Do NOT break out of the loop through any other means than a break
+ * statement, as other ways of breaking the loop will skip past important
+ * cleanup work.
+ */
+
+#define MONO_LLS_FOREACH_FILTERED_SAFE(list, type, elem, filter) \
+       do { \
+               /* NOTE: Keep this macro's code in sync with the mono_lls_find () logic. */ \
+               MonoLinkedListSet *list__ = (list); \
+               MonoThreadHazardPointers *hp__ = mono_hazard_pointer_get (); \
+               gboolean progress__ = FALSE; \
+               uintptr_t hkey__; \
+               gboolean restart__; \
+               do { \
+                       restart__ = FALSE; \
+                       MonoLinkedListSetNode **prev__ = &list__->head; \
+                       mono_hazard_pointer_set (hp__, 2, prev__); \
+                       MonoLinkedListSetNode *cur__ = (MonoLinkedListSetNode *) get_hazardous_pointer_with_mask ((gpointer *) prev__, hp__, 1); \
+                       while (1) { \
+                               if (!cur__) { \
+                                       break; \
+                               } \
+                               MonoLinkedListSetNode *next__ = (MonoLinkedListSetNode *) get_hazardous_pointer_with_mask ((gpointer *) &cur__->next, hp__, 0); \
+                               uintptr_t ckey__ = cur__->key; \
+                               mono_memory_read_barrier (); \
+                               if (*prev__ != cur__) { \
+                                       restart__ = TRUE; \
+                                       break; \
+                               } \
+                               if (!mono_lls_pointer_get_mark (next__)) { \
+                                       if (!progress__ || ckey__ > hkey__) { \
+                                               progress__ = TRUE; \
+                                               hkey__ = ckey__; \
+                                               type *elem = (type *) cur__; \
+                                               if (filter (elem)) { \
+                                                       gboolean broke__ = TRUE; \
+                                                       gboolean done__ = FALSE; \
+                                                       do { \
+                                                               if (done__) { \
+                                                                       broke__ = FALSE; \
+                                                                       break; \
+                                                               } \
+                                                               done__ = TRUE;
+
+#define MONO_LLS_FOREACH_SAFE_END \
+                                                               broke__ = FALSE; \
+                                                               break; \
+                                                       } while (1); \
+                                                       if (broke__) { \
+                                                               break; \
+                                                       } \
+                                               } \
+                                       } \
+                                       prev__ = &cur__->next; \
+                                       mono_hazard_pointer_set (hp__, 2, cur__); \
+                               } else { \
+                                       next__ = (MonoLinkedListSetNode *) mono_lls_pointer_unmask (next__); \
+                                       if (InterlockedCompareExchangePointer ((volatile gpointer *) prev__, next__, cur__) == cur__) { \
+                                               mono_memory_write_barrier (); \
+                                               mono_hazard_pointer_clear (hp__, 1); \
+                                               if (list__->free_node_func) { \
+                                                       mono_thread_hazardous_free_or_queue (cur__, list__->free_node_func, list__->locking, HAZARD_FREE_ASYNC_CTX); \
+                                               } \
+                                       } else { \
+                                               restart__ = TRUE; \
+                                               break; \
+                                       } \
+                               } \
+                               cur__ = (MonoLinkedListSetNode *) mono_lls_pointer_unmask (next__); \
+                               mono_hazard_pointer_set (hp__, 1, cur__); \
+                       } \
+               } while (restart__); \
+               mono_hazard_pointer_clear (hp__, 0); \
+               mono_hazard_pointer_clear (hp__, 1); \
+               mono_hazard_pointer_clear (hp__, 2); \
+       } while (0);
+
+#define MONO_LLS_FOREACH_SAFE(list, type, elem) \
+       MONO_LLS_FOREACH_FILTERED_SAFE ((list), type, elem, mono_lls_filter_accept_all)
 
 #endif /* __MONO_SPLIT_ORDERED_LIST_H__ */
index 921398bca1815651b709ca557e495bf5082d3777..5d08308885afd113ee3e52b0abd8b2eb6ed3ead9 100644 (file)
@@ -187,7 +187,6 @@ mono_threads_end_global_suspend (void)
 static void
 dump_threads (void)
 {
-       MonoThreadInfo *info;
        MonoThreadInfo *cur = mono_thread_info_current ();
 
        MOSTLY_ASYNC_SAFE_PRINTF ("STATE CUE CARD: (? means a positive number, usually 1 or 2, * means any number)\n");
@@ -210,8 +209,7 @@ dump_threads (void)
 #else
                MOSTLY_ASYNC_SAFE_PRINTF ("--thread %p id %p [%p] state %x  %s\n", info, (void *) mono_thread_info_get_tid (info), (void*)(size_t)info->native_handle, info->thread_state, info == cur ? "GC INITIATOR" : "" );
 #endif
-
-       } END_FOREACH_THREAD_SAFE
+       } FOREACH_THREAD_SAFE_END
 }
 
 gboolean
@@ -271,7 +269,7 @@ mono_thread_info_lookup (MonoNativeThreadId id)
 {
                MonoThreadHazardPointers *hp = mono_hazard_pointer_get ();
 
-       if (!mono_lls_find (&thread_list, hp, (uintptr_t)id)) {
+       if (!mono_lls_find (&thread_list, hp, (uintptr_t)id, HAZARD_FREE_ASYNC_CTX)) {
                mono_hazard_pointer_clear_all (hp, -1);
                return NULL;
        } 
@@ -285,7 +283,7 @@ mono_thread_info_insert (MonoThreadInfo *info)
 {
        MonoThreadHazardPointers *hp = mono_hazard_pointer_get ();
 
-       if (!mono_lls_insert (&thread_list, hp, (MonoLinkedListSetNode*)info)) {
+       if (!mono_lls_insert (&thread_list, hp, (MonoLinkedListSetNode*)info, HAZARD_FREE_SAFE_CTX)) {
                mono_hazard_pointer_clear_all (hp, -1);
                return FALSE;
        } 
@@ -301,7 +299,7 @@ mono_thread_info_remove (MonoThreadInfo *info)
        gboolean res;
 
        THREADS_DEBUG ("removing info %p\n", info);
-       res = mono_lls_remove (&thread_list, hp, (MonoLinkedListSetNode*)info);
+       res = mono_lls_remove (&thread_list, hp, (MonoLinkedListSetNode*)info, HAZARD_FREE_SAFE_CTX);
        mono_hazard_pointer_clear_all (hp, -1);
        return res;
 }
@@ -426,7 +424,7 @@ unregister_thread (void *arg)
        g_byte_array_free (info->stackdata, /*free_segment=*/TRUE);
 
        /*now it's safe to free the thread info.*/
-       mono_thread_hazardous_free_or_queue (info, free_thread_info, TRUE, FALSE);
+       mono_thread_hazardous_free_or_queue (info, free_thread_info, HAZARD_FREE_MAY_LOCK, HAZARD_FREE_SAFE_CTX);
        mono_thread_small_id_free (small_id);
 }
 
@@ -637,7 +635,7 @@ mono_threads_init (MonoThreadInfoCallbacks *callbacks, size_t info_size)
        mono_coop_sem_init (&global_suspend_semaphore, 1);
        mono_os_sem_init (&suspend_semaphore, 0);
 
-       mono_lls_init (&thread_list, NULL);
+       mono_lls_init (&thread_list, NULL, HAZARD_FREE_NO_LOCK);
        mono_thread_smr_init ();
        mono_threads_init_platform ();
        mono_threads_init_coop ();
index 854bbe6e62365550b1b70b3dda13083fe2bac40d..1019dda1884e4c078e4f9de583e74a339c223bfc 100644 (file)
@@ -300,14 +300,20 @@ mono_threads_filter_tools_threads (THREAD_INFO_TYPE *info)
 /*
 Requires the world to be stoped
 */
-#define FOREACH_THREAD(thread) MONO_LLS_FOREACH_FILTERED (mono_thread_info_list_head (), thread, mono_threads_filter_tools_threads, THREAD_INFO_TYPE*)
-#define END_FOREACH_THREAD MONO_LLS_END_FOREACH
+#define FOREACH_THREAD(thread) \
+       MONO_LLS_FOREACH_FILTERED (mono_thread_info_list_head (), THREAD_INFO_TYPE, thread, mono_threads_filter_tools_threads)
+
+#define FOREACH_THREAD_END \
+       MONO_LLS_FOREACH_END
 
 /*
 Snapshot iteration.
 */
-#define FOREACH_THREAD_SAFE(thread) MONO_LLS_FOREACH_FILTERED_SAFE (mono_thread_info_list_head (), thread, mono_threads_filter_tools_threads, THREAD_INFO_TYPE*)
-#define END_FOREACH_THREAD_SAFE MONO_LLS_END_FOREACH_SAFE
+#define FOREACH_THREAD_SAFE(thread) \
+       MONO_LLS_FOREACH_FILTERED_SAFE (mono_thread_info_list_head (), THREAD_INFO_TYPE, thread, mono_threads_filter_tools_threads)
+
+#define FOREACH_THREAD_SAFE_END \
+       MONO_LLS_FOREACH_SAFE_END
 
 static inline MonoNativeThreadId
 mono_thread_info_get_tid (THREAD_INFO_TYPE *info)