点击(此处)折叠或打开
-
#define __lll_lock(futex, private) \
-
((void) \
-
({ \
-
int *__futex = (futex); \
-
if (__glibc_unlikely \
-
(atomic_compare_and_exchange_bool_acq (__futex, 1, 0))) \
-
{ \
-
if (__builtin_constant_p (private) && (private) == LLL_PRIVATE) \
-
__lll_lock_wait_private (__futex); \
-
else \
-
__lll_lock_wait (__futex, private); \
-
} \
-
}))
-
#define lll_lock(futex, private) \
- __lll_lock (&(futex), private)
点击(此处)折叠或打开
-
/* Atomically store NEWVAL in *MEM if *MEM is equal to OLDVAL.
-
Return zero if *MEM was changed or non-zero if no exchange happened. */
-
#ifndef atomic_compare_and_exchange_bool_acq
-
# ifdef __arch_compare_and_exchange_bool_32_acq
-
# define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \
-
__atomic_bool_bysize (__arch_compare_and_exchange_bool,acq, \
-
mem, newval, oldval)
-
# else
-
# define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \
-
({ /* Cannot use __oldval here, because macros later in this file might \
-
call this macro with __oldval argument. */ \
-
__typeof (oldval) __atg3_old = (oldval); \
-
atomic_compare_and_exchange_val_acq (mem, newval, __atg3_old) \
-
!= __atg3_old; \
-
})
-
# endif
- #endif
和atomic_compare_and_exchange_bool_acq对应的还有atomic_compare_and_exchange_val_acq,代码如下:
点击(此处)折叠或打开
-
/* Atomically store NEWVAL in *MEM if *MEM is equal to OLDVAL.
-
Return the old *MEM value. */
-
#if !defined atomic_compare_and_exchange_val_acq \
-
&& defined __arch_compare_and_exchange_val_32_acq
-
# define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \
-
__atomic_val_bysize (__arch_compare_and_exchange_val,acq, \
-
mem, newval, oldval)
- #endif
还有一个atomic_exchange_acq,从名字就可以看出,这个原子操作没有比较,直接把newval存储在*mem中,然后返回就的*mem值。
点击(此处)折叠或打开
-
/* Store NEWVALUE in *MEM and return the old value. */
-
#ifndef atomic_exchange_acq
-
# define atomic_exchange_acq(mem, newvalue) \
-
({ __typeof (*(mem)) __atg5_oldval; \
-
__typeof (mem) __atg5_memp = (mem); \
-
__typeof (*(mem)) __atg5_value = (newvalue); \
-
\
-
do \
-
__atg5_oldval = *__atg5_memp; \
-
while (__builtin_expect \
-
(atomic_compare_and_exchange_bool_acq (__atg5_memp, __atg5_value, \
-
__atg5_oldval), 0)); \
-
\
-
__atg5_oldval; })
- #endif
继续回到__lll_lock.
从5-6行的if可以看到,如果_futex的值为0,表示没有其他的竞争者,那么atomic_compare_and_exchange_bool_acq就把1存储在_futex里,然后直接返回。否则就要调用__lll_lock_wait.
点击(此处)折叠或打开
-
void
-
__lll_lock_wait_private (int *futex)
-
{
-
if (*futex == 2)
-
lll_futex_wait (futex, 2, LLL_PRIVATE); /* Wait if *futex == 2. */
-
-
while (atomic_exchange_acq (futex, 2) != 0)
-
lll_futex_wait (futex, 2, LLL_PRIVATE); /* Wait if *futex == 2. */
-
}
-
-
-
/* This function doesn't get included in libc. */
-
#if IS_IN (libpthread)
-
void
-
__lll_lock_wait (int *futex, int private)
-
{
-
if (*futex == 2)
-
lll_futex_wait (futex, 2, private); /* Wait if *futex == 2. */
-
-
while (atomic_exchange_acq (futex, 2) != 0)
-
lll_futex_wait (futex, 2, private); /* Wait if *futex == 2. */
-
}
-
#endif
这个函数把futex设置为2,如果futex的旧值不是2,就调用lll_futex_wait等待。