Supposons que nous ayons le bout de code suivant :
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
void guarantee(bool cond, const char *msg) {
if (!cond) {
fprintf(stderr, "%s", msg);
exit(1);
}
}
bool do_shutdown = false; // Not volatile!
pthread_cond_t shutdown_cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t shutdown_cond_mutex = PTHREAD_MUTEX_INITIALIZER;
/* Called in Thread 1. Intended behavior is to block until
trigger_shutdown() is called. */
void wait_for_shutdown_signal() {
int res;
res = pthread_mutex_lock(&shutdown_cond_mutex);
guarantee(res == 0, "Could not lock shutdown cond mutex");
while (!do_shutdown) { // while loop guards against spurious wakeups
res = pthread_cond_wait(&shutdown_cond, &shutdown_cond_mutex);
guarantee(res == 0, "Could not wait for shutdown cond");
}
res = pthread_mutex_unlock(&shutdown_cond_mutex);
guarantee(res == 0, "Could not unlock shutdown cond mutex");
}
/* Called in Thread 2. */
void trigger_shutdown() {
int res;
res = pthread_mutex_lock(&shutdown_cond_mutex);
guarantee(res == 0, "Could not lock shutdown cond mutex");
do_shutdown = true;
res = pthread_cond_signal(&shutdown_cond);
guarantee(res == 0, "Could not signal shutdown cond");
res = pthread_mutex_unlock(&shutdown_cond_mutex);
guarantee(res == 0, "Could not unlock shutdown cond mutex");
}
Un compilateur C/C++ conforme aux normes peut-il jamais mettre en cache la valeur de do_shutdown
dans un registre à travers l'appel à pthread_cond_wait()
? Si non, quelles normes/clauses le garantissent ?
Le compilateur pourrait hypothétiquement savoir que pthread_cond_wait()
ne modifie pas do_shutdown
. Cela semble plutôt improbable, mais je ne connais pas de norme qui l'empêche.
En pratique, existe-t-il des compilateurs C/C++ qui mettent en cache la valeur de do_shutdown
dans un registre à travers l'appel à pthread_cond_wait()
?
Quels appels de fonction le compilateur est-il assuré de ne pas mettre en cache la valeur de do_shutdown
à travers ? Il est clair que si la fonction est déclarée en externe et que le compilateur ne peut pas accéder à sa définition, il ne doit faire aucune hypothèse sur son comportement et ne peut donc pas prouver qu'elle n'accède pas à do_shutdown
. Si le compilateur peut mettre en ligne la fonction et prouver qu'elle n'accède pas à do_shutdown
alors il peut cacher do_shutdown
même dans un cadre multithread ? Qu'en est-il d'une fonction non-inlined dans la même unité de compilation ?