The generic Linux version of sem_post (nptl/sysdeps/unix/sysv/linux/sem_post.c) uses atomic_compare_and_exchange_bool_acq to increment the semaphore. This is an unlock operation and should actually be using a release barrier. The following test fails on some MIPS systems (MIPS uses the generic version of sem_post where various architectures use their own .S versions). Testing a patch. #include <pthread.h> #include <semaphore.h> #include <stdio.h> #define NTHREADS 10 #define NITER 100000 sem_t sem; int c; volatile int thread_fail; static void * tf (void *arg) { for (int i = 0; i < NITER; i++) { if (sem_wait (&sem) != 0) { perror ("sem_wait"); thread_fail = 1; } ++c; if (sem_post (&sem) != 0) { perror ("sem_post"); thread_fail = 1; } } return NULL; } int main (void) { if (sem_init (&sem, 0, 0) != 0) { perror ("sem_init"); return 1; } pthread_t th[NTHREADS]; for (int i = 0; i < NTHREADS; i++) { if (pthread_create (&th[i], NULL, tf, NULL) != 0) { puts ("pthread_create failed"); return 1; } } if (sem_post (&sem) != 0) { perror ("sem_post"); return 1; } for (int i = 0; i < NTHREADS; i++) if (pthread_join (th[i], NULL) != 0) { puts ("pthread_join failed"); return 1; } if (c != NTHREADS * NITER) { printf ("c = %d, should be %d\n", c, NTHREADS * NITER); return 1; } return thread_fail; }
Fixed for 2.17 by: commit 033d54a2d43a92cdb1794a4dfece4d465cf36f6b Author: Joseph Myers <joseph@codesourcery.com> Date: Fri Aug 31 19:49:31 2012 +0000 Fix sem_post race (bug 14532).