pthread_mutex_lock源码分析
直接把注释写到代码中:
int __pthread_mutex_lock (pthread_mutex_t *mutex) { unsigned int type = PTHREAD_MUTEX_TYPE_ELISION (mutex); //安全检查 LIBC_PROBE (mutex_entry, 1, mutex); //返回 __pthread_mutex_lock_full if (__builtin_expect (type & ~(PTHREAD_MUTEX_KIND_MASK_NP | PTHREAD_MUTEX_ELISION_FLAGS_NP), 0)) return __pthread_mutex_lock_full (mutex); //普通锁 if (__glibc_likely (type == PTHREAD_MUTEX_TIMED_NP)) { FORCE_ELISION (mutex, goto elision); simple: /* Normal mutex. */ //LLL_MUTEX_LOCK 通过原子操作将0变为1,失败阻塞 /* 最终调用的是__lll_lock: #define __lll_lock(futex, private) \ ((void) \ ({ \ int *__futex = (futex); \ if (__glibc_unlikely \ (atomic_compare_and_exchange_bool_acq (__futex, 1, 0))) \ { \ if (__builtin_constant_p (private) && (private) == LLL_PRIVATE) \ __lll_lock_wait_private (__futex); \ else \ __lll_lock_wait (__futex, private); \ } \ })) 阻塞的实现(futex系统调用): #define lll_futex_syscall(nargs, futexp, op, ...) \ ({ \ INTERNAL_SYSCALL_DECL (__err); \ long int __ret = INTERNAL_SYSCALL (futex, __err, nargs, futexp, op, \ __VA_ARGS__); \ (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (__ret, __err)) \ ? -INTERNAL_SYSCALL_ERRNO (__ret, __err) : 0); \ }) */ LLL_MUTEX_LOCK (mutex); //获取失败中断 assert (mutex->__data.__owner == 0); } #ifdef HAVE_ELISION else if (__glibc_likely (type == PTHREAD_MUTEX_TIMED_ELISION_NP)) { elision: __attribute__((unused)) /* This case can never happen on a system without elision, as the mutex type initialization functions will not allow to set the elision flags. */ /* Don't record owner or users for elision case. This is a tail call. */ return LLL_MUTEX_LOCK_ELISION (mutex); } #endif //自旋锁 else if (__builtin_expect (PTHREAD_MUTEX_TYPE (mutex) == PTHREAD_MUTEX_RECURSIVE_NP, 1)) { //获取线程id pid_t id = THREAD_GETMEM (THREAD_SELF, tid); //已经持有锁直接返回 if (mutex->__data.__owner == id) { //防止计数溢出 if (__glibc_unlikely (mutex->__data.__count + 1 == 0)) /* Overflow of the counter. */ return EAGAIN; //计数加一 ++mutex->__data.__count; return 0; } //获取锁 LLL_MUTEX_LOCK (mutex); assert (mutex->__data.__owner == 0); mutex->__data.__count = 1; } //适应锁 等待解锁后重新竞争 else if (__builtin_expect (PTHREAD_MUTEX_TYPE (mutex) == PTHREAD_MUTEX_ADAPTIVE_NP, 1)) { if (! __is_smp) goto simple; if (LLL_MUTEX_TRYLOCK (mutex) != 0) { int cnt = 0; int max_cnt = MIN (MAX_ADAPTIVE_COUNT, mutex->__data.__spins * 2 + 10); //循环等待获得锁 do { if (cnt++ >= max_cnt) { LLL_MUTEX_LOCK (mutex); break; } atomic_spin_nop (); } while (LLL_MUTEX_TRYLOCK (mutex) != 0); mutex->__data.__spins += (cnt - mutex->__data.__spins) / 8; } assert (mutex->__data.__owner == 0); } //检错锁 else { pid_t id = THREAD_GETMEM (THREAD_SELF, tid); assert (PTHREAD_MUTEX_TYPE (mutex) == PTHREAD_MUTEX_ERRORCHECK_NP); //线程持有锁返回EDEADLK if (__glibc_unlikely (mutex->__data.__owner == id)) return EDEADLK; //跳转到普通锁加锁 goto simple; } pid_t id = THREAD_GETMEM (THREAD_SELF, tid); //记录线程id mutex->__data.__owner = id; #ifndef NO_INCR ++mutex->__data.__nusers; #endif LIBC_PROBE (mutex_acquired, 1, mutex); return 0; }