diff -Naur glibc-2.3.2/nptl/pthread_mutex_lock.c glibc-2.3.2-dd/nptl/pthread_mutex_lock.c --- glibc-2.3.2/nptl/pthread_mutex_lock.c 2003-09-08 00:30:15.000000000 -0400 +++ glibc-2.3.2-dd/nptl/pthread_mutex_lock.c 2004-09-16 23:31:20.000000000 -0400 @@ -75,7 +75,16 @@ } /* Record the ownership. */ +#if 0 + /* Temporarily remove this assertion. This is just a quick-and-dirty + * solution. The general solution should have an interface to the kernel + * so that the kernel knows what other conditions (other than only the + * wait address having some value) should satisfy when it speculatively + * unblocks the waiting thread. In this library, these conditions would + * include mutex lock, owner, and nusers all have certain values. + * -- tongli */ assert (mutex->__data.__owner == 0); +#endif mutex->__data.__owner = id; #ifndef NO_INCR ++mutex->__data.__nusers; diff -Naur glibc-2.3.2/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S glibc-2.3.2-dd/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S --- glibc-2.3.2/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S 2003-09-22 14:50:20.000000000 -0400 +++ glibc-2.3.2-dd/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S 2005-01-25 16:46:39.000000000 -0500 @@ -32,10 +32,10 @@ #define SYS_gettimeofday __NR_gettimeofday #define SYS_futex 240 +#define SYS_futex_dd 284 /* New syscall -- tongli */ #define FUTEX_WAIT 0 #define FUTEX_WAKE 1 - .globl __lll_mutex_lock_wait .type __lll_mutex_lock_wait,@function .hidden __lll_mutex_lock_wait @@ -75,6 +75,52 @@ ret .size __lll_mutex_lock_wait,.-__lll_mutex_lock_wait +# New function for deadlock detection, adapted from __lll_mutex_lock_wait. +# -- tongli + .globl __lll_mutex_lock_wait_dd + .type __lll_mutex_lock_wait_dd,@function + .hidden __lll_mutex_lock_wait_dd + .align 16 +__lll_mutex_lock_wait_dd: + pushl %edx + pushl %ebx + pushl %esi + pushl %edi + pushl %ebp + + movl %ecx, %ebx /* ebx: uaddr */ + xorl %ecx, %ecx /* ecx: op (FUTEX_WAIT 0) */ + movl $2, %edx /* edx: val */ + movl $2, %esi /* esi: wait_op = '==' */ + xorl %edi, %edi /* edi: wait_val (0) */ + xorl %ebp, %ebp /* utime (no timeout) */ + +1: cmpl %edx, %eax /* NB: %edx == 2 */ + je 3f + + movl $1, %eax + LOCK + cmpxchgl %edx, (%ebx) + + testl %eax, %eax + je 2f + +3: movl $SYS_futex_dd, %eax + ENTER_KERNEL + + xorl %eax, %eax +2: LOCK + cmpxchgl %edx, (%ebx) + + jnz,pn 1b + + popl %ebp + popl %edi + popl %esi + popl %ebx + popl %edx + ret + .size __lll_mutex_lock_wait_dd,.-__lll_mutex_lock_wait_dd #ifdef NOT_IN_libc .globl __lll_mutex_timedlock_wait @@ -196,7 +242,6 @@ .size lll_unlock_wake_cb,.-lll_unlock_wake_cb #endif - .globl __lll_mutex_unlock_wake .type __lll_mutex_unlock_wake,@function .hidden __lll_mutex_unlock_wake @@ -219,6 +264,37 @@ ret .size __lll_mutex_unlock_wake,.-__lll_mutex_unlock_wake +# New function for deadlock detection, adapted from __lll_mutex_unlock_wake. +# -- tongli + .globl __lll_mutex_unlock_wake_dd + .type __lll_mutex_unlock_wake_dd,@function + .hidden __lll_mutex_unlock_wake_dd + .align 16 +__lll_mutex_unlock_wake_dd: + pushl %ebx + pushl %ecx + pushl %edx + pushl %esi + pushl %edi + + movl %eax, %ebx /* ebx: uaddr */ + movl $0, (%eax) /* futex = 0 (unlocked) */ + movl $FUTEX_WAKE, %ecx /* ecx: op (FUTEX_WAKE) */ + movl $1, %edx /* edx: val (wake one thread) */ + movl $2, %esi /* esi: wait_op = '==' */ + xorl %edi, %edi /* edi: wait_val (0) */ + xorl %ebp, %ebp /* utime (no timeout) */ + + movl $SYS_futex_dd, %eax + ENTER_KERNEL + + popl %edi + popl %esi + popl %edx + popl %ecx + popl %ebx + ret + .size __lll_mutex_unlock_wake_dd,.-__lll_mutex_unlock_wake_dd #ifdef NOT_IN_libc .globl __lll_timedwait_tid diff -Naur glibc-2.3.2/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_post.S glibc-2.3.2-dd/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_post.S --- glibc-2.3.2/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_post.S 2003-03-12 19:53:12.000000000 -0500 +++ glibc-2.3.2-dd/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_post.S 2004-09-21 09:52:28.000000000 -0400 @@ -28,6 +28,7 @@ #endif #define SYS_futex 240 +#define SYS_futex_dd 284 /* New syscall -- tongli */ #define FUTEX_WAKE 1 @@ -44,10 +45,26 @@ LOCK xaddl %edx, (%ebx) +# Changed the following code for deadlock detection. -- tongli +#if 0 movl $SYS_futex, %eax movl $FUTEX_WAKE, %ecx addl $1, %edx ENTER_KERNEL +#endif +# New code for deadlock detection. -- tongli +# %ebx (uaddr) and %edx: (# threads to wake up) must have already been set +# properly. + pushl %edi + pushl %esi + movl $FUTEX_WAKE, %ecx + movl $3, %esi /* esi: wait_op = '>' */ + xorl %edi, %edi /* edi: wait_val (0) */ + movl $SYS_futex_dd, %eax + ENTER_KERNEL + popl %esi + popl %edi +# End of new code. -- tongli testl %eax, %eax js 1f diff -Naur glibc-2.3.2/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S glibc-2.3.2-dd/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S --- glibc-2.3.2/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S 2003-07-08 17:03:42.000000000 -0400 +++ glibc-2.3.2-dd/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S 2004-09-21 09:52:22.000000000 -0400 @@ -28,6 +28,7 @@ #endif #define SYS_futex 240 +#define SYS_futex_dd 284 /* New syscall -- tongli */ #define FUTEX_WAKE 1 @@ -77,6 +78,8 @@ cfi_offset(3, -8) /* %ebx */ cfi_offset(6, -12) /* %esi */ 1: call __pthread_enable_asynccancel +# Changed the following code for deadlock detection. -- tongli +#if 0 movl %eax, (%esp) xorl %esi, %esi @@ -87,6 +90,27 @@ movl %eax, %esi movl (%esp), %eax +#endif +# Below is the new code for deadlock detection. -- tongli + pushl %eax + pushl %ebx + pushl %edi + pushl %ebp +# %ebx (uaddr) must have already been set properly. + xor %ecx, %ecx /* ecx: op (FUTEX_WAIT 0) */ + xor %edx, %edx /* edx: val */ + movl $3, %esi /* esi: wait_op = '>' */ + xorl %edi, %edi /* edi: wait_val (0) */ + xorl %ebp, %ebp /* utime (no timeout) */ + movl $SYS_futex_dd, %eax + ENTER_KERNEL + movl %eax, %esi + popl %ebp + popl %edi + popl %ebx + popl %eax +# End of new code. -- tongli + call __pthread_disable_asynccancel testl %esi, %esi diff -Naur glibc-2.3.2/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h glibc-2.3.2-dd/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h --- glibc-2.3.2/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h 2003-09-21 04:52:22.000000000 -0400 +++ glibc-2.3.2-dd/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h 2004-09-20 23:55:44.000000000 -0400 @@ -74,7 +74,6 @@ "i" (offsetof (tcbhead_t, sysinfo))); \ } while (0) - #define lll_futex_wake(futex, nr) \ do { \ int __ignore; \ @@ -112,6 +111,8 @@ ret; }) +/* Replaced lll_mutex_lock with a new implementation below. -- tongli */ +#if 0 #define lll_mutex_lock(futex) \ (void) ({ int ignore1, ignore2; \ __asm __volatile (LOCK_INSTR "cmpxchgl %1, %2\n\t" \ @@ -128,6 +129,26 @@ : "=a" (ignore1), "=c" (ignore2), "=m" (futex) \ : "0" (0), "1" (1), "m" (futex) \ : "memory"); }) +#endif + +/* New lll_mutex_lock for deadlock detection. Instead of calling + * __lll_mutex_lock_wait, we call __lll_mutex_lock_wait_dd. -- tongli */ +#define lll_mutex_lock(futex) \ + (void) ({ int ignore1, ignore2; \ + __asm __volatile (LOCK_INSTR "cmpxchgl %1, %2\n\t" \ + "jnz _L_mutex_lock_%=\n\t" \ + ".subsection 1\n\t" \ + ".type _L_mutex_lock_%=,@function\n" \ + "_L_mutex_lock_%=:\n\t" \ + "leal %2, %%ecx\n\t" \ + "call __lll_mutex_lock_wait_dd\n\t" \ + "jmp 1f\n\t" \ + ".size _L_mutex_lock_%=,.-_L_mutex_lock_%=\n" \ + ".previous\n" \ + "1:" \ + : "=a" (ignore1), "=c" (ignore2), "=m" (futex) \ + : "0" (0), "1" (1), "m" (futex) \ + : "memory"); }) /* Special version of lll_mutex_lock which causes the unlock function to @@ -171,6 +192,8 @@ result; }) +/* Replaced lll_mutex_unlock with a new implementation below. -- tongli */ +#if 0 #define lll_mutex_unlock(futex) \ (void) ({ int ignore; \ __asm __volatile (LOCK_INSTR "subl $1,%0\n\t" \ @@ -187,7 +210,26 @@ : "=m" (futex), "=&a" (ignore) \ : "m" (futex) \ : "memory"); }) +#endif +/* New lll_mutex_unlock for deadlock detection. Instead of calling + * __lll_mutex_unlock_wake, we call __lll_mutex_unlock_wake_dd. -- tongli */ +#define lll_mutex_unlock(futex) \ + (void) ({ int ignore; \ + __asm __volatile (LOCK_INSTR "subl $1,%0\n\t" \ + "jne _L_mutex_unlock_%=\n\t" \ + ".subsection 1\n\t" \ + ".type _L_mutex_unlock_%=,@function\n" \ + "_L_mutex_unlock_%=:\n\t" \ + "leal %0, %%eax\n\t" \ + "call __lll_mutex_unlock_wake_dd\n\t" \ + "jmp 1f\n\t" \ + ".size _L_mutex_unlock_%=,.-_L_mutex_unlock_%=\n" \ + ".previous\n" \ + "1:" \ + : "=m" (futex), "=&a" (ignore) \ + : "m" (futex) \ + : "memory"); }) #define lll_mutex_islocked(futex) \ (futex != 0)