PIP在Linux+glibc中的实现

优先级反转

优先级反转指一个高优先级任务因为资源被低优先级任务占用,而不得不等待。这个逻辑本身没有什么问题。优先级反转带来最直接的问题就是高优先级可能因为这次阻塞,而无法确定阻塞时延。如下图所示。

Task 9优先级较低,所以很容易被其他优先级的任务抢占运行,导致对资源S的锁无法释放,而高优先级的任务因为要持有该锁,不得不等待。

优先级继承

Priority Inheritance Protocol翻译为优先级继承,简称PIP。这是解决上述Unbounded inversion最直接的办法,就是将占有锁的线程优先级调整到在等待的任务的最高值。这个算法是贪婪的,局部最优,但不是整体最优解,在此之上又有PCP(优先级天花板)和SRP(基于栈的资源策略)。本文不做讨论。本文主要从源码的角度,阐述PIP在Linux和glibc中的具体实现。

Overview

Linux下的PIP实现分成以上3个部分:

  • glibc中的pthread_mutex_lock提供用户接口,通过FUTEX_LOCK_PI实现优先级调整
  • Linux的futex部分提供FUTEX_LOCK_PI的实现
  • 最终的锁机制通过rt_mutex来实现

pthread_mutex

Types

pthread mutex是POSIX pthread库中定义的一种锁机制,与信号量不同的是,这个锁只有两种状态:locked或unlocked。与binary semaphore不同的是,mutex只能被lock的线程unlock,即只能被mutex owner unlock。

目前POSIX标准(1003.1-2008)中定义了4种类型的mutex:

  • PTHREAD_MUTEX_NORMAL
  • PTHREAD_MUTEX_ERRORCHECK
  • PTHREAD_MUTEX_RECURSIVE
  • PTHREAD_MUTEX_DEFAULT

这4种mutex不同之处如下

attempting to relock this mutex without first unlockingAttempting to unlock a mutex locked by a different thread
NORMALdeadlockundefined
ERRORCHECKreturn error -EDEADLOCKreturn error
RECURSIVEsucceed in lockingreturn error
DEFAULTundefinedundefined

glibc对上述4种类型的mutex进行了扩展,例如:

    case PTHREAD_MUTEX_PI_RECURSIVE_NP:
    case PTHREAD_MUTEX_PI_ERRORCHECK_NP:
    case PTHREAD_MUTEX_PI_NORMAL_NP:
    case PTHREAD_MUTEX_PI_ADAPTIVE_NP:
    case PTHREAD_MUTEX_PI_ROBUST_RECURSIVE_NP:
    case PTHREAD_MUTEX_PI_ROBUST_ERRORCHECK_NP:
    case PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP:
    case PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP:

主要多了这3种属性:

  • ADAPTIVE:在SMP架构下,并不直接进入wait,而是先调用spinlock等待一小段时间。musl里默认都采用了这种实现

  • PI:包含该属性的mutex,实现了优先级继承(Priority Inheritance, PI)

  • ROBUST:若线程退出时未释放锁,则以后对该锁操作都会返回-EOWNERDEAD,与之对应的是PTHREAD_MUTEX_STALLED(这是默认配置),对该异常锁的操作会出现undefined行为。

再与原先的4种属性进行排列组合。

"_NP" suffix

Note: the _NP suffix indicates a non-portable extension to the POSIX specification. In fact the latest specification, 1003.1-2008 [2], includes most of the Linux additions so you can leave the _NP ending off. I have chosen not to because some older versions of the header files only have the _NP variants.

根据最新的POSIX标准1003.1-2008,这些扩展并没有加入。

本文只关注MUTEX_PI实现。

PTHREAD_MUTEX_PI

pthread_mutex_lock

重要数据结构如下:

typedef union
{
  struct __pthread_mutex_s __data;
  char __size[__SIZEOF_PTHREAD_MUTEX_T];
  long int __align;
} pthread_mutex_t;
struct __pthread_mutex_s
{
  int __lock __LOCK_ALIGNMENT;
  unsigned int __count;
  int __owner;
  ...
}

如果不考虑ROBUST情况的处理,一次针对实现了PI属性的pthread_mutex_lock操作如下:

atomic_compare_and_exchange_val_acq

这是一种原子操作,先比较再赋值,伪代码如下:

int compare_and_swap(int* reg, int oldval, int newval)
{
    ATOMIC();
    int old_reg_val = *reg;
    if (old_reg_val == oldval)
      *reg = newval;
    END_ATOMIC();
    return old_reg_val;
}

针对代码中的具体情况:

  • oldval == 0: 表示mutex->__data.__lock == 0,即该lock无owner,可以获得。
  • oldval != 0: 表示该mutex被lock了,从而进入kernel来处理锁的情况。

pthread_mutex_lock的逻辑比较简单,就是通过一个原子操作判断锁是否已经被锁住。如果没锁住就更新owner,以及user计数。如果已经被锁住,则陷入内核调用FUTEX_LOCK_PI系统调用完成上锁的操作。

pthread_mutex_unlock

这个接口基本上就是直接调用futex_unlock_pi SYSCALL来完成工作:

      /* Unlock the mutex using a CAS unless there are futex waiters or our
›    TID is not the value of __lock anymore, in which case we let the
›    kernel take care of the situation.  Use release MO in the CAS to
›    synchronize with acquire MO in lock acquisitions.  */
      int l = atomic_load_relaxed (&mutex->__data.__lock);
      do
›   {
›     if (((l & FUTEX_WAITERS) != 0)
›         || (l != THREAD_GETMEM (THREAD_SELF, tid)))
›       {
›         INTERNAL_SYSCALL_DECL (__err);
›         INTERNAL_SYSCALL (futex, __err, 2, &mutex->__data.__lock,
›   ›   ›   ›   __lll_private_flag (FUTEX_UNLOCK_PI, private));
›         break;
›       }
›   }
      while (!atomic_compare_exchange_weak_release (&mutex->__data.__lock,
›   ›   ›   ›   ›   ›       &l, 0));

futex

futex是一种内核的等待机制,等待某个用户态数据被设置成某个值。针对优先级继承的futex略有不同。它不再等待用户传入的地址上的值,而是基于内核rt_mutex机制实现等待,上锁和解锁的功能。看下面glibc和Linux的接口对接:

// glibc: pthread_mutex_lock.c
int e = INTERNAL_SYSCALL (futex, __err, 4, &mutex->__data.__lock,
›   ›         __lll_private_flag (FUTEX_LOCK_PI,
›   ›   ›   ›   ›     private), 1, 0);

// Linux: futex.c
long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout,
›   ›   u32 __user *uaddr2, u32 val2, u32 val3)
{
...
	case FUTEX_LOCK_PI:
›   	return futex_lock_pi(uaddr, flags, NULL, 1);    
... 
}

可见:

  • uaddr = &mutex->__data.__lock
  • flags = __lll_private_flag (FUTEX_LOCK_PI, private)
  • val = 1, timeout = NULL

关于lock/unlock的叙述会简化掉time相关部分,以及PI无关的ROBUST等特性。

重要数据结构

/*
 * Hash buckets are shared by all the futex_keys that hash to the same
 * location.  Each key may have multiple futex_q structures, one for each task
 * waiting on a futex.
 */
struct futex_hash_bucket {atomic_t waiters;
›   spinlock_t lock;
›   struct plist_head chain;
} ____cacheline_aligned_in_smp;

/**
 * struct futex_q - The hashed futex queue entry, one per waiting task
 * @list:›  ›   priority-sorted list of tasks waiting on this futex
 * @task:›  ›   the task waiting on the futex
 * @lock_ptr:›  ›   the hash bucket lock
 * @key:›   ›   the key the futex is hashed on
 * @pi_state:›  ›   optional priority inheritance state
 * @rt_waiter:› ›   rt_waiter storage for use with requeue_pi
 * @requeue_pi_key:›the requeue_pi target futex key
 * @bitset:››   bitset for the optional bitmasked wakeup
 *
 * We use this hashed waitqueue, instead of a normal wait_queue_entry_t, so
 * we can wake only the relevant ones (hashed queues may be shared).
 *
 * A futex_q has a woken state, just like tasks have TASK_RUNNING.
 * It is considered woken when plist_node_empty(&q->list) || q->lock_ptr == 0.
 * The order of wakeup is always to make the first condition true, then
 * the second.
 *
 * PI futexes are typically woken before they are removed from the hash list via
 * the rt_mutex code. See unqueue_me_pi().
 */
struct futex_q {struct plist_node list;struct task_struct *task;spinlock_t *lock_ptr;
›   union futex_key key;
›   struct futex_pi_state *pi_state;struct rt_mutex_waiter *rt_waiter;union futex_key *requeue_pi_key;
›   u32 bitset;
} __randomize_layout;

/*
 * Priority Inheritance state:
 */
struct futex_pi_state {/*
›    * list of 'owned' pi_state instances - these have to be
›    * cleaned up in do_exit() if the task exits prematurely:
›    */struct list_head list;/*
›    * The PI object:
›    */struct rt_mutex pi_mutex;struct task_struct *owner;atomic_t refcount;

›   union futex_key key;
} __randomize_layout;

futex_hash_bucket对应一个用户态的uaddr。通过用户态传入的uaddr地址,来获得对应的futex结构体。用hash的原因是传入的是uaddr地址值,数字很大,分布很散,所以用hash可以有效索引。

futex_q是一个临时变量,对应了一个futex的waiter线程。它通常被用来传递各种数据结构。

pi_statetask_struct内部的一个变量,在futex_lock_pi调用refill_pi_state_cache里面做分配。

static int refill_pi_state_cache(void)
{
...
	pi_state = kzalloc(sizeof(*pi_state), GFP_KERNEL);
    current->pi_state_cache = pi_state;
...
}

futex_lock_pi

这个函数的逻辑还是比较直线的,同大多数锁的实现一样,先尝试原子锁,如果不行,则调用rt_mutex的实现来处理优先级继承的机制。以下捡取比较重要的函数做阐述,也可以参考参考文献[3], [4]中的描述。

queue_lock, queue_unlock

对hash_bucket进行锁操作。他们操作的是hash_bucket下的lock,同时也是futex_q下的lock_ptr。这里锁的出现比较混乱,有时调用上面的这两个函数,有时直接对lock指针操作。需要小心。

__queue_me, unqueue_me

这里将申请futex的线程在hash_bucket的chain上做添加或移除操作。还会涉及锁的操作。

以上4个函数更多的与futex的实现相关,与优先级继承并无关系,所以可以略过。

futex_lock_pi_atomic

这个函数做的就是原子操作来请求锁,

  • 如果futex没有waiter,则直接获得锁并返回1,表示成功获得锁
  • 如果有waiter,就返回0,表示ready to wait

这个函数不同的是会做一些与PI相关的处理:

  • 有waiter的情况:
    • 调用attach_to_pi_state来获得该top_waiter的pi_state
  • 没有waiter的情况
    • 调用attach_to_pi_owner来取用本线程里分配的pi_state结构体,并更新数据。之后,会被queue到hash_bucket的队列中。

rt_mutex接口

futex_lock_pi中使用到如下这些rt_mutex接口:

  • rt_mutex_init_waiter:初始化waiter数据结构,其实为一个红黑树的节点。这个waiter对应当前线程,并反映线程在某个锁上的等待关系。
  • __rt_mutex_start_proxy_lock:这个是PI的核心函数,用来对各waiters数据进行操作,以及遍历lock链来检查死锁。这个函数与之前的原子检查类似,如果返回1表示已经获得锁,如果返回0,则ready to wait。
  • rt_mutex_wait_proxy_lock:通过__rt_mutex_start_proxy_lock处理之后,如果还没有获得锁,那就可以开始等待了,这个函数将线程切换为TASK_INTERRUPTIBLE状态,并开始等待。这其间会处理基于时间的等待,且会触发调度。
  • rt_mutex_cleanup_proxy_lock:现在已经阻塞结束了,如果还没获得锁,要么是超时,要么是出错,总之要将本线程从waiters中移除,这个函数就是起这个作用。

fixup_owner

从注释上看,是为了处理lock steal。而lock steal似乎多发生在futex requeue操作上,目前尚未仔细研究。

futex_unlock_pi

futex_unlock_pi释放futex以及更新相应的pi_state和rt_mutex的owner字段。函数调用层次比较深,基本上都是每一层做一些基本的更新工作,最终调用到__rt_mutex_futex_unlock来重新调整本线程的优先级,并将top waiter放到wake queue上。在rt_mutex_postunlock调用的rt_mutex_postunlock将新线程唤醒。

如果没有waiter,则使用cmpxchg_futex_value_locked来将用户态地址uaddr上的值设为0。因为锁没有waiter了,所以优先级也不需要恢复了,或者已经恢复过了。

如果有waiter,就使用下面几个函数来切换lock owner,并恢复优先级继承的优先级。

wake_futex_pi

这个函数做了下面几件事:

  1. 用cmpxchg_futex_value_locked将用户态传入的uaddr处的数值更新为新的rt_mutex_next_owner() | FUTEX_WAITERS
  2. list_del_init(&pi_state->list):将list从原先的表上删除,并重新初始化,准备移到其他的表上。
  3. list_add(&pi_state->list, &new_owner->pi_state_list)
  4. pi_state->owner = new_owner
  5. __rt_mutex_futex_unlock
  6. rt_mutex_postunlock

mark_wakeup_next_waiter

注意:此时pi_state->owner已经设置过了,但是pi_state->pi_mutex->owner还没有设置。这个函数主要做了下面几件事情:

  1. rt_mutex_dequeue_pi(current, waiter);
  2. rt_mutex_adjust_prio(current):在这里调整了当前线程的优先级,完成了整个优先级继承协议。
  3. wake_q_add(wake_q, waiter->task)

put_pi_state

这个函数更多的是清理工作:

  1. 调用了rt_mutex_proxy_unlock来释放pi_state->pi_mutex.
  2. 释放了current->pi_state_cache空间

cmpxchg_futex_value_locked原子操作

static int cmpxchg_futex_value_locked(u32 *uval, u32 __user *uaddr,
›   ›   ›   ›         u32 oldval, u32 newval)
{
ATOMIC();
int val = *uaddr;
if (val == oldval) {
*uaddr = newval;
}
*uval = val;
END_ATOMIC();
return 0;
}

其中ATOMIC操作通过page_disable()和preempt_disable()保证。

__rt_mutex_start_proxy_lock

从上面futex_lock_pi用到的rt_mutex接口介绍中可知,这个函数是整个PI处理的核心,这个函数又主要调用task_blocks_on_rt_mutex来处理PI。

rt_mutex_adjust_prio(owner)

这个函数就是调整阻塞线程的优先级,从而实现优先级继承的。实现方式也很简单:

if (task_has_pi_waiters(p))
›   pi_task = task_top_pi_waiter(p)->task;

rt_mutex_setprio(p, pi_task);

把owner线程设置为owner线程所有waiter(可能来自多个锁)的最高优先级。

rt_mutex_adjust_prio_chain

为什么有这个链式调整?

这里有两张表格:

  • 每个rt_mutex有张waiters表格,表示所有等待的线程

  • 每个task也有张表格,表格里的每一项对应owner线程占有的锁,每一项是一个rt_mutex_waiter,表示申请该锁的最高优先级waiter

假设Task1就是owner,Task0对Lock0的申请导致Task1提升优先级,如果Task1同时被Task2持有的某个锁阻塞,则Task1优先级的改变,有可能会导致Task2 pi_waiters列表改变,同时可能导致Task2优先级改变。依此类推,就会导致上面的这种链式反应。

链处理流程

整个chain的处理流程大致如下:

  1. 如果Task0是Lock0的top waiter,则激发该链式调整。
  2. 因为Task0成为Lock0的topwaiter,则Task1的pi_waiters需要调整,则Task1的优先级可能需要调整。退出可能:
    • 起点锁释放了

    • 链的当前环节被更改( next_lock ≠waiter->lock)

    • Task1没有占锁

  3. 如果Task1也wait在某个lock的时候,则该lock的waiters需要调整,这里有若干种退出可能。
  • Task1没有被block
  • Task1 pi_waiters中有优先级高于Task0的waiter,换句话说,lock0的top_waiter不是Task1的top pi_waiter,优先级继承不需要继续传递
  • 如果Task1在申请Lock1 的时候的优先级(这个记录在waiter->prio里)与当前调整后的优先级相等,则后续没必要在继续调整优先级
  • 检测到DEADLOCK
  1. 回到1继续执行,直到退出链式处理
死锁

有3种情况,函数会返回死锁

  • 链上超过1024个锁节点
  • 链上任意Task节点申请第一个锁节点,即Lock0
  • 链上任意一个锁owner是第一个Task节点,即Task0

参考文献

[1] [Mutex mutandis: understanding mutex types and attributes]. (http://2net.co.uk/tutorial/mutex_mutandis)

[2] POSIX Revision of IEEE Std 1003.1-2008

[3] Source code analysis of pthread_mutex_lock

[4] linux pi_futex浅析

[5] Linux 4.20-rc3 source code

[6] glibc 2.28 source code

%23%23%20%E4%BC%98%E5%85%88%E7%BA%A7%E5%8F%8D%E8%BD%AC%0A%0A%E4%BC%98%E5%85%88%E7%BA%A7%E5%8F%8D%E8%BD%AC%E6%8C%87%E4%B8%80%E4%B8%AA%E9%AB%98%E4%BC%98%E5%85%88%E7%BA%A7%E4%BB%BB%E5%8A%A1%E5%9B%A0%E4%B8%BA%E8%B5%84%E6%BA%90%E8%A2%AB%E4%BD%8E%E4%BC%98%E5%85%88%E7%BA%A7%E4%BB%BB%E5%8A%A1%E5%8D%A0%E7%94%A8%EF%BC%8C%E8%80%8C%E4%B8%8D%E5%BE%97%E4%B8%8D%E7%AD%89%E5%BE%85%E3%80%82%E8%BF%99%E4%B8%AA%E9%80%BB%E8%BE%91%E6%9C%AC%E8%BA%AB%E6%B2%A1%E6%9C%89%E4%BB%80%E4%B9%88%E9%97%AE%E9%A2%98%E3%80%82%E4%BC%98%E5%85%88%E7%BA%A7%E5%8F%8D%E8%BD%AC%E5%B8%A6%E6%9D%A5%E6%9C%80%E7%9B%B4%E6%8E%A5%E7%9A%84%E9%97%AE%E9%A2%98%E5%B0%B1%E6%98%AF%E9%AB%98%E4%BC%98%E5%85%88%E7%BA%A7%E5%8F%AF%E8%83%BD%E5%9B%A0%E4%B8%BA%E8%BF%99%E6%AC%A1%E9%98%BB%E5%A1%9E%EF%BC%8C%E8%80%8C%E6%97%A0%E6%B3%95%E7%A1%AE%E5%AE%9A%E9%98%BB%E5%A1%9E%E6%97%B6%E5%BB%B6%E3%80%82%E5%A6%82%E4%B8%8B%E5%9B%BE%E6%89%80%E7%A4%BA%E3%80%82%0A!%5B8df099f053cbeaee4881a9d6ffc8963f.png%5D(evernotecid%3A%2F%2F22617523-9521-4D00-B771-5F27B85F00EB%2Fappyinxiangcom%2F161681%2FENResource%2Fp5789)%0A%0ATask%209%E4%BC%98%E5%85%88%E7%BA%A7%E8%BE%83%E4%BD%8E%EF%BC%8C%E6%89%80%E4%BB%A5%E5%BE%88%E5%AE%B9%E6%98%93%E8%A2%AB%E5%85%B6%E4%BB%96%E4%BC%98%E5%85%88%E7%BA%A7%E7%9A%84%E4%BB%BB%E5%8A%A1%E6%8A%A2%E5%8D%A0%E8%BF%90%E8%A1%8C%EF%BC%8C%E5%AF%BC%E8%87%B4%E5%AF%B9%E8%B5%84%E6%BA%90S%E7%9A%84%E9%94%81%E6%97%A0%E6%B3%95%E9%87%8A%E6%94%BE%EF%BC%8C%E8%80%8C%E9%AB%98%E4%BC%98%E5%85%88%E7%BA%A7%E7%9A%84%E4%BB%BB%E5%8A%A1%E5%9B%A0%E4%B8%BA%E8%A6%81%E6%8C%81%E6%9C%89%E8%AF%A5%E9%94%81%EF%BC%8C%E4%B8%8D%E5%BE%97%E4%B8%8D%E7%AD%89%E5%BE%85%E3%80%82%0A%0A%23%23%20%E4%BC%98%E5%85%88%E7%BA%A7%E7%BB%A7%E6%89%BF%0A%0APriority%20Inheritance%20Protocol%E7%BF%BB%E8%AF%91%E4%B8%BA%E4%BC%98%E5%85%88%E7%BA%A7%E7%BB%A7%E6%89%BF%EF%BC%8C%E7%AE%80%E7%A7%B0PIP%E3%80%82%E8%BF%99%E6%98%AF%E8%A7%A3%E5%86%B3%E4%B8%8A%E8%BF%B0Unbounded%20inversion%E6%9C%80%E7%9B%B4%E6%8E%A5%E7%9A%84%E5%8A%9E%E6%B3%95%EF%BC%8C%E5%B0%B1%E6%98%AF%E5%B0%86%E5%8D%A0%E6%9C%89%E9%94%81%E7%9A%84%E7%BA%BF%E7%A8%8B%E4%BC%98%E5%85%88%E7%BA%A7%E8%B0%83%E6%95%B4%E5%88%B0%E5%9C%A8%E7%AD%89%E5%BE%85%E7%9A%84%E4%BB%BB%E5%8A%A1%E7%9A%84%E6%9C%80%E9%AB%98%E5%80%BC%E3%80%82%E8%BF%99%E4%B8%AA%E7%AE%97%E6%B3%95%E6%98%AF%E8%B4%AA%E5%A9%AA%E7%9A%84%EF%BC%8C%E5%B1%80%E9%83%A8%E6%9C%80%E4%BC%98%EF%BC%8C%E4%BD%86%E4%B8%8D%E6%98%AF%E6%95%B4%E4%BD%93%E6%9C%80%E4%BC%98%E8%A7%A3%EF%BC%8C%E5%9C%A8%E6%AD%A4%E4%B9%8B%E4%B8%8A%E5%8F%88%E6%9C%89PCP(%E4%BC%98%E5%85%88%E7%BA%A7%E5%A4%A9%E8%8A%B1%E6%9D%BF)%E5%92%8CSRP(%E5%9F%BA%E4%BA%8E%E6%A0%88%E7%9A%84%E8%B5%84%E6%BA%90%E7%AD%96%E7%95%A5)%E3%80%82%E6%9C%AC%E6%96%87%E4%B8%8D%E5%81%9A%E8%AE%A8%E8%AE%BA%E3%80%82%E6%9C%AC%E6%96%87%E4%B8%BB%E8%A6%81%E4%BB%8E%E6%BA%90%E7%A0%81%E7%9A%84%E8%A7%92%E5%BA%A6%EF%BC%8C%E9%98%90%E8%BF%B0PIP%E5%9C%A8Linux%E5%92%8Cglibc%E4%B8%AD%E7%9A%84%E5%85%B7%E4%BD%93%E5%AE%9E%E7%8E%B0%E3%80%82%0A%0A%23%23%20Overview%0A!%5Bb16f478e9d2cf9485b4b8bba9e81e3b0.png%5D(evernotecid%3A%2F%2F22617523-9521-4D00-B771-5F27B85F00EB%2Fappyinxiangcom%2F161681%2FENResource%2Fp5790)%0A%0ALinux%E4%B8%8B%E7%9A%84PIP%E5%AE%9E%E7%8E%B0%E5%88%86%E6%88%90%E4%BB%A5%E4%B8%8A3%E4%B8%AA%E9%83%A8%E5%88%86%EF%BC%9A%0A%0A-%20glibc%E4%B8%AD%E7%9A%84pthread_mutex_lock%E6%8F%90%E4%BE%9B%E7%94%A8%E6%88%B7%E6%8E%A5%E5%8F%A3%EF%BC%8C%E9%80%9A%E8%BF%87FUTEX_LOCK_PI%E5%AE%9E%E7%8E%B0%E4%BC%98%E5%85%88%E7%BA%A7%E8%B0%83%E6%95%B4%0A-%20Linux%E7%9A%84futex%E9%83%A8%E5%88%86%E6%8F%90%E4%BE%9BFUTEX_LOCK_PI%E7%9A%84%E5%AE%9E%E7%8E%B0%0A-%20%E6%9C%80%E7%BB%88%E7%9A%84%E9%94%81%E6%9C%BA%E5%88%B6%E9%80%9A%E8%BF%87rt_mutex%E6%9D%A5%E5%AE%9E%E7%8E%B0%0A%0A%23%23%20pthread_mutex%0A%0A%23%23%23%20Types%0A%0Apthread%20mutex%E6%98%AFPOSIX%20pthread%E5%BA%93%E4%B8%AD%E5%AE%9A%E4%B9%89%E7%9A%84%E4%B8%80%E7%A7%8D%E9%94%81%E6%9C%BA%E5%88%B6%EF%BC%8C%E4%B8%8E%E4%BF%A1%E5%8F%B7%E9%87%8F%E4%B8%8D%E5%90%8C%E7%9A%84%E6%98%AF%EF%BC%8C%E8%BF%99%E4%B8%AA%E9%94%81%E5%8F%AA%E6%9C%89%E4%B8%A4%E7%A7%8D%E7%8A%B6%E6%80%81%EF%BC%9Alocked%E6%88%96unlocked%E3%80%82%E4%B8%8Ebinary%20semaphore%E4%B8%8D%E5%90%8C%E7%9A%84%E6%98%AF%EF%BC%8Cmutex%E5%8F%AA%E8%83%BD%E8%A2%ABlock%E7%9A%84%E7%BA%BF%E7%A8%8Bunlock%EF%BC%8C%E5%8D%B3%E5%8F%AA%E8%83%BD%E8%A2%ABmutex%20owner%20unlock%E3%80%82%0A%0A%E7%9B%AE%E5%89%8D%5BPOSIX%E6%A0%87%E5%87%86(1003.1-2008)%5D(http%3A%2F%2Fpubs.opengroup.org%2Fonlinepubs%2F9699919799%2Ffunctions%2Fcontents.html)%E4%B8%AD%E5%AE%9A%E4%B9%89%E4%BA%864%E7%A7%8D%E7%B1%BB%E5%9E%8B%E7%9A%84mutex%3A%0A%0A-%20PTHREAD_MUTEX_NORMAL%0A-%20PTHREAD_MUTEX_ERRORCHECK%0A-%20PTHREAD_MUTEX_RECURSIVE%0A-%20PTHREAD_MUTEX_DEFAULT%0A%0A%E8%BF%994%E7%A7%8Dmutex%E4%B8%8D%E5%90%8C%E4%B9%8B%E5%A4%84%E5%A6%82%E4%B8%8B%0A%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%7C%20attempting%20to%20relock%20this%20mutex%20without%20first%20unlocking%20%7C%20Attempting%20to%20unlock%20a%20mutex%20locked%20by%20a%20different%20thread%20%7C%0A%7C%20----------%20%7C%20-------------------------------------------------------%20%7C%20---------------------------------------------------------%20%7C%0A%7C%20NORMAL%20%20%20%20%20%7C%20deadlock%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20undefined%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20ERRORCHECK%20%7C%20return%20error%20-EDEADLOCK%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20return%20error%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20RECURSIVE%20%20%7C%20succeed%20in%20locking%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20return%20error%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20DEFAULT%20%20%20%20%7C%20undefined%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%20undefined%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%0Aglibc%E5%AF%B9%E4%B8%8A%E8%BF%B04%E7%A7%8D%E7%B1%BB%E5%9E%8B%E7%9A%84mutex%E8%BF%9B%E8%A1%8C%E4%BA%86%E6%89%A9%E5%B1%95%EF%BC%8C%E4%BE%8B%E5%A6%82%EF%BC%9A%0A%0A%60%60%60c%0A%20%20%20%20case%20PTHREAD_MUTEX_PI_RECURSIVE_NP%3A%0A%20%20%20%20case%20PTHREAD_MUTEX_PI_ERRORCHECK_NP%3A%0A%20%20%20%20case%20PTHREAD_MUTEX_PI_NORMAL_NP%3A%0A%20%20%20%20case%20PTHREAD_MUTEX_PI_ADAPTIVE_NP%3A%0A%20%20%20%20case%20PTHREAD_MUTEX_PI_ROBUST_RECURSIVE_NP%3A%0A%20%20%20%20case%20PTHREAD_MUTEX_PI_ROBUST_ERRORCHECK_NP%3A%0A%20%20%20%20case%20PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP%3A%0A%20%20%20%20case%20PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP%3A%0A%60%60%60%0A%0A%E4%B8%BB%E8%A6%81%E5%A4%9A%E4%BA%86%E8%BF%993%E7%A7%8D%E5%B1%9E%E6%80%A7%EF%BC%9A%0A%0A-%20ADAPTIVE%EF%BC%9A%E5%9C%A8SMP%E6%9E%B6%E6%9E%84%E4%B8%8B%EF%BC%8C%E5%B9%B6%E4%B8%8D%E7%9B%B4%E6%8E%A5%E8%BF%9B%E5%85%A5wait%EF%BC%8C%E8%80%8C%E6%98%AF%E5%85%88%E8%B0%83%E7%94%A8spinlock%E7%AD%89%E5%BE%85%E4%B8%80%E5%B0%8F%E6%AE%B5%E6%97%B6%E9%97%B4%E3%80%82musl%E9%87%8C%E9%BB%98%E8%AE%A4%E9%83%BD%E9%87%87%E7%94%A8%E4%BA%86%E8%BF%99%E7%A7%8D%E5%AE%9E%E7%8E%B0%0A%0A-%20PI%EF%BC%9A%E5%8C%85%E5%90%AB%E8%AF%A5%E5%B1%9E%E6%80%A7%E7%9A%84mutex%EF%BC%8C%E5%AE%9E%E7%8E%B0%E4%BA%86%E4%BC%98%E5%85%88%E7%BA%A7%E7%BB%A7%E6%89%BF(Priority%20Inheritance%2C%20PI)%0A%0A-%20ROBUST%EF%BC%9A%E8%8B%A5%E7%BA%BF%E7%A8%8B%E9%80%80%E5%87%BA%E6%97%B6%E6%9C%AA%E9%87%8A%E6%94%BE%E9%94%81%EF%BC%8C%E5%88%99%E4%BB%A5%E5%90%8E%E5%AF%B9%E8%AF%A5%E9%94%81%E6%93%8D%E4%BD%9C%E9%83%BD%E4%BC%9A%E8%BF%94%E5%9B%9E-EOWNERDEAD%EF%BC%8C%E4%B8%8E%E4%B9%8B%E5%AF%B9%E5%BA%94%E7%9A%84%E6%98%AFPTHREAD_MUTEX_STALLED(%E8%BF%99%E6%98%AF%E9%BB%98%E8%AE%A4%E9%85%8D%E7%BD%AE)%EF%BC%8C%E5%AF%B9%E8%AF%A5%E5%BC%82%E5%B8%B8%E9%94%81%E7%9A%84%E6%93%8D%E4%BD%9C%E4%BC%9A%E5%87%BA%E7%8E%B0undefined%E8%A1%8C%E4%B8%BA%E3%80%82%0A%0A%E5%86%8D%E4%B8%8E%E5%8E%9F%E5%85%88%E7%9A%844%E7%A7%8D%E5%B1%9E%E6%80%A7%E8%BF%9B%E8%A1%8C%E6%8E%92%E5%88%97%E7%BB%84%E5%90%88%E3%80%82%0A%0A%3E%20**%22_NP%22%20suffix**%0A%3E%0A%3E%20Note%3A%20the%20_NP%20suffix%20indicates%20a%20non-portable%20extension%20to%20the%20POSIX%20specification.%20In%20fact%20the%20latest%20specification%2C%201003.1-2008%20%5B%5B2%5C%5D%5D(http%3A%2F%2F2net.co.uk%2Ftutorial%2Fmutex_mutandis%23ref_2)%2C%20includes%20most%20of%20the%20Linux%20additions%20so%20you%20can%20leave%20the%20_NP%20ending%20off.%20I%20have%20chosen%20not%20to%20because%20some%20older%20versions%20of%20the%20header%20files%20only%20have%20the%20_NP%20variants.%0A%3E%0A%3E%20%E6%A0%B9%E6%8D%AE%E6%9C%80%E6%96%B0%E7%9A%84POSIX%E6%A0%87%E5%87%861003.1-2008%EF%BC%8C%E8%BF%99%E4%BA%9B%E6%89%A9%E5%B1%95%E5%B9%B6%E6%B2%A1%E6%9C%89%E5%8A%A0%E5%85%A5%E3%80%82%0A%0A%E6%9C%AC%E6%96%87%E5%8F%AA%E5%85%B3%E6%B3%A8MUTEX_PI%E5%AE%9E%E7%8E%B0%E3%80%82%0A%0A%23%23%23%20PTHREAD_MUTEX_PI%0A%0A%23%23%23%23%20pthread_mutex_lock%0A%0A%E9%87%8D%E8%A6%81%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E5%A6%82%E4%B8%8B%EF%BC%9A%0A%0A%60%60%60C%0Atypedef%20union%0A%7B%0A%20%20struct%20__pthread_mutex_s%20__data%3B%0A%20%20char%20__size%5B__SIZEOF_PTHREAD_MUTEX_T%5D%3B%0A%20%20long%20int%20__align%3B%0A%7D%20pthread_mutex_t%3B%0Astruct%20__pthread_mutex_s%0A%7B%0A%20%20int%20__lock%20__LOCK_ALIGNMENT%3B%0A%20%20unsigned%20int%20__count%3B%0A%20%20int%20__owner%3B%0A%20%20...%0A%7D%0A%60%60%60%0A%0A%E5%A6%82%E6%9E%9C%E4%B8%8D%E8%80%83%E8%99%91ROBUST%E6%83%85%E5%86%B5%E7%9A%84%E5%A4%84%E7%90%86%EF%BC%8C%E4%B8%80%E6%AC%A1%E9%92%88%E5%AF%B9%E5%AE%9E%E7%8E%B0%E4%BA%86PI%E5%B1%9E%E6%80%A7%E7%9A%84pthread_mutex_lock%E6%93%8D%E4%BD%9C%E5%A6%82%E4%B8%8B%EF%BC%9A%0A!%5B36c67b688ae44843223a576d9cc0be30.png%5D(evernotecid%3A%2F%2F22617523-9521-4D00-B771-5F27B85F00EB%2Fappyinxiangcom%2F161681%2FENResource%2Fp5791)%0A%0A%0A%3E%20**atomic_compare_and_exchange_val_acq**%0A%3E%0A%3E%20%E8%BF%99%E6%98%AF%E4%B8%80%E7%A7%8D%E5%8E%9F%E5%AD%90%E6%93%8D%E4%BD%9C%EF%BC%8C%E5%85%88%E6%AF%94%E8%BE%83%E5%86%8D%E8%B5%8B%E5%80%BC%EF%BC%8C%E4%BC%AA%E4%BB%A3%E7%A0%81%E5%A6%82%E4%B8%8B%EF%BC%9A%0A%3E%0A%3E%20%60%60%60C%0A%3E%20int%20compare_and_swap(int*%20reg%2C%20int%20oldval%2C%20int%20newval)%0A%3E%20%7B%0A%3E%20%20%20%20%20ATOMIC()%3B%0A%3E%20%20%20%20%20int%20old_reg_val%20%3D%20*reg%3B%0A%3E%20%20%20%20%20if%20(old_reg_val%20%3D%3D%20oldval)%0A%3E%20%20%20%20%20%20%20*reg%20%3D%20newval%3B%0A%3E%20%20%20%20%20END_ATOMIC()%3B%0A%3E%20%20%20%20%20return%20old_reg_val%3B%0A%3E%20%7D%0A%3E%20%60%60%60%0A%3E%0A%3E%20%E9%92%88%E5%AF%B9%E4%BB%A3%E7%A0%81%E4%B8%AD%E7%9A%84%E5%85%B7%E4%BD%93%E6%83%85%E5%86%B5%EF%BC%9A%0A%3E%0A%3E%20-%20%60oldval%20%3D%3D%200%60%3A%20%E8%A1%A8%E7%A4%BA%60mutex-%3E__data.__lock%20%3D%3D%200%60%EF%BC%8C%E5%8D%B3%E8%AF%A5lock%E6%97%A0owner%EF%BC%8C%E5%8F%AF%E4%BB%A5%E8%8E%B7%E5%BE%97%E3%80%82%0A%3E%20-%20%60oldval%20!%3D%200%60%3A%20%E8%A1%A8%E7%A4%BA%E8%AF%A5mutex%E8%A2%ABlock%E4%BA%86%EF%BC%8C%E4%BB%8E%E8%80%8C%E8%BF%9B%E5%85%A5kernel%E6%9D%A5%E5%A4%84%E7%90%86%E9%94%81%E7%9A%84%E6%83%85%E5%86%B5%E3%80%82%0A%0Apthread_mutex_lock%E7%9A%84%E9%80%BB%E8%BE%91%E6%AF%94%E8%BE%83%E7%AE%80%E5%8D%95%EF%BC%8C%E5%B0%B1%E6%98%AF%E9%80%9A%E8%BF%87%E4%B8%80%E4%B8%AA%E5%8E%9F%E5%AD%90%E6%93%8D%E4%BD%9C%E5%88%A4%E6%96%AD%E9%94%81%E6%98%AF%E5%90%A6%E5%B7%B2%E7%BB%8F%E8%A2%AB%E9%94%81%E4%BD%8F%E3%80%82%E5%A6%82%E6%9E%9C%E6%B2%A1%E9%94%81%E4%BD%8F%E5%B0%B1%E6%9B%B4%E6%96%B0owner%EF%BC%8C%E4%BB%A5%E5%8F%8Auser%E8%AE%A1%E6%95%B0%E3%80%82%E5%A6%82%E6%9E%9C%E5%B7%B2%E7%BB%8F%E8%A2%AB%E9%94%81%E4%BD%8F%EF%BC%8C%E5%88%99%E9%99%B7%E5%85%A5%E5%86%85%E6%A0%B8%E8%B0%83%E7%94%A8FUTEX_LOCK_PI%E7%B3%BB%E7%BB%9F%E8%B0%83%E7%94%A8%E5%AE%8C%E6%88%90%E4%B8%8A%E9%94%81%E7%9A%84%E6%93%8D%E4%BD%9C%E3%80%82%0A%0A%23%23%23%23%20pthread_mutex_unlock%0A%0A%E8%BF%99%E4%B8%AA%E6%8E%A5%E5%8F%A3%E5%9F%BA%E6%9C%AC%E4%B8%8A%E5%B0%B1%E6%98%AF%E7%9B%B4%E6%8E%A5%E8%B0%83%E7%94%A8futex_unlock_pi%20SYSCALL%E6%9D%A5%E5%AE%8C%E6%88%90%E5%B7%A5%E4%BD%9C%EF%BC%9A%0A%0A%60%60%60c%0A%20%20%20%20%20%20%2F*%20Unlock%20the%20mutex%20using%20a%20CAS%20unless%20there%20are%20futex%20waiters%20or%20our%0A%E2%80%BA%20%20%20%20TID%20is%20not%20the%20value%20of%20__lock%20anymore%2C%20in%20which%20case%20we%20let%20the%0A%E2%80%BA%20%20%20%20kernel%20take%20care%20of%20the%20situation.%20%20Use%20release%20MO%20in%20the%20CAS%20to%0A%E2%80%BA%20%20%20%20synchronize%20with%20acquire%20MO%20in%20lock%20acquisitions.%20%20*%2F%0A%20%20%20%20%20%20int%20l%20%3D%20atomic_load_relaxed%20(%26mutex-%3E__data.__lock)%3B%0A%20%20%20%20%20%20do%0A%E2%80%BA%20%20%20%7B%0A%E2%80%BA%20%20%20%20%20if%20(((l%20%26%20FUTEX_WAITERS)%20!%3D%200)%0A%E2%80%BA%20%20%20%20%20%20%20%20%20%7C%7C%20(l%20!%3D%20THREAD_GETMEM%20(THREAD_SELF%2C%20tid)))%0A%E2%80%BA%20%20%20%20%20%20%20%7B%0A%E2%80%BA%20%20%20%20%20%20%20%20%20INTERNAL_SYSCALL_DECL%20(__err)%3B%0A%E2%80%BA%20%20%20%20%20%20%20%20%20INTERNAL_SYSCALL%20(futex%2C%20__err%2C%202%2C%20%26mutex-%3E__data.__lock%2C%0A%E2%80%BA%20%20%20%E2%80%BA%20%20%20%E2%80%BA%20%20%20%E2%80%BA%20%20%20__lll_private_flag%20(FUTEX_UNLOCK_PI%2C%20private))%3B%0A%E2%80%BA%20%20%20%20%20%20%20%20%20break%3B%0A%E2%80%BA%20%20%20%20%20%20%20%7D%0A%E2%80%BA%20%20%20%7D%0A%20%20%20%20%20%20while%20(!atomic_compare_exchange_weak_release%20(%26mutex-%3E__data.__lock%2C%0A%E2%80%BA%20%20%20%E2%80%BA%20%20%20%E2%80%BA%20%20%20%E2%80%BA%20%20%20%E2%80%BA%20%20%20%E2%80%BA%20%20%20%20%20%20%20%26l%2C%200))%3B%0A%60%60%60%0A%0A%0A%0A%23%23%20futex%0A%0Afutex%E6%98%AF%E4%B8%80%E7%A7%8D%E5%86%85%E6%A0%B8%E7%9A%84%E7%AD%89%E5%BE%85%E6%9C%BA%E5%88%B6%EF%BC%8C%E7%AD%89%E5%BE%85%E6%9F%90%E4%B8%AA%E7%94%A8%E6%88%B7%E6%80%81%E6%95%B0%E6%8D%AE%E8%A2%AB%E8%AE%BE%E7%BD%AE%E6%88%90%E6%9F%90%E4%B8%AA%E5%80%BC%E3%80%82%E9%92%88%E5%AF%B9%E4%BC%98%E5%85%88%E7%BA%A7%E7%BB%A7%E6%89%BF%E7%9A%84futex%E7%95%A5%E6%9C%89%E4%B8%8D%E5%90%8C%E3%80%82%E5%AE%83%E4%B8%8D%E5%86%8D%E7%AD%89%E5%BE%85%E7%94%A8%E6%88%B7%E4%BC%A0%E5%85%A5%E7%9A%84%E5%9C%B0%E5%9D%80%E4%B8%8A%E7%9A%84%E5%80%BC%EF%BC%8C%E8%80%8C%E6%98%AF%E5%9F%BA%E4%BA%8E%E5%86%85%E6%A0%B8rt_mutex%E6%9C%BA%E5%88%B6%E5%AE%9E%E7%8E%B0%E7%AD%89%E5%BE%85%EF%BC%8C%E4%B8%8A%E9%94%81%E5%92%8C%E8%A7%A3%E9%94%81%E7%9A%84%E5%8A%9F%E8%83%BD%E3%80%82%E7%9C%8B%E4%B8%8B%E9%9D%A2glibc%E5%92%8CLinux%E7%9A%84%E6%8E%A5%E5%8F%A3%E5%AF%B9%E6%8E%A5%EF%BC%9A%0A%0A%60%60%60c%0A%2F%2F%20glibc%3A%20pthread_mutex_lock.c%0Aint%20e%20%3D%20INTERNAL_SYSCALL%20(futex%2C%20__err%2C%204%2C%20%26mutex-%3E__data.__lock%2C%0A%E2%80%BA%20%20%20%E2%80%BA%20%20%20%20%20%20%20%20%20__lll_private_flag%20(FUTEX_LOCK_PI%2C%0A%E2%80%BA%20%20%20%E2%80%BA%20%20%20%E2%80%BA%20%20%20%E2%80%BA%20%20%20%E2%80%BA%20%20%20%20%20private)%2C%201%2C%200)%3B%0A%0A%2F%2F%20Linux%3A%20futex.c%0Along%20do_futex(u32%20__user%20*uaddr%2C%20int%20op%2C%20u32%20val%2C%20ktime_t%20*timeout%2C%0A%E2%80%BA%20%20%20%E2%80%BA%20%20%20u32%20__user%20*uaddr2%2C%20u32%20val2%2C%20u32%20val3)%0A%7B%0A...%0A%09case%20FUTEX_LOCK_PI%3A%0A%E2%80%BA%20%20%20%09return%20futex_lock_pi(uaddr%2C%20flags%2C%20NULL%2C%201)%3B%20%20%20%20%0A...%20%0A%7D%0A%60%60%60%0A%0A%E5%8F%AF%E8%A7%81%EF%BC%9A%0A%0A-%20%60uaddr%20%3D%20%26mutex-%3E__data.__lock%60%0A-%20%60flags%20%3D%20__lll_private_flag%20(FUTEX_LOCK_PI%2C%20private)%60%0A-%20%60val%20%3D%201%2C%20timeout%20%3D%20NULL%60%0A%0A%3E%20%E5%85%B3%E4%BA%8Elock%2Funlock%E7%9A%84%E5%8F%99%E8%BF%B0%E4%BC%9A%E7%AE%80%E5%8C%96%E6%8E%89time%E7%9B%B8%E5%85%B3%E9%83%A8%E5%88%86%EF%BC%8C%E4%BB%A5%E5%8F%8API%E6%97%A0%E5%85%B3%E7%9A%84ROBUST%E7%AD%89%E7%89%B9%E6%80%A7%E3%80%82%0A%0A%23%23%23%20%E9%87%8D%E8%A6%81%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%0A%0A%60%60%60c%0A%2F*%0A%20*%20Hash%20buckets%20are%20shared%20by%20all%20the%20futex_keys%20that%20hash%20to%20the%20same%0A%20*%20location.%20%20Each%20key%20may%20have%20multiple%20futex_q%20structures%2C%20one%20for%20each%20task%0A%20*%20waiting%20on%20a%20futex.%0A%20*%2F%0Astruct%20futex_hash_bucket%20%7B%0A%E2%80%BA%20%20%20atomic_t%20waiters%3B%0A%E2%80%BA%20%20%20spinlock_t%20lock%3B%0A%E2%80%BA%20%20%20struct%20plist_head%20chain%3B%0A%7D%20____cacheline_aligned_in_smp%3B%0A%0A%2F**%0A%20*%20struct%20futex_q%20-%20The%20hashed%20futex%20queue%20entry%2C%20one%20per%20waiting%20task%0A%20*%20%40list%3A%E2%80%BA%20%20%E2%80%BA%20%20%20priority-sorted%20list%20of%20tasks%20waiting%20on%20this%20futex%0A%20*%20%40task%3A%E2%80%BA%20%20%E2%80%BA%20%20%20the%20task%20waiting%20on%20the%20futex%0A%20*%20%40lock_ptr%3A%E2%80%BA%20%20%E2%80%BA%20%20%20the%20hash%20bucket%20lock%0A%20*%20%40key%3A%E2%80%BA%20%20%20%E2%80%BA%20%20%20the%20key%20the%20futex%20is%20hashed%20on%0A%20*%20%40pi_state%3A%E2%80%BA%20%20%E2%80%BA%20%20%20optional%20priority%20inheritance%20state%0A%20*%20%40rt_waiter%3A%E2%80%BA%20%E2%80%BA%20%20%20rt_waiter%20storage%20for%20use%20with%20requeue_pi%0A%20*%20%40requeue_pi_key%3A%E2%80%BAthe%20requeue_pi%20target%20futex%20key%0A%20*%20%40bitset%3A%E2%80%BA%E2%80%BA%20%20%20bitset%20for%20the%20optional%20bitmasked%20wakeup%0A%20*%0A%20*%20We%20use%20this%20hashed%20waitqueue%2C%20instead%20of%20a%20normal%20wait_queue_entry_t%2C%20so%0A%20*%20we%20can%20wake%20only%20the%20relevant%20ones%20(hashed%20queues%20may%20be%20shared).%0A%20*%0A%20*%20A%20futex_q%20has%20a%20woken%20state%2C%20just%20like%20tasks%20have%20TASK_RUNNING.%0A%20*%20It%20is%20considered%20woken%20when%20plist_node_empty(%26q-%3Elist)%20%7C%7C%20q-%3Elock_ptr%20%3D%3D%200.%0A%20*%20The%20order%20of%20wakeup%20is%20always%20to%20make%20the%20first%20condition%20true%2C%20then%0A%20*%20the%20second.%0A%20*%0A%20*%20PI%20futexes%20are%20typically%20woken%20before%20they%20are%20removed%20from%20the%20hash%20list%20via%0A%20*%20the%20rt_mutex%20code.%20See%20unqueue_me_pi().%0A%20*%2F%0Astruct%20futex_q%20%7B%0A%E2%80%BA%20%20%20struct%20plist_node%20list%3B%0A%0A%E2%80%BA%20%20%20struct%20task_struct%20*task%3B%0A%E2%80%BA%20%20%20spinlock_t%20*lock_ptr%3B%0A%E2%80%BA%20%20%20union%20futex_key%20key%3B%0A%E2%80%BA%20%20%20struct%20futex_pi_state%20*pi_state%3B%0A%E2%80%BA%20%20%20struct%20rt_mutex_waiter%20*rt_waiter%3B%0A%E2%80%BA%20%20%20union%20futex_key%20*requeue_pi_key%3B%0A%E2%80%BA%20%20%20u32%20bitset%3B%0A%7D%20__randomize_layout%3B%0A%0A%2F*%0A%20*%20Priority%20Inheritance%20state%3A%0A%20*%2F%0Astruct%20futex_pi_state%20%7B%0A%E2%80%BA%20%20%20%2F*%0A%E2%80%BA%20%20%20%20*%20list%20of%20'owned'%20pi_state%20instances%20-%20these%20have%20to%20be%0A%E2%80%BA%20%20%20%20*%20cleaned%20up%20in%20do_exit()%20if%20the%20task%20exits%20prematurely%3A%0A%E2%80%BA%20%20%20%20*%2F%0A%E2%80%BA%20%20%20struct%20list_head%20list%3B%0A%0A%E2%80%BA%20%20%20%2F*%0A%E2%80%BA%20%20%20%20*%20The%20PI%20object%3A%0A%E2%80%BA%20%20%20%20*%2F%0A%E2%80%BA%20%20%20struct%20rt_mutex%20pi_mutex%3B%0A%0A%E2%80%BA%20%20%20struct%20task_struct%20*owner%3B%0A%E2%80%BA%20%20%20atomic_t%20refcount%3B%0A%0A%E2%80%BA%20%20%20union%20futex_key%20key%3B%0A%7D%20__randomize_layout%3B%0A%60%60%60%0A%0A%60futex_hash_bucket%60%E5%AF%B9%E5%BA%94%E4%B8%80%E4%B8%AA%E7%94%A8%E6%88%B7%E6%80%81%E7%9A%84%60uaddr%60%E3%80%82%E9%80%9A%E8%BF%87%E7%94%A8%E6%88%B7%E6%80%81%E4%BC%A0%E5%85%A5%E7%9A%84uaddr%E5%9C%B0%E5%9D%80%EF%BC%8C%E6%9D%A5%E8%8E%B7%E5%BE%97%E5%AF%B9%E5%BA%94%E7%9A%84futex%E7%BB%93%E6%9E%84%E4%BD%93%E3%80%82%E7%94%A8hash%E7%9A%84%E5%8E%9F%E5%9B%A0%E6%98%AF%E4%BC%A0%E5%85%A5%E7%9A%84%E6%98%AFuaddr%E5%9C%B0%E5%9D%80%E5%80%BC%EF%BC%8C%E6%95%B0%E5%AD%97%E5%BE%88%E5%A4%A7%EF%BC%8C%E5%88%86%E5%B8%83%E5%BE%88%E6%95%A3%EF%BC%8C%E6%89%80%E4%BB%A5%E7%94%A8hash%E5%8F%AF%E4%BB%A5%E6%9C%89%E6%95%88%E7%B4%A2%E5%BC%95%E3%80%82%0A%0A%60futex_q%20%60%E6%98%AF%E4%B8%80%E4%B8%AA%E4%B8%B4%E6%97%B6%E5%8F%98%E9%87%8F%EF%BC%8C%E5%AF%B9%E5%BA%94%E4%BA%86%E4%B8%80%E4%B8%AAfutex%E7%9A%84waiter%E7%BA%BF%E7%A8%8B%E3%80%82%E5%AE%83%E9%80%9A%E5%B8%B8%E8%A2%AB%E7%94%A8%E6%9D%A5%E4%BC%A0%E9%80%92%E5%90%84%E7%A7%8D%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E3%80%82%0A%0A%60pi_state%60%E6%98%AF%60task_struct%60%E5%86%85%E9%83%A8%E7%9A%84%E4%B8%80%E4%B8%AA%E5%8F%98%E9%87%8F%EF%BC%8C%E5%9C%A8%60futex_lock_pi%60%E8%B0%83%E7%94%A8%60refill_pi_state_cache%60%E9%87%8C%E9%9D%A2%E5%81%9A%E5%88%86%E9%85%8D%E3%80%82%0A%0A%0A%60%60%60c%0Astatic%20int%20refill_pi_state_cache(void)%0A%7B%0A...%0A%09pi_state%20%3D%20kzalloc(sizeof(*pi_state)%2C%20GFP_KERNEL)%3B%0A%20%20%20%20current-%3Epi_state_cache%20%3D%20pi_state%3B%0A...%0A%7D%0A%60%60%60%0A%23%23%23%20futex_lock_pi%0A%0A%E8%BF%99%E4%B8%AA%E5%87%BD%E6%95%B0%E7%9A%84%E9%80%BB%E8%BE%91%E8%BF%98%E6%98%AF%E6%AF%94%E8%BE%83%E7%9B%B4%E7%BA%BF%E7%9A%84%EF%BC%8C%E5%90%8C%E5%A4%A7%E5%A4%9A%E6%95%B0%E9%94%81%E7%9A%84%E5%AE%9E%E7%8E%B0%E4%B8%80%E6%A0%B7%EF%BC%8C%E5%85%88%E5%B0%9D%E8%AF%95%E5%8E%9F%E5%AD%90%E9%94%81%EF%BC%8C%E5%A6%82%E6%9E%9C%E4%B8%8D%E8%A1%8C%EF%BC%8C%E5%88%99%E8%B0%83%E7%94%A8rt_mutex%E7%9A%84%E5%AE%9E%E7%8E%B0%E6%9D%A5%E5%A4%84%E7%90%86%E4%BC%98%E5%85%88%E7%BA%A7%E7%BB%A7%E6%89%BF%E7%9A%84%E6%9C%BA%E5%88%B6%E3%80%82%E4%BB%A5%E4%B8%8B%E6%8D%A1%E5%8F%96%E6%AF%94%E8%BE%83%E9%87%8D%E8%A6%81%E7%9A%84%E5%87%BD%E6%95%B0%E5%81%9A%E9%98%90%E8%BF%B0%EF%BC%8C%E4%B9%9F%E5%8F%AF%E4%BB%A5%E5%8F%82%E8%80%83%E5%8F%82%E8%80%83%E6%96%87%E7%8C%AE%5C%5B3%5D%2C%20%5C%5B4%5D%E4%B8%AD%E7%9A%84%E6%8F%8F%E8%BF%B0%E3%80%82%0A%0A%23%23%23%23%20queue_lock%2C%20queue_unlock%0A%0A%E5%AF%B9hash_bucket%E8%BF%9B%E8%A1%8C%E9%94%81%E6%93%8D%E4%BD%9C%E3%80%82%E4%BB%96%E4%BB%AC%E6%93%8D%E4%BD%9C%E7%9A%84%E6%98%AF%60hash_bucket%60%E4%B8%8B%E7%9A%84%60lock%60%EF%BC%8C%E5%90%8C%E6%97%B6%E4%B9%9F%E6%98%AF%60futex_q%60%E4%B8%8B%E7%9A%84%60lock_ptr%60%E3%80%82%E8%BF%99%E9%87%8C%E9%94%81%E7%9A%84%E5%87%BA%E7%8E%B0%E6%AF%94%E8%BE%83%E6%B7%B7%E4%B9%B1%EF%BC%8C%E6%9C%89%E6%97%B6%E8%B0%83%E7%94%A8%E4%B8%8A%E9%9D%A2%E7%9A%84%E8%BF%99%E4%B8%A4%E4%B8%AA%E5%87%BD%E6%95%B0%EF%BC%8C%E6%9C%89%E6%97%B6%E7%9B%B4%E6%8E%A5%E5%AF%B9lock%E6%8C%87%E9%92%88%E6%93%8D%E4%BD%9C%E3%80%82%E9%9C%80%E8%A6%81%E5%B0%8F%E5%BF%83%E3%80%82%0A%0A%23%23%23%23%20__queue_me%2C%20unqueue_me%0A%0A%E8%BF%99%E9%87%8C%E5%B0%86%E7%94%B3%E8%AF%B7futex%E7%9A%84%E7%BA%BF%E7%A8%8B%E5%9C%A8hash_bucket%E7%9A%84chain%E4%B8%8A%E5%81%9A%E6%B7%BB%E5%8A%A0%E6%88%96%E7%A7%BB%E9%99%A4%E6%93%8D%E4%BD%9C%E3%80%82%E8%BF%98%E4%BC%9A%E6%B6%89%E5%8F%8A%E9%94%81%E7%9A%84%E6%93%8D%E4%BD%9C%E3%80%82%0A%0A%E4%BB%A5%E4%B8%8A4%E4%B8%AA%E5%87%BD%E6%95%B0%E6%9B%B4%E5%A4%9A%E7%9A%84%E4%B8%8Efutex%E7%9A%84%E5%AE%9E%E7%8E%B0%E7%9B%B8%E5%85%B3%EF%BC%8C%E4%B8%8E%E4%BC%98%E5%85%88%E7%BA%A7%E7%BB%A7%E6%89%BF%E5%B9%B6%E6%97%A0%E5%85%B3%E7%B3%BB%EF%BC%8C%E6%89%80%E4%BB%A5%E5%8F%AF%E4%BB%A5%E7%95%A5%E8%BF%87%E3%80%82%0A%0A%23%23%23%23%20futex_lock_pi_atomic%0A!%5B8f64be7a14c9e36fb86aff8b54e61062.png%5D(evernotecid%3A%2F%2F22617523-9521-4D00-B771-5F27B85F00EB%2Fappyinxiangcom%2F161681%2FENResource%2Fp5792)%0A%0A%0A%E8%BF%99%E4%B8%AA%E5%87%BD%E6%95%B0%E5%81%9A%E7%9A%84%E5%B0%B1%E6%98%AF%E5%8E%9F%E5%AD%90%E6%93%8D%E4%BD%9C%E6%9D%A5%E8%AF%B7%E6%B1%82%E9%94%81%EF%BC%8C%0A%0A-%20%E5%A6%82%E6%9E%9Cfutex%E6%B2%A1%E6%9C%89waiter%EF%BC%8C%E5%88%99%E7%9B%B4%E6%8E%A5%E8%8E%B7%E5%BE%97%E9%94%81%E5%B9%B6%E8%BF%94%E5%9B%9E1%EF%BC%8C%E8%A1%A8%E7%A4%BA%E6%88%90%E5%8A%9F%E8%8E%B7%E5%BE%97%E9%94%81%0A-%20%E5%A6%82%E6%9E%9C%E6%9C%89waiter%EF%BC%8C%E5%B0%B1%E8%BF%94%E5%9B%9E0%EF%BC%8C%E8%A1%A8%E7%A4%BAready%20to%20wait%0A%0A%E8%BF%99%E4%B8%AA%E5%87%BD%E6%95%B0%E4%B8%8D%E5%90%8C%E7%9A%84%E6%98%AF%E4%BC%9A%E5%81%9A%E4%B8%80%E4%BA%9B%E4%B8%8EPI%E7%9B%B8%E5%85%B3%E7%9A%84%E5%A4%84%E7%90%86%EF%BC%9A%0A%0A-%20%E6%9C%89waiter%E7%9A%84%E6%83%85%E5%86%B5%EF%BC%9A%0A%20%20-%20%E8%B0%83%E7%94%A8attach_to_pi_state%E6%9D%A5%E8%8E%B7%E5%BE%97%E8%AF%A5top_waiter%E7%9A%84pi_state%0A-%20%E6%B2%A1%E6%9C%89waiter%E7%9A%84%E6%83%85%E5%86%B5%0A%20%20-%20%E8%B0%83%E7%94%A8attach_to_pi_owner%E6%9D%A5%E5%8F%96%E7%94%A8%E6%9C%AC%E7%BA%BF%E7%A8%8B%E9%87%8C%E5%88%86%E9%85%8D%E7%9A%84pi_state%E7%BB%93%E6%9E%84%E4%BD%93%EF%BC%8C%E5%B9%B6%E6%9B%B4%E6%96%B0%E6%95%B0%E6%8D%AE%E3%80%82%E4%B9%8B%E5%90%8E%EF%BC%8C%E4%BC%9A%E8%A2%ABqueue%E5%88%B0hash_bucket%E7%9A%84%E9%98%9F%E5%88%97%E4%B8%AD%E3%80%82%0A%0A%23%23%23%23%20rt_mutex%E6%8E%A5%E5%8F%A3%0A%0Afutex_lock_pi%E4%B8%AD%E4%BD%BF%E7%94%A8%E5%88%B0%E5%A6%82%E4%B8%8B%E8%BF%99%E4%BA%9Brt_mutex%E6%8E%A5%E5%8F%A3%EF%BC%9A%0A%0A-%20rt_mutex_init_waiter%EF%BC%9A%E5%88%9D%E5%A7%8B%E5%8C%96waiter%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%EF%BC%8C%E5%85%B6%E5%AE%9E%E4%B8%BA%E4%B8%80%E4%B8%AA%E7%BA%A2%E9%BB%91%E6%A0%91%E7%9A%84%E8%8A%82%E7%82%B9%E3%80%82%E8%BF%99%E4%B8%AAwaiter%E5%AF%B9%E5%BA%94%E5%BD%93%E5%89%8D%E7%BA%BF%E7%A8%8B%EF%BC%8C%E5%B9%B6%E5%8F%8D%E6%98%A0%E7%BA%BF%E7%A8%8B%E5%9C%A8%E6%9F%90%E4%B8%AA%E9%94%81%E4%B8%8A%E7%9A%84%E7%AD%89%E5%BE%85%E5%85%B3%E7%B3%BB%E3%80%82%0A-%20__rt_mutex_start_proxy_lock%EF%BC%9A%E8%BF%99%E4%B8%AA%E6%98%AFPI%E7%9A%84%E6%A0%B8%E5%BF%83%E5%87%BD%E6%95%B0%EF%BC%8C%E7%94%A8%E6%9D%A5%E5%AF%B9%E5%90%84waiters%E6%95%B0%E6%8D%AE%E8%BF%9B%E8%A1%8C%E6%93%8D%E4%BD%9C%EF%BC%8C%E4%BB%A5%E5%8F%8A%E9%81%8D%E5%8E%86lock%E9%93%BE%E6%9D%A5%E6%A3%80%E6%9F%A5%E6%AD%BB%E9%94%81%E3%80%82%E8%BF%99%E4%B8%AA%E5%87%BD%E6%95%B0%E4%B8%8E%E4%B9%8B%E5%89%8D%E7%9A%84%E5%8E%9F%E5%AD%90%E6%A3%80%E6%9F%A5%E7%B1%BB%E4%BC%BC%EF%BC%8C%E5%A6%82%E6%9E%9C%E8%BF%94%E5%9B%9E1%E8%A1%A8%E7%A4%BA%E5%B7%B2%E7%BB%8F%E8%8E%B7%E5%BE%97%E9%94%81%EF%BC%8C%E5%A6%82%E6%9E%9C%E8%BF%94%E5%9B%9E0%EF%BC%8C%E5%88%99ready%20to%20wait%E3%80%82%0A-%20rt_mutex_wait_proxy_lock%EF%BC%9A%E9%80%9A%E8%BF%87__rt_mutex_start_proxy_lock%E5%A4%84%E7%90%86%E4%B9%8B%E5%90%8E%EF%BC%8C%E5%A6%82%E6%9E%9C%E8%BF%98%E6%B2%A1%E6%9C%89%E8%8E%B7%E5%BE%97%E9%94%81%EF%BC%8C%E9%82%A3%E5%B0%B1%E5%8F%AF%E4%BB%A5%E5%BC%80%E5%A7%8B%E7%AD%89%E5%BE%85%E4%BA%86%EF%BC%8C%E8%BF%99%E4%B8%AA%E5%87%BD%E6%95%B0%E5%B0%86%E7%BA%BF%E7%A8%8B%E5%88%87%E6%8D%A2%E4%B8%BATASK_INTERRUPTIBLE%E7%8A%B6%E6%80%81%EF%BC%8C%E5%B9%B6%E5%BC%80%E5%A7%8B%E7%AD%89%E5%BE%85%E3%80%82%E8%BF%99%E5%85%B6%E9%97%B4%E4%BC%9A%E5%A4%84%E7%90%86%E5%9F%BA%E4%BA%8E%E6%97%B6%E9%97%B4%E7%9A%84%E7%AD%89%E5%BE%85%EF%BC%8C%E4%B8%94%E4%BC%9A%E8%A7%A6%E5%8F%91%E8%B0%83%E5%BA%A6%E3%80%82%0A-%20rt_mutex_cleanup_proxy_lock%EF%BC%9A%E7%8E%B0%E5%9C%A8%E5%B7%B2%E7%BB%8F%E9%98%BB%E5%A1%9E%E7%BB%93%E6%9D%9F%E4%BA%86%EF%BC%8C%E5%A6%82%E6%9E%9C%E8%BF%98%E6%B2%A1%E8%8E%B7%E5%BE%97%E9%94%81%EF%BC%8C%E8%A6%81%E4%B9%88%E6%98%AF%E8%B6%85%E6%97%B6%EF%BC%8C%E8%A6%81%E4%B9%88%E6%98%AF%E5%87%BA%E9%94%99%EF%BC%8C%E6%80%BB%E4%B9%8B%E8%A6%81%E5%B0%86%E6%9C%AC%E7%BA%BF%E7%A8%8B%E4%BB%8Ewaiters%E4%B8%AD%E7%A7%BB%E9%99%A4%EF%BC%8C%E8%BF%99%E4%B8%AA%E5%87%BD%E6%95%B0%E5%B0%B1%E6%98%AF%E8%B5%B7%E8%BF%99%E4%B8%AA%E4%BD%9C%E7%94%A8%E3%80%82%0A%0A%23%23%23%23%20fixup_owner%0A%0A%E4%BB%8E%E6%B3%A8%E9%87%8A%E4%B8%8A%E7%9C%8B%EF%BC%8C%E6%98%AF%E4%B8%BA%E4%BA%86%E5%A4%84%E7%90%86lock%20steal%E3%80%82%E8%80%8Clock%20steal%E4%BC%BC%E4%B9%8E%E5%A4%9A%E5%8F%91%E7%94%9F%E5%9C%A8futex%20requeue%E6%93%8D%E4%BD%9C%E4%B8%8A%EF%BC%8C%E7%9B%AE%E5%89%8D%E5%B0%9A%E6%9C%AA%E4%BB%94%E7%BB%86%E7%A0%94%E7%A9%B6%E3%80%82%0A%0A%23%23%23%20futex_unlock_pi%0A%0Afutex_unlock_pi%E9%87%8A%E6%94%BEfutex%E4%BB%A5%E5%8F%8A%E6%9B%B4%E6%96%B0%E7%9B%B8%E5%BA%94%E7%9A%84pi_state%E5%92%8Crt_mutex%E7%9A%84owner%E5%AD%97%E6%AE%B5%E3%80%82%E5%87%BD%E6%95%B0%E8%B0%83%E7%94%A8%E5%B1%82%E6%AC%A1%E6%AF%94%E8%BE%83%E6%B7%B1%EF%BC%8C%E5%9F%BA%E6%9C%AC%E4%B8%8A%E9%83%BD%E6%98%AF%E6%AF%8F%E4%B8%80%E5%B1%82%E5%81%9A%E4%B8%80%E4%BA%9B%E5%9F%BA%E6%9C%AC%E7%9A%84%E6%9B%B4%E6%96%B0%E5%B7%A5%E4%BD%9C%EF%BC%8C%E6%9C%80%E7%BB%88%E8%B0%83%E7%94%A8%E5%88%B0__rt_mutex_futex_unlock%E6%9D%A5%E9%87%8D%E6%96%B0%E8%B0%83%E6%95%B4%E6%9C%AC%E7%BA%BF%E7%A8%8B%E7%9A%84%E4%BC%98%E5%85%88%E7%BA%A7%EF%BC%8C%E5%B9%B6%E5%B0%86top%20waiter%E6%94%BE%E5%88%B0wake%20queue%E4%B8%8A%E3%80%82%E5%9C%A8rt_mutex_postunlock%E8%B0%83%E7%94%A8%E7%9A%84rt_mutex_postunlock%E5%B0%86%E6%96%B0%E7%BA%BF%E7%A8%8B%E5%94%A4%E9%86%92%E3%80%82%0A%0A%E5%A6%82%E6%9E%9C%E6%B2%A1%E6%9C%89waiter%EF%BC%8C%E5%88%99%E4%BD%BF%E7%94%A8%60cmpxchg_futex_value_locked%60%E6%9D%A5%E5%B0%86%E7%94%A8%E6%88%B7%E6%80%81%E5%9C%B0%E5%9D%80uaddr%E4%B8%8A%E7%9A%84%E5%80%BC%E8%AE%BE%E4%B8%BA0%E3%80%82%E5%9B%A0%E4%B8%BA%E9%94%81%E6%B2%A1%E6%9C%89waiter%E4%BA%86%EF%BC%8C%E6%89%80%E4%BB%A5%E4%BC%98%E5%85%88%E7%BA%A7%E4%B9%9F%E4%B8%8D%E9%9C%80%E8%A6%81%E6%81%A2%E5%A4%8D%E4%BA%86%EF%BC%8C%E6%88%96%E8%80%85%E5%B7%B2%E7%BB%8F%E6%81%A2%E5%A4%8D%E8%BF%87%E4%BA%86%E3%80%82%0A%0A%E5%A6%82%E6%9E%9C%E6%9C%89waiter%EF%BC%8C%E5%B0%B1%E4%BD%BF%E7%94%A8%E4%B8%8B%E9%9D%A2%E5%87%A0%E4%B8%AA%E5%87%BD%E6%95%B0%E6%9D%A5%E5%88%87%E6%8D%A2lock%20owner%EF%BC%8C%E5%B9%B6%E6%81%A2%E5%A4%8D%E4%BC%98%E5%85%88%E7%BA%A7%E7%BB%A7%E6%89%BF%E7%9A%84%E4%BC%98%E5%85%88%E7%BA%A7%E3%80%82%0A%0A%23%23%23%23%20wake_futex_pi%0A%0A%E8%BF%99%E4%B8%AA%E5%87%BD%E6%95%B0%E5%81%9A%E4%BA%86%E4%B8%8B%E9%9D%A2%E5%87%A0%E4%BB%B6%E4%BA%8B%EF%BC%9A%0A%0A1.%20%E7%94%A8cmpxchg_futex_value_locked%E5%B0%86%E7%94%A8%E6%88%B7%E6%80%81%E4%BC%A0%E5%85%A5%E7%9A%84uaddr%E5%A4%84%E7%9A%84%E6%95%B0%E5%80%BC%E6%9B%B4%E6%96%B0%E4%B8%BA%E6%96%B0%E7%9A%84%60rt_mutex_next_owner()%20%7C%20FUTEX_WAITERS%60%0A2.%20%60list_del_init(%26pi_state-%3Elist)%60%EF%BC%9A%E5%B0%86list%E4%BB%8E%E5%8E%9F%E5%85%88%E7%9A%84%E8%A1%A8%E4%B8%8A%E5%88%A0%E9%99%A4%EF%BC%8C%E5%B9%B6%E9%87%8D%E6%96%B0%E5%88%9D%E5%A7%8B%E5%8C%96%EF%BC%8C%E5%87%86%E5%A4%87%E7%A7%BB%E5%88%B0%E5%85%B6%E4%BB%96%E7%9A%84%E8%A1%A8%E4%B8%8A%E3%80%82%0A3.%20%60list_add(%26pi_state-%3Elist%2C%20%26new_owner-%3Epi_state_list)%60%0A4.%20%60pi_state-%3Eowner%20%3D%20new_owner%60%0A5.%20%60__rt_mutex_futex_unlock%60%0A6.%20%60rt_mutex_postunlock%60%0A%0A%23%23%23%23%20mark_wakeup_next_waiter%0A%0A%E6%B3%A8%E6%84%8F%EF%BC%9A%E6%AD%A4%E6%97%B6pi_state-%3Eowner%E5%B7%B2%E7%BB%8F%E8%AE%BE%E7%BD%AE%E8%BF%87%E4%BA%86%EF%BC%8C%E4%BD%86%E6%98%AFpi_state-%3Epi_mutex-%3Eowner%E8%BF%98%E6%B2%A1%E6%9C%89%E8%AE%BE%E7%BD%AE%E3%80%82%E8%BF%99%E4%B8%AA%E5%87%BD%E6%95%B0%E4%B8%BB%E8%A6%81%E5%81%9A%E4%BA%86%E4%B8%8B%E9%9D%A2%E5%87%A0%E4%BB%B6%E4%BA%8B%E6%83%85%EF%BC%9A%0A%0A1.%20%60rt_mutex_dequeue_pi(current%2C%20waiter)%3B%60%0A2.%20%60rt_mutex_adjust_prio(current)%60%3A%E5%9C%A8%E8%BF%99%E9%87%8C%E8%B0%83%E6%95%B4%E4%BA%86%E5%BD%93%E5%89%8D%E7%BA%BF%E7%A8%8B%E7%9A%84%E4%BC%98%E5%85%88%E7%BA%A7%EF%BC%8C%E5%AE%8C%E6%88%90%E4%BA%86%E6%95%B4%E4%B8%AA%E4%BC%98%E5%85%88%E7%BA%A7%E7%BB%A7%E6%89%BF%E5%8D%8F%E8%AE%AE%E3%80%82%0A3.%20%60wake_q_add(wake_q%2C%20waiter-%3Etask)%60%0A%0A%23%23%23%23%20put_pi_state%0A%0A%E8%BF%99%E4%B8%AA%E5%87%BD%E6%95%B0%E6%9B%B4%E5%A4%9A%E7%9A%84%E6%98%AF%E6%B8%85%E7%90%86%E5%B7%A5%E4%BD%9C%3A%0A%0A1.%20%E8%B0%83%E7%94%A8%E4%BA%86%60rt_mutex_proxy_unlock%60%E6%9D%A5%E9%87%8A%E6%94%BEpi_state-%3Epi_mutex.%0A2.%20%E9%87%8A%E6%94%BE%E4%BA%86current-%3Epi_state_cache%E7%A9%BA%E9%97%B4%0A%0A%3E**cmpxchg_futex_value_locked%E5%8E%9F%E5%AD%90%E6%93%8D%E4%BD%9C**%0A%3E%0A%3E%60%60%60c%0A%3Estatic%20int%20cmpxchg_futex_value_locked(u32%20*uval%2C%20u32%20__user%20*uaddr%2C%0A%3E%E2%80%BA%20%20%20%E2%80%BA%20%20%20%E2%80%BA%20%20%20%E2%80%BA%20%20%20%20%20%20%20%20%20u32%20oldval%2C%20u32%20newval)%0A%3E%7B%0A%3EATOMIC()%3B%0A%3Eint%20val%20%3D%20*uaddr%3B%0A%3Eif%20(val%20%3D%3D%20oldval)%20%7B%0A%3E*uaddr%20%3D%20newval%3B%0A%3E%7D%0A%3E*uval%20%3D%20val%3B%0A%3EEND_ATOMIC()%3B%0A%3Ereturn%200%3B%0A%3E%7D%0A%3E%0A%3E%E5%85%B6%E4%B8%ADATOMIC%E6%93%8D%E4%BD%9C%E9%80%9A%E8%BF%87page_disable()%E5%92%8Cpreempt_disable()%E4%BF%9D%E8%AF%81%E3%80%82%0A%3E%60%60%60%0A%0A%23%23%20__rt_mutex_start_proxy_lock%0A%0A%E4%BB%8E%E4%B8%8A%E9%9D%A2futex_lock_pi%E7%94%A8%E5%88%B0%E7%9A%84rt_mutex%E6%8E%A5%E5%8F%A3%E4%BB%8B%E7%BB%8D%E4%B8%AD%E5%8F%AF%E7%9F%A5%EF%BC%8C%E8%BF%99%E4%B8%AA%E5%87%BD%E6%95%B0%E6%98%AF%E6%95%B4%E4%B8%AAPI%E5%A4%84%E7%90%86%E7%9A%84%E6%A0%B8%E5%BF%83%EF%BC%8C%E8%BF%99%E4%B8%AA%E5%87%BD%E6%95%B0%E5%8F%88%E4%B8%BB%E8%A6%81%E8%B0%83%E7%94%A8task_blocks_on_rt_mutex%E6%9D%A5%E5%A4%84%E7%90%86PI%E3%80%82%0A%0A!%5B692787b6adf4be8b04b3aa57c3612c37.png%5D(evernotecid%3A%2F%2F22617523-9521-4D00-B771-5F27B85F00EB%2Fappyinxiangcom%2F161681%2FENResource%2Fp5793)%0A%0A%0A%23%23%23%23%20rt_mutex_adjust_prio(owner)%0A%0A%E8%BF%99%E4%B8%AA%E5%87%BD%E6%95%B0%E5%B0%B1%E6%98%AF%E8%B0%83%E6%95%B4%E9%98%BB%E5%A1%9E%E7%BA%BF%E7%A8%8B%E7%9A%84%E4%BC%98%E5%85%88%E7%BA%A7%EF%BC%8C%E4%BB%8E%E8%80%8C%E5%AE%9E%E7%8E%B0%E4%BC%98%E5%85%88%E7%BA%A7%E7%BB%A7%E6%89%BF%E7%9A%84%E3%80%82%E5%AE%9E%E7%8E%B0%E6%96%B9%E5%BC%8F%E4%B9%9F%E5%BE%88%E7%AE%80%E5%8D%95%EF%BC%9A%0A%0A%60%60%60c%0Aif%20(task_has_pi_waiters(p))%0A%E2%80%BA%20%20%20pi_task%20%3D%20task_top_pi_waiter(p)-%3Etask%3B%0A%0Art_mutex_setprio(p%2C%20pi_task)%3B%0A%60%60%60%0A%0A%E6%8A%8Aowner%E7%BA%BF%E7%A8%8B%E8%AE%BE%E7%BD%AE%E4%B8%BAowner%E7%BA%BF%E7%A8%8B%E6%89%80%E6%9C%89waiter(%E5%8F%AF%E8%83%BD%E6%9D%A5%E8%87%AA%E5%A4%9A%E4%B8%AA%E9%94%81)%E7%9A%84%E6%9C%80%E9%AB%98%E4%BC%98%E5%85%88%E7%BA%A7%E3%80%82%0A%0A%23%23%23%23%20rt_mutex_adjust_prio_chain%0A%0A%23%23%23%23%23%20%E4%B8%BA%E4%BB%80%E4%B9%88%E6%9C%89%E8%BF%99%E4%B8%AA%E9%93%BE%E5%BC%8F%E8%B0%83%E6%95%B4%EF%BC%9F%0A!%5Bc4badef8862a4db7fb98b88635d31ecb.png%5D(evernotecid%3A%2F%2F22617523-9521-4D00-B771-5F27B85F00EB%2Fappyinxiangcom%2F161681%2FENResource%2Fp5794)%0A%0A%E8%BF%99%E9%87%8C%E6%9C%89%E4%B8%A4%E5%BC%A0%E8%A1%A8%E6%A0%BC%EF%BC%9A%0A%0A-%20%E6%AF%8F%E4%B8%AArt_mutex%E6%9C%89%E5%BC%A0waiters%E8%A1%A8%E6%A0%BC%EF%BC%8C%E8%A1%A8%E7%A4%BA%E6%89%80%E6%9C%89%E7%AD%89%E5%BE%85%E7%9A%84%E7%BA%BF%E7%A8%8B%0A%0A-%20%E6%AF%8F%E4%B8%AAtask%E4%B9%9F%E6%9C%89%E5%BC%A0%E8%A1%A8%E6%A0%BC%EF%BC%8C%E8%A1%A8%E6%A0%BC%E9%87%8C%E7%9A%84%E6%AF%8F%E4%B8%80%E9%A1%B9%E5%AF%B9%E5%BA%94owner%E7%BA%BF%E7%A8%8B%E5%8D%A0%E6%9C%89%E7%9A%84%E9%94%81%EF%BC%8C%E6%AF%8F%E4%B8%80%E9%A1%B9%E6%98%AF%E4%B8%80%E4%B8%AArt_mutex_waiter%EF%BC%8C%E8%A1%A8%E7%A4%BA%E7%94%B3%E8%AF%B7%E8%AF%A5%E9%94%81%E7%9A%84%E6%9C%80%E9%AB%98%E4%BC%98%E5%85%88%E7%BA%A7waiter%0A%0A%E5%81%87%E8%AE%BETask1%E5%B0%B1%E6%98%AFowner%EF%BC%8CTask0%E5%AF%B9Lock0%E7%9A%84%E7%94%B3%E8%AF%B7%E5%AF%BC%E8%87%B4Task1%E6%8F%90%E5%8D%87%E4%BC%98%E5%85%88%E7%BA%A7%EF%BC%8C%E5%A6%82%E6%9E%9CTask1%E5%90%8C%E6%97%B6%E8%A2%ABTask2%E6%8C%81%E6%9C%89%E7%9A%84%E6%9F%90%E4%B8%AA%E9%94%81%E9%98%BB%E5%A1%9E%EF%BC%8C%E5%88%99Task1%E4%BC%98%E5%85%88%E7%BA%A7%E7%9A%84%E6%94%B9%E5%8F%98%EF%BC%8C%E6%9C%89%E5%8F%AF%E8%83%BD%E4%BC%9A%E5%AF%BC%E8%87%B4Task2%20pi_waiters%E5%88%97%E8%A1%A8%E6%94%B9%E5%8F%98%EF%BC%8C%E5%90%8C%E6%97%B6%E5%8F%AF%E8%83%BD%E5%AF%BC%E8%87%B4Task2%E4%BC%98%E5%85%88%E7%BA%A7%E6%94%B9%E5%8F%98%E3%80%82%E4%BE%9D%E6%AD%A4%E7%B1%BB%E6%8E%A8%EF%BC%8C%E5%B0%B1%E4%BC%9A%E5%AF%BC%E8%87%B4%E4%B8%8A%E9%9D%A2%E7%9A%84%E8%BF%99%E7%A7%8D%E9%93%BE%E5%BC%8F%E5%8F%8D%E5%BA%94%E3%80%82%0A%0A%0A%0A%23%23%23%23%23%20%E9%93%BE%E5%A4%84%E7%90%86%E6%B5%81%E7%A8%8B%0A%E6%95%B4%E4%B8%AAchain%E7%9A%84%E5%A4%84%E7%90%86%E6%B5%81%E7%A8%8B%E5%A4%A7%E8%87%B4%E5%A6%82%E4%B8%8B%EF%BC%9A%0A%0A1.%20%E5%A6%82%E6%9E%9CTask0%E6%98%AFLock0%E7%9A%84top%20waiter%EF%BC%8C%E5%88%99%E6%BF%80%E5%8F%91%E8%AF%A5%E9%93%BE%E5%BC%8F%E8%B0%83%E6%95%B4%E3%80%82%0A2.%20%E5%9B%A0%E4%B8%BATask0%E6%88%90%E4%B8%BALock0%E7%9A%84topwaiter%EF%BC%8C%E5%88%99Task1%E7%9A%84pi_waiters%E9%9C%80%E8%A6%81%E8%B0%83%E6%95%B4%EF%BC%8C%E5%88%99Task1%E7%9A%84%E4%BC%98%E5%85%88%E7%BA%A7%E5%8F%AF%E8%83%BD%E9%9C%80%E8%A6%81%E8%B0%83%E6%95%B4%E3%80%82%E9%80%80%E5%87%BA%E5%8F%AF%E8%83%BD%EF%BC%9A%0A%20%20%20%20-%20%E8%B5%B7%E7%82%B9%E9%94%81%E9%87%8A%E6%94%BE%E4%BA%86%0A%0A%20%20%20%20-%20%E9%93%BE%E7%9A%84%E5%BD%93%E5%89%8D%E7%8E%AF%E8%8A%82%E8%A2%AB%E6%9B%B4%E6%94%B9(%20next_lock%20%E2%89%A0waiter-%3Elock)%0A%0A%20%20%20%20-%20Task1%E6%B2%A1%E6%9C%89%E5%8D%A0%E9%94%81%0A3.%20%E5%A6%82%E6%9E%9CTask1%E4%B9%9Fwait%E5%9C%A8%E6%9F%90%E4%B8%AAlock%E7%9A%84%E6%97%B6%E5%80%99%EF%BC%8C%E5%88%99%E8%AF%A5lock%E7%9A%84waiters%E9%9C%80%E8%A6%81%E8%B0%83%E6%95%B4%EF%BC%8C%E8%BF%99%E9%87%8C%E6%9C%89%E8%8B%A5%E5%B9%B2%E7%A7%8D%E9%80%80%E5%87%BA%E5%8F%AF%E8%83%BD%E3%80%82%0A%0A%20%20-%20Task1%E6%B2%A1%E6%9C%89%E8%A2%ABblock%0A%20%20-%20Task1%20pi_waiters%E4%B8%AD%E6%9C%89%E4%BC%98%E5%85%88%E7%BA%A7%E9%AB%98%E4%BA%8ETask0%E7%9A%84waiter%EF%BC%8C%E6%8D%A2%E5%8F%A5%E8%AF%9D%E8%AF%B4%EF%BC%8Clock0%E7%9A%84top_waiter%E4%B8%8D%E6%98%AFTask1%E7%9A%84top%20pi_waiter%EF%BC%8C%E4%BC%98%E5%85%88%E7%BA%A7%E7%BB%A7%E6%89%BF%E4%B8%8D%E9%9C%80%E8%A6%81%E7%BB%A7%E7%BB%AD%E4%BC%A0%E9%80%92%20%0A%20%20-%20%E5%A6%82%E6%9E%9CTask1%E5%9C%A8%E7%94%B3%E8%AF%B7Lock1%20%E7%9A%84%E6%97%B6%E5%80%99%E7%9A%84%E4%BC%98%E5%85%88%E7%BA%A7%EF%BC%88%E8%BF%99%E4%B8%AA%E8%AE%B0%E5%BD%95%E5%9C%A8waiter-%3Eprio%E9%87%8C%EF%BC%89%E4%B8%8E%E5%BD%93%E5%89%8D%E8%B0%83%E6%95%B4%E5%90%8E%E7%9A%84%E4%BC%98%E5%85%88%E7%BA%A7%E7%9B%B8%E7%AD%89%EF%BC%8C%E5%88%99%E5%90%8E%E7%BB%AD%E6%B2%A1%E5%BF%85%E8%A6%81%E5%9C%A8%E7%BB%A7%E7%BB%AD%E8%B0%83%E6%95%B4%E4%BC%98%E5%85%88%E7%BA%A7%0A%20%20-%20%E6%A3%80%E6%B5%8B%E5%88%B0DEADLOCK%0A4.%20%E5%9B%9E%E5%88%B01%E7%BB%A7%E7%BB%AD%E6%89%A7%E8%A1%8C%EF%BC%8C%E7%9B%B4%E5%88%B0%E9%80%80%E5%87%BA%E9%93%BE%E5%BC%8F%E5%A4%84%E7%90%86%0A%0A%23%23%23%23%23%20%E6%AD%BB%E9%94%81%0A%0A%E6%9C%893%E7%A7%8D%E6%83%85%E5%86%B5%EF%BC%8C%E5%87%BD%E6%95%B0%E4%BC%9A%E8%BF%94%E5%9B%9E%E6%AD%BB%E9%94%81%0A%0A-%20%E9%93%BE%E4%B8%8A%E8%B6%85%E8%BF%871024%E4%B8%AA%E9%94%81%E8%8A%82%E7%82%B9%0A-%20%E9%93%BE%E4%B8%8A%E4%BB%BB%E6%84%8FTask%E8%8A%82%E7%82%B9%E7%94%B3%E8%AF%B7%E7%AC%AC%E4%B8%80%E4%B8%AA%E9%94%81%E8%8A%82%E7%82%B9%EF%BC%8C%E5%8D%B3Lock0%0A-%20%E9%93%BE%E4%B8%8A%E4%BB%BB%E6%84%8F%E4%B8%80%E4%B8%AA%E9%94%81owner%E6%98%AF%E7%AC%AC%E4%B8%80%E4%B8%AATask%E8%8A%82%E7%82%B9%EF%BC%8C%E5%8D%B3Task0%0A%0A%0A%23%23%20%E5%8F%82%E8%80%83%E6%96%87%E7%8C%AE%0A%0A%5C%5B1%5D%20%5BMutex%20mutandis%3A%20understanding%20mutex%20types%20and%20attributes%5D.%20(http%3A%2F%2F2net.co.uk%2Ftutorial%2Fmutex_mutandis)%0A%0A%5C%5B2%5D%20%5BPOSIX%20Revision%20of%20IEEE%20Std%201003.1-2008%5D(http%3A%2F%2Fpubs.opengroup.org%2Fonlinepubs%2F9699919799%2Ffunctions%2Fcontents.html)%0A%0A%5C%5B3%5D%20%5BSource%20code%20analysis%20of%20pthread_mutex_lock%5D(https%3A%2F%2Fzihan.me%2F2018%2F08%2F15%2Fsource-code-analysis-pthread-mutex-lock%2F)%0A%0A%5C%5B4%5D%20%5Blinux%20pi_futex%E6%B5%85%E6%9E%90%5D(https%3A%2F%2Fyq.aliyun.com%2Farticles%2F6044)%0A%0A%5C%5B5%5D%20Linux%204.20-rc3%20source%20code%0A%0A%5C%5B6%5D%20glibc%202.28%20source%20code%0A