static SgenRememberedSet remset;
+#ifdef MONO_ATOMIC_USES_LOCK
+#include <pthread.h>
+static pthread_mutex_t sgen_atomic_spin_lock G_GNUC_UNUSED = PTHREAD_MUTEX_INITIALIZER;
+
+static gint64
+mono_sgen_atomic_cas_i64(volatile gint64 *dest, gint64 exch, gint64 comp)
+{
+ gint64 old;
+ int ret;
+
+ pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock, (void *)&sgen_atomic_spin_lock);
+ ret = pthread_mutex_lock(&sgen_atomic_spin_lock);
+ g_assert (ret == 0);
+
+ old= *dest;
+ if(old==comp) {
+ *dest=exch;
+ }
+
+ ret = pthread_mutex_unlock(&sgen_atomic_spin_lock);
+ g_assert (ret == 0);
+
+ pthread_cleanup_pop (0);
+
+ return(old);
+}
+#endif
+
/*
* The gray queue a worker job must use. If we're not parallel or
* concurrent, we use the main gray queue.
SGEN_TV_GETTIME (atv);
sgen_major_collector.scan_card_table (CARDTABLE_SCAN_GLOBAL, ctx, job_data->job_index, job_data->job_split_count, job_data->data);
SGEN_TV_GETTIME (btv);
- time_minor_scan_major_blocks += SGEN_TV_ELAPSED (atv, btv);
+
+ gint64 elapsed_time = SGEN_TV_ELAPSED (atv, btv);
+ SGEN_ATOMIC_ADD_I64 (time_minor_scan_major_blocks, elapsed_time);
if (worker_data_untyped)
- ((WorkerData*)worker_data_untyped)->major_scan_time += SGEN_TV_ELAPSED (atv, btv);
+ ((WorkerData*)worker_data_untyped)->major_scan_time += elapsed_time;
}
static void
SGEN_TV_GETTIME (atv);
sgen_los_scan_card_table (CARDTABLE_SCAN_GLOBAL, ctx, job_data->job_index, job_data->job_split_count);
SGEN_TV_GETTIME (btv);
- time_minor_scan_los += SGEN_TV_ELAPSED (atv, btv);
+
+ gint64 elapsed_time = SGEN_TV_ELAPSED (atv, btv);
+ SGEN_ATOMIC_ADD_I64 (time_minor_scan_los, elapsed_time);
if (worker_data_untyped)
- ((WorkerData*)worker_data_untyped)->los_scan_time += SGEN_TV_ELAPSED (atv, btv);
+ ((WorkerData*)worker_data_untyped)->los_scan_time += elapsed_time;
}
static void
SGEN_TV_GETTIME (atv);
sgen_major_collector.scan_card_table (CARDTABLE_SCAN_MOD_UNION, ctx, job_data->job_index, job_data->job_split_count, job_data->data);
SGEN_TV_GETTIME (btv);
- time_major_scan_mod_union_blocks += SGEN_TV_ELAPSED (atv, btv);
+
+ gint64 elapsed_time = SGEN_TV_ELAPSED (atv, btv);
+ SGEN_ATOMIC_ADD_I64 (time_minor_scan_los, time_major_scan_mod_union_blocks);
if (worker_data_untyped)
- ((WorkerData*)worker_data_untyped)->major_scan_time += SGEN_TV_ELAPSED (atv, btv);
+ ((WorkerData*)worker_data_untyped)->major_scan_time += elapsed_time;
}
static void
SGEN_TV_GETTIME (atv);
sgen_los_scan_card_table (CARDTABLE_SCAN_MOD_UNION, ctx, job_data->job_index, job_data->job_split_count);
SGEN_TV_GETTIME (btv);
- time_major_scan_mod_union_los += SGEN_TV_ELAPSED (atv, btv);
+
+ gint64 elapsed_time = SGEN_TV_ELAPSED (atv, btv);
+ SGEN_ATOMIC_ADD_I64 (time_minor_scan_los, time_major_scan_mod_union_los);
if (worker_data_untyped)
- ((WorkerData*)worker_data_untyped)->los_scan_time += SGEN_TV_ELAPSED (atv, btv);
+ ((WorkerData*)worker_data_untyped)->los_scan_time += elapsed_time;
}
static void
} while (mono_atomic_cas_ptr ((void**)&(x), (void*)(__old_x + (i)), (void*)__old_x) != (void*)__old_x); \
} while (0)
+#ifndef MONO_ATOMIC_USES_LOCK
+#define SGEN_ATOMIC_ADD_I64(x,i) do { \
+ mono_atomic_add_i64 ((volatile gint64 *)&x, i); \
+ } while (0)
+#else
+#define SGEN_ATOMIC_ADD_I64(x,i) do { \
+ gint64 __old_x; \
+ do { \
+ __old_x = (x); \
+ } while (mono_sgen_atomic_cas_i64 ((volatile gint64 *)&(x), __old_x + (i), __old_x) != __old_x); \
+ } while (0)
+#endif /* BROKEN_64BIT_ATOMICS_INTRINSIC */
+
#ifdef HEAVY_STATISTICS
extern guint64 stat_objects_alloced_degraded;
extern guint64 stat_bytes_alloced_degraded;
#include <mono/utils/mono-compiler.h>
#if defined (WAPI_NO_ATOMIC_ASM) || defined (BROKEN_64BIT_ATOMICS_INTRINSIC)
+#define NEED_64BIT_CMPXCHG_FALLBACK
+#endif
+#ifdef MONO_ATOMIC_USES_LOCK
#include <pthread.h>
-
static pthread_mutex_t spin G_GNUC_UNUSED = PTHREAD_MUTEX_INITIALIZER;
-
-#define NEED_64BIT_CMPXCHG_FALLBACK
-
#endif
#ifdef WAPI_NO_ATOMIC_ASM
+#ifndef MONO_ATOMIC_USES_LOCK
+#error MONO_ATOMIC_USES_LOCK NOT defined
+#endif
+
gint32 mono_atomic_cas_i32(volatile gint32 *dest, gint32 exch,
gint32 comp)
{
#if defined (TARGET_OSX)
+#ifdef MONO_ATOMIC_USES_LOCK
+#error MONO_ATOMIC_USES_LOCK defined
+#endif
+
/* The compiler breaks if this code is in the header... */
gint64
#elif defined (__arm__) && defined (HAVE_ARMV7) && (defined(TARGET_IOS) || defined(TARGET_WATCHOS) || defined(TARGET_ANDROID))
+#ifdef MONO_ATOMIC_USES_LOCK
+#error MONO_ATOMIC_USES_LOCK defined
+#endif
+
#if defined (TARGET_IOS) || defined (TARGET_WATCHOS)
#ifndef __clang__
#else
+#ifndef MONO_ATOMIC_USES_LOCK
+#error MONO_ATOMIC_USES_LOCK NOT defined
+#endif
+
gint64
mono_atomic_cas_i64(volatile gint64 *dest, gint64 exch, gint64 comp)
{