Przeglądaj źródła

Implement Volatile.Read/Write<T> and Interlocked.MemoryBarrier ().

Zoltan Varga 13 lat temu
rodzic
commit
0ff40ae70a

+ 6 - 1
mcs/class/corlib/System.Threading/Interlocked.cs

@@ -40,7 +40,6 @@ namespace System.Threading
 {
 	public static class Interlocked 
 	{
-
 		[ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
 		[MethodImplAttribute(MethodImplOptions.InternalCall)]
 		public extern static int CompareExchange(ref int location1, int value, int comparand);
@@ -118,5 +117,11 @@ namespace System.Threading
 		[ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]		
 		[MethodImplAttribute(MethodImplOptions.InternalCall)]
 		public extern static long Add(ref long location1, long value);
+
+#if NET_4_5
+		public static void MemoryBarrier () {
+			Thread.MemoryBarrier ();
+		}
+#endif
 	}
 }

+ 9 - 0
mcs/class/corlib/System.Threading/Volatile.cs

@@ -90,6 +90,13 @@ namespace System.Threading
 		[ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
 		public extern static float Read (ref float location);
 
+		[MethodImplAttribute (MethodImplOptions.InternalCall)]
+		[ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
+		public extern static object Read (ref object location);
+
+		[MethodImplAttribute (MethodImplOptions.InternalCall)]
+		public extern static T Read<T> (ref T location) where T : class;
+
 		[MethodImplAttribute (MethodImplOptions.InternalCall)]
 		[ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
 		public extern static void Write (ref bool location, bool value);
@@ -147,6 +154,8 @@ namespace System.Threading
 		[ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
 		public extern static void Write (ref float location, float value);
 
+		[MethodImplAttribute (MethodImplOptions.InternalCall)]
+		public extern static void Write<T>(ref T location, T value) where T : class;
 	}
 }
 

+ 7 - 0
mcs/class/corlib/Test/System.Threading/VolatileTest.cs

@@ -78,6 +78,9 @@ namespace MonoTests.System.Threading
 
 			ushort v13 = ushort.MaxValue;
 			Assert.AreEqual (ushort.MaxValue, Volatile.Read (ref v13), "#v13");
+
+			string s = "ABC";
+			Assert.AreEqual (s, Volatile.Read (ref s));
 		}
 
 		[Test]
@@ -134,6 +137,10 @@ namespace MonoTests.System.Threading
 			ushort v13 = 1;
 			Volatile.Write (ref v13, ushort.MaxValue);
 			Assert.AreEqual (ushort.MaxValue, v13, "#v13");
+
+			string s = "ABC";
+			Volatile.Write (ref s, "DEF");
+			Assert.AreEqual ("DEF", s);
 		}
 
 	}

+ 3 - 1
mono/metadata/icall-def.h

@@ -933,7 +933,8 @@ ICALL(THREADP_35, "SetMaxThreads", ves_icall_System_Threading_ThreadPool_SetMaxT
 ICALL(THREADP_4, "SetMinThreads", ves_icall_System_Threading_ThreadPool_SetMinThreads)
 ICALL(THREADP_5, "pool_queue", icall_append_job)
 
-ICALL_TYPE(VOLATILE, "System.Threading.Volatile", VOLATILE_1)
+ICALL_TYPE(VOLATILE, "System.Threading.Volatile", VOLATILE_28)
+ICALL(VOLATILE_28, "Read(T&)", ves_icall_System_Threading_Volatile_Read_T)
 ICALL(VOLATILE_1, "Read(bool&)", ves_icall_System_Threading_Thread_VolatileRead1)
 ICALL(VOLATILE_2, "Read(byte&)", ves_icall_System_Threading_Thread_VolatileRead1)
 ICALL(VOLATILE_3, "Read(double&)", ves_icall_System_Threading_Thread_VolatileReadDouble)
@@ -947,6 +948,7 @@ ICALL(VOLATILE_10, "Read(uint&)", ves_icall_System_Threading_Thread_VolatileRead
 ICALL(VOLATILE_11, "Read(uint16&)", ves_icall_System_Threading_Thread_VolatileRead2)
 ICALL(VOLATILE_12, "Read(uintptr&)", ves_icall_System_Threading_Thread_VolatileReadIntPtr)
 ICALL(VOLATILE_13, "Read(ulong&)", ves_icall_System_Threading_Thread_VolatileRead8)
+ICALL(VOLATILE_27, "Write(T&,T)", ves_icall_System_Threading_Volatile_Write_T)
 ICALL(VOLATILE_14, "Write(bool&,bool)", ves_icall_System_Threading_Thread_VolatileWrite1)
 ICALL(VOLATILE_15, "Write(byte&,byte)", ves_icall_System_Threading_Thread_VolatileWrite1)
 ICALL(VOLATILE_16, "Write(double&,double)", ves_icall_System_Threading_Thread_VolatileWriteDouble)

+ 3 - 0
mono/metadata/threads-types.h

@@ -152,6 +152,9 @@ void ves_icall_System_Threading_Thread_VolatileWriteObject (void *ptr, void *) M
 void ves_icall_System_Threading_Thread_VolatileWriteFloat (void *ptr, float) MONO_INTERNAL;
 void ves_icall_System_Threading_Thread_VolatileWriteDouble (void *ptr, double) MONO_INTERNAL;
 
+MonoObject* ves_icall_System_Threading_Volatile_Read_T (void *ptr) MONO_INTERNAL;
+void ves_icall_System_Threading_Volatile_Write_T (void *ptr, MonoObject *value) MONO_INTERNAL;
+
 void ves_icall_System_Threading_Thread_MemoryBarrier (void) MONO_INTERNAL;
 void ves_icall_System_Threading_Thread_Interrupt_internal (MonoInternalThread *this_obj) MONO_INTERNAL;
 void ves_icall_System_Threading_Thread_SpinWait_nop (void) MONO_INTERNAL;

+ 13 - 0
mono/metadata/threads.c

@@ -2466,6 +2466,12 @@ ves_icall_System_Threading_Thread_VolatileReadFloat (void *ptr)
 	return *((volatile float *) (ptr));
 }
 
+MonoObject*
+ves_icall_System_Threading_Volatile_Read_T (void *ptr)
+{
+	return (MonoObject*)*((volatile MonoObject**)ptr);
+}
+
 void
 ves_icall_System_Threading_Thread_VolatileWrite1 (void *ptr, gint8 value)
 {
@@ -2514,6 +2520,13 @@ ves_icall_System_Threading_Thread_VolatileWriteFloat (void *ptr, float value)
 	*((volatile float *) ptr) = value;
 }
 
+void
+ves_icall_System_Threading_Volatile_Write_T (void *ptr, MonoObject *value)
+{
+	*((volatile MonoObject **) ptr) = value;
+	mono_gc_wbarrier_generic_nostore (ptr);
+}
+
 void mono_thread_init (MonoThreadStartCB start_cb,
 		       MonoThreadAttachCB attach_cb)
 {

+ 3 - 0
mono/mini/method-to-ir.c

@@ -5086,6 +5086,9 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign
 		}
 #endif /* MONO_ARCH_HAVE_ATOMIC_CAS */
 
+		if (strcmp (cmethod->name, "MemoryBarrier") == 0)
+			ins = emit_memory_barrier (cfg, FullBarrier);
+
 		if (ins)
 			return ins;
 	} else if (cmethod->klass->image == mono_defaults.corlib) {