preshing / cpp11-on-multicore

Various synchronization primitives for multithreaded applications in C++11.
zlib License
517 stars 102 forks source link

NonRecursiveRWLock::unlockWriter is broken with gcc-11 #13

Open kirbyzhou opened 2 years ago

kirbyzhou commented 2 years ago

As It mentiond in https://bugzilla.redhat.com/show_bug.cgi?id=2109065

            assert(oldStatus.readers == 0);
            newStatus = oldStatus;
            newStatus.writers--;
            waitToRead = oldStatus.waitToRead;
            if (waitToRead > 0)
            {
                newStatus.waitToRead = 0;
                newStatus.readers = waitToRead;
            }

This code fragment will become wrong assembly with "gcc -O2".

The buggy assembly like:

mov    %eax,%edx
lea    -0x100000(%rax),%ecx
and    $0xfff00000,%eax
shr    $0xa,%edx
and    $0x3ff,%edx
or     %edx,%eax
test   %edx,%edx
cmove  %ecx,%eax

So if waitToRead>0 then newStatus.writers will not be changed.

Somebody said "so this union(Status) has 4 members. [class.union] says that "At most one of the non-static data members of an object of union type can be active at any time, that is, the value of at most one of the non-static data members can be stored in a union at any time."

kirbyzhou commented 2 years ago

I suggest just drop the bitfield wrappers to avoid the trouble of the compiler.