From dc39124662b25ce2db28454f1749d67550e4de31 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Thu, 19 Feb 2004 00:55:28 +0000 Subject: [PATCH] Update. 2004-02-18 Carlos O'Donell * test-skeleton.c (main): If set, use environment variable TIMEOUTFACTOR to scale test TIMEOUT. --- ChangeLog | 5 ++ nptl/ChangeLog | 12 +++++ nptl/sysdeps/pthread/pthread_cond_timedwait.c | 11 ++-- .../linux/i386/i486/pthread_cond_timedwait.S | 53 ++++++------------- .../linux/x86_64/pthread_cond_timedwait.S | 51 +++++------------- test-skeleton.c | 18 ++++++- 6 files changed, 66 insertions(+), 84 deletions(-) diff --git a/ChangeLog b/ChangeLog index 39ae87011d..dff56bf8b2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2004-02-18 Carlos O'Donell + + * test-skeleton.c (main): If set, use environment variable + TIMEOUTFACTOR to scale test TIMEOUT. + 2004-02-18 Ulrich Drepper * nscd/nscd_conf.c: Include . diff --git a/nptl/ChangeLog b/nptl/ChangeLog index ad2073d224..35f37cba88 100644 --- a/nptl/ChangeLog +++ b/nptl/ChangeLog @@ -1,3 +1,15 @@ +2004-02-18 Ulrich Drepper + + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S + (__pthread_cond_timedwait): Perform timeout test while holding + internal lock to prevent wakeup race. + Patch by Dinakar Guniguntala . + * sysdeps/pthread/pthread_cond_timedwait.c + (__pthread_cond_timedwait): Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S + (__pthread_cond_timedwait): Likewise. + 2004-02-18 Jakub Jelinek * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_unlock.S diff --git a/nptl/sysdeps/pthread/pthread_cond_timedwait.c b/nptl/sysdeps/pthread/pthread_cond_timedwait.c index 71e9cf7c8d..80b83107f5 100644 --- a/nptl/sysdeps/pthread/pthread_cond_timedwait.c +++ b/nptl/sysdeps/pthread/pthread_cond_timedwait.c @@ -98,9 +98,6 @@ __pthread_cond_timedwait (cond, mutex, abstime) while (1) { - /* Prepare to wait. Release the condvar futex. */ - lll_mutex_unlock (cond->__data.__lock); - struct timespec rt; { #ifdef __NR_clock_gettime @@ -142,12 +139,10 @@ __pthread_cond_timedwait (cond, mutex, abstime) } /* Did we already time out? */ if (__builtin_expect (rt.tv_sec < 0, 0)) - { - /* We are going to look at shared data again, so get the lock. */ - lll_mutex_lock(cond->__data.__lock); + goto timeout; - goto timeout; - } + /* Prepare to wait. Release the condvar futex. */ + lll_mutex_unlock (cond->__data.__lock); /* Enable asynchronous cancellation. Required by the standard. */ cbuffer.oldtype = __pthread_enable_asynccancel (); diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S index 6d1a325b9b..8e6e4bfdf5 100644 --- a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S +++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S @@ -92,21 +92,8 @@ __pthread_cond_timedwait: movl %edi, 12(%esp) movl %edx, 16(%esp) - /* Unlock. */ -8: LOCK -#if cond_lock == 0 - subl $1, (%ebx) -#else - subl $1, cond_lock(%ebx) -#endif - jne 3f - -.LcleanupSTART: -4: call __pthread_enable_asynccancel - movl %eax, (%esp) - /* Get the current time. */ - movl %ebx, %edx +8: movl %ebx, %edx .LebxmovedUR: #ifdef __NR_clock_gettime /* Get the clock number. Note that the field in the condvar @@ -156,6 +143,20 @@ __pthread_cond_timedwait: /* Store relative timeout. */ 21: movl %ecx, 4(%esp) movl %edx, 8(%esp) + + /* Unlock. */ + LOCK +#if cond_lock == 0 + subl $1, (%ebx) +#else + subl $1, cond_lock(%ebx) +#endif + jne 3f + +.LcleanupSTART: +4: call __pthread_enable_asynccancel + movl %eax, (%esp) + leal 4(%esp), %esi xorl %ecx, %ecx /* movl $FUTEX_WAIT, %ecx */ movl %edi, %edx @@ -202,20 +203,8 @@ __pthread_cond_timedwait: 15: cmpl $-ETIMEDOUT, %esi jne 8b - jmp 24f - /* Lock. */ -13: movl $1, %edx - xorl %eax, %eax - LOCK -#if cond_lock == 0 - cmpxchgl %edx, (%ebx) -#else - cmpxchgl %edx, cond_lock(%ebx) -#endif - jnz 23f - -24: addl $1, wakeup_seq(%ebx) +13: addl $1, wakeup_seq(%ebx) adcl $0, wakeup_seq+4(%ebx) movl $ETIMEDOUT, %esi jmp 14f @@ -347,16 +336,6 @@ __pthread_cond_timedwait: js 13b jmp 21b #endif - - /* Locking after time elapsed failed. */ -23: -#if cond_lock == 0 - movl %ebx, %ecx -#else - leal cond_lock(%ebx), %ecx -#endif - call __lll_mutex_lock_wait - jmp 24b .size __pthread_cond_timedwait, .-__pthread_cond_timedwait versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait, GLIBC_2_3_2) diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S index cd5d64791f..f6b6ab246c 100644 --- a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S +++ b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S @@ -118,19 +118,8 @@ __pthread_cond_timedwait: movq wakeup_seq(%rdi), %r12 movq %r12, 40(%rsp) - /* Unlock. */ -8: LOCK -#if cond_lock == 0 - decl (%rdi) -#else - decl cond_lock(%rdi) -#endif - jne 3f - -4: callq __pthread_enable_asynccancel - movl %eax, (%rsp) - /* Get the current time. */ +8: #ifdef __NR_clock_gettime /* Get the clock number. Note that the field in the condvar structure stores the number minus 1. */ @@ -177,6 +166,18 @@ __pthread_cond_timedwait: 21: movq %rcx, 24(%rsp) movq %rdx, 32(%rsp) + /* Unlock. */ + LOCK +#if cond_lock == 0 + decl (%rdi) +#else + decl cond_lock(%rdi) +#endif + jne 3f + +4: callq __pthread_enable_asynccancel + movl %eax, (%rsp) + leaq 24(%rsp), %r10 xorq %rsi, %rsi /* movq $FUTEX_WAIT, %rsi */ movq %r12, %rdx @@ -212,21 +213,8 @@ __pthread_cond_timedwait: 15: cmpq $-ETIMEDOUT, %r14 jne 8b - jmp 24f - /* Lock. */ -13: movq 8(%rsp), %rdi - movl $1, %esi - xorl %eax, %eax - LOCK -#if cond_lock == 0 - cmpxchgl %esi, (%rdi) -#else - cmpxchgl %esi, cond_lock(%rdi) -#endif - jne 23f - -24: incq wakeup_seq(%rdi) +13: incq wakeup_seq(%rdi) movq $ETIMEDOUT, %r14 jmp 14f @@ -340,17 +328,6 @@ __pthread_cond_timedwait: js 13b jmp 21b #endif - - /* Locking after time elapsed failed. */ -23: -#if cond_lock != 0 - addq $cond_lock, %rdi -#endif - callq __lll_mutex_lock_wait -#if cond_lock != 0 - subq $cond_lock, %rdi -#endif - jmp 24b .LENDCODE: .size __pthread_cond_timedwait, .-__pthread_cond_timedwait versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait, diff --git a/test-skeleton.c b/test-skeleton.c index f9061ca186..9d9a68b62c 100644 --- a/test-skeleton.c +++ b/test-skeleton.c @@ -1,5 +1,5 @@ /* Skeleton for test programs. - Copyright (C) 1998, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + Copyright (C) 1998,2000,2001,2002,2003,2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 1998. @@ -193,6 +193,7 @@ main (int argc, char *argv[]) int direct = 0; /* Directly call the test function? */ int status; int opt; + unsigned int timeoutfactor = 1; pid_t termpid; #ifdef STDOUT_UNBUFFERED @@ -215,6 +216,19 @@ main (int argc, char *argv[]) #endif } + /* If set, read the test TIMEOUTFACTOR value from the environment. + This value is used to scale the default test timeout values. */ + char *envstr_timeoutfactor = getenv ("TIMEOUTFACTOR"); + if (envstr_timeoutfactor != NULL) + { + char *envstr_conv = envstr_timeoutfactor; + unsigned long int env_fact; + + env_fact = strtoul (envstr_timeoutfactor, &envstr_conv, 0); + if (*envstr_conv == '\0' && envstr_conv != envstr_timeoutfactor) + timeoutfactor = MAX (env_fact, 1); + } + /* Set TMPDIR to specified test directory. */ if (test_dir != NULL) { @@ -306,7 +320,7 @@ main (int argc, char *argv[]) # define TIMEOUT 2 #endif signal (SIGALRM, timeout_handler); - alarm (TIMEOUT); + alarm (TIMEOUT * timeoutfactor); /* Wait for the regular termination. */ termpid = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0));