Skip to content

Commit

Permalink
Support requeueing for condvars using PI mutex. x86-64 only.
Browse files Browse the repository at this point in the history
Add support for the new FUTEX_WAIT_REQUEUE_PI and FUTEX_CMP_REQUEUE_PI
options of futex.
  • Loading branch information
Ulrich Drepper committed Jul 20, 2009
1 parent 515a890 commit 42e69bc
Show file tree
Hide file tree
Showing 6 changed files with 177 additions and 36 deletions.
9 changes: 9 additions & 0 deletions nptl/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
2009-07-19 Ulrich Drepper <drepper@redhat.com>

* sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Define
FUTEX_WAIT_REQUEUE_PI and FUTEX_CMP_REQUEUE_PI.
* sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S: If mutex
is a PI mutex, then use FUTEX_CMP_REQUEUE_PI.
* sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S: Likewise.
* sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: If mutex
is a PI mutex, then use FUTEX_WAIT_REQUEUE_PI.
* sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Likewise.

* sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S
(__pthread_cond_timedwait): Make more robust.

Expand Down
2 changes: 2 additions & 0 deletions nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@
#define FUTEX_TRYLOCK_PI 8
#define FUTEX_WAIT_BITSET 9
#define FUTEX_WAKE_BITSET 10
#define FUTEX_WAIT_REQUEUE_PI 11
#define FUTEX_CMP_REQUEUE_PI 12
#define FUTEX_PRIVATE_FLAG 128
#define FUTEX_CLOCK_REALTIME 256

Expand Down
26 changes: 21 additions & 5 deletions nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007
/* Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2009
Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
Expand Down Expand Up @@ -70,12 +70,14 @@ __pthread_cond_broadcast:
8: cmpq $-1, %r8
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(%r8)
/* Do not use requeue for pshared condvars. */
testl $PS_BIT, MUTEX_KIND(%r8)
jne 9f

/* Requeue to a PI mutex if the PI bit is set. */
testl $PI_BIT, MUTEX_KIND(%r8)
jne 81f

/* Wake up all threads. */
#ifdef __ASSUME_PRIVATE_FUTEX
movl $(FUTEX_CMP_REQUEUE|FUTEX_PRIVATE_FLAG), %esi
Expand All @@ -97,6 +99,20 @@ __pthread_cond_broadcast:
10: xorl %eax, %eax
retq

/* Wake up all threads. */
81: movl $(FUTEX_CMP_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %esi
movl $SYS_futex, %eax
movl $1, %edx
movl $0x7fffffff, %r10d
syscall

/* For any kind of error, which mainly is EAGAIN, we try again
with WAKE. The general test also covers running on old
kernels. */
cmpq $-4095, %rax
jb 10b
jmp 9f

.align 16
/* Unlock. */
4: LOCK
Expand Down
47 changes: 35 additions & 12 deletions nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright (C) 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
/* Copyright (C) 2002-2005, 2007, 2009 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
Expand All @@ -21,6 +21,7 @@
#include <shlib-compat.h>
#include <lowlevellock.h>
#include <lowlevelcond.h>
#include <pthread-pi-defines.h>
#include <kernel-features.h>
#include <pthread-errnos.h>

Expand Down Expand Up @@ -56,19 +57,23 @@ __pthread_cond_signal:

/* Wake up one thread. */
cmpq $-1, dep_mutex(%r8)
movl $FUTEX_WAKE_OP, %esi
movl $1, %edx
movl $SYS_futex, %eax
je 8f

/* Get the address of the mutex used. */
movq dep_mutex(%r8), %rcx
testl $PI_BIT, MUTEX_KIND(%rcx)
jne 9f

#ifdef __ASSUME_PRIVATE_FUTEX
movl $FUTEX_WAKE_OP, %eax
movl $(FUTEX_WAKE_OP|FUTEX_PRIVATE_FLAG), %esi
cmove %eax, %esi
#else
movl $0, %eax
movl %fs:PRIVATE_FUTEX, %esi
cmove %eax, %esi
orl $FUTEX_WAKE_OP, %esi
orl %fs:PRIVATE_FUTEX, %esi
#endif
movl $1, %r10d
movl $SYS_futex, %eax

8: movl $1, %r10d
#if cond_lock != 0
addq $cond_lock, %r8
#endif
Expand All @@ -85,9 +90,27 @@ __pthread_cond_signal:
xorl %eax, %eax
retq

7: /* %esi should be either FUTEX_WAKE_OP or
FUTEX_WAKE_OP|FUTEX_PRIVATE_FLAG from the previous syscall. */
xorl $(FUTEX_WAKE ^ FUTEX_WAKE_OP), %esi
/* Wake up one thread and requeue none in the PI Mutex case. */
9: movl $(FUTEX_CMP_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %esi
movq %rcx, %r8
xorq %r10, %r10
movl (%rdi), %r9d // XXX Can this be right?
syscall

leaq -cond_futex(%rdi), %r8

/* For any kind of error, we try again with WAKE.
The general test also covers running on old kernels. */
cmpq $-4095, %rax
jb 4f

7:
#ifdef __ASSUME_PRIVATE_FUTEX
andl $FUTEX_PRIVATE_FLAG, %esi
#else
andl %fs:PRIVATE_FUTEX, %esi
#endif
orl $FUTEX_WAKE, %esi
movl $SYS_futex, %eax
/* %rdx should be 1 already from $FUTEX_WAKE_OP syscall.
movl $1, %edx */
Expand Down
69 changes: 59 additions & 10 deletions nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <shlib-compat.h>
#include <lowlevellock.h>
#include <lowlevelcond.h>
#include <pthread-pi-defines.h>
#include <pthread-errnos.h>

#include <kernel-features.h>
Expand Down Expand Up @@ -58,6 +59,9 @@ __pthread_cond_timedwait:
pushq %r14
cfi_adjust_cfa_offset(8)
cfi_rel_offset(%r14, 0)
pushq %r15
cfi_adjust_cfa_offset(8)
cfi_rel_offset(%r15, 0)
#ifdef __ASSUME_FUTEX_CLOCK_REALTIME
# define FRAME_SIZE 32
#else
Expand Down Expand Up @@ -160,9 +164,41 @@ __pthread_cond_timedwait:
movl $FUTEX_WAIT_BITSET, %eax
movl $(FUTEX_WAIT_BITSET|FUTEX_PRIVATE_FLAG), %esi
cmove %eax, %esi
je 60f

movq dep_mutex(%rdi), %r8
/* Requeue to a PI mutex if the PI bit is set. */
testl $PI_BIT, MUTEX_KIND(%r8)
je 60f

movl $(FUTEX_WAIT_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %esi
xorl %eax, %eax
/* The following only works like this because we only support
two clocks, represented using a single bit. */
testl $1, cond_nwaiters(%rdi)
movl $FUTEX_CLOCK_REALTIME, %edx
cmove %edx, %eax
orl %eax, %esi
movq %r12, %rdx
addq $cond_futex, %rdi
movl $SYS_futex, %eax
syscall

movl $1, %r15d
#ifdef __ASSUME_REQUEUE_PI
jmp 62f
#else
cmpq $-4095, %rax
jnae 62f

movl $(FUTEX_WAIT_BITSET|FUTEX_PRIVATE_FLAG), %esi
subq $cond_futex, %rdi
#endif

60: xorl %r15d, %r15d
xorl %eax, %eax
/* The following only works like this because we only support
two clocks, represented using a single bit. */
testl $1, cond_nwaiters(%rdi)
movl $FUTEX_CLOCK_REALTIME, %edx
movl $0xffffffff, %r9d
Expand All @@ -172,7 +208,7 @@ __pthread_cond_timedwait:
addq $cond_futex, %rdi
movl $SYS_futex, %eax
syscall
movq %rax, %r14
62: movq %rax, %r14

movl (%rsp), %edi
callq __pthread_disable_asynccancel
Expand Down Expand Up @@ -253,14 +289,23 @@ __pthread_cond_timedwait:
#endif
jne 40f

41: movq 16(%rsp), %rdi
/* If requeue_pi is used the kernel performs the locking of the
mutex. */
41: xorl %eax, %eax
testl %r15d, %r15d
jnz 63f

movq 16(%rsp), %rdi
callq __pthread_mutex_cond_lock

testq %rax, %rax
63: testq %rax, %rax
cmoveq %r14, %rax

48: addq $FRAME_SIZE, %rsp
cfi_adjust_cfa_offset(-FRAME_SIZE)
popq %r15
cfi_adjust_cfa_offset(-8)
cfi_restore(%r15)
popq %r14
cfi_adjust_cfa_offset(-8)
cfi_restore(%r14)
Expand All @@ -274,10 +319,11 @@ __pthread_cond_timedwait:
retq

/* Initial locking failed. */
31: cfi_adjust_cfa_offset(3 * 8 + FRAME_SIZE)
cfi_rel_offset(%r12, FRAME_SIZE + 16)
cfi_rel_offset(%r13, FRAME_SIZE + 8)
cfi_rel_offset(%r14, FRAME_SIZE)
31: cfi_adjust_cfa_offset(4 * 8 + FRAME_SIZE)
cfi_rel_offset(%r12, FRAME_SIZE + 24)
cfi_rel_offset(%r13, FRAME_SIZE + 16)
cfi_rel_offset(%r14, FRAME_SIZE + 8)
cfi_rel_offset(%r15, FRAME_SIZE)
#if cond_lock != 0
addq $cond_lock, %rdi
#endif
Expand Down Expand Up @@ -353,6 +399,8 @@ __pthread_cond_timedwait:

#ifndef __ASSUME_FUTEX_CLOCK_REALTIME
.Lreltmo:
xorl %r15d, %r15d

/* Get internal lock. */
movl $1, %esi
xorl %eax, %eax
Expand Down Expand Up @@ -716,9 +764,10 @@ __condvar_cleanup2:
callq __pthread_mutex_cond_lock

movq 24(%rsp), %rdi
movq FRAME_SIZE(%rsp), %r14
movq FRAME_SIZE+8(%rsp), %r13
movq FRAME_SIZE+16(%rsp), %r12
movq FRAME_SIZE(%rsp), %r15
movq FRAME_SIZE+8(%rsp), %r14
movq FRAME_SIZE+16(%rsp), %r13
movq FRAME_SIZE+24(%rsp), %r12
.LcallUR:
call _Unwind_Resume@PLT
hlt
Expand Down
Loading

0 comments on commit 42e69bc

Please sign in to comment.