Skip to content

Commit

Permalink
Add Requeue-PI support for x86 arch.
Browse files Browse the repository at this point in the history
  • Loading branch information
Dinakar Guniguntala authored and Ulrich Drepper committed Dec 13, 2009
1 parent 51ddd2c commit 7595669
Show file tree
Hide file tree
Showing 6 changed files with 198 additions and 28 deletions.
11 changes: 11 additions & 0 deletions nptl/ChangeLog
Original file line number Diff line number Diff line change
@@ -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>

* sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S (sem_timedwait):
Expand Down
30 changes: 26 additions & 4 deletions nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,17 @@ __pthread_cond_broadcast:
8: cmpl $-1, %edi
je 9f

/* XXX: The kernel so far doesn't support requeue to PI futex. */
/* XXX: The kernel only supports FUTEX_CMP_REQUEUE to the same
type of futex (private resp. shared). */
testl $(PI_BIT | PS_BIT), MUTEX_KIND(%edi)
/* Do not use requeue for pshared condvars. */
testl $PS_BIT, MUTEX_KIND(%edi)
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. */
#ifdef __ASSUME_PRIVATE_FUTEX
movl $(FUTEX_CMP_REQUEUE|FUTEX_PRIVATE_FLAG), %ecx
Expand Down Expand Up @@ -138,6 +143,23 @@ __pthread_cond_broadcast:

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. */
1:
#if cond_lock == 0
Expand Down
43 changes: 40 additions & 3 deletions nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <lowlevellock.h>
#include <lowlevelcond.h>
#include <kernel-features.h>
#include <pthread-pi-defines.h>
#include <pthread-errnos.h>


Expand Down Expand Up @@ -86,7 +87,17 @@ __pthread_cond_signal:
#endif
cmpl $-1, dep_mutex-cond_futex(%ebx)
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
andl $FUTEX_PRIVATE_FLAG, %ecx
#else
Expand Down Expand Up @@ -124,8 +135,34 @@ __pthread_cond_signal:

cfi_restore_state

7: /* %ecx should be either FUTEX_WAKE_OP or
FUTEX_WAKE_OP|FUTEX_PRIVATE_FLAG from the previous syscall. */
9: movl $(FUTEX_CMP_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %ecx
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
movl $SYS_futex, %eax
/* %edx should be 1 already from $FUTEX_WAKE_OP syscall.
Expand Down
67 changes: 59 additions & 8 deletions nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <lowlevellock.h>
#include <lowlevelcond.h>
#include <pthread-errnos.h>
#include <pthread-pi-defines.h>
#include <kernel-features.h>


Expand Down Expand Up @@ -95,7 +96,7 @@ __pthread_cond_timedwait:
addl $1, cond_futex(%ebx)
addl $(1 << nwaiters_shift), cond_nwaiters(%ebx)

#define FRAME_SIZE 24
#define FRAME_SIZE 32
subl $FRAME_SIZE, %esp
cfi_adjust_cfa_offset(FRAME_SIZE)

Expand All @@ -107,8 +108,10 @@ __pthread_cond_timedwait:
movl %edx, 16(%esp)
movl %eax, 20(%esp)

/* Reset the pi-requeued flag. */
8: movl $0, 24(%esp)
/* Get the current time. */
8: movl %ebx, %edx
movl %ebx, %edx
#ifdef __NR_clock_gettime
/* Get the clock number. */
movl cond_nwaiters(%ebx), %ebx
Expand Down Expand Up @@ -158,6 +161,7 @@ __pthread_cond_timedwait:
movl %edx, 8(%esp)

movl cond_futex(%ebx), %edi
movl %edi, 28(%esp)

/* Unlock. */
LOCK
Expand All @@ -172,13 +176,50 @@ __pthread_cond_timedwait:
4: call __pthread_enable_asynccancel
movl %eax, (%esp)

leal 4(%esp), %esi
#if FUTEX_PRIVATE_FLAG > 255
xorl %ecx, %ecx
#endif
cmpl $-1, dep_mutex(%ebx)
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
andl $FUTEX_PRIVATE_FLAG, %ecx
#else
Expand All @@ -187,7 +228,8 @@ __pthread_cond_timedwait:
#if FUTEX_WAIT != 0
addl $FUTEX_WAIT, %ecx
#endif
movl %edi, %edx
leal 4(%esp), %esi
movl 28(%esp), %edx
addl $cond_futex, %ebx
.Ladd_cond_futex:
movl $SYS_futex, %eax
Expand All @@ -196,7 +238,7 @@ __pthread_cond_timedwait:
.Lsub_cond_futex:
movl %eax, %esi

movl (%esp), %eax
41: movl (%esp), %eax
call __pthread_disable_asynccancel
.LcleanupEND:

Expand Down Expand Up @@ -284,10 +326,16 @@ __pthread_cond_timedwait:
#endif
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. */
11: movl 24+FRAME_SIZE(%esp), %eax
movl 24+FRAME_SIZE(%esp), %eax
call __pthread_mutex_cond_lock
addl $FRAME_SIZE, %esp
26: addl $FRAME_SIZE, %esp
cfi_adjust_cfa_offset(-FRAME_SIZE);

/* We return the result of the mutex_lock operation if it failed. */
Expand Down Expand Up @@ -317,6 +365,9 @@ __pthread_cond_timedwait:

cfi_restore_state

27: call __pthread_mutex_cond_lock_adjust
jmp 26b

/* Initial locking failed. */
1:
#if cond_lock == 0
Expand Down
Loading

0 comments on commit 7595669

Please sign in to comment.