Add Requeue-PI support for x86 arch.

This commit is contained in:
Dinakar Guniguntala 2009-12-13 11:50:16 -08:00 committed by Ulrich Drepper
parent 51ddd2c01e
commit 75956694f3
6 changed files with 198 additions and 28 deletions

View File

@ -1,3 +1,14 @@
2009-12-01 Dinakar Guniguntala <dino@in.ibm.com>
* sysdeps/unix/sysv/linux/i386/i486/lowlevellock.h: Define
FUTEX_WAIT_REQUEUE_PI and FUTEX_CMP_REQUEUE_PI.
* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S: If mutex
is a non robust PI mutex, then use FUTEX_CMP_REQUEUE_PI.
* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S: Likewise.
* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: If mutex
is a non robust PI mutex, then use FUTEX_WAIT_REQUEUE_PI.
* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Likewise.
2009-12-12 Ulrich Drepper <drepper@redhat.com> 2009-12-12 Ulrich Drepper <drepper@redhat.com>
* sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S (sem_timedwait): * sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S (sem_timedwait):

View File

@ -91,12 +91,17 @@ __pthread_cond_broadcast:
8: cmpl $-1, %edi 8: cmpl $-1, %edi
je 9f je 9f
/* XXX: The kernel so far doesn't support requeue to PI futex. */ /* Do not use requeue for pshared condvars. */
/* XXX: The kernel only supports FUTEX_CMP_REQUEUE to the same testl $PS_BIT, MUTEX_KIND(%edi)
type of futex (private resp. shared). */
testl $(PI_BIT | PS_BIT), MUTEX_KIND(%edi)
jne 9f jne 9f
/* Requeue to a non-robust PI mutex if the PI bit is set and
the robust bit is not set. */
movl MUTEX_KIND(%edi), %eax
andl $(ROBUST_BIT|PI_BIT), %eax
cmpl $PI_BIT, %eax
je 81f
/* Wake up all threads. */ /* Wake up all threads. */
#ifdef __ASSUME_PRIVATE_FUTEX #ifdef __ASSUME_PRIVATE_FUTEX
movl $(FUTEX_CMP_REQUEUE|FUTEX_PRIVATE_FLAG), %ecx movl $(FUTEX_CMP_REQUEUE|FUTEX_PRIVATE_FLAG), %ecx
@ -138,6 +143,23 @@ __pthread_cond_broadcast:
cfi_restore_state cfi_restore_state
81: movl $(FUTEX_CMP_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %ecx
movl $SYS_futex, %eax
movl $0x7fffffff, %esi
movl $1, %edx
/* Get the address of the futex involved. */
# if MUTEX_FUTEX != 0
addl $MUTEX_FUTEX, %edi
# endif
int $0x80
/* For any kind of error, which mainly is EAGAIN, we try again
with WAKE. The general test also covers running on old
kernels. */
cmpl $0xfffff001, %eax
jb 6b
jmp 9f
/* Initial locking failed. */ /* Initial locking failed. */
1: 1:
#if cond_lock == 0 #if cond_lock == 0

View File

@ -22,6 +22,7 @@
#include <lowlevellock.h> #include <lowlevellock.h>
#include <lowlevelcond.h> #include <lowlevelcond.h>
#include <kernel-features.h> #include <kernel-features.h>
#include <pthread-pi-defines.h>
#include <pthread-errnos.h> #include <pthread-errnos.h>
@ -86,7 +87,17 @@ __pthread_cond_signal:
#endif #endif
cmpl $-1, dep_mutex-cond_futex(%ebx) cmpl $-1, dep_mutex-cond_futex(%ebx)
sete %cl sete %cl
subl $1, %ecx je 8f
movl dep_mutex-cond_futex(%ebx), %edx
/* Requeue to a non-robust PI mutex if the PI bit is set and
the robust bit is not set. */
movl MUTEX_KIND(%edx), %eax
andl $(ROBUST_BIT|PI_BIT), %eax
cmpl $PI_BIT, %eax
je 9f
8: subl $1, %ecx
#ifdef __ASSUME_PRIVATE_FUTEX #ifdef __ASSUME_PRIVATE_FUTEX
andl $FUTEX_PRIVATE_FLAG, %ecx andl $FUTEX_PRIVATE_FLAG, %ecx
#else #else
@ -124,8 +135,34 @@ __pthread_cond_signal:
cfi_restore_state cfi_restore_state
7: /* %ecx should be either FUTEX_WAKE_OP or 9: movl $(FUTEX_CMP_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %ecx
FUTEX_WAKE_OP|FUTEX_PRIVATE_FLAG from the previous syscall. */ movl $SYS_futex, %eax
movl $1, %edx
xorl %esi, %esi
movl dep_mutex-cond_futex(%ebx), %edi
movl (%ebx), %ebp
/* FIXME: Until Ingo fixes 4G/4G vDSO, 6 arg syscalls are broken for
sysenter.
ENTER_KERNEL */
int $0x80
popl %ebp
popl %esi
leal -cond_futex(%ebx), %edi
/* For any kind of error, we try again with WAKE.
The general test also covers running on old kernels. */
cmpl $-4095, %eax
jb 4f
7:
#ifdef __ASSUME_PRIVATE_FUTEX
andl $FUTEX_PRIVATE_FLAG, %ecx
#else
andl %gs:PRIVATE_FUTEX, %ecx
#endif
orl $FUTEX_WAKE, %ecx
xorl $(FUTEX_WAKE ^ FUTEX_WAKE_OP), %ecx xorl $(FUTEX_WAKE ^ FUTEX_WAKE_OP), %ecx
movl $SYS_futex, %eax movl $SYS_futex, %eax
/* %edx should be 1 already from $FUTEX_WAKE_OP syscall. /* %edx should be 1 already from $FUTEX_WAKE_OP syscall.

View File

@ -22,6 +22,7 @@
#include <lowlevellock.h> #include <lowlevellock.h>
#include <lowlevelcond.h> #include <lowlevelcond.h>
#include <pthread-errnos.h> #include <pthread-errnos.h>
#include <pthread-pi-defines.h>
#include <kernel-features.h> #include <kernel-features.h>
@ -95,7 +96,7 @@ __pthread_cond_timedwait:
addl $1, cond_futex(%ebx) addl $1, cond_futex(%ebx)
addl $(1 << nwaiters_shift), cond_nwaiters(%ebx) addl $(1 << nwaiters_shift), cond_nwaiters(%ebx)
#define FRAME_SIZE 24 #define FRAME_SIZE 32
subl $FRAME_SIZE, %esp subl $FRAME_SIZE, %esp
cfi_adjust_cfa_offset(FRAME_SIZE) cfi_adjust_cfa_offset(FRAME_SIZE)
@ -107,8 +108,10 @@ __pthread_cond_timedwait:
movl %edx, 16(%esp) movl %edx, 16(%esp)
movl %eax, 20(%esp) movl %eax, 20(%esp)
/* Reset the pi-requeued flag. */
8: movl $0, 24(%esp)
/* Get the current time. */ /* Get the current time. */
8: movl %ebx, %edx movl %ebx, %edx
#ifdef __NR_clock_gettime #ifdef __NR_clock_gettime
/* Get the clock number. */ /* Get the clock number. */
movl cond_nwaiters(%ebx), %ebx movl cond_nwaiters(%ebx), %ebx
@ -158,6 +161,7 @@ __pthread_cond_timedwait:
movl %edx, 8(%esp) movl %edx, 8(%esp)
movl cond_futex(%ebx), %edi movl cond_futex(%ebx), %edi
movl %edi, 28(%esp)
/* Unlock. */ /* Unlock. */
LOCK LOCK
@ -172,13 +176,50 @@ __pthread_cond_timedwait:
4: call __pthread_enable_asynccancel 4: call __pthread_enable_asynccancel
movl %eax, (%esp) movl %eax, (%esp)
leal 4(%esp), %esi
#if FUTEX_PRIVATE_FLAG > 255 #if FUTEX_PRIVATE_FLAG > 255
xorl %ecx, %ecx xorl %ecx, %ecx
#endif #endif
cmpl $-1, dep_mutex(%ebx) cmpl $-1, dep_mutex(%ebx)
sete %cl sete %cl
subl $1, %ecx je 40f
movl dep_mutex(%ebx), %edi
/* Requeue to a non-robust PI mutex if the PI bit is set and
the robust bit is not set. */
movl MUTEX_KIND(%edi), %eax
andl $(ROBUST_BIT|PI_BIT), %eax
cmpl $PI_BIT, %eax
jne 40f
movl $(FUTEX_WAIT_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %ecx
/* The following only works like this because we only support
two clocks, represented using a single bit. */
testl $1, cond_nwaiters(%ebx)
/* XXX Need to implement using sete instead of a jump. */
jne 42f
orl $FUTEX_CLOCK_REALTIME, %ecx
/* Requeue-PI uses absolute timeout */
42: leal (%ebp), %esi
movl 28(%esp), %edx
addl $cond_futex, %ebx
movl $SYS_futex, %eax
ENTER_KERNEL
subl $cond_futex, %ebx
movl %eax, %esi
/* Set the pi-requeued flag only if the kernel has returned 0. The
kernel does not hold the mutex on ETIMEDOUT or any other error. */
cmpl $0, %eax
sete 24(%esp)
je 41f
/* Normal and PI futexes dont mix. Use normal futex functions only
if the kernel does not support the PI futex functions. */
cmpl $-ENOSYS, %eax
jne 41f
xorl %ecx, %ecx
40: subl $1, %ecx
#ifdef __ASSUME_PRIVATE_FUTEX #ifdef __ASSUME_PRIVATE_FUTEX
andl $FUTEX_PRIVATE_FLAG, %ecx andl $FUTEX_PRIVATE_FLAG, %ecx
#else #else
@ -187,7 +228,8 @@ __pthread_cond_timedwait:
#if FUTEX_WAIT != 0 #if FUTEX_WAIT != 0
addl $FUTEX_WAIT, %ecx addl $FUTEX_WAIT, %ecx
#endif #endif
movl %edi, %edx leal 4(%esp), %esi
movl 28(%esp), %edx
addl $cond_futex, %ebx addl $cond_futex, %ebx
.Ladd_cond_futex: .Ladd_cond_futex:
movl $SYS_futex, %eax movl $SYS_futex, %eax
@ -196,7 +238,7 @@ __pthread_cond_timedwait:
.Lsub_cond_futex: .Lsub_cond_futex:
movl %eax, %esi movl %eax, %esi
movl (%esp), %eax 41: movl (%esp), %eax
call __pthread_disable_asynccancel call __pthread_disable_asynccancel
.LcleanupEND: .LcleanupEND:
@ -284,10 +326,16 @@ __pthread_cond_timedwait:
#endif #endif
jne 10f jne 10f
11: xorl %eax, %eax
/* With requeue_pi, the mutex lock is held in the kernel. */
movl 24(%esp), %ecx
testl %ecx, %ecx
jnz 26f
/* Remove cancellation handler. */ /* Remove cancellation handler. */
11: movl 24+FRAME_SIZE(%esp), %eax movl 24+FRAME_SIZE(%esp), %eax
call __pthread_mutex_cond_lock call __pthread_mutex_cond_lock
addl $FRAME_SIZE, %esp 26: addl $FRAME_SIZE, %esp
cfi_adjust_cfa_offset(-FRAME_SIZE); cfi_adjust_cfa_offset(-FRAME_SIZE);
/* We return the result of the mutex_lock operation if it failed. */ /* We return the result of the mutex_lock operation if it failed. */
@ -317,6 +365,9 @@ __pthread_cond_timedwait:
cfi_restore_state cfi_restore_state
27: call __pthread_mutex_cond_lock_adjust
jmp 26b
/* Initial locking failed. */ /* Initial locking failed. */
1: 1:
#if cond_lock == 0 #if cond_lock == 0

View File

@ -22,6 +22,8 @@
#include <lowlevellock.h> #include <lowlevellock.h>
#include <lowlevelcond.h> #include <lowlevelcond.h>
#include <tcb-offsets.h> #include <tcb-offsets.h>
#include <pthread-errnos.h>
#include <pthread-pi-defines.h>
#include <kernel-features.h> #include <kernel-features.h>
@ -43,6 +45,9 @@ __pthread_cond_wait:
cfi_lsda(DW_EH_PE_udata4, .LexceptSTART) cfi_lsda(DW_EH_PE_udata4, .LexceptSTART)
#endif #endif
pushl %ebp
cfi_adjust_cfa_offset(4)
cfi_rel_offset(%ebp, 0)
pushl %edi pushl %edi
cfi_adjust_cfa_offset(4) cfi_adjust_cfa_offset(4)
cfi_rel_offset(%edi, 0) cfi_rel_offset(%edi, 0)
@ -55,7 +60,7 @@ __pthread_cond_wait:
cfi_remember_state cfi_remember_state
xorl %esi, %esi xorl %esi, %esi
movl 16(%esp), %ebx movl 20(%esp), %ebx
/* Get internal lock. */ /* Get internal lock. */
movl $1, %edx movl $1, %edx
@ -71,7 +76,7 @@ __pthread_cond_wait:
/* Store the reference to the mutex. If there is already a /* Store the reference to the mutex. If there is already a
different value in there this is a bad user bug. */ different value in there this is a bad user bug. */
2: cmpl $-1, dep_mutex(%ebx) 2: cmpl $-1, dep_mutex(%ebx)
movl 20(%esp), %eax movl 24(%esp), %eax
je 15f je 15f
movl %eax, dep_mutex(%ebx) movl %eax, dep_mutex(%ebx)
@ -87,7 +92,7 @@ __pthread_cond_wait:
addl $1, cond_futex(%ebx) addl $1, cond_futex(%ebx)
addl $(1 << nwaiters_shift), cond_nwaiters(%ebx) addl $(1 << nwaiters_shift), cond_nwaiters(%ebx)
#define FRAME_SIZE 16 #define FRAME_SIZE 20
subl $FRAME_SIZE, %esp subl $FRAME_SIZE, %esp
cfi_adjust_cfa_offset(FRAME_SIZE) cfi_adjust_cfa_offset(FRAME_SIZE)
@ -99,8 +104,10 @@ __pthread_cond_wait:
movl %edx, 8(%esp) movl %edx, 8(%esp)
movl %eax, 12(%esp) movl %eax, 12(%esp)
8: movl cond_futex(%ebx), %edi /* Reset the pi-requeued flag. */
8: movl $0, 16(%esp)
movl cond_futex(%ebx), %ebp
/* Unlock. */ /* Unlock. */
LOCK LOCK
#if cond_lock == 0 #if cond_lock == 0
@ -114,12 +121,39 @@ __pthread_cond_wait:
4: call __pthread_enable_asynccancel 4: call __pthread_enable_asynccancel
movl %eax, (%esp) movl %eax, (%esp)
#if FUTEX_PRIVATE_FLAG > 255
xorl %ecx, %ecx xorl %ecx, %ecx
#endif
cmpl $-1, dep_mutex(%ebx) cmpl $-1, dep_mutex(%ebx)
sete %cl sete %cl
subl $1, %ecx je 18f
movl dep_mutex(%ebx), %edi
/* Requeue to a non-robust PI mutex if the PI bit is set and
the robust bit is not set. */
movl MUTEX_KIND(%edi), %eax
andl $(ROBUST_BIT|PI_BIT), %eax
cmpl $PI_BIT, %eax
jne 18f
movl $(FUTEX_WAIT_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %ecx
movl %ebp, %edx
xorl %esi, %esi
addl $cond_futex, %ebx
movl $SYS_futex, %eax
ENTER_KERNEL
subl $cond_futex, %ebx
/* Set the pi-requeued flag only if the kernel has returned 0. The
kernel does not hold the mutex on error. */
cmpl $0, %eax
sete 16(%esp)
je 19f
/* Normal and PI futexes dont mix. Use normal futex functions only
if the kernel does not support the PI futex functions. */
cmpl $-ENOSYS, %eax
jne 19f
xorl %ecx, %ecx
18: subl $1, %ecx
#ifdef __ASSUME_PRIVATE_FUTEX #ifdef __ASSUME_PRIVATE_FUTEX
andl $FUTEX_PRIVATE_FLAG, %ecx andl $FUTEX_PRIVATE_FLAG, %ecx
#else #else
@ -128,7 +162,7 @@ __pthread_cond_wait:
#if FUTEX_WAIT != 0 #if FUTEX_WAIT != 0
addl $FUTEX_WAIT, %ecx addl $FUTEX_WAIT, %ecx
#endif #endif
movl %edi, %edx movl %ebp, %edx
addl $cond_futex, %ebx addl $cond_futex, %ebx
.Ladd_cond_futex: .Ladd_cond_futex:
movl $SYS_futex, %eax movl $SYS_futex, %eax
@ -136,7 +170,7 @@ __pthread_cond_wait:
subl $cond_futex, %ebx subl $cond_futex, %ebx
.Lsub_cond_futex: .Lsub_cond_futex:
movl (%esp), %eax 19: movl (%esp), %eax
call __pthread_disable_asynccancel call __pthread_disable_asynccancel
.LcleanupEND: .LcleanupEND:
@ -212,9 +246,15 @@ __pthread_cond_wait:
#endif #endif
jne 10f jne 10f
11: movl 20+FRAME_SIZE(%esp), %eax /* With requeue_pi, the mutex lock is held in the kernel. */
11: xorl %eax, %eax
movl 16(%esp), %ecx
testl %ecx, %ecx
jnz 20f
movl 24+FRAME_SIZE(%esp), %eax
call __pthread_mutex_cond_lock call __pthread_mutex_cond_lock
addl $FRAME_SIZE, %esp 20: addl $FRAME_SIZE, %esp
cfi_adjust_cfa_offset(-FRAME_SIZE); cfi_adjust_cfa_offset(-FRAME_SIZE);
14: popl %ebx 14: popl %ebx
@ -226,12 +266,19 @@ __pthread_cond_wait:
popl %edi popl %edi
cfi_adjust_cfa_offset(-4) cfi_adjust_cfa_offset(-4)
cfi_restore(%edi) cfi_restore(%edi)
popl %ebp
cfi_adjust_cfa_offset(-4)
cfi_restore(%ebp)
/* We return the result of the mutex_lock operation. */ /* We return the result of the mutex_lock operation. */
ret ret
cfi_restore_state cfi_restore_state
21: call __pthread_mutex_cond_lock_adjust
xorl %eax, %eax
jmp 20b
/* Initial locking failed. */ /* Initial locking failed. */
1: 1:
#if cond_lock == 0 #if cond_lock == 0
@ -484,7 +531,7 @@ __condvar_w_cleanup:
movl $0x7fffffff, %edx movl $0x7fffffff, %edx
ENTER_KERNEL ENTER_KERNEL
5: movl 20+FRAME_SIZE(%esp), %eax 5: movl 24+FRAME_SIZE(%esp), %eax
call __pthread_mutex_cond_lock call __pthread_mutex_cond_lock
movl %esi, (%esp) movl %esi, (%esp)

View File

@ -54,6 +54,8 @@
#define FUTEX_TRYLOCK_PI 8 #define FUTEX_TRYLOCK_PI 8
#define FUTEX_WAIT_BITSET 9 #define FUTEX_WAIT_BITSET 9
#define FUTEX_WAKE_BITSET 10 #define FUTEX_WAKE_BITSET 10
#define FUTEX_WAIT_REQUEUE_PI 11
#define FUTEX_CMP_REQUEUE_PI 12
#define FUTEX_PRIVATE_FLAG 128 #define FUTEX_PRIVATE_FLAG 128
#define FUTEX_CLOCK_REALTIME 256 #define FUTEX_CLOCK_REALTIME 256