Re: Interesting GCC optimization, but is it legal if POSIX thread support is claimed?

Greg Herlihy wrote:

int acquires_count;

int trylock()
int res;
res = pthread_mutex_trylock(&mutex);
if (res == 0)
return res;

The bug in this program is that the acquires_count is a volatile
object - but not declared as such. Recall that a volatile variable is
one whose value can change asynchronously to the program's execution.
So even though acquires_count's value changes synchronously to the
execution of the thread that holds the mutex (and increments its
value), the value of acquires_count nonetheless changes asynchronously
with regard to the execution of other, suspended threads (and which
might be executing this same function.)

No, it's NOT volatile -- it's protected by a mutex.

This is an argument that's appeared before in this newsgroup. I know what ISO C says, and it's a red herring in this context. What ISO C allows simply doesn't matter.

The use of pthread_mutex_trylock() makes this a POSIX application, not an ISO C application. As such, the platform, INCLUDING the compiler, is subject to POSIX rules, not merely ISO C rules.

POSIX rules are a superset of ISO C, and in particular this code fragment SHALL operate correctly without volatile under POSIX rules.

If the compiler is willing to make the "optimizations" under discussion here, then it may well be a conforming ISO C compiler -- but it is NOT part of a conforming POSIX system. (POSIX doesn't specifically speak of a "POSIX conforming compiler", so I'll avoid that term... but it amounts to the same thing.) This is no different from an OS that chooses to implement pthread_mutex_trylock() without providing memory synchronization. It's simply broken. Whether it would be broken in a DIFFERENT context, without the mutex, is irrelevant. (Or, conversely, if the use of an ISO C compiler and ISO-conforming optimization is appropriate, then the use of POSIX mutex operations is inappropriate.)

Note that such optimizations may be made for non-threaded code; but code built to run in a threaded environment generally will need to completely disable them, (unless the compiler can reliably perform the analysis necessary to determine it's safe); perhaps based on the standard "thread environment" compile options. (-pthread, -mt, $(getconf _CS_POSIX_V7_THREADS_CFLAGS))

POSIX is not just a set of C99 APIs -- it's an environment. That environment must be consistent. If it isn't, then the environment isn't POSIX and trying to write POSIX code is a waste of time.