pthread_mutex_lock源码分析
Posted hadesblog
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了pthread_mutex_lock源码分析相关的知识,希望对你有一定的参考价值。
直接把注释写到代码中:
1 int 2 __pthread_mutex_lock (pthread_mutex_t *mutex) 3 { 4 unsigned int type = PTHREAD_MUTEX_TYPE_ELISION (mutex); 5 6 //安全检查 7 LIBC_PROBE (mutex_entry, 1, mutex); 8 9 //返回 __pthread_mutex_lock_full 10 if (__builtin_expect (type & ~(PTHREAD_MUTEX_KIND_MASK_NP 11 | PTHREAD_MUTEX_ELISION_FLAGS_NP), 0)) 12 return __pthread_mutex_lock_full (mutex); 13 14 //普通锁 15 if (__glibc_likely (type == PTHREAD_MUTEX_TIMED_NP)) 16 { 17 FORCE_ELISION (mutex, goto elision); 18 simple: 19 /* Normal mutex. */ 20 //LLL_MUTEX_LOCK 通过原子操作将0变为1,失败阻塞 21 /* 22 最终调用的是__lll_lock: 23 #define __lll_lock(futex, private) 24 ((void) 25 ({ 26 int *__futex = (futex); 27 if (__glibc_unlikely 28 (atomic_compare_and_exchange_bool_acq (__futex, 1, 0))) 29 { 30 if (__builtin_constant_p (private) && (private) == LLL_PRIVATE) 31 __lll_lock_wait_private (__futex); 32 else 33 __lll_lock_wait (__futex, private); 34 } 35 })) 36 37 阻塞的实现(futex系统调用): 38 #define lll_futex_syscall(nargs, futexp, op, ...) 39 ({ 40 INTERNAL_SYSCALL_DECL (__err); 41 long int __ret = INTERNAL_SYSCALL (futex, __err, nargs, futexp, op, 42 __VA_ARGS__); 43 (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (__ret, __err)) 44 ? -INTERNAL_SYSCALL_ERRNO (__ret, __err) : 0); 45 }) 46 47 */ 48 LLL_MUTEX_LOCK (mutex); 49 //获取失败中断 50 assert (mutex->__data.__owner == 0); 51 } 52 #ifdef HAVE_ELISION 53 else if (__glibc_likely (type == PTHREAD_MUTEX_TIMED_ELISION_NP)) 54 { 55 elision: __attribute__((unused)) 56 /* This case can never happen on a system without elision, 57 as the mutex type initialization functions will not 58 allow to set the elision flags. */ 59 /* Don‘t record owner or users for elision case. This is a 60 tail call. */ 61 return LLL_MUTEX_LOCK_ELISION (mutex); 62 } 63 #endif 64 65 //自旋锁 66 else if (__builtin_expect (PTHREAD_MUTEX_TYPE (mutex) 67 == PTHREAD_MUTEX_RECURSIVE_NP, 1)) 68 { 69 //获取线程id 70 pid_t id = THREAD_GETMEM (THREAD_SELF, tid); 71 72 //已经持有锁直接返回 73 if (mutex->__data.__owner == id) 74 { 75 //防止计数溢出 76 if (__glibc_unlikely (mutex->__data.__count + 1 == 0)) 77 /* Overflow of the counter. */ 78 return EAGAIN; 79 80 //计数加一 81 ++mutex->__data.__count; 82 83 return 0; 84 } 85 86 //获取锁 87 LLL_MUTEX_LOCK (mutex); 88 89 assert (mutex->__data.__owner == 0); 90 mutex->__data.__count = 1; 91 } 92 //适应锁 等待解锁后重新竞争 93 else if (__builtin_expect (PTHREAD_MUTEX_TYPE (mutex) 94 == PTHREAD_MUTEX_ADAPTIVE_NP, 1)) 95 { 96 if (! __is_smp) 97 goto simple; 98 99 if (LLL_MUTEX_TRYLOCK (mutex) != 0) 100 { 101 int cnt = 0; 102 int max_cnt = MIN (MAX_ADAPTIVE_COUNT, 103 mutex->__data.__spins * 2 + 10); 104 //循环等待获得锁 105 do 106 { 107 if (cnt++ >= max_cnt) 108 { 109 LLL_MUTEX_LOCK (mutex); 110 break; 111 } 112 atomic_spin_nop (); 113 } 114 while (LLL_MUTEX_TRYLOCK (mutex) != 0); 115 116 mutex->__data.__spins += (cnt - mutex->__data.__spins) / 8; 117 } 118 assert (mutex->__data.__owner == 0); 119 } 120 //检错锁 121 else 122 { 123 pid_t id = THREAD_GETMEM (THREAD_SELF, tid); 124 assert (PTHREAD_MUTEX_TYPE (mutex) == PTHREAD_MUTEX_ERRORCHECK_NP); 125 //线程持有锁返回EDEADLK 126 if (__glibc_unlikely (mutex->__data.__owner == id)) 127 return EDEADLK; 128 //跳转到普通锁加锁 129 goto simple; 130 } 131 132 pid_t id = THREAD_GETMEM (THREAD_SELF, tid); 133 134 //记录线程id 135 mutex->__data.__owner = id; 136 #ifndef NO_INCR 137 ++mutex->__data.__nusers; 138 #endif 139 140 LIBC_PROBE (mutex_acquired, 1, mutex); 141 142 return 0; 143 }
以上是关于pthread_mutex_lock源码分析的主要内容,如果未能解决你的问题,请参考以下文章
ThreadX内核源码分析 - 定时器及线程时间片调度(arm)
Android 逆向整体加固脱壳 ( DexClassLoader 加载 dex 流程分析 | DexFile loadDexFile 函数 | 构造函数 | openDexFile 函数 )(代码片