138032Speter/* Copyright (C) 2005 Free Software Foundation, Inc.
238032Speter   Contributed by Richard Henderson <rth@redhat.com>.
338032Speter
438032Speter   This file is part of the GNU OpenMP Library (libgomp).
538032Speter
638032Speter   Libgomp is free software; you can redistribute it and/or modify it
738032Speter   under the terms of the GNU Lesser General Public License as published by
8285303Sgshapiro   the Free Software Foundation; either version 2.1 of the License, or
9285303Sgshapiro   (at your option) any later version.
10285303Sgshapiro
11285303Sgshapiro   Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
12285303Sgshapiro   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13285303Sgshapiro   FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
14285303Sgshapiro   more details.
15285303Sgshapiro
16285303Sgshapiro   You should have received a copy of the GNU Lesser General Public License
17285303Sgshapiro   along with libgomp; see the file COPYING.LIB.  If not, write to the
18285303Sgshapiro   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19285303Sgshapiro   MA 02110-1301, USA.  */
20285303Sgshapiro
21285303Sgshapiro/* As a special exception, if you link this library with other files, some
22285303Sgshapiro   of which are compiled with GCC, to produce an executable, this library
23285303Sgshapiro   does not by itself cause the resulting executable to be covered by the
24285303Sgshapiro   GNU General Public License.  This exception does not however invalidate
25285303Sgshapiro   any other reasons why the executable file might be covered by the GNU
26285303Sgshapiro   General Public License.  */
27285303Sgshapiro
28285303Sgshapiro/* This is a Linux specific implementation of a semaphore synchronization
29285303Sgshapiro   mechanism for libgomp.  This type is private to the library.  This
30285303Sgshapiro   implementation uses atomic instructions and the futex syscall.  */
31285303Sgshapiro
32285303Sgshapiro#include "libgomp.h"
33285303Sgshapiro#include "futex.h"
34285303Sgshapiro
35285303Sgshapiro
36285303Sgshapirovoid
37285303Sgshapirogomp_sem_wait_slow (gomp_sem_t *sem)
38285303Sgshapiro{
39285303Sgshapiro  while (1)
40285303Sgshapiro    {
41285303Sgshapiro      int val = __sync_val_compare_and_swap (sem, 0, -1);
42285303Sgshapiro      if (val > 0)
43285303Sgshapiro	{
44285303Sgshapiro	  if (__sync_bool_compare_and_swap (sem, val, val - 1))
45285303Sgshapiro	    return;
46285303Sgshapiro	}
47285303Sgshapiro      futex_wait (sem, -1);
48285303Sgshapiro    }
49285303Sgshapiro}
50285303Sgshapiro
51285303Sgshapirovoid
52285303Sgshapirogomp_sem_post_slow (gomp_sem_t *sem)
53285303Sgshapiro{
54285303Sgshapiro  int old, tmp = *sem, wake;
55285303Sgshapiro
56285303Sgshapiro  do
57285303Sgshapiro    {
58285303Sgshapiro      old = tmp;
59285303Sgshapiro      wake = old > 0 ? old + 1 : 1;
60285303Sgshapiro      tmp = __sync_val_compare_and_swap (sem, old, wake);
61285303Sgshapiro    }
62285303Sgshapiro  while (old != tmp);
63285303Sgshapiro
64285303Sgshapiro  futex_wake (sem, wake);
65285303Sgshapiro}
66285303Sgshapiro