pthread_mutex的实现
============================================================
pthread_mutex_t定义如下:
struct pthread_mutex_t {
int __lock;
unsigned int __count;
int __owner;
/* KIND must stay at this position in the structure to maintain
binary compatibility. */
int __kind;
unsigned int __nusers;
__extension__ union
{
int __spins;
__pthread_slist_t __list;
};
}
|
其中,mutex的类型有:
TIMED_NP
RECURSIVE_NP
ERRORCHECK_NP
ADAPTIVE_NP
FAST_NP
mutex protocol有:
PRIO_NONE
PRIO_INHERIT
PRIO_PROTECT
===========================
使用pthread_mutex最常用就是pthread_mutex_lock(*mutex),
pthread_mutex_lock函数的实现简单描述如下:
首先根据mutex类型决定处理方式:
PTHREAD_MUTEX_RECURSIVE_NP:
检查 mutex owner 是否为当前thread (mutex->__data.__owner == thread_id),
如果是,直接 ++mutex->__data.__count
否则 LLL_MUTEX_LOCK (mutex)
PTHREAD_MUTEX_ERRORCHECK_NP:
检查 mutex owner 是否为当前thread,
如果是将返回错误,否则fallthrough
PTHREAD_MUTEX_TIMED_NP:
最简单情况,直接 lock
LLL_MUTEX_LOCK (mutex)
PTHREAD_MUTEX_ADAPTIVE_NP:
判断是否为smp,如果不是smp直接按PTHREAD_MUTEX_TIMED_NP处理
如果为smp,
尝试采用 LLL_MUTEX_TRYLOCK
如果失败,对当前mutex采用adaptive的方式计算 try 的次数 max_cnt
循环 LLL_MUTEX_TRYLOCK,
如果max_cnt次后仍然lock失败,直接使用 LLL_MUTEX_LOCK (mutex), 可能进入等待
lock成功后,根据本次try的次数,对mutex的 mutex->__data.__spins 进行动态更新
=====================
对于LLL_MUTEX_LOCK的定义如下:
#define LLL_MUTEX_LOCK(mutex) \
lll_cond_lock ((mutex)->__data.__lock, PTHREAD_MUTEX_PSHARED (mutex))
|
lll_cond_lock(futex, private) 的实现简单可描述为
这个futex就是mutex->__data.__lock
首先采用cmpxchgl尝试是否能直接上锁
直接上锁成功, 直接到.previous
上锁失败,调用__lll_lock_wait完成上锁工作, edx是__lock
具体代码为:
#define lll_cond_lock(futex, private) \
(void) \
({ int ignore1, ignore2, ignore3; \
__asm __volatile (LOCK_INSTR "cmpxchgl %1, %2\n\t" \
"jnz _L_cond_lock_%=\n\t" \
".subsection 1\n\t" \
".type _L_cond_lock_%=,@function\n" \
"_L_cond_lock_%=:\n" \
"1:\tleal %2, %%edx\n" \
"0:\tmovl %7, %%ecx\n" \
"2:\tcall __lll_lock_wait\n" \
"3:\tjmp 18f\n" \
"4:\t.size _L_cond_lock_%=, 4b-1b\n\t" \
".previous\n" \
LLL_STUB_UNWIND_INFO_4 \
"18:" \
: "=a" (ignore1), "=c" (ignore2), "=m" (futex),\
"=&d" (ignore3) \
: "0" (0), "1" (2), "m" (futex), "g" (private) \
: "memory"); \
})
|
其中,__lll_lock_wait的实现如下,主要就是调用sys_futex完成上锁
__lll_lock_wait:
cfi_startproc
pushl %edx
cfi_adjust_cfa_offset(4)
pushl %ebx
cfi_adjust_cfa_offset(4)
pushl %esi
cfi_adjust_cfa_offset(4)
cfi_offset(%edx, -8)
cfi_offset(%ebx, -12)
cfi_offset(%esi, -16)
movl %edx, %ebx
movl $2, %edx
xorl %esi, %esi /* No timeout. */
LOAD_FUTEX_WAIT (%ecx)
cmpl %edx, %eax /* NB: %edx == 2 */
jne 2f
1: movl $SYS_futex, %eax 系统调用 futex(...)
ENTER_KERNEL
2: movl %edx, %eax
xchgl %eax, (%ebx) /* NB: lock is implied */
testl %eax, %eax
jnz 1b
popl %esi
cfi_adjust_cfa_offset(-4)
cfi_restore(%esi)
popl %ebx
cfi_adjust_cfa_offset(-4)
cfi_restore(%ebx)
popl %edx
cfi_adjust_cfa_offset(-4)
cfi_restore(%edx)
ret
cfi_endproc
.size __lll_lock_wait,.-__lll_lock_wait
|
阅读(1442) | 评论(0) | 转发(0) |