src/dpdk/lib/librte_eal/include/generic/rte_mcslock.h
static inline void
rte_mcslock_lock(rte_mcslock_t **msl, rte_mcslock_t *me)
{
	rte_mcslock_t *prev;

	/* Init me node */
	__atomic_store_n(&me->locked, 1, __ATOMIC_RELAXED);
	__atomic_store_n(&me->next, NULL, __ATOMIC_RELAXED);

	/* If the queue is empty, the exchange operation is enough to acquire
	 * the lock. Hence, the exchange operation requires acquire semantics.
	 * The store to me->next above should complete before the node is
	 * visible to other CPUs/threads. Hence, the exchange operation requires
	 * release semantics as well.
	 */
	prev = __atomic_exchange_n(msl, me, __ATOMIC_ACQ_REL);
	if (likely(prev == NULL)) {
		/* Queue was empty, no further action required,
		 * proceed with lock taken.
		 */
		return;
	}
	/* The store to me->next above should also complete before the node is
	 * visible to predecessor thread releasing the lock. Hence, the store
	 * prev->next also requires release semantics. Note that, for example,
	 * on ARM, the release semantics in the exchange operation is not
	 * strong as a release fence and is not sufficient to enforce the
	 * desired order here.
	 */
	__atomic_store_n(&prev->next, me, __ATOMIC_RELEASE);

	/* The while-load of me->locked should not move above the previous
	 * store to prev->next. Otherwise it will cause a deadlock. Need a
	 * store-load barrier.
	 */
	__atomic_thread_fence(__ATOMIC_ACQ_REL);
	/* If the lock has already been acquired, it first atomically
	 * places the node at the end of the queue and then proceeds
	 * to spin on me->locked until the previous lock holder resets
	 * the me->locked using mcslock_unlock().
	 */
	while (__atomic_load_n(&me->locked, __ATOMIC_ACQUIRE))
		rte_pause();
}
/**
 * Take the MCS lock.
 *
 * @param msl
 *   A pointer to the pointer of a MCS lock.
 *   When the lock is initialized or declared, the msl pointer should be
 *   set to NULL.
 * @param me
 *   A pointer to a new node of MCS lock. Each CPU/thread acquiring the
 *   lock should use its 'own node'.
 */
Take the MCS lock.
@param msl
A pointer to the pointer of a MCS lock.
When the lock is initialized or declared, the msl pointer should be
set to NULL.
@param me
A pointer to a new node of MCS lock. Each CPU/thread acquiring the
lock should use its 'own node'.
Take the MCS lock . @param msl A pointer to the pointer of a MCS lock . When the lock is initialized or declared the msl pointer should be set to NULL . @param me A pointer to a new node of MCS lock . Each CPU / thread acquiring the lock should use its ' own node ' .
static inline void
rte_mcslock_lock(rte_mcslock_t **msl, rte_mcslock_t *me)
{
	rte_mcslock_t *prev;
	__atomic_store_n(&me->locked, 1, __ATOMIC_RELAXED);
	__atomic_store_n(&me->next, NULL, __ATOMIC_RELAXED);
	prev = __atomic_exchange_n(msl, me, __ATOMIC_ACQ_REL);
	if (likely(prev == NULL)) {
		return;
	}
	__atomic_store_n(&prev->next, me, __ATOMIC_RELEASE);
	__atomic_thread_fence(__ATOMIC_ACQ_REL);
	while (__atomic_load_n(&me->locked, __ATOMIC_ACQUIRE))
		rte_pause();
}
static inline void rte_mcslock_lock ( rte_mcslock_t * * msl , rte_mcslock_t * me ) { rte_mcslock_t * prev ; __atomic_store_n ( & me -> locked , 1 , __ATOMIC_RELAXED ) ; __atomic_store_n ( & me -> next , NULL , __ATOMIC_RELAXED ) ; prev = __atomic_exchange_n ( msl , me , __ATOMIC_ACQ_REL ) ; if ( likely ( prev == NULL ) ) { return ; } __atomic_store_n ( & prev -> next , me , __ATOMIC_RELEASE ) ; __atomic_thread_fence ( __ATOMIC_ACQ_REL ) ; while ( __atomic_load_n ( & me -> locked , __ATOMIC_ACQUIRE ) ) rte_pause ( ) ; }
Take the MCS lock.
Take the MCS lock .
/* Init me node */ /* If the queue is empty, the exchange operation is enough to acquire
	 * the lock. Hence, the exchange operation requires acquire semantics.
	 * The store to me->next above should complete before the node is
	 * visible to other CPUs/threads. Hence, the exchange operation requires
	 * release semantics as well.
	 */ /* Queue was empty, no further action required,
		 * proceed with lock taken.
		 */ /* The store to me->next above should also complete before the node is
	 * visible to predecessor thread releasing the lock. Hence, the store
	 * prev->next also requires release semantics. Note that, for example,
	 * on ARM, the release semantics in the exchange operation is not
	 * strong as a release fence and is not sufficient to enforce the
	 * desired order here.
	 */ /* The while-load of me->locked should not move above the previous
	 * store to prev->next. Otherwise it will cause a deadlock. Need a
	 * store-load barrier.
	 */ /* If the lock has already been acquired, it first atomically
	 * places the node at the end of the queue and then proceeds
	 * to spin on me->locked until the previous lock holder resets
	 * the me->locked using mcslock_unlock().
	 */