Chinaunix首页 | 论坛 | 博客
  • 博客访问: 453645
  • 博文数量: 143
  • 博客积分: 6159
  • 博客等级: 准将
  • 技术积分: 1667
  • 用 户 组: 普通用户
  • 注册时间: 2010-08-25 23:08
文章分类

全部博文(143)

文章存档

2013年(1)

2012年(11)

2011年(55)

2010年(76)

分类:

2010-10-13 23:45:06

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


阅读(1363) | 评论(0) | 转发(0) |
0

上一篇:鲁迅知道的太多了

下一篇:futex介绍

给主人留下些什么吧!~~