(root)/
glibc-2.38/
mach/
lowlevellock.h
       1  /* Low-level lock implementation.  Mach gsync-based version.
       2     Copyright (C) 1994-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #ifndef _MACH_LOWLEVELLOCK_H
      20  #define _MACH_LOWLEVELLOCK_H   1
      21  
      22  #include <mach/gnumach.h>
      23  #include <atomic.h>
      24  
      25  /* Gsync flags.  */
      26  #ifndef GSYNC_SHARED
      27  # define GSYNC_SHARED      0x01
      28  # define GSYNC_QUAD        0x02
      29  # define GSYNC_TIMED       0x04
      30  # define GSYNC_BROADCAST   0x08
      31  # define GSYNC_MUTATE      0x10
      32  #endif
      33  
      34  /* Static initializer for low-level locks.  */
      35  #define LLL_LOCK_INITIALIZER   0
      36  
      37  #define LLL_PRIVATE        0
      38  #define LLL_SHARED         GSYNC_SHARED
      39  
      40  /* Interruptible version of __gsync_wait.  */
      41  extern kern_return_t __gsync_wait_intr
      42  (
      43  	mach_port_t task,
      44  	vm_offset_t addr,
      45  	unsigned val1,
      46  	unsigned val2,
      47  	natural_t msec,
      48  	int flags
      49  );
      50  
      51  /* Wait on address PTR, without blocking if its contents
      52   * are different from VAL.  */
      53  #define __lll_wait(ptr, val, flags)   \
      54    __gsync_wait (__mach_task_self (),   \
      55      (vm_offset_t)(ptr), (val), 0, 0, (flags))
      56  #define lll_wait(var, val, flags) \
      57    __lll_wait (&(var), val, flags)
      58  
      59  /* Interruptible version.  */
      60  #define __lll_wait_intr(ptr, val, flags)   \
      61    __gsync_wait_intr (__mach_task_self (),   \
      62      (vm_offset_t)(ptr), (val), 0, 0, (flags))
      63  #define lll_wait_intr(var, val, flags) \
      64    __lll_wait_intr ((&var), val, flags)
      65  
      66  /* Wake one or more threads waiting on address PTR.  */
      67  #define __lll_wake(ptr, flags)   \
      68    __gsync_wake (__mach_task_self (), (vm_offset_t)(ptr), 0, (flags))
      69  #define lll_wake(var, flags) \
      70    __lll_wake (&(var), flags)
      71  
      72  /* Acquire the lock at PTR.  */
      73  #define __lll_lock(ptr, flags)   \
      74    ({   \
      75       int *__iptr = (int *)(ptr);   \
      76       int __flags = (flags);   \
      77       if (*__iptr != 0   \
      78           || atomic_compare_and_exchange_bool_acq (__iptr, 1, 0) != 0)   \
      79         while (1)   \
      80           {   \
      81             if (atomic_exchange_acquire (__iptr, 2) == 0)   \
      82               break;   \
      83             __lll_wait (__iptr, 2, __flags);   \
      84           }   \
      85       (void)0;   \
      86     })
      87  #define lll_lock(var, flags) \
      88    __lll_lock (&(var), flags)
      89  
      90  /* Try to acquire the lock at PTR, without blocking.
      91     Evaluates to zero on success.  */
      92  #define __lll_trylock(ptr)   \
      93    ({   \
      94       int *__iptr = (int *)(ptr);   \
      95       *__iptr == 0   \
      96         && atomic_compare_and_exchange_bool_acq (__iptr, 1, 0) == 0 ? 0 : -1;   \
      97     })
      98  #define lll_trylock(var) \
      99    __lll_trylock (&(var))
     100  
     101  /* Release the lock at PTR.  */
     102  #define __lll_unlock(ptr, flags)   \
     103    ({   \
     104       int *__iptr = (int *)(ptr);   \
     105       if (atomic_exchange_release (__iptr, 0) == 2)   \
     106         __lll_wake (__iptr, (flags));   \
     107       (void)0;   \
     108     })
     109  #define lll_unlock(var, flags) \
     110    __lll_unlock (&(var), flags)
     111  
     112  #endif