Current librtpi API breaks down for process shared condvars
The current librtpi API creates a strong association between a user mutex and a conditional variable by passing a pointer to the mutex to pi_cond_init() along with the pointer to the conditional variable to be initialized. The pointer to the associated mutex is stored in the private data for the conditional variable.
This is done because in order to guarantee proper RT behaviour we have to use the FUTEX_WAIT_REQUEUE_PI and FUTEX_CMP_REQUEUE_PI futex ops for waiting and signalling respectively and the user mutex is a parameter for both calls. Storing a pointer to the user mutex at init time prevents the practice of signalling the condition prior to the association of the mutex.
The problem is the current librtpi API breaks down for process shared conditional variables as illustrated by glibc tests: tst-cond4.c, tst-cond6.c, tst-cond12.c, and tst-cond13.c.
For process-shared use cases the user mutex and the condvar are allocated in shared memory. This shared memory is (usually) mapped at different addresses in the different processes that interact with the condvar. As a result the pointer to the mutex stored by the pi_cond_init() call points to a valid address only for the process that calls init. All other processes that interact with the process-shared condvar will cause an invalid memory access when accessing the stored mutex pointer.
A good example of this problem is glibc test tst-cond12.c. In this test a parent process creates a memory mapping for a process shared conditional variable and mutex that is later re-mapped by the child process at a different address and the old mapping is unmapped via munmap(). Because the conditional variable was initialized before the fork() the stored mutex pointer now points to an unmapped address in the child process and it results in a SIGSEGV crash when the mutex is accessed inside the pi_cond.c code.
A proposed solution would be to change the librtpi API to pass the user mutex for the condvar operations that need it and do away with storing a pointer to the user mutex inside the condvar at init.
The new API would look like this:
int pi_cond_init(pi_cond_t *cond, uint32_t flags) int pi_cond_destroy(pi_cond_t *cond) int pi_cond_wait(pi_cond_t *cond, pi_mutex_t *mutex) int pi_cond_timedwait(pi_cond_t *cond, pi_mutex_t *mutex, const struct timespec *restrict abstime) int pi_cond_signal(pi_cond_t *cond, pi_mutex_t *mutex) int pi_cond_broadcast(pi_cond_t *cond, pi_mutex_t *mutex)
I can follow up with patches if we're in agreement this is the correct path forward.