Assume that the shared POSIX mutex has allready been initialized (using PTHREAD_PROCESS_SHARED).
Then, consider the following procedure:
typedef struct {
pthread_mutex_t mutex;
// ...
} Shared;
Shared *shared = (Shared *)mmap(...); // MAP
pthread_mutex_lock(&shared->mutex); // LOCK
// REMAP
munmap(shared, ...);
shared = (Shared *)mmap(...);
pthread_mutex_unlock(&shared->mutex); // UNLOCK
Does POSIX guarantee that this will work as "naively" intended?
As far as I can see, none of the relevant man pages mention such a scenario.
Also, what about the following Linux specific alternative:
Shared *shared = (Shared *)mmap(...); // MAP
pthread_mutex_lock(&shared->mutex); // LOCK
shared = (Shared *)mremap(shared, ...); // MREMAP_MAYMOVE
pthread_mutex_unlock(&shared->mutex); // UNLOCK
I can imagine, for example, a PTHREADS implementation that will store a pointer to a locked mutex somewhere inside the process. If the mutex is configured as robust (PTHREAD_MUTEX_ROBUST), it would allow the implementation to mark the mutex as 'abandoned' if the process dies while the mutex is locked.
I have no idea whether such a scheme would actually work, whether it is allowed by POSIX, or how mutex robustness is actually implemented on any platform, but if an implementation along these lines would work, and would be valid according to POSIX, then the remapping scenario above would have undefined behaviour.
No!
As pointed out by @Celada, the implementation of robust mutexes in Linux assumes that a locked robust mutex remains at a fixed address:
http://www.kernel.org/doc/Documentation/robust-futexes.txt
From this we can conclude with some certainty that POSIX allows for implementations that prohibit remapping of a locked mutex. Otherwise the Linux implementation would be incorrect.
Ergo, the procedure that I outlined in my question should be regarded as incorrect, and leading to undefined behaviour.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With