xref: /netbsd-src/external/gpl3/gcc.old/dist/libgomp/config/linux/ptrlock.c (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
1*8feb0f0bSmrg /* Copyright (C) 2008-2020 Free Software Foundation, Inc.
236ac495dSmrg    Contributed by Jakub Jelinek <jakub@redhat.com>.
336ac495dSmrg 
436ac495dSmrg    This file is part of the GNU Offloading and Multi Processing Library
536ac495dSmrg    (libgomp).
636ac495dSmrg 
736ac495dSmrg    Libgomp is free software; you can redistribute it and/or modify it
836ac495dSmrg    under the terms of the GNU General Public License as published by
936ac495dSmrg    the Free Software Foundation; either version 3, or (at your option)
1036ac495dSmrg    any later version.
1136ac495dSmrg 
1236ac495dSmrg    Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
1336ac495dSmrg    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1436ac495dSmrg    FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
1536ac495dSmrg    more details.
1636ac495dSmrg 
1736ac495dSmrg    Under Section 7 of GPL version 3, you are granted additional
1836ac495dSmrg    permissions described in the GCC Runtime Library Exception, version
1936ac495dSmrg    3.1, as published by the Free Software Foundation.
2036ac495dSmrg 
2136ac495dSmrg    You should have received a copy of the GNU General Public License and
2236ac495dSmrg    a copy of the GCC Runtime Library Exception along with this program;
2336ac495dSmrg    see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
2436ac495dSmrg    <http://www.gnu.org/licenses/>.  */
2536ac495dSmrg 
2636ac495dSmrg /* This is a Linux specific implementation of a mutex synchronization
2736ac495dSmrg    mechanism for libgomp.  This type is private to the library.  This
2836ac495dSmrg    implementation uses atomic instructions and the futex syscall.  */
2936ac495dSmrg 
3036ac495dSmrg #include <endian.h>
3136ac495dSmrg #include <limits.h>
3236ac495dSmrg #include "wait.h"
3336ac495dSmrg 
3436ac495dSmrg void *
gomp_ptrlock_get_slow(gomp_ptrlock_t * ptrlock)3536ac495dSmrg gomp_ptrlock_get_slow (gomp_ptrlock_t *ptrlock)
3636ac495dSmrg {
3736ac495dSmrg   int *intptr;
3836ac495dSmrg   uintptr_t oldval = 1;
3936ac495dSmrg 
4036ac495dSmrg   __atomic_compare_exchange_n (ptrlock, &oldval, 2, false,
4136ac495dSmrg 			       MEMMODEL_RELAXED, MEMMODEL_RELAXED);
4236ac495dSmrg 
4336ac495dSmrg   /* futex works on ints, not pointers.
4436ac495dSmrg      But a valid work share pointer will be at least
4536ac495dSmrg      8 byte aligned, so it is safe to assume the low
4636ac495dSmrg      32-bits of the pointer won't contain values 1 or 2.  */
4736ac495dSmrg   __asm volatile ("" : "=r" (intptr) : "0" (ptrlock));
4836ac495dSmrg #if __BYTE_ORDER == __BIG_ENDIAN
4936ac495dSmrg   if (sizeof (*ptrlock) > sizeof (int))
5036ac495dSmrg     intptr += (sizeof (*ptrlock) / sizeof (int)) - 1;
5136ac495dSmrg #endif
5236ac495dSmrg   do
5336ac495dSmrg     do_wait (intptr, 2);
5436ac495dSmrg   while (__atomic_load_n (intptr, MEMMODEL_RELAXED) == 2);
5536ac495dSmrg   __asm volatile ("" : : : "memory");
5636ac495dSmrg   return (void *) __atomic_load_n (ptrlock, MEMMODEL_ACQUIRE);
5736ac495dSmrg }
5836ac495dSmrg 
5936ac495dSmrg void
gomp_ptrlock_set_slow(gomp_ptrlock_t * ptrlock)6036ac495dSmrg gomp_ptrlock_set_slow (gomp_ptrlock_t *ptrlock)
6136ac495dSmrg {
6236ac495dSmrg   int *intptr;
6336ac495dSmrg 
6436ac495dSmrg   __asm volatile ("" : "=r" (intptr) : "0" (ptrlock));
6536ac495dSmrg #if __BYTE_ORDER == __BIG_ENDIAN
6636ac495dSmrg   if (sizeof (*ptrlock) > sizeof (int))
6736ac495dSmrg     intptr += (sizeof (*ptrlock) / sizeof (int)) - 1;
6836ac495dSmrg #endif
6936ac495dSmrg   futex_wake (intptr, INT_MAX);
7036ac495dSmrg }
71