diff options
author | Joseph Myers <joseph@codesourcery.com> | 2012-08-31 19:49:31 +0000 |
---|---|---|
committer | Joseph Myers <joseph@codesourcery.com> | 2012-08-31 19:49:31 +0000 |
commit | 033d54a2d43a92cdb1794a4dfece4d465cf36f6b (patch) | |
tree | 398c6f127057702fb0f9254ee1c76e2cb224fdcf /nptl | |
parent | d22e28b070d3d1572d39a463d711c6f223078552 (diff) | |
download | glibc-033d54a2d43a92cdb1794a4dfece4d465cf36f6b.tar.gz glibc-033d54a2d43a92cdb1794a4dfece4d465cf36f6b.tar.xz glibc-033d54a2d43a92cdb1794a4dfece4d465cf36f6b.zip |
Fix sem_post race (bug 14532).
Diffstat (limited to 'nptl')
-rw-r--r-- | nptl/ChangeLog | 8 | ||||
-rw-r--r-- | nptl/Makefile | 2 | ||||
-rw-r--r-- | nptl/sysdeps/unix/sysv/linux/sem_post.c | 4 | ||||
-rw-r--r-- | nptl/tst-sem14.c | 91 |
4 files changed, 100 insertions, 5 deletions
diff --git a/nptl/ChangeLog b/nptl/ChangeLog index eb84863588..f59c3d720e 100644 --- a/nptl/ChangeLog +++ b/nptl/ChangeLog @@ -1,6 +1,10 @@ -2012-08-15 Roland McGrath <roland@hack.frob.com> +2012-08-31 Joseph Myers <joseph@codesourcery.com> -2012-08-15 Roland McGrath <roland@hack.frob.com> + [BZ #14532] + * sysdeps/unix/sysv/linux/sem_post.c (__new_sem_post): Use + atomic_compare_and_exchange_bool_rel. + * tst-sem14.c: New file. + * Makefile (tests): Add tst-sem14. 2012-08-15 Roland McGrath <roland@hack.frob.com> diff --git a/nptl/Makefile b/nptl/Makefile index 8cd168d451..614f0ceea9 100644 --- a/nptl/Makefile +++ b/nptl/Makefile @@ -217,7 +217,7 @@ tests = tst-typesizes \ tst-once1 tst-once2 tst-once3 tst-once4 \ tst-key1 tst-key2 tst-key3 tst-key4 \ tst-sem1 tst-sem2 tst-sem3 tst-sem4 tst-sem5 tst-sem6 tst-sem7 \ - tst-sem8 tst-sem9 tst-sem10 tst-sem11 tst-sem12 tst-sem13 \ + tst-sem8 tst-sem9 tst-sem10 tst-sem11 tst-sem12 tst-sem13 tst-sem14 \ tst-barrier1 tst-barrier2 tst-barrier3 tst-barrier4 \ tst-align tst-align2 tst-align3 \ tst-basic1 tst-basic2 tst-basic3 tst-basic4 tst-basic5 tst-basic6 \ diff --git a/nptl/sysdeps/unix/sysv/linux/sem_post.c b/nptl/sysdeps/unix/sysv/linux/sem_post.c index 56f27e977e..67e8cc5429 100644 --- a/nptl/sysdeps/unix/sysv/linux/sem_post.c +++ b/nptl/sysdeps/unix/sysv/linux/sem_post.c @@ -1,5 +1,5 @@ /* sem_post -- post to a POSIX semaphore. Generic futex-using version. - Copyright (C) 2003, 2004, 2007, 2008 Free Software Foundation, Inc. + Copyright (C) 2003-2012 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Jakub Jelinek <jakub@redhat.com>, 2003. @@ -40,7 +40,7 @@ __new_sem_post (sem_t *sem) return -1; } } - while (atomic_compare_and_exchange_bool_acq (&isem->value, cur + 1, cur)); + while (atomic_compare_and_exchange_bool_rel (&isem->value, cur + 1, cur)); atomic_full_barrier (); if (isem->nwaiters > 0) diff --git a/nptl/tst-sem14.c b/nptl/tst-sem14.c new file mode 100644 index 0000000000..949c03fcc6 --- /dev/null +++ b/nptl/tst-sem14.c @@ -0,0 +1,91 @@ +/* Test for sem_post race: bug 14532. + Copyright (C) 2012 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#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; +} + +static int +do_test (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; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" |