一个进程中不可能只有一个线程在战斗,所以一个进程中一般都是有多个线程的同时协助工作,多线程情况下,对于一些全局变量,也就是多个线程能够同时访问的变量,我们需要通过加锁来防止“同时”访问这个变量,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 #else
43 int32_t __private[1]; //长度为1 的整形数组
44 #endif
45 } pthread_mutex_t;
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设置为 0
245
246 if (__predict_true(attr == NULL)) { //没有设置相关属性时
247 atomic_init(&mutex->state, MUTEX_TYPE_BITS_NORMAL); //mutex->state = (((0) & ((1 << (2))-1)) << (14)) 也就是0
248 return 0;
249 }
... //因为针对上面的实现传入的attr 为NULL,所以这部分的代码先不做分析
272 return 0;
273 }
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 #endif
509
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->state
513 uint16_t mtype = (old_state & MUTEX_TYPE_MASK); //mtype =old_state &(((1 << (2))-1) << (14)) 也就是mtype =old_state & 49152
514 uint16_t shared = (old_state & MUTEX_SHARED_MASK);//shared =old_state &(((1 << (1))-1) << (13)) 也就是shared =old_state & 8192
515 // Avoid slowing down fast path of normal mutex lock operation.
516 if (__predict_true(mtype == MUTEX_TYPE_BITS_NORMAL)) { //MUTEX_TYPE_BITS_NORMAL =0
517 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 = 0
278 const uint16_t locked_uncontended = shared | MUTEX_STATE_BITS_LOCKED_UNCONTENDED; //MUTEX_STATE_BITS_LOCKED_UNCONTENDED = 16384
279
280 uint16_t old_state = unlocked;
//如果 mutex->state == old_state, mutex->state = locked_uncontended
//否则 mutex->state = old_state
281 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->state
425 uint16_t mtype = (old_state & MUTEX_TYPE_MASK); //mtype =old_state &(((1 << (2))-1) << (14)) 也就是mtype =old_state & 49152
426 uint16_t shared = (old_state & MUTEX_SHARED_MASK); //shared =old_state &(((1 << (1))-1) << (13)) 也就是shared =old_state & 8192
427
428 // Handle common case first.
429 if ( __predict_true(mtype == MUTEX_TYPE_BITS_NORMAL) ) { //MUTEX_TYPE_BITS_NORMAL = 0
430 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); //这里会返回 0
308 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 requires
318 // promoting it to locked_contended. We need to swap in the new state
319 // 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 another
322 // thread still holds the lock and we should wait again.
323 // If lock is acquired, an acquire fence is needed to make all memory accesses
324 // 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 }
传入的参数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 increments
2429 * 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 can
2299 * wake it. set_current_state() is implemented using smp_store_mb() and
2300 * queue_me() calls spin_unlock() upon completion, both serializing
2301 * 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 task
2312 * 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 be
2317 * flagged for rescheduling. Only call schedule if there
2318 * 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 is
2029 * - either the real thread-priority for the real-time threads
2030 * (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, and
2033 * 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.h
168 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 #endif
530
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 state
345 // is returned, some threads is waiting for the lock and we need to wake up
346 // one of them.
347 // A release fence is required to make previous stores visible to next
348 // 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 be
352 // woken or when it'll start executing -- futexes make no guarantees
353 // here. There may not even be a thread waiting.
354 //
355 // The newly-woken thread will replace the unlocked state we just set above
356 // with locked_contended state, which means that when it eventually releases
357 // the mutex it will also call FUTEX_WAKE. This results in one extra wake
358 // call whenever a lock is contended, but let us avoid forgetting anyone
359 // without requiring us to track the number of sleepers.
360 //
361 // It's possible for another thread to sneak in and grab the lock between
362 // 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 swap
364 // in locked_uncontended state and then go back to sleep since the lock is
365 // still held. If the new thread is "fast", running to completion before
366 // we call wake, the thread we eventually wake will find an unlocked mutex
367 // and will execute. Either way we have correct behavior and nobody is
368 // orphaned on the wait queue.
369 __futex_wake_ex(&mutex->state, shared, 1);
370 }
371 }
__pthread_normal_mutex_unlock()会判断当前线程是否还持有这个锁,如果是,会调用到__futex_wake_ex()
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 }
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 int
1412 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 released
1281 * 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 as
1287 * q->lock_ptr = NULL is written, without taking any locks. A
1288 * memory barrier is required here to prevent the following
1289 * 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 undefined
638 // 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 == 0
640 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 ,表示不可用了