Browse Source

[corlib] LocalDataStoreSlot from reference sources

Marek Safar 10 years ago
parent
commit
317c3a8efb

+ 1 - 1
external/referencesource

@@ -1 +1 @@
-Subproject commit b8813958c3630d1b06d2a34d8d3b74bf3db79a38
+Subproject commit ce1b13e7cdfd610d243207faab3e7a1237d36132

+ 28 - 31
mcs/class/corlib/System.Runtime.Remoting.Contexts/Context.cs

@@ -62,8 +62,6 @@ namespace System.Runtime.Remoting.Contexts {
 		[ContextStatic]
 		static object[] local_slots;
 
-		static NamedDataSlot namedDataSlot;
-
 		// Default server context sink chain
 		static IMessageSink default_server_context_sink;
 
@@ -78,6 +76,10 @@ namespace System.Runtime.Remoting.Contexts {
 		
 		static int global_count;
 
+		volatile LocalDataStoreHolder _localDataStore;
+
+		static LocalDataStoreMgr _localDataStoreMgr = new LocalDataStoreMgr();
+
 		static DynamicPropertyCollection global_dynamic_properties;
 		DynamicPropertyCollection context_dynamic_properties;
 		ContextCallbackObject callback_object = null;
@@ -368,60 +370,55 @@ namespace System.Runtime.Remoting.Contexts {
 			callback_object.DoCallBack (deleg);
 		}
 
-		static NamedDataSlot NamedDataSlot {
-			get {
-				if (namedDataSlot == null)
-					Interlocked.CompareExchange (ref namedDataSlot, new NamedDataSlot (false), null);
-
-				return namedDataSlot;
+		private LocalDataStore MyLocalStore 
+		{
+			get 
+			{ 
+				if (_localDataStore == null)
+				{
+					// It's OK to lock the manager here because it is going to lock
+					// itself anyway.
+					lock (_localDataStoreMgr)
+					{
+						if (_localDataStore == null)
+						{
+							// The local store has not yet been created for this thread.
+							_localDataStore = _localDataStoreMgr.CreateLocalDataStore();
+						}
+					}
+				}
+				return _localDataStore.Store;
 			}
 		}
 
 		public static LocalDataStoreSlot AllocateDataSlot ()
 		{
-			return new LocalDataStoreSlot (false);
+			return _localDataStoreMgr.AllocateDataSlot ();
 		}
 
 		public static LocalDataStoreSlot AllocateNamedDataSlot (string name)
 		{
-			return NamedDataSlot.Allocate (name);
+			return _localDataStoreMgr.AllocateNamedDataSlot (name);
 		}
 
 		public static void FreeNamedDataSlot (string name)
 		{
-			NamedDataSlot.Free (name);
+			_localDataStoreMgr.FreeNamedDataSlot (name);
 		}
 
 		public static LocalDataStoreSlot GetNamedDataSlot (string name)
 		{
-			return NamedDataSlot.Get (name);
+			return _localDataStoreMgr.GetNamedDataSlot (name);
 		}
 
 		public static object GetData (LocalDataStoreSlot slot)
 		{
-			object[] slots = local_slots;
-			if (slot == null)
-				throw new ArgumentNullException ("slot");
-			if (slots != null && slot.slot < slots.Length)
-				return slots [slot.slot];
-			return null;
+			return Thread.CurrentContext.MyLocalStore.GetData (slot);
 		}
 
 		public static void SetData (LocalDataStoreSlot slot, object data)
 		{
-			object[] slots = local_slots;
-			if (slot == null)
-				throw new ArgumentNullException ("slot");
-			if (slots == null) {
-				slots = new object [slot.slot + 2];
-				local_slots = slots;
-			} else if (slot.slot >= slots.Length) {
-				object[] nslots = new object [slot.slot + 2];
-				slots.CopyTo (nslots, 0);
-				slots = nslots;
-				local_slots = slots;
-			}
-			slots [slot.slot] = data;
+			Thread.CurrentContext.MyLocalStore.SetData (slot, data);
 		}
 	}
 

+ 0 - 92
mcs/class/corlib/System.Threading/NamedDataSlot.cs

@@ -1,92 +0,0 @@
-//
-// NamedDataSlot.cs:
-//
-// Authors:
-//   Dick Porter ([email protected])
-//   Marek Safar ([email protected])
-//
-// (C) Ximian, Inc.  http://www.ximian.com
-// Copyright (C) 2004-2006 Novell, Inc (http://www.novell.com)
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-// 
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-// 
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-using System.Collections.Generic;
-
-namespace System.Threading
-{
-	sealed class NamedDataSlot
-	{
-		bool thread_local;
-		// Stores a hash keyed by strings of LocalDataStoreSlot objects
-		Dictionary<string, LocalDataStoreSlot> datastorehash;
-
-		public NamedDataSlot (bool thread_local)
-		{
-			this.thread_local = thread_local;
-		}
-
-		public LocalDataStoreSlot Allocate (string name)
-		{		
-			lock (this) {
-				if (datastorehash == null)
-					datastorehash = new Dictionary<string, LocalDataStoreSlot> ();
-
-				if (datastorehash.ContainsKey (name)) {
-					// This exception isnt documented (of
-					// course) but .net throws it
-					throw new ArgumentException ("Named data slot already added");
-				}
-			
-				var slot = new LocalDataStoreSlot (thread_local);
-				datastorehash.Add (name, slot);
-				return slot;
-			}
-		}
-
-		public LocalDataStoreSlot Get (string name)
-		{
-			lock (this) {
-				if (datastorehash == null)
-					datastorehash = new Dictionary<string, LocalDataStoreSlot> ();
-
-				LocalDataStoreSlot slot;
-				if (!datastorehash.TryGetValue (name, out slot)) {
-					slot = new LocalDataStoreSlot (thread_local);
-					datastorehash.Add (name, slot);
-				}
-			
-				return slot;
-			}
-		}		
-
-		public void Free (string name)
-		{			
-			lock (this) {
-				if (datastorehash == null)
-					datastorehash = new Dictionary<string, LocalDataStoreSlot> ();
-
-				if (datastorehash.ContainsKey (name)) {
-					datastorehash.Remove (name);
-				}
-			}
-		}
-	}
-}

+ 0 - 82
mcs/class/corlib/System.Threading/Thread.cs

@@ -141,8 +141,6 @@ namespace System.Threading {
 		[ThreadStatic]
 		static ExecutionContext _ec;
 
-		static NamedDataSlot namedDataSlot;		
-
 		static internal CultureInfo default_culture;
 		static internal CultureInfo default_ui_culture;
 
@@ -317,64 +315,7 @@ namespace System.Threading {
 				return (int)(CurrentThread.internal_thread.thread_id);
 			}
 		}
-		
-		static NamedDataSlot NamedDataSlot {
-			get {
-				if (namedDataSlot == null)
-					Interlocked.CompareExchange (ref namedDataSlot, new NamedDataSlot (true), null);
-
-				return namedDataSlot;
-			}
-		}
-		
-		public static LocalDataStoreSlot AllocateNamedDataSlot (string name)
-		{
-			return NamedDataSlot.Allocate (name);
-		}
-
-		public static void FreeNamedDataSlot (string name)
-		{
-			NamedDataSlot.Free (name);
-		}
-
-		public static LocalDataStoreSlot AllocateDataSlot ()
-		{
-			return new LocalDataStoreSlot (true);
-		}
-
-		public static object GetData (LocalDataStoreSlot slot) {
-			object[] slots = local_slots;
-			if (slot == null)
-				throw new ArgumentNullException ("slot");
-			if (slots != null && slot.slot < slots.Length)
-				return slots [slot.slot];
-			return null;
-		}
-
-		public static void SetData (LocalDataStoreSlot slot, object data) {
-			object[] slots = local_slots;
-			if (slot == null)
-				throw new ArgumentNullException ("slot");
-			if (slots == null) {
-				slots = new object [slot.slot + 2];
-				local_slots = slots;
-			} else if (slot.slot >= slots.Length) {
-				object[] nslots = new object [slot.slot + 2];
-				slots.CopyTo (nslots, 0);
-				slots = nslots;
-				local_slots = slots;
-			}
-			slots [slot.slot] = data;
-		}
 
-		[MethodImplAttribute (MethodImplOptions.InternalCall)]
-		internal extern static void FreeLocalSlotValues (int slot, bool thread_local);
-
-		public static LocalDataStoreSlot GetNamedDataSlot(string name)
-	 	{
-	 		return NamedDataSlot.Get (name);
-		}
-		
 		public static AppDomain GetDomain() {
 			return AppDomain.CurrentDomain;
 		}
@@ -936,29 +877,6 @@ namespace System.Threading {
 			Start ();
 		}
 
-#if !MOBILE
-		void _Thread.GetIDsOfNames ([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
-		{
-			throw new NotImplementedException ();
-		}
-
-		void _Thread.GetTypeInfo (uint iTInfo, uint lcid, IntPtr ppTInfo)
-		{
-			throw new NotImplementedException ();
-		}
-
-		void _Thread.GetTypeInfoCount (out uint pcTInfo)
-		{
-			throw new NotImplementedException ();
-		}
-
-		void _Thread.Invoke (uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams,
-			IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
-		{
-			throw new NotImplementedException ();
-		}
-#endif
-
 		internal CultureInfo GetCurrentUICultureNoAppX ()
 		{
 			return CultureInfo.CurrentUICulture;

+ 0 - 97
mcs/class/corlib/System/LocalDataStoreSlot.cs

@@ -1,97 +0,0 @@
-//
-// System.LocalDataStoreSlot.cs
-//
-// Author:
-//   Dick Porter ([email protected])
-//
-// (C) Ximian, Inc.  http://www.ximian.com
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-// 
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-// 
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-namespace System 
-{
-	[ComVisible (true)]
-	public sealed class LocalDataStoreSlot
-	{
-		internal int slot;
-		internal bool thread_local; // false for context-local
-
-		static object lock_obj = new object ();
-		static bool[] slot_bitmap_thread;
-		static bool[] slot_bitmap_context;
-
-		internal LocalDataStoreSlot (bool in_thread)
-		{
-			thread_local = in_thread;
-			lock (lock_obj) {
-				int i;
-				bool[] slot_bitmap;
-				if (in_thread)
-					slot_bitmap = slot_bitmap_thread;
-				else
-					slot_bitmap = slot_bitmap_context;
-				if (slot_bitmap != null) {
-					for (i = 0; i < slot_bitmap.Length; ++i) {
-						if (!slot_bitmap [i]) {
-							slot = i;
-							slot_bitmap [i] = true;
-							return;
-						}
-					}
-					bool[] new_bitmap = new bool [i + 2];
-					slot_bitmap.CopyTo (new_bitmap, 0);
-					slot_bitmap = new_bitmap;
-				} else {
-					slot_bitmap = new bool [2];
-					i = 0;
-				}
-				slot_bitmap [i] = true;
-				slot = i;
-				if (in_thread)
-					slot_bitmap_thread = slot_bitmap;
-				else
-					slot_bitmap_context = slot_bitmap;
-			}
-		}
-
-		~LocalDataStoreSlot ()
-		{
-			/* first remove all the values from the slots and
-			 * then free the slot itself for reuse.
-			 */
-			System.Threading.Thread.FreeLocalSlotValues (slot, thread_local);
-			lock (lock_obj) {
-				if (thread_local)
-					slot_bitmap_thread [slot] = false;
-				else
-					slot_bitmap_context [slot] = false;
-			}
-		}
-	}
-}

+ 2 - 2
mcs/class/corlib/corlib.dll.sources

@@ -108,7 +108,6 @@ System/Guid.MonoTouch.cs
 System/IConsoleDriver.cs
 System/IntPtr.cs
 System/KnownTerminals.cs
-System/LocalDataStoreSlot.cs
 System/MarshalByRefObject.cs
 System/Math.cs
 System/MonoAsyncCall.cs
@@ -877,7 +876,6 @@ System.Threading/LockCookie.cs
 System.Threading/LockQueue.cs
 System.Threading/Monitor.cs
 System.Threading/Mutex.cs
-System.Threading/NamedDataSlot.cs
 System.Threading/NativeEventCalls.cs
 System.Threading/NativeOverlapped.cs
 System.Threading/Overlapped.cs
@@ -925,6 +923,8 @@ ReferenceSources/SharedStatics.cs
 
 ../../../external/referencesource/mscorlib/system/__filters.cs
 ../../../external/referencesource/mscorlib/system/__hresults.cs
+../../../external/referencesource/mscorlib/system/_localdatastore.cs
+../../../external/referencesource/mscorlib/system/_localdatastoremgr.cs
 ../../../external/referencesource/mscorlib/system/accessviolationexception.cs
 ../../../external/referencesource/mscorlib/system/action.cs
 ../../../external/referencesource/mscorlib/system/activator.cs

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

@@ -917,7 +917,6 @@ ICALL(THREAD_2, "ClrState(System.Threading.InternalThread,System.Threading.Threa
 ICALL(THREAD_2a, "ConstructInternalThread", ves_icall_System_Threading_Thread_ConstructInternalThread)
 ICALL(THREAD_3, "CurrentInternalThread_internal", mono_thread_internal_current)
 ICALL(THREAD_3a, "DestroyTlsData", mono_thread_destroy_tls)
-ICALL(THREAD_4, "FreeLocalSlotValues", mono_thread_free_local_slot_values)
 ICALL(THREAD_55, "GetAbortExceptionState", ves_icall_System_Threading_Thread_GetAbortExceptionState)
 ICALL(THREAD_7, "GetDomainID", ves_icall_System_Threading_Thread_GetDomainID)
 ICALL(THREAD_8, "GetName_internal(System.Threading.InternalThread)", ves_icall_System_Threading_Thread_GetName_internal)

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

@@ -198,7 +198,6 @@ void mono_alloc_special_static_data_free (GHashTable *special_static_fields);
 uint32_t mono_thread_alloc_tls   (MonoReflectionType *type);
 void     mono_thread_destroy_tls (uint32_t tls_offset);
 void     mono_thread_destroy_domain_tls (MonoDomain *domain);
-void mono_thread_free_local_slot_values (int slot, MonoBoolean is_thread_local);
 void mono_thread_current_check_pending_interrupt (void);
 
 void mono_thread_set_state (MonoInternalThread *thread, MonoThreadState state);

+ 0 - 49
mono/metadata/threads.c

@@ -4064,9 +4064,6 @@ mono_thread_destroy_domain_tls (MonoDomain *domain)
 		destroy_tls (domain, domain->tlsrec_list->tls_offset);
 }
 
-static MonoClassField *thread_local_slots = NULL;
-static MonoClassField *context_local_slots = NULL;
-
 typedef struct {
 	/* local tls data to get locals_slot from a thread */
 	guint32 offset;
@@ -4128,52 +4125,6 @@ clear_context_local_slot (gpointer key, gpointer value, gpointer user_data)
 	mono_array_set (slots_array, MonoObject *, sid->slot, NULL);
 }
 
-void
-mono_thread_free_local_slot_values (int slot, MonoBoolean thread_local)
-{
-	if (!thread_local_slots) {
-		thread_local_slots = mono_class_get_field_from_name (mono_defaults.thread_class, "local_slots");
-		if (!thread_local_slots) {
-			g_warning ("local_slots field not found in Thread class");
-			return;
-		}
-	}
-
-	if (!context_local_slots) {
-		MonoClass *ctx_class = mono_class_from_name (mono_defaults.corlib, "System.Runtime.Remoting.Contexts", "Context");
-		context_local_slots = mono_class_get_field_from_name (ctx_class, "local_slots");
-		if (!context_local_slots) {
-			g_warning ("local_slots field not found in Context class");
-			return;
-		}
-	}
-
-	void *addr = NULL;
-	MonoDomain *domain = mono_domain_get ();
-
-	mono_domain_lock (domain);
-
-	if (domain->special_static_fields)
-		addr = g_hash_table_lookup (domain->special_static_fields, thread_local ? thread_local_slots : context_local_slots);
-
-	mono_domain_unlock (domain);
-
-	if (!addr)
-		return;
-
-	LocalSlotID sid = { .slot = slot, .offset = GPOINTER_TO_UINT (addr) };
-
-	mono_threads_lock ();
-
-	if (thread_local) {
-		mono_g_hash_table_foreach (threads, clear_thread_local_slot, &sid);
-	} else {
-		g_hash_table_foreach (contexts, clear_context_local_slot, &sid);
-	}
-
-	mono_threads_unlock ();
-}
-
 #ifdef HOST_WIN32
 static void CALLBACK dummy_apc (ULONG_PTR param)
 {