Skip to content

Commit

Permalink
[NativeAOT] Respect Align8 flag for thread statics (#105905)
Browse files Browse the repository at this point in the history
* Respect Align8 flag for thread statics

* Port WASM test

Co-authored-by: yowl <scott.waye@hubse.com>

---------

Co-authored-by: yowl <scott.waye@hubse.com>
  • Loading branch information
filipnavara and yowl authored Aug 3, 2024
1 parent a4fe68f commit 1cc0186
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,15 @@ private static unsafe object AllocateThreadStaticStorageForType(TypeManagerHandl
gcDesc = Internal.Runtime.Augments.RuntimeAugments.TypeLoaderCallbacks.GetThreadStaticGCDescForDynamicType(typeManager, typeTlsIndex);
}

return RuntimeImports.RhNewObject((MethodTable*)gcDesc);
MethodTable *pMethodTable = (MethodTable*)gcDesc;
#if FEATURE_64BIT_ALIGNMENT
if (pMethodTable->RequiresAlign8)
{
return InternalCalls.RhpNewFastAlign8(pMethodTable);
}
#endif

return RuntimeImports.RhNewObject(pMethodTable);
}
}
}
57 changes: 57 additions & 0 deletions src/tests/nativeaot/SmokeTests/UnitTests/BasicThreading.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;

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

ThreadStaticsTestWithTasks.Run();

if (ThreadStaticAlignmentTest.Run() != Pass)
return Fail;

if (ThreadTest.Run() != Pass)
return Fail;

Expand Down Expand Up @@ -187,6 +191,59 @@ public static void Run()
}
}

class ThreadStaticAlignmentTest
{
public static int Run()
{
// Check for 8-byte alignment requirement
if (RuntimeInformation.ProcessArchitecture is Architecture.Arm or Architecture.Wasm)
{
// Assume that these are allocated sequentially, use a padding object of size 12 (mod 8 is not 0)
// to move the alignment of the second AddressOfReturnArea in case the first is coincidentally aligned 8.
var ts1Addr = ThreadStaticAlignCheck1.returnArea.AddressOfReturnArea();
var p = new Padder();
var ts2Addr = ThreadStaticAlignCheck2.returnArea.AddressOfReturnArea();

if (((nint)ts1Addr) % 8 != 0)
return BasicThreading.Fail;
if (((nint)ts2Addr) % 8 != 0)
return BasicThreading.Fail;
}

return BasicThreading.Pass;
}

[InlineArray(3)]
private struct ReturnArea
{
private ulong buffer;

internal unsafe nint AddressOfReturnArea()
{
return (nint)Unsafe.AsPointer(ref buffer);
}
}

private class ThreadStaticAlignCheck1
{
[ThreadStatic]
[FixedAddressValueType]
internal static ReturnArea returnArea = default;
}

private class Padder
{
private object o1;
}

private class ThreadStaticAlignCheck2
{
[ThreadStatic]
[FixedAddressValueType]
internal static ReturnArea returnArea = default;
}
}

class ThreadTest
{
private static readonly List<Thread> s_startedThreads = new List<Thread>();
Expand Down

0 comments on commit 1cc0186

Please sign in to comment.