LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 3352|回复: 3

pthread中pthread_mutex_lock()是怎么锁住互斥量的啊?

[复制链接]
发表于 2004-12-4 22:43:01 | 显示全部楼层 |阅读模式
看了一个晚上的源代码,还是有很多东西没弄明白
感觉里面的注释太少了。
有谁看过得啊?能不能给我解释一下
而且我觉得里面的很多操作都不能保证原子性
发表于 2004-12-9 03:43:26 | 显示全部楼层
个人认识:

glibc为了实现pthread的跨平台将函数实现置于sysdep之上。
所以我们看代码的时候总觉得在绕圈子一样。

pthread_mutex_lock终究会到sysdep上面的。
看看代码这里还挺有意思的,386上面没有lock指令,所以glibc就来了这么一段sysdep/i386/pthread_spin_lock.c

  1. int
  2. pthread_spin_lock (lock)
  3.      pthread_spinlock_t *lock;
  4. {
  5.   asm ("\n"
  6.        "1:\t" LOCK_PREFIX "decl %0\n\t"
  7.        "jne 2f\n\t"
  8.        ".subsection 1\n\t"
  9.        ".align 16\n"
  10.        "2:\trep; nop\n\t"
  11.        "cmpl $0, %0\n\t"
  12.        "jg 1b\n\t"
  13.        "jmp 2b\n\t"
  14.        ".previous"
  15.        : "=m" (*lock)
  16.        : "0" (*lock));

  17.   return 0;
  18. }
复制代码

整个一个忙等。
到了486及其以后就简单多了,直接使用lock指令sysdep/i486/pthread_spin_trylock.S:

  1. #ifdef UP
  2. # define LOCK
  3. #else
  4. # define LOCK lock
  5. #endif

  6.         .globl        pthread_spin_trylock
  7.         .type        pthread_spin_trylock,@function
  8.         .align        16
  9. pthread_spin_trylock:
  10.         movl        4(%esp), %edx
  11.         movl        $1, %eax
  12.         xorl        %ecx, %ecx
  13.         LOCK
  14.         cmpxchgl %ecx, (%edx)
  15.         movl        $EBUSY, %eax
  16. #ifdef HAVE_CMOV
  17.         cmovel        %ecx, %eax
  18. #else
  19.         jne        0f
  20.         movl        %ecx, %eax
  21. 0:
  22. #endif
  23.         ret
  24.         .size        pthread_spin_trylock,.-pthread_spin_trylock
复制代码


所以原子操作是可以保证的。
 楼主| 发表于 2004-12-9 23:24:45 | 显示全部楼层
不好意思,能不能解释一下这几条汇编啊?怎么跟我在书上介绍的gcc inline汇编有些不一样啊?
  asm ("\n"
       "1:\t" LOCK_PREFIX "decl %0\n\t"
       "jne 2f\n\t"
            ^^这里的2f和下面的2b有什么区别?
       ".subsection 1\n\t"
        ^^^^^^^^^^^^^
       ".align 16\n"
        ^^^^^^^^^这两条语句作了什么啊?
       "2:\trep; nop\n\t"
          ^^这里怎么会有一个\?
       "cmpl $0, %0\n\t"
       "jg 1b\n\t"
       "jmp 2b\n\t"
       ".previous"
       : "=m" (*lock)
       : "0" (*lock));
发表于 2004-12-10 00:46:17 | 显示全部楼层
jump 2f 就是说跳转到标号为2的地方,但是forward向前
jump 2b就是说跳转到标号为2的地方,但是backward向后
仔细阅读这段代码,他却不同于while(lock);的忙等。

设想,当while(lock);检测到lock被解开,那么他将离开循环进入临界区
在尚未设置lock时内核调度到另一个线程,另一个线程也会发现lock为解
开状态,也将离开循环进入临界区。所以while(lock);是不正确的。

如果增加循环同样有这个问题,就是无法解决进入临界区和设置锁之间不被
调度。(尽管可以减少出错几率)

那么,上面的代码如何工作的?

说实话我不是很明白,需要查查资料,明白的给个解释吧。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表