android mutex 详细介绍

来源:互联网 发布:sor文件打开软件 编辑:程序博客网 时间:2024/06/02 00:59

一个进程中不可能只有一个线程在战斗,所以一个进程中一般都是有多个线程的同时协助工作,多线程情况下,对于一些全局变量,也就是多个线程能够同时访问的变量,我们需要通过加锁来防止“同时”访问这个变量,Mutex 就是我们常用的一个。

frameworks/av/include/camera/CameraBase.h

113      Mutex                            mLock;
frameworks/av/camera/Camera.cpp

214  void Camera::stopRecording()215  {216      ALOGV("stopRecording");217      {218          Mutex::Autolock _l(mLock);219          mRecordingProxyListener.clear();220      }221      sp <::android::hardware::ICamera> c = mCamera;222      if (c == 0) return;223      c->stopRecording();224  }
例如上面的代码,首先会定义一个Mutex 对象mLock,在代码中对全局变量访问时,先要获取mLock,例如上面在操作mRecordingProxyListener 时,先通过Mutex::Autolock _l(mLock);获取这把锁,加了大括号是限制这个锁的作用域,离开这个作用域之后,这把锁会自动释放,下面会介绍。

system/core/include/utils/Mutex.h

100   pthread_mutex_t mMutex;
111  inline Mutex::Mutex() {112      pthread_mutex_init(&mMutex, NULL);113  }83      class Autolock {84      public:85          inline Autolock(Mutex& mutex) : mLock(mutex)  { mLock.lock(); }86          inline Autolock(Mutex* mutex) : mLock(*mutex) { mLock.lock(); }87          inline ~Autolock() { mLock.unlock(); }88      private:89          Mutex& mLock;90      };131  inline status_t Mutex::lock() {132      return -pthread_mutex_lock(&mMutex);133  }134  inline void Mutex::unlock() {135      pthread_mutex_unlock(&mMutex);136  }128  inline Mutex::~Mutex() {129      pthread_mutex_destroy(&mMutex);130  }
通过上面的代码我们知道 Mutex::Autolock _l(mLock) 获取锁和释放锁 是利用了C++ 类的构造函数和析构函数的特性实现的。在.h头文件里面定义 Mutex    mLock; 的时候就已经调用了Mutex   的构造函数,进而调用到pthread_mutex_init()初始化pthread_mutex_t mMutex;  而Mutex::Autolock _l(mLock); 放在函数里面定义,是一个局部变量,也会调用Autolock 的构造函数,进而调用到Mutex::lock();  Autolock 对象 _l 跑出大括号后,也就是跑出它的作用域后,会调用它的析构函数,进而调用到Mutex::unlock() 释放锁。

Mutex 只是对对pthread_mutex_xxx()接口做了一层封装而已,真正的实现在pthread_mutex_xxx()接口。
pthread_mutex_xxx()声明在bionic/libc/include/pthread.h

39  typedef struct {40  #if defined(__LP64__)41    int32_t __private[10];  //长度为10的整形数组42  #else43    int32_t __private[1];  //长度为1 的整形数组44  #endif45  } pthread_mutex_t;

1、初始化函数pthread_mutex_init()

 bionic/libc/bionic/pthread_mutex.cpp

241  int pthread_mutex_init(pthread_mutex_t* mutex_interface, const pthread_mutexattr_t* attr) {/* *   struct pthread_mutex_internal_t { *    _Atomic(uint16_t) state;  //2 byte *  #if defined(__LP64__)  //64为定义是长度为10的整形数组, 40 byte *    uint16_t __pad;       //2 byte *    atomic_int owner_tid; //4 byte *    char __reserved[32];  //32 byte *  #else                  //长度为1 的整形数组, 4 byte *    _Atomic(uint16_t) owner_tid; //2 byte *  #endif *  } __attribute__((aligned(4)));*/242      pthread_mutex_internal_t* mutex = __get_internal_mutex(mutex_interface);243  244      memset(mutex, 0, sizeof(pthread_mutex_internal_t));  //mutex 所有byte设置为 0245  246      if (__predict_true(attr == NULL)) {  //没有设置相关属性时247          atomic_init(&mutex->state, MUTEX_TYPE_BITS_NORMAL);  //mutex->state = (((0) & ((1 << (2))-1)) << (14)) 也就是0248          return 0;249      }...    //因为针对上面的实现传入的attr 为NULL,所以这部分的代码先不做分析272      return 0;273  }

2、获取锁函数pthread_mutex_lock()
bionic/libc/bionic/pthread_mutex.cpp
503  int pthread_mutex_lock(pthread_mutex_t* mutex_interface) {504  #if !defined(__LP64__)  //非64为系统505      if (mutex_interface == NULL) {506          return EINVAL;507      }508  #endif509  510      pthread_mutex_internal_t* mutex = __get_internal_mutex(mutex_interface);511  512      uint16_t old_state = atomic_load_explicit(&mutex->state, memory_order_relaxed); //old_state = mutex->state513      uint16_t mtype = (old_state & MUTEX_TYPE_MASK);   //mtype =old_state &(((1 << (2))-1) << (14)) 也就是mtype =old_state & 49152514      uint16_t shared = (old_state & MUTEX_SHARED_MASK);//shared =old_state &(((1 << (1))-1) << (13)) 也就是shared =old_state & 8192515      // Avoid slowing down fast path of normal mutex lock operation.516      if (__predict_true(mtype == MUTEX_TYPE_BITS_NORMAL)) {  //MUTEX_TYPE_BITS_NORMAL =0517        if (__predict_true(__pthread_normal_mutex_trylock(mutex, shared) == 0)) {518          return 0;  519        }520      }521      return __pthread_mutex_lock_with_timeout(mutex, false, nullptr);522  }
pthread_mutex_lock() 先判断 是否可以直接获取锁,没有其他线程在使用的时候可以获取,通过__pthread_normal_mutex_trylock()来实现


275  static inline __always_inline int __pthread_normal_mutex_trylock(pthread_mutex_internal_t* mutex,276                                                                   uint16_t shared) {277      const uint16_t unlocked           = shared | MUTEX_STATE_BITS_UNLOCKED;  //MUTEX_STATE_BITS_UNLOCKED = 0278      const uint16_t locked_uncontended = shared | MUTEX_STATE_BITS_LOCKED_UNCONTENDED; //MUTEX_STATE_BITS_LOCKED_UNCONTENDED = 16384279  280      uint16_t old_state = unlocked;         //如果 mutex->state == old_state, mutex->state = locked_uncontended         //否则 mutex->state = old_state281      if (__predict_true(atomic_compare_exchange_strong_explicit(&mutex->state, &old_state, //282                           locked_uncontended, memory_order_acquire, memory_order_relaxed))) {283          return 0;  284      }285      return EBUSY;286  }
__pthread_normal_mutex_trylock()会判读mutex->state 是否等于old_state,如果相等 ,将 mutex->state 的值设置成 locked_uncontended,否则设置成old_state 。

如果获取不到这个锁,就会往下走到__pthread_mutex_lock_with_timeout()。

421  static int __pthread_mutex_lock_with_timeout(pthread_mutex_internal_t* mutex,422                                               bool use_realtime_clock,423                                               const timespec* abs_timeout_or_null) {424      uint16_t old_state = atomic_load_explicit(&mutex->state, memory_order_relaxed); //old_state = mutex->state425      uint16_t mtype = (old_state & MUTEX_TYPE_MASK); //mtype =old_state &(((1 << (2))-1) << (14)) 也就是mtype =old_state & 49152426      uint16_t shared = (old_state & MUTEX_SHARED_MASK); //shared =old_state &(((1 << (1))-1) << (13)) 也就是shared =old_state & 8192427  428      // Handle common case first.429      if ( __predict_true(mtype == MUTEX_TYPE_BITS_NORMAL) ) {  //MUTEX_TYPE_BITS_NORMAL = 0430          return __pthread_normal_mutex_lock(mutex, shared, use_realtime_clock, abs_timeout_or_null);431      }...     //我们重点关注实现的流程,其他额外处理部分的代码先不分析501  }
接着走到__pthread_normal_mutex_lock(), 传入的参数use_realtime_clock 为false,abs_timeout_or_null 为 nullptr

static inline __always_inline int __pthread_normal_mutex_lock(pthread_mutex_internal_t* mutex,301                                                                uint16_t shared,302                                                                bool use_realtime_clock,303                                                                const timespec* abs_timeout_or_null) {304      if (__predict_true(__pthread_normal_mutex_trylock(mutex, shared) == 0)) {  //前面解释过了305          return 0;306      }307      int result = check_timespec(abs_timeout_or_null, true); //这里会返回 0308      if (result != 0) {309          return result;310      }311  312      ScopedTrace trace("Contending for pthread mutex");313  314      const uint16_t unlocked           = shared | MUTEX_STATE_BITS_UNLOCKED;315      const uint16_t locked_contended = shared | MUTEX_STATE_BITS_LOCKED_CONTENDED;316  317      // We want to go to sleep until the mutex is available, which requires318      // promoting it to locked_contended. We need to swap in the new state319      // and then wait until somebody wakes us up.320      // An atomic_exchange is used to compete with other threads for the lock.321      // If it returns unlocked, we have acquired the lock, otherwise another322      // thread still holds the lock and we should wait again.323      // If lock is acquired, an acquire fence is needed to make all memory accesses324      // made by other threads visible to the current CPU./*  * atomic_exchange_explicit()执行的结果是mutex->state = locked_contended ,返回值是之前的 mutex->state * 所以这个条件可以理解成 uint16_t temp = mutex->state;mutex->state = locked_contended , temp != unlocked*/325      while (atomic_exchange_explicit(&mutex->state, locked_contended,  326                                      memory_order_acquire) != unlocked) { 327          if (__futex_wait_ex(&mutex->state, shared, locked_contended, use_realtime_clock,328                              abs_timeout_or_null) == -ETIMEDOUT) {329              return ETIMEDOUT;330          }331      }332      return 0;333  }
首先会重新去获取锁,调用__pthread_normal_mutex_trylock() 尝试去获取,前面有介绍这个函数,如果还是拿不到,会走到最后的while 里面,atomic_exchange_explicit() 的返回值是修改之前的mutex->state,也就是进入这个函数之前的mutex->state,如果状态不是unlocked,继续走到__futex_wait_ex(),

bionic/libc/private/bionic_futex.h

68  static inline int __futex_wait_ex(volatile void* ftx, bool shared, int value,69                                    bool use_realtime_clock, const struct timespec* abs_timeout) {70    return __futex(ftx, (shared ? FUTEX_WAIT_BITSET : FUTEX_WAIT_BITSET_PRIVATE) |71                   (use_realtime_clock ? FUTEX_CLOCK_REALTIME : 0), value, abs_timeout,72                   FUTEX_BITSET_MATCH_ANY);73  }
继续调用__futex_wait_ex()

43  static inline __always_inline int __futex(volatile void* ftx, int op, int value,44                                            const struct timespec* timeout,45                                            int bitset) {46    // Our generated syscall assembler sets errno, but our callers (pthread functions) don't want to.47    int saved_errno = errno;48    int result = syscall(__NR_futex, ftx, op, value, timeout, NULL, bitset);49    if (__predict_false(result == -1)) {50      result = -errno;51      errno = saved_errno;52    }53    return result;54  }
__futex_wait_ex()会调用到syscall()函数,是一个系统调用函数,所以接下里就跑到kernel。

linux-4.10/kernel/futex.c

3243  SYSCALL_DEFINE6(futex, u32 __user *, uaddr, int, op, u32, val,3244  struct timespec __user *, utime, u32 __user *, uaddr2,3245  u32, val3)3246  {...3275  return do_futex(uaddr, op, val, tp, uaddr2, val2, val3);3276  }

系统调用从user 空间切换到kernel 空间,前面的博客有详细介绍过,这里不再介绍,我们理所当然地认为就调用到了kernel 的do_futex()。

传入的参数uaddr 就是指向mutex->state 的地址,op 是FUTEX_WAIT/FUTEX_WAIT_BITSET, val 是上面的locked_contended,tp 是 NULL。

3185  long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout,3186  u32 __user *uaddr2, u32 val2, u32 val3)3187  {3188  int cmd = op & FUTEX_CMD_MASK;...3211  switch (cmd) {3212  case FUTEX_WAIT:3213  val3 = FUTEX_BITSET_MATCH_ANY;3214  case FUTEX_WAIT_BITSET:3215  return futex_wait(uaddr, flags, val, timeout, val3); //原子检查uaddr 的值是否和val相等...3238  }3239  return -ENOSYS;3240  }
根据前面参数的解释,我们知道上面的case 会走到 futex_wait()

2402  static int futex_wait(u32 __user *uaddr, unsigned int flags, u32 val,2403        ktime_t *abs_time, u32 bitset)2404  {2405  struct hrtimer_sleeper timeout, *to = NULL;2406  struct restart_block *restart;2407  struct futex_hash_bucket *hb;2408  struct futex_q q = futex_q_init;2409  int ret;2410  2411  if (!bitset)2412  return -EINVAL;2413  q.bitset = bitset;2414  2415  if (abs_time) {2416  to = &timeout;2417  2418  hrtimer_init_on_stack(&to->timer, (flags & FLAGS_CLOCKRT) ?2419        CLOCK_REALTIME : CLOCK_MONOTONIC,2420        HRTIMER_MODE_ABS);2421  hrtimer_init_sleeper(to, current);2422  hrtimer_set_expires_range_ns(&to->timer, *abs_time,2423       current->timer_slack_ns);2424  }2425  2426  retry:2427  /*2428   * Prepare to wait on uaddr. On success, holds hb lock and increments2429   * q.key refs.2430   */2431  ret = futex_wait_setup(uaddr, val, flags, &q, &hb); //2432  if (ret)2433  goto out;2434  2435  /* queue_me and wait for wakeup, timeout, or a signal. */2436  futex_wait_queue_me(hb, &q, to);2437  2438  /* If we were woken (and unqueued), we succeeded, whatever. */2439  ret = 0;2440  /* unqueue_me() drops q.key ref */2441  if (!unqueue_me(&q))2442  goto out;...2468  out:2469  if (to) {2470  hrtimer_cancel(&to->timer);2471  destroy_hrtimer_on_stack(&to->timer);2472  }2473  return ret;2474  }
如果设置有超时,会挂到hrtimer(高精度实时定时器)上,这里没有设置,我们重点关注futex_wait_setup() 和futex_wait_queue_me()

static int futex_wait_setup(u32 __user *uaddr, u32 val, unsigned int flags,2344     struct futex_q *q, struct futex_hash_bucket **hb)2345  {2346  u32 uval;2347  int ret;...2367  retry:2368  ret = get_futex_key(uaddr, flags & FLAGS_SHARED, &q->key, VERIFY_READ);2369  if (unlikely(ret != 0))2370  return ret;2371  2372  retry_private:2373  *hb = queue_lock(q);2374  2375  ret = get_futex_value_locked(&uval, uaddr);2376  2377  if (ret) {2378  queue_unlock(*hb);2379  2380  ret = get_user(uval, uaddr);2381  if (ret)2382  goto out;2383  2384  if (!(flags & FLAGS_SHARED))2385  goto retry_private;2386  2387  put_futex_key(&q->key);2388  goto retry;2389  }2390  2391  if (uval != val) {2392  queue_unlock(*hb);2393  ret = -EWOULDBLOCK;2394  }2395  2396  out:2397  if (ret)2398  put_futex_key(&q->key);2399  return ret;2400  }
这个函数里面会比较mutex->state 和 val(locked_contended)是否相等,因为可能这时候有线程把锁释放了,不相等表示可以拿到锁了。

2294  static void futex_wait_queue_me(struct futex_hash_bucket *hb, struct futex_q *q,2295  struct hrtimer_sleeper *timeout)2296  {2297  /*2298   * The task state is guaranteed to be set before another task can2299   * wake it. set_current_state() is implemented using smp_store_mb() and2300   * queue_me() calls spin_unlock() upon completion, both serializing2301   * access to the hash list and forcing another memory barrier.2302   */2303  set_current_state(TASK_INTERRUPTIBLE);  //可以被中断2304  queue_me(q, hb);2305  2306  /* Arm the timer */2307  if (timeout)2308  hrtimer_start_expires(&timeout->timer, HRTIMER_MODE_ABS);2309  2310  /*2311   * If we have been removed from the hash list, then another task2312   * has tried to wake us, and we can skip the call to schedule().2313   */2314  if (likely(!plist_node_empty(&q->list))) {2315  /*2316   * If the timer has already expired, current will already be2317   * flagged for rescheduling. Only call schedule if there2318   * is no timeout, or if it has yet to expire.2319   */2320  if (!timeout || timeout->task)2321  freezable_schedule();  //调用 schedule() 进行调度2322  }2323  __set_current_state(TASK_RUNNING);2324  }
如果还是没有拿到锁,就会进入到上面的futex_wait_queue_me(),这个里面会把当前进程设置为可中断的,并且把当前task_structr放到 futex_q 中。

2022  static inline void queue_me(struct futex_q *q, struct futex_hash_bucket *hb)2023  __releases(&hb->lock)2024  {2025  int prio;2026  2027  /*2028   * The priority used to register this element is2029   * - either the real thread-priority for the real-time threads2030   * (i.e. threads with a priority lower than MAX_RT_PRIO)2031   * - or MAX_RT_PRIO for non-RT threads.2032   * Thus, all RT-threads are woken first in priority order, and2033   * the others are woken last, in FIFO order.2034   */2035  prio = min(current->normal_prio, MAX_RT_PRIO); //设置进程的优先级2036  2037  plist_node_init(&q->list, prio);2038  plist_add(&q->list, &hb->chain);2039  q->task = current;2040  spin_unlock(&hb->lock);2041  }
把当前task_structr放到 futex_q 后,调用freezable_schedule() 做进程调度,所以这个进程就被调度出去了。

linux-4.10/include/linux/freezer.h168  static inline void freezable_schedule(void)169  {170  freezer_do_not_count();171  schedule();172  freezer_count();173  }
走到这里,相当于当前进程陷入到kernel 的系统调用中,并且被调度出cpu的运行队列,放到futex_q  队列中。


3、释放锁函数pthread_mutex_unlock()

bionic/libc/bionic/pthread_mutex.cpp

524  int pthread_mutex_unlock(pthread_mutex_t* mutex_interface) {525  #if !defined(__LP64__)526      if (mutex_interface == NULL) {527          return EINVAL;528      }529  #endif530  531      pthread_mutex_internal_t* mutex = __get_internal_mutex(mutex_interface);532  533      uint16_t old_state = atomic_load_explicit(&mutex->state, memory_order_relaxed);534      uint16_t mtype  = (old_state & MUTEX_TYPE_MASK);535      uint16_t shared = (old_state & MUTEX_SHARED_MASK);536  537      // Handle common case first.538      if (__predict_true(mtype == MUTEX_TYPE_BITS_NORMAL)) {539          __pthread_normal_mutex_unlock(mutex, shared);540          return 0;541      }...571      return 0;572  }
如前面描述的,跑出作用域后,会释放这个锁,继而调用到pthread_mutex_unlock()

339  static inline __always_inline void __pthread_normal_mutex_unlock(pthread_mutex_internal_t* mutex,340                                                                   uint16_t shared) {341      const uint16_t unlocked         = shared | MUTEX_STATE_BITS_UNLOCKED;342      const uint16_t locked_contended = shared | MUTEX_STATE_BITS_LOCKED_CONTENDED;343  344      // We use an atomic_exchange to release the lock. If locked_contended state345      // is returned, some threads is waiting for the lock and we need to wake up346      // one of them.347      // A release fence is required to make previous stores visible to next348      // lock owner threads.349      if (atomic_exchange_explicit(&mutex->state, unlocked,350                                   memory_order_release) == locked_contended) {351          // Wake up one waiting thread. We don't know which thread will be352          // woken or when it'll start executing -- futexes make no guarantees353          // here. There may not even be a thread waiting.354          //355          // The newly-woken thread will replace the unlocked state we just set above356          // with locked_contended state, which means that when it eventually releases357          // the mutex it will also call FUTEX_WAKE. This results in one extra wake358          // call whenever a lock is contended, but let us avoid forgetting anyone359          // without requiring us to track the number of sleepers.360          //361          // It's possible for another thread to sneak in and grab the lock between362          // the exchange above and the wake call below. If the new thread is "slow"363          // and holds the lock for a while, we'll wake up a sleeper, which will swap364          // in locked_uncontended state and then go back to sleep since the lock is365          // still held. If the new thread is "fast", running to completion before366          // we call wake, the thread we eventually wake will find an unlocked mutex367          // and will execute. Either way we have correct behavior and nobody is368          // orphaned on the wait queue.369          __futex_wake_ex(&mutex->state, shared, 1);370      }371  }
__pthread_normal_mutex_unlock()会判断当前线程是否还持有这个锁,如果是,会调用到__futex_wake_ex() 

bionic/libc/private/bionic_futex.h
60  static inline int __futex_wake_ex(volatile void* ftx, bool shared, int count) {61    return __futex(ftx, shared ? FUTEX_WAKE : FUTEX_WAKE_PRIVATE, count, NULL, 0);62  }

43  static inline __always_inline int __futex(volatile void* ftx, int op, int value,44                                            const struct timespec* timeout,45                                            int bitset) {46    // Our generated syscall assembler sets errno, but our callers (pthread functions) don't want to.47    int saved_errno = errno;48    int result = syscall(__NR_futex, ftx, op, value, timeout, NULL, bitset);49    if (__predict_false(result == -1)) {50      result = -errno;51      errno = saved_errno;52    }53    return result;54  }

又是系统调用,这里我们直接跳到kernel 的 do_futex() 
linux-4.10/kernel/futex.c
3185  long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout,3186  u32 __user *uaddr2, u32 val2, u32 val3)3187  {3188  int cmd = op & FUTEX_CMD_MASK;...3211  switch (cmd) {...3216  case FUTEX_WAKE:3217  val3 = FUTEX_BITSET_MATCH_ANY;3218  case FUTEX_WAKE_BITSET:3219  return futex_wake(uaddr, flags, val, val3);...3238  }3239  return -ENOSYS;3240  }
传入的参数uaddr 指向&mutex->state,op 为FUTEX_WAKE / FUTEX_WAKE_PRIVATE ,val等于 1,接着跑到futex_wake()

1411  static int1412  futex_wake(u32 __user *uaddr, unsigned int flags, int nr_wake, u32 bitset)1413  {1414  struct futex_hash_bucket *hb;1415  struct futex_q *this, *next;1416  union futex_key key = FUTEX_KEY_INIT;1417  int ret;1418  DEFINE_WAKE_Q(wake_q);1419  1420  if (!bitset)1421  return -EINVAL;1422  1423  ret = get_futex_key(uaddr, flags & FLAGS_SHARED, &key, VERIFY_READ);1424  if (unlikely(ret != 0))1425  goto out;1426  1427  hb = hash_futex(&key);1428  1429  /* Make sure we really have tasks to wakeup */1430  if (!hb_waiters_pending(hb))1431  goto out_put_key;1432  1433  spin_lock(&hb->lock);1434  1435  plist_for_each_entry_safe(this, next, &hb->chain, list) {1436  if (match_futex (&this->key, &key)) {1437  if (this->pi_state || this->rt_waiter) {1438  ret = -EINVAL;1439  break;1440  }1441  1442  /* Check if one of the bits is set in both bitsets */1443  if (!(this->bitset & bitset))1444  continue;1445  1446  mark_wake_futex(&wake_q, this);1447  if (++ret >= nr_wake)1448  break;1449  }1450  }1451  1452  spin_unlock(&hb->lock);1453  wake_up_q(&wake_q); //唤醒队列中的task_struct 1454  out_put_key:1455  put_futex_key(&key);1456  out:1457  return ret;1458  }
根据上传下来的值知道nr_wake 为1,所以mark_wake_futex()只会跑一次。

1272  static void mark_wake_futex(struct wake_q_head *wake_q, struct futex_q *q)1273  {1274  struct task_struct *p = q->task;1275  1276  if (WARN(q->pi_state || q->rt_waiter, "refusing to wake PI futex\n"))1277  return;1278  1279  /*1280   * Queue the task for later wakeup for after we've released1281   * the hb->lock. wake_q_add() grabs reference to p.1282   */1283  wake_q_add(wake_q, p);1284  __unqueue_futex(q);1285  /*1286   * The waiting task can free the futex_q as soon as1287   * q->lock_ptr = NULL is written, without taking any locks. A1288   * memory barrier is required here to prevent the following1289   * store to lock_ptr from getting ahead of the plist_del.1290   */1291  smp_wmb();1292  q->lock_ptr = NULL;1293  }
mark_wake_futex() 就是把要唤醒的task_struct 放入wake_q 队列中 ,wake_q_add() ,最后调用wake_up_q(&wake_q); 来唤醒(调度)task_struct, 所以前面获取锁的系统调用就会返回。


4、销毁mutex pthread_mutex_destroy()
bionic/libc/bionic/pthread_mutex.cpp

634  int pthread_mutex_destroy(pthread_mutex_t* mutex_interface) {635      pthread_mutex_internal_t* mutex = __get_internal_mutex(mutex_interface);636      uint16_t old_state = atomic_load_explicit(&mutex->state, memory_order_relaxed);637      // Store 0xffff to make the mutex unusable. Although POSIX standard says it is undefined638      // behavior to destroy a locked mutex, we prefer not to change mutex->state in that situation.639      if (MUTEX_STATE_BITS_IS_UNLOCKED(old_state) && //old_state & 49152 == 0640          atomic_compare_exchange_strong_explicit(&mutex->state, &old_state, 0xffff,641                                                  memory_order_relaxed, memory_order_relaxed)) {642        return 0;643      }644      return EBUSY;645  }
如果没有线程在使用,就把mutex->state 设置成0xffff  ,表示不可用了





阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 珠算练习 珠算四级试题 珠算除法怎么打 珠算等级 珠算乘法口诀表 儿童珠算教程 珠算加法 珠算证有什么用 会计从业资格考试珠算 小翼管家app 辣辣小管家 省钱小管家 小翼管家下载 小翼管家app下载 小易管家 健康小管家 小滴管家下载 小箭雀 无敌小箭箭礼包 无敌小箭箭破解版 无敌小箭箭攻略 无敌小箭箭什么门派好 无敌小箭箭兑换码 伤心小箭 无敌小箭箭和暴走大侠 抖音无敌小箭箭礼包 抖音无敌小箭箭兑换礼包 无敌小箭箭辅助 无敌小箭箭手游 小篆体 折纸小篮子折法 水果篮子小透和谁在一起了 手工编篮子塑胶条 手工篮子制作方法 编织篮子的步骤 小篮子怎么叠 纸篮子 纸篮子的折法 怎么折篮子 手编篮子的做法 手工篮子的折法