sem.c revision 169695
1139825Simp/* Copyright (C) 2005 Free Software Foundation, Inc.
21549Srgrimes   Contributed by Richard Henderson <rth@redhat.com>.
31549Srgrimes
44Srgrimes   This file is part of the GNU OpenMP Library (libgomp).
54Srgrimes
64Srgrimes   Libgomp is free software; you can redistribute it and/or modify it
74Srgrimes   under the terms of the GNU Lesser General Public License as published by
84Srgrimes   the Free Software Foundation; either version 2.1 of the License, or
94Srgrimes   (at your option) any later version.
104Srgrimes
114Srgrimes   Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
124Srgrimes   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
134Srgrimes   FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
144Srgrimes   more details.
154Srgrimes
164Srgrimes   You should have received a copy of the GNU Lesser General Public License
174Srgrimes   along with libgomp; see the file COPYING.LIB.  If not, write to the
184Srgrimes   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
194Srgrimes   MA 02110-1301, USA.  */
204Srgrimes
214Srgrimes/* As a special exception, if you link this library with other files, some
224Srgrimes   of which are compiled with GCC, to produce an executable, this library
234Srgrimes   does not by itself cause the resulting executable to be covered by the
244Srgrimes   GNU General Public License.  This exception does not however invalidate
254Srgrimes   any other reasons why the executable file might be covered by the GNU
264Srgrimes   General Public License.  */
274Srgrimes
284Srgrimes/* This is a Linux specific implementation of a semaphore synchronization
291549Srgrimes   mechanism for libgomp.  This type is private to the library.  This
3050477Speter   implementation uses atomic instructions and the futex syscall.  */
314Srgrimes
324Srgrimes#include "libgomp.h"
33115164Skan#include "futex.h"
346165Sbde
35719Swollman
36143063Sjoergvoid
37143063Sjoerggomp_sem_wait_slow (gomp_sem_t *sem)
38143063Sjoerg{
39114216Skan  while (1)
4047347Sache    {
4147347Sache      int val = __sync_val_compare_and_swap (sem, 0, -1);
42114216Skan      if (val > 0)
431549Srgrimes	{
446165Sbde	  if (__sync_bool_compare_and_swap (sem, val, val - 1))
45	    return;
46	}
47      futex_wait (sem, -1);
48    }
49}
50
51void
52gomp_sem_post_slow (gomp_sem_t *sem)
53{
54  int old, tmp = *sem, wake;
55
56  do
57    {
58      old = tmp;
59      wake = old > 0 ? old + 1 : 1;
60      tmp = __sync_val_compare_and_swap (sem, old, wake);
61    }
62  while (old != tmp);
63
64  futex_wake (sem, wake);
65}
66