直接把注釋寫到代碼中:
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; }