2

I am having trouble understanding the implications of the MSDN documentation for the Interlocked Variable Access family of functions. I use InterlockedExchange for setting and InterlockedCompareExchange for getting a member variable that is used by multiple threads.

The member is inside a 1 byte packed class:

#pragma pack(1)
class MyClass {
    char _;
    long m_MyMember;
    // ...
}

So the member is set by

InterlockedExchange(&m_MyMember, 1);

and gotten by

long value = InterlockedCompareExchange(&m_MyMember, 0, 0);

InterlockedExchange documentation does not refer to alignment in any way (Strg+F "align"), but InterlockedCompareExchange does:

The parameters for this function must be aligned on a 32-bit boundary; otherwise, the function will behave unpredictably on multiprocessor x86 systems and any non-x86 systems.

However, as I understand it, the parameters are all stack variables, because one could rewrite the above call

long *ptr  = &m_MyMember;
long zero  = 0;
long value = InterlockedCompareExchange(ptr, zero, zero);

So we have block local auto storage class variables. All perfectly 4 byte aligned regardless of the class m_MyMember resides in. Of course, I assume that this is wrong and it is meant that the address behind ptr must be aligned on a 4 byte boundary.

So my questions are:

  1. Is InterlockedExchange really alignment agnostic or is this a let out in the documentation?
  2. Can you confirm that not literally the parameters, but the address behind the long* has to be 4 byte aligned (I cannot assume how the other parameters could not be 4 byte aligned because they are stack variables)?
  3. If the answer to 2 is yes: How could this be resolved? Changing the surrounding class' alignment is not an option, neither is c++ 11 atomic or boost (all due to corporate limitations and required compilability for msvc10 to msvc14).

I considered declaring m_MyMember volatile and using critical sections to access it. Although I would like it better to properly declare m_MyMember to be aligned as needed because those Interlocked Variable Access functions are all around the given code base and I'd like not to add an extra companion CS to every variable.

die_hoernse
  • 171
  • 1
  • 9
  • 1
    Why-oh-why would you do this?? On x86 and x64, InterlockedExchange() generates the XCHG instruction, it is always atomic. How much it costs on a misaligned variable is something you'll have to measure yourself, I'd guess at an arm and a leg. – Hans Passant Feb 12 '16 at 17:28
  • You claim that since the parameters are on the stack the documented contract is satisfied... This is nitpicking on the language being used. Clearly, the docs means that the pointer must be aligned. No way to lawyer yourself out of the contract! – usr Feb 12 '16 at 17:40
  • @Hans Passant: Because of legacy interfaces I have to use. Again, this is not a subject of measuring, but of specification compliant code. I have read about the generated instructions (and hardware exceptions, see csgordons comment to http://stackoverflow.com/questions/881820/interlockedexchange-and-memory-alignment) in other places on SO, but I lack the insight to evaluate those statements. – die_hoernse Feb 12 '16 at 17:55
  • @usr: Yes, that is what I am supposing, too. It is really annoying that such lax wording is used in that critical place on MSDN. – die_hoernse Feb 12 '16 at 18:01

1 Answers1

1

The limitation is not really Microsoft's, but the hardware. In order to atomically change stuff, it has to be aligned (the pointer).

This is also true for members of a critical section, or STD::atomic

Without re-aligning the class, if you could of the interlock variable to guarantee 4 byte alignment with the class, then that should work

mksteve
  • 12,614
  • 3
  • 28
  • 50
  • I meant i would use the critical section to guarantee sole ownership and then read and write contents of volatile variables. Or what do you mean by "members of a critical section"? And sorry, I do not understand your last sentence: "Without re-aligning the class, if you could of the interlock variable to guarantee 4 byte alignment with the class, then that should work" – die_hoernse Feb 12 '16 at 17:46