Skip to content

Commit 1cc0186

Browse files
filipnavarayowl
andauthored
[NativeAOT] Respect Align8 flag for thread statics (#105905)
* Respect Align8 flag for thread statics * Port WASM test Co-authored-by: yowl <[email protected]> --------- Co-authored-by: yowl <[email protected]>
1 parent a4fe68f commit 1cc0186

File tree

2 files changed

+66
-1
lines changed

2 files changed

+66
-1
lines changed

src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/ThreadStatics.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,15 @@ private static unsafe object AllocateThreadStaticStorageForType(TypeManagerHandl
137137
gcDesc = Internal.Runtime.Augments.RuntimeAugments.TypeLoaderCallbacks.GetThreadStaticGCDescForDynamicType(typeManager, typeTlsIndex);
138138
}
139139

140-
return RuntimeImports.RhNewObject((MethodTable*)gcDesc);
140+
MethodTable *pMethodTable = (MethodTable*)gcDesc;
141+
#if FEATURE_64BIT_ALIGNMENT
142+
if (pMethodTable->RequiresAlign8)
143+
{
144+
return InternalCalls.RhpNewFastAlign8(pMethodTable);
145+
}
146+
#endif
147+
148+
return RuntimeImports.RhNewObject(pMethodTable);
141149
}
142150
}
143151
}

src/tests/nativeaot/SmokeTests/UnitTests/BasicThreading.cs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System;
55
using System.Collections.Generic;
66
using System.Runtime.CompilerServices;
7+
using System.Runtime.InteropServices;
78
using System.Threading;
89
using System.Threading.Tasks;
910

@@ -18,6 +19,9 @@ internal static int Run()
1819

1920
ThreadStaticsTestWithTasks.Run();
2021

22+
if (ThreadStaticAlignmentTest.Run() != Pass)
23+
return Fail;
24+
2125
if (ThreadTest.Run() != Pass)
2226
return Fail;
2327

@@ -187,6 +191,59 @@ public static void Run()
187191
}
188192
}
189193

194+
class ThreadStaticAlignmentTest
195+
{
196+
public static int Run()
197+
{
198+
// Check for 8-byte alignment requirement
199+
if (RuntimeInformation.ProcessArchitecture is Architecture.Arm or Architecture.Wasm)
200+
{
201+
// Assume that these are allocated sequentially, use a padding object of size 12 (mod 8 is not 0)
202+
// to move the alignment of the second AddressOfReturnArea in case the first is coincidentally aligned 8.
203+
var ts1Addr = ThreadStaticAlignCheck1.returnArea.AddressOfReturnArea();
204+
var p = new Padder();
205+
var ts2Addr = ThreadStaticAlignCheck2.returnArea.AddressOfReturnArea();
206+
207+
if (((nint)ts1Addr) % 8 != 0)
208+
return BasicThreading.Fail;
209+
if (((nint)ts2Addr) % 8 != 0)
210+
return BasicThreading.Fail;
211+
}
212+
213+
return BasicThreading.Pass;
214+
}
215+
216+
[InlineArray(3)]
217+
private struct ReturnArea
218+
{
219+
private ulong buffer;
220+
221+
internal unsafe nint AddressOfReturnArea()
222+
{
223+
return (nint)Unsafe.AsPointer(ref buffer);
224+
}
225+
}
226+
227+
private class ThreadStaticAlignCheck1
228+
{
229+
[ThreadStatic]
230+
[FixedAddressValueType]
231+
internal static ReturnArea returnArea = default;
232+
}
233+
234+
private class Padder
235+
{
236+
private object o1;
237+
}
238+
239+
private class ThreadStaticAlignCheck2
240+
{
241+
[ThreadStatic]
242+
[FixedAddressValueType]
243+
internal static ReturnArea returnArea = default;
244+
}
245+
}
246+
190247
class ThreadTest
191248
{
192249
private static readonly List<Thread> s_startedThreads = new List<Thread>();

0 commit comments

Comments
 (0)