00001 /* Copyright (C) 2008, 2009 Free Software Foundation, Inc. 00002 Contributed by Jakub Jelinek <jakub@redhat.com>. 00003 00004 This file is part of the GNU OpenMP Library (libgomp). 00005 00006 Libgomp is free software; you can redistribute it and/or modify it 00007 under the terms of the GNU General Public License as published by 00008 the Free Software Foundation; either version 3, or (at your option) 00009 any later version. 00010 00011 Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY 00012 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 00013 FOR A PARTICULAR PURPOSE. See the GNU General Public License for 00014 more details. 00015 00016 Under Section 7 of GPL version 3, you are granted additional 00017 permissions described in the GCC Runtime Library Exception, version 00018 3.1, as published by the Free Software Foundation. 00019 00020 You should have received a copy of the GNU General Public License and 00021 a copy of the GCC Runtime Library Exception along with this program; 00022 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 00023 <http://www.gnu.org/licenses/>. */ 00024 00025 /* This is a Linux specific implementation of a mutex synchronization 00026 mechanism for libgomp. This type is private to the library. This 00027 implementation uses atomic instructions and the futex syscall. */ 00028 00029 #include <endian.h> 00030 #include <limits.h> 00031 #include "wait.h" 00032 00033 void * 00034 gomp_ptrlock_get_slow (gomp_ptrlock_t *ptrlock) 00035 { 00036 int *intptr; 00037 __sync_bool_compare_and_swap (ptrlock, 1, 2); 00038 00039 /* futex works on ints, not pointers. 00040 But a valid work share pointer will be at least 00041 8 byte aligned, so it is safe to assume the low 00042 32-bits of the pointer won't contain values 1 or 2. */ 00043 __asm volatile ("" : "=r" (intptr) : "0" (ptrlock)); 00044 #if __BYTE_ORDER == __BIG_ENDIAN 00045 if (sizeof (*ptrlock) > sizeof (int)) 00046 intptr += (sizeof (*ptrlock) / sizeof (int)) - 1; 00047 #endif 00048 do 00049 do_wait (intptr, 2); 00050 while (*intptr == 2); 00051 __asm volatile ("" : : : "memory"); 00052 return *ptrlock; 00053 } 00054 00055 void 00056 gomp_ptrlock_set_slow (gomp_ptrlock_t *ptrlock, void *ptr) 00057 { 00058 int *intptr; 00059 00060 *ptrlock = ptr; 00061 __asm volatile ("" : "=r" (intptr) : "0" (ptrlock)); 00062 #if __BYTE_ORDER == __BIG_ENDIAN 00063 if (sizeof (*ptrlock) > sizeof (int)) 00064 intptr += (sizeof (*ptrlock) / sizeof (int)) - 1; 00065 #endif 00066 futex_wake (intptr, INT_MAX); 00067 }