Skip to content

[NativeAOT] ordering issue around ensuring static constructor execution #81151

Closed
@VSadov

Description

@VSadov

Re:

We check pContext->initialized with an ordinary read, before accessing the static fields. There is a possibility that we will read the fields before reading the flag on weak-ordered architectures.

The code orders the write to the flag after running constructors by doing full memory fence, but that is both too much and not sufficient.
Too much is because just doing Volatile.Write(ref pContext->initialized, 1) is enough to guarantee the order of writes.
Not sufficient because the read side can still read ahead of the flag check.

A simple fix would be to do volatile read of the flag when checking.
However the same flag check is emitted by the JIT. Not sure if we emit ldar there. I suspect we do not. If that is a case, emitting ldar would be a simple solution.

If ultimately, we do not want to emit ldar, an alternative could be using a slightly different pattern where initialized instead of being a condition flag, could be a pointer used to access the statics. I.E. if it is null the cctor has not run yet, and if it is not null, use it as a pointer (or an offset even if it is fixed, as long as it is used to compute the address) to access static state, then we could benefit from data dependency ordering the reads.

Replacing Interlocked.MemoryBarrier() with a process-wide barrier would work too, but seems too heavy.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-NativeAOT-coreclrin-prThere is an active PR which will close this issue when it is merged

    Type

    No type

    Projects

    Status

    No status

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions