4

I'm using .Net 4.5 (preview... 4 is fine for the purposes of this question). I'm doing threading work.

Based on my studies, I know that x86 CPUs have a strong memory model, which means writes won't be reordered. This makes releasing locks safe. This is not true for Itanium CPUs, which have a weak memory model.

I understand volatile, memory barriers, and execution reordering principles.

What I need ideally is to insert memory barriers at key points if the CPU is Itanium, but not if it's x86. Is it possible to do this dynamically, as in have runtime compiler directives that the JIT processes?

If not, I realise I will need to have separate builds for the two platforms. In that case, what is the most elegant way to do this without having 2 sets of C# files, but rather simply changing the target?

IamIC
  • 17,747
  • 20
  • 91
  • 154
  • 6
    It is the job of the CLR to hide these differences from you. The Itanium version has a very different implementation of the locking primitives. Avoid not taking advantage of that. http://stackoverflow.com/questions/3855671/how-do-i-atomically-swap-2-ints-in-c/3855824#3855824 – Hans Passant Oct 24 '11 at 21:00
  • Switch to C++ if you want to program the machine. – David Heffernan Oct 24 '11 at 21:37
  • @HansPassant yes, but that doesn't negate the need for memory barriers being used before lock releases on IA64, and not x86/x86-64. – IamIC Oct 24 '11 at 22:09
  • @DavidHeffernan that won't help. In C++ I most certainly would have to have seperate projects for each platform family. – IamIC Oct 24 '11 at 22:10
  • @HansPassant I am liberally using CompareExchange. In fact, I use it in the one case I need to take a lock. But this is off topic. I'm not sure why you ref. your other answer. – IamIC Oct 24 '11 at 22:12
  • It's the memory model of the CLR that matters. – David Heffernan Oct 24 '11 at 22:29
  • @DavidHeffernan the pro texts on the subject differ from what you're saying. See http://www.albahari.com/threading/part4.aspx#_Memory_Barriers_and_Volatility – IamIC Oct 24 '11 at 22:31
  • Does that really contradict what I say? I thought the CLR memory model was a lowest common denominator. – David Heffernan Oct 24 '11 at 22:40
  • @DavidHeffernan LCD isn't the question. It's how the different CPUs order the instructions that's the question. Itanium can reorder writes, which meanse locks can be released before flags are correctly set. This requires a memory barrier. x86 never reorders writes, so no barrier is needed. – IamIC Oct 25 '11 at 09:45
  • Are you saying that .net locks don't work on itanium? – David Heffernan Oct 25 '11 at 11:10
  • @DavidHeffernan I'm not saying that at all. You're missing the comm here. – IamIC Oct 25 '11 at 19:06
  • Clearly I'm not understanding you at all. Anyway, never mind. – David Heffernan Oct 25 '11 at 19:09

2 Answers2

1

I have no idea if this will help you or not, but there are a couple of options described in this answer:

In another answer, somebody provided a link to the following sample code (from Paint.NET) to determine OS architecture. You could make a minor adjustment to include the IA64 check:

private enum Platform
{
    X86,
    X64,
    Unknown
}

internal const ushort PROCESSOR_ARCHITECTURE_INTEL = 0;
internal const ushort PROCESSOR_ARCHITECTURE_IA64 = 6;
internal const ushort PROCESSOR_ARCHITECTURE_AMD64 = 9;
internal const ushort PROCESSOR_ARCHITECTURE_UNKNOWN = 0xFFFF;

[StructLayout(LayoutKind.Sequential)]
internal struct SYSTEM_INFO
{
    public ushort wProcessorArchitecture;
    public ushort wReserved;
    public uint dwPageSize;
    public IntPtr lpMinimumApplicationAddress;
    public IntPtr lpMaximumApplicationAddress;
    public UIntPtr dwActiveProcessorMask;
    public uint dwNumberOfProcessors;
    public uint dwProcessorType;
    public uint dwAllocationGranularity;
    public ushort wProcessorLevel;
    public ushort wProcessorRevision;
};

[DllImport("kernel32.dll")]
internal static extern void GetNativeSystemInfo(ref SYSTEM_INFO lpSystemInfo);        

private static Platform GetPlatform()
{
    SYSTEM_INFO sysInfo = new SYSTEM_INFO();
    GetNativeSystemInfo(ref sysInfo);

    switch (sysInfo.wProcessorArchitecture)
    {
        case PROCESSOR_ARCHITECTURE_AMD64:
            return Platform.X64;

        case PROCESSOR_ARCHITECTURE_INTEL:
            return Platform.X86;

        default:
            return Platform.Unknown;
    }
}
Community
  • 1
  • 1
Cᴏʀʏ
  • 105,112
  • 20
  • 162
  • 194
1

In answer to your main question; I don't think it's currently possible to have CIL instructions conditionally compiled to machine instructions based on platform (other than what's been baked into the JIT compiler).

Your primary tool for creating two (or more) builds from one set of source is still preprocessor directives.

Jake T.
  • 621
  • 5
  • 7