Blame mach/lowlevellock.h

Packit 6c4009
/* Low-level lock implementation.  Mach gsync-based version.
Packit 6c4009
   Copyright (C) 1994-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library; if not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
#ifndef _MACH_LOWLEVELLOCK_H
Packit 6c4009
#define _MACH_LOWLEVELLOCK_H   1
Packit 6c4009
Packit 6c4009
#include <mach/gnumach.h>
Packit 6c4009
#include <atomic.h>
Packit 6c4009
Packit 6c4009
/* Gsync flags.  */
Packit 6c4009
#ifndef GSYNC_SHARED
Packit 6c4009
# define GSYNC_SHARED      0x01
Packit 6c4009
# define GSYNC_QUAD        0x02
Packit 6c4009
# define GSYNC_TIMED       0x04
Packit 6c4009
# define GSYNC_BROADCAST   0x08
Packit 6c4009
# define GSYNC_MUTATE      0x10
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
/* Static initializer for low-level locks.  */
Packit 6c4009
#define LLL_INITIALIZER   0
Packit 6c4009
Packit 6c4009
/* Wait on address PTR, without blocking if its contents
Packit 6c4009
 * are different from VAL.  */
Packit 6c4009
#define lll_wait(ptr, val, flags)   \
Packit 6c4009
  __gsync_wait (__mach_task_self (),   \
Packit 6c4009
    (vm_offset_t)(ptr), (val), 0, 0, (flags))
Packit 6c4009
Packit 6c4009
/* Wake one or more threads waiting on address PTR.  */
Packit 6c4009
#define lll_wake(ptr, flags)   \
Packit 6c4009
  __gsync_wake (__mach_task_self (), (vm_offset_t)(ptr), 0, (flags))
Packit 6c4009
Packit 6c4009
/* Acquire the lock at PTR.  */
Packit 6c4009
#define lll_lock(ptr, flags)   \
Packit 6c4009
  ({   \
Packit 6c4009
     int *__iptr = (int *)(ptr);   \
Packit 6c4009
     int __flags = (flags);   \
Packit 6c4009
     if (*__iptr != 0 ||   \
Packit 6c4009
         atomic_compare_and_exchange_bool_acq (__iptr, 1, 0) != 0)   \
Packit 6c4009
       while (1)   \
Packit 6c4009
         {   \
Packit 6c4009
           if (atomic_exchange_acq (__iptr, 2) == 0)   \
Packit 6c4009
             break;   \
Packit 6c4009
           lll_wait (__iptr, 2, __flags);   \
Packit 6c4009
         }   \
Packit 6c4009
     (void)0;   \
Packit 6c4009
   })
Packit 6c4009
Packit 6c4009
/* Try to acquire the lock at PTR, without blocking.
Packit 6c4009
   Evaluates to zero on success.  */
Packit 6c4009
#define lll_trylock(ptr)   \
Packit 6c4009
  ({   \
Packit 6c4009
     int *__iptr = (int *)(ptr);   \
Packit 6c4009
     *__iptr == 0 &&   \
Packit 6c4009
       atomic_compare_and_exchange_bool_acq (__iptr, 1, 0) == 0 ? 0 : -1;   \
Packit 6c4009
   })
Packit 6c4009
Packit 6c4009
/* Release the lock at PTR.  */
Packit 6c4009
#define lll_unlock(ptr, flags)   \
Packit 6c4009
  ({   \
Packit 6c4009
     int *__iptr = (int *)(ptr);   \
Packit 6c4009
     if (atomic_exchange_rel (__iptr, 0) == 2)   \
Packit 6c4009
       lll_wake (__iptr, (flags));   \
Packit 6c4009
     (void)0;   \
Packit 6c4009
   })
Packit 6c4009
Packit 6c4009
#endif