sem.c revision 1.1
10Sduke/* Copyright (C) 2005, 2008, 2009 Free Software Foundation, Inc.
22362Sohair   Contributed by Richard Henderson <rth@redhat.com>.
30Sduke
40Sduke   This file is part of the GNU OpenMP Library (libgomp).
50Sduke
60Sduke   Libgomp is free software; you can redistribute it and/or modify it
70Sduke   under the terms of the GNU General Public License as published by
80Sduke   the Free Software Foundation; either version 3, or (at your option)
90Sduke   any later version.
100Sduke
110Sduke   Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
120Sduke   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
130Sduke   FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
140Sduke   more details.
150Sduke
160Sduke   Under Section 7 of GPL version 3, you are granted additional
170Sduke   permissions described in the GCC Runtime Library Exception, version
180Sduke   3.1, as published by the Free Software Foundation.
192362Sohair
202362Sohair   You should have received a copy of the GNU General Public License and
212362Sohair   a copy of the GCC Runtime Library Exception along with this program;
220Sduke   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
230Sduke   <http://www.gnu.org/licenses/>.  */
240Sduke
250Sduke/* This is a Linux specific implementation of a semaphore synchronization
260Sduke   mechanism for libgomp.  This type is private to the library.  This
270Sduke   implementation uses atomic instructions and the futex syscall.  */
280Sduke
290Sduke#include "wait.h"
300Sduke
310Sduke
320Sdukevoid
330Sdukegomp_sem_wait_slow (gomp_sem_t *sem)
340Sduke{
350Sduke  while (1)
360Sduke    {
370Sduke      int val = __sync_val_compare_and_swap (sem, 0, -1);
380Sduke      if (val > 0)
390Sduke	{
400Sduke	  if (__sync_bool_compare_and_swap (sem, val, val - 1))
410Sduke	    return;
420Sduke	}
430Sduke      do_wait (sem, -1);
440Sduke    }
450Sduke}
460Sduke
470Sdukevoid
480Sdukegomp_sem_post_slow (gomp_sem_t *sem)
490Sduke{
500Sduke  int old, tmp = *sem, wake;
510Sduke
520Sduke  do
530Sduke    {
54      old = tmp;
55      wake = old > 0 ? old + 1 : 1;
56      tmp = __sync_val_compare_and_swap (sem, old, wake);
57    }
58  while (old != tmp);
59
60  futex_wake (sem, wake);
61}
62