-Subproject commit b8813958c3630d1b06d2a34d8d3b74bf3db79a38
+Subproject commit ce1b13e7cdfd610d243207faab3e7a1237d36132
[ContextStatic]
static object[] local_slots;
- static NamedDataSlot namedDataSlot;
-
// Default server context sink chain
static IMessageSink default_server_context_sink;
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;
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);
}
}
+++ /dev/null
-//
-// NamedDataSlot.cs:
-//
-// Authors:
-// Dick Porter (dick@ximian.com)
-// Marek Safar (marek.safar@gmail.com)
-//
-// (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);
- }
- }
- }
- }
-}
[ThreadStatic]
static ExecutionContext _ec;
- static NamedDataSlot namedDataSlot;
-
static internal CultureInfo default_culture;
static internal CultureInfo default_ui_culture;
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;
}
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;
+++ /dev/null
-//
-// System.LocalDataStoreSlot.cs
-//
-// Author:
-// Dick Porter (dick@ximian.com)
-//
-// (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;
- }
- }
- }
-}
System/IConsoleDriver.cs
System/IntPtr.cs
System/KnownTerminals.cs
-System/LocalDataStoreSlot.cs
System/MarshalByRefObject.cs
System/Math.cs
System/MonoAsyncCall.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
../../../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
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)
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);
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;
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)
{