From rolla.n.selbak at intel.com Mon May 3 18:45:07 2004 From: rolla.n.selbak at intel.com (Selbak, Rolla N) Date: Mon, 3 May 2004 11:45:07 -0700 Subject: Open POSIX Test Suite 1.4.1 release Message-ID: <3A0061D7D277B5489DCBBA264884D61E89D1A8@orsmsx403.amr.corp.intel.com> Release 1.4.1 of the Open POSIX Test Suite is now available at http://posixtest.sf.net POSIX Test Suite 1.4.1 includes more pthread conformance test cases. It now also contains test cases covering almost all pthread APIs. Conformance test cases for options like CPT, TCT, TMR added as well. Bug fixes made from the previous 1.3.0 version (thanks for Ulrich Drepper's patches and to everyone who made contributions). This release has been tested on glibc-2004-04-29 cvs pull (NPTL enabled) and linux-2.6.5-mm6 kernel. It is noted that "POSIX Message Queues" has been integrated into linux kernel and glibc. Please see http://posixtest.sf.net for the latest downloads, test results and more information. Thanks, Rolla Selbak http://posixtest.sf.net [POSIX Test Suite project] * my views are not necessarily my employer's * -------------- next part -------------- An HTML attachment was scrubbed... URL: From jason.baietto at ccur.com Mon May 3 20:11:36 2004 From: jason.baietto at ccur.com (Jason Baietto) Date: Mon, 03 May 2004 16:11:36 -0400 Subject: init hook and notify desired Message-ID: <1083614511.18951.79.camel@sprout> I have a need for the following NPTL features: - The ability to register a user-specified function with the NPTL that will be called during thread initialization for all future created threads. - The ability to force all existing threads to call a user-specified function (via a reserved signal). Looking through the 2.3.3 source I don't see anything obvious that provides this functionality. Any advice on how best to implement these hooks? Emphasis on performance. Is there any general interest in this functionality? Take care, Jason -- Jason Baietto http://www.ccur.com/oss From drepper at redhat.com Mon May 3 20:42:44 2004 From: drepper at redhat.com (Ulrich Drepper) Date: Mon, 03 May 2004 13:42:44 -0700 Subject: init hook and notify desired In-Reply-To: <1083614511.18951.79.camel@sprout> References: <1083614511.18951.79.camel@sprout> Message-ID: <4096AEC4.5070009@redhat.com> Jason Baietto wrote: > Is there any general interest in this functionality? I'm not going to add any such non-standard functionality. Especially for something which is implementable as trivial as this without any help of the thread library. -- ? Ulrich Drepper ? Red Hat, Inc. ? 444 Castro St ? Mountain View, CA ? From jason.baietto at ccur.com Mon May 3 21:19:10 2004 From: jason.baietto at ccur.com (Jason Baietto) Date: Mon, 03 May 2004 17:19:10 -0400 Subject: init hook and notify desired In-Reply-To: <4096AEC4.5070009@redhat.com> References: <1083614511.18951.79.camel@sprout> <4096AEC4.5070009@redhat.com> Message-ID: <1083619150.18951.135.camel@sprout> Hi Ulrich, Thanks for the quick response! > I'm not going to add any such non-standard functionality. Understood. I already saw some non-standard things like tkill and gettid so it seemed to be worth asking the question. > Especially for something which is implementable as trivial as this > without any help of the thread library. It is trivial if you control the application code and design. However, the scenario that is interesting to me is when you are using a debugger that can patch code into an executable on the fly. My proposed operations then become more interesting, as their presence in the thread library allows the debugger to do some powerful things with all current and future threads, without having to understand the low-level details of the threads library. In any case, I'll be implementing these features for my own use, so if anyone does have any comments or suggestions I'll be happy to listen and/or share the patches. Take care, Jason -- Jason Baietto http://www.ccur.com/oss From Tony.Reix at bull.net Tue May 4 07:27:46 2004 From: Tony.Reix at bull.net (Tony Reix) Date: Tue, 4 May 2004 09:27:46 +0200 Subject: Version 0.3 of NPTL Trace mechanism design Message-ID: <200405040727.JAA217322@isatis.frec.bull.fr> Hi, The version 0.3 of our Design document about a NPTL Trace mechanism is available at: http://nptl.bullopensource.org/Trace/TraceDesign.v03.html Anyone interested in such a tool can provide comments at: http://nptl.bullopensource.org/phpBB/ NPTL Trace Trace - Design Review About end-users searching a tool for "visualizing" the behaviour of their complex multi-threaded applications or for finding a bug, they should look at the "User's point of view" paragraph and tell us if they find the features they need: http://nptl.bullopensource.org/Trace/TraceDesign.v03.html#user_pov If not, your recommendations/requests about such tools are welcome. Now, our next step is to start coding a first "simple" version. Also, look at our work on testing NPTL in depth: http://nptl.bullopensource.org/ Volunteers are welcome ! Tony Reix Carpe Diem From Tony.Reix at bull.net Thu May 6 08:45:34 2004 From: Tony.Reix at bull.net (Tony Reix) Date: Thu, 6 May 2004 10:45:34 +0200 Subject: EAGAIN (Resource temporarily unavailable) Message-ID: <200405060845.KAA349658@isatis.frec.bull.fr> Hi, While using strace -f with a multi-threaded program, I got many times: [pid 13602] <... futex resumed> ) = -1 EAGAIN (Resource temporarily unavailable) After a while, while cancelling and then joining threads the program hangs: [pid 13601] tgkill(13601, 13602, SIGRTMIN [pid 13602] <... futex resumed> ) = -1 EINTR (Interrupted system call) [pid 13601] <... tgkill resumed> ) = 0 [pid 13602] --- SIGRTMIN (Unknown signal 32) @ 0 (0) --- >>>>>>>>>>> HANG What does it mean ? Environment: Linux version 2.4.21-4.ELsmp (bhcompile at daffy.perf.redhat.com) (gcc version 3.2.3 20030502 (Red Hat Linux 3.2.3-20)) #1 SMP Fri Oct 3 17:52:56 EDT 2003 NPTL 0.60 by Ulrich Drepper Thanks, Amicalement/Regards, Tony Reix (Carpe Diem) From sdeokulecluster at yahoo.com Thu May 13 21:17:41 2004 From: sdeokulecluster at yahoo.com (Sameer Suhas Deokule) Date: Thu, 13 May 2004 14:17:41 -0700 (PDT) Subject: VSZ keeps on increasing as threads created and cancelled on rhel3.0 Message-ID: <20040513211741.66248.qmail@web13123.mail.yahoo.com> Hi , We are observing that even though number of threads in the application is the same (rhel3.0) as the application has to create some threads and cancel them, eventually over a period of time the VSZ for the app. process increases. Why does the stack for the cleanly cancelled thread not get reused when a new thread is created ? I would expect that if the number of threads in use by the application is constant then thread creation and cancellation should not result in VSZ increasing over a period of time. Memory leak testing does not indicate any leaks. thanks Sameer --------------------------------- Do you Yahoo!? Yahoo! Movies - Buy advance tickets for 'Shrek 2' -------------- next part -------------- An HTML attachment was scrubbed... URL: From mru at kth.se Thu May 13 21:26:11 2004 From: mru at kth.se (=?iso-8859-1?q?M=E5ns_Rullg=E5rd?=) Date: Thu, 13 May 2004 23:26:11 +0200 Subject: VSZ keeps on increasing as threads created and cancelled on rhel3.0 In-Reply-To: <20040513211741.66248.qmail@web13123.mail.yahoo.com> (Sameer Suhas Deokule's message of "Thu, 13 May 2004 14:17:41 -0700 (PDT)") References: <20040513211741.66248.qmail@web13123.mail.yahoo.com> Message-ID: Sameer Suhas Deokule writes: > Hi , We are observing that even though number of threads in the > application is the same (rhel3.0) as the application has to create > some threads and cancel them, eventually over a period of time the VSZ > for the app. process increases. Why does the stack for the cleanly > cancelled thread not get reused when a new thread is created ? I would > expect that if the number of threads in use by the application is > constant then thread creation and cancellation should not result in > VSZ increasing over a period of time. Memory leak testing does not > indicate any leaks. I used to see something similar on my machine running regular 2.6 kernels and glibc from cvs. It stopped some time ago though. Supposedly some bug has been fixed. -- M?ns Rullg?rd mru at kth.se From sdeokulecluster at yahoo.com Thu May 13 22:02:56 2004 From: sdeokulecluster at yahoo.com (Sameer Suhas Deokule) Date: Thu, 13 May 2004 15:02:56 -0700 (PDT) Subject: VSZ keeps on increasing as threads created and cancelled on rhel3.0 In-Reply-To: Message-ID: <20040513220256.72720.qmail@web13125.mail.yahoo.com> I am observing this with RHEL3.0. Any information about a patch/update that fixes this for RHEL3.0 would be appreciated.. Linux 2.4.21-4.ELsmp #1 SMP Fri Oct 3 17:52:56 EDT 2003 i686 i686 i386 GNU/Linux libpthread-0.60 libgcc_s-3.2.3-20030829 libc-2.3.2 thanks Sameer M?ns_Rullg?rd wrote:Sameer Suhas Deokule writes: > Hi , We are observing that even though number of threads in the > application is the same (rhel3.0) as the application has to create > some threads and cancel them, eventually over a period of time the VSZ > for the app. process increases. Why does the stack for the cleanly > cancelled thread not get reused when a new thread is created ? I would > expect that if the number of threads in use by the application is > constant then thread creation and cancellation should not result in > VSZ increasing over a period of time. Memory leak testing does not > indicate any leaks. I used to see something similar on my machine running regular 2.6 kernels and glibc from cvs. It stopped some time ago though. Supposedly some bug has been fixed. -- M?ns Rullg?rd mru at kth.se --------------------------------- Do you Yahoo!? Yahoo! Movies - Buy advance tickets for 'Shrek 2' -------------- next part -------------- An HTML attachment was scrubbed... URL: From boris at kolpackov.net Tue May 11 20:17:04 2004 From: boris at kolpackov.net (Boris Kolpackov) Date: Tue, 11 May 2004 15:17:04 -0500 Subject: [PATCH] thread cancellation via C++ exception Message-ID: <20040511201704.GA7908@kolpackov.net> Good day, Just in case somebody would be interested: This patch alters nptl to use C++ exception for thread cancellation. When HAVE_FORCED_UNWIND is defined nptl uses forced unwinding of exception handling mechanism (should we call it ABI exception handling?) to unwind the stack and call cleanup handlers. This allows catching cancellation exception with C++ catch(...) handler. This patch makes nptl throw a C++ exception (std::thread_canceled, defined in pthread.h) during thread cancellation. As a result you can use typed handler to identify this situation: try { // ... } catch (std::thread_caceled const&) { // ... throw; } The patch is against cvs-2004-05-07 and is available from ftp://kolpackov.net/pub/projects/glibc/ comments are welcome, -boris -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 652 bytes Desc: Digital signature URL: From ali at binish.com Mon May 17 19:11:45 2004 From: ali at binish.com (Ali Ijaz Sheikh) Date: Mon, 17 May 2004 15:11:45 -0400 Subject: Debugging and NPTL Message-ID: <1084821105.40a90e71376a1@binish.com> Hi, I have recently started seeing some problems with debugging of multithreaded applications with NPTL on 2.6 series kernels. It seems that GDB is no longer being informed of the events occurring in the child threads because create_thread (nptl/sysdeps/pthread/create_thread.c) routine does not pass the CLONE_PTRACE flag to the clone system call. For example, if the child thread gets a SEGV, the whole thread group is terminated without GDB ever being told. When creating a thread in a thread group that is being ptraced, shouldn't the child thread be created with a CLONE_PTRACE? It this a nptl bug? Or is this GDB's fault? A simple program that creates a thread and does raise(SIGSEGV) in the child thread can be used to reproduce this problem. Try running that in gdb. -Ali ali at binish.com From slamb at slamb.org Mon May 17 20:28:48 2004 From: slamb at slamb.org (Scott Lamb) Date: Mon, 17 May 2004 15:28:48 -0500 Subject: [PATCH] thread cancellation via C++ exception In-Reply-To: <20040511201704.GA7908@kolpackov.net> References: <20040511201704.GA7908@kolpackov.net> Message-ID: On 11 May 2004, at 3:17 PM, Boris Kolpackov wrote: > When HAVE_FORCED_UNWIND is defined nptl uses forced unwinding of > exception > handling mechanism (should we call it ABI exception handling?) to > unwind > the stack and call cleanup handlers. This allows catching cancellation > exception with C++ catch(...) handler. > > This patch makes nptl throw a C++ exception (std::thread_canceled, > defined > in pthread.h) during thread cancellation. As a result you can use typed > handler to identify this situation: A couple questions: 1) Can it be caught and rethrown? I read an earlier thread in which someone mentioned using boost::python. He wanted to catch the cancellation, throw an equivalent Python exception, and rethrow the C++ exception at the other end. This is not allowed currently in NPTL. I'd like to be able to do something similar with C code that is not cancellation-safe. OpenSSL, for example. It would be prohibitively difficult to modify these libraries to use cancellation and get the patches integrated upstream, but much easier to propogate a C error code through then rethrow the exception at the other end. No changes to the C code would then be required. 2) What happens if the thread is canceled while a C++ exception is already active? Unless my test is flawed (it's at ) or NPTL's behavior has changed since the version I tested, it will abort with "terminate called without an active exception". I think the ideal behavior would be to defer the cancellation until the exception is handled. I probably wouldn't use it, even if your patch allowed me to do these things. I've given up on pthread cancellation, due to bugs and the lack of standardization w.r.t. C++. This new behavior might be helpful for code intended to run solely under that environment, but for portable code new behaviors can only make things worse. Instead, I'm working on implementing my own thing on top of my sigsafe library. None of the standard library functions will be cancellation points to my code (just sigsafe_XXX() system call wrappers and code that uses them), but that's life. Thanks, Scott From drow at false.org Mon May 17 20:32:17 2004 From: drow at false.org (Daniel Jacobowitz) Date: Mon, 17 May 2004 16:32:17 -0400 Subject: Debugging and NPTL In-Reply-To: <1084821105.40a90e71376a1@binish.com> References: <1084821105.40a90e71376a1@binish.com> Message-ID: <20040517203217.GA27279@nevyn.them.org> On Mon, May 17, 2004 at 03:11:45PM -0400, Ali Ijaz Sheikh wrote: > > Hi, > > I have recently started seeing some problems with debugging of multithreaded > applications with NPTL on 2.6 series kernels. It seems that GDB is no longer > being informed of the events occurring in the child threads because > create_thread (nptl/sysdeps/pthread/create_thread.c) routine does not pass the > CLONE_PTRACE flag to the clone system call. For example, if the child thread > gets a SEGV, the whole thread group is terminated without GDB ever being told. > > When creating a thread in a thread group that is being ptraced, shouldn't the > child thread be created with a CLONE_PTRACE? It this a nptl bug? Or is this > GDB's fault? > > A simple program that creates a thread and does raise(SIGSEGV) in the child > thread can be used to reproduce this problem. Try running that in gdb. No, it should not be using CLONE_PTRACE. You didn't say what version of GDB you were using; you may want to try a newer one. -- Daniel Jacobowitz From ali at binish.com Mon May 17 20:59:30 2004 From: ali at binish.com (Ali Ijaz Sheikh) Date: Mon, 17 May 2004 16:59:30 -0400 Subject: Debugging and NPTL In-Reply-To: <20040517203217.GA27279@nevyn.them.org> References: <1084821105.40a90e71376a1@binish.com> <20040517203217.GA27279@nevyn.them.org> Message-ID: <1084827570.40a927b2e09cf@binish.com> Quoting Daniel Jacobowitz : > On Mon, May 17, 2004 at 03:11:45PM -0400, Ali Ijaz Sheikh wrote: > > > > Hi, > > > > I have recently started seeing some problems with debugging of > multithreaded > > applications with NPTL on 2.6 series kernels. It seems that GDB is no > longer > > being informed of the events occurring in the child threads because > > create_thread (nptl/sysdeps/pthread/create_thread.c) routine does not pass > the > > CLONE_PTRACE flag to the clone system call. For example, if the child > thread > > gets a SEGV, the whole thread group is terminated without GDB ever being > told. > > > > When creating a thread in a thread group that is being ptraced, shouldn't > the > > child thread be created with a CLONE_PTRACE? It this a nptl bug? Or is > this > > GDB's fault? > > > > A simple program that creates a thread and does raise(SIGSEGV) in the child > > thread can be used to reproduce this problem. Try running that in gdb. > > No, it should not be using CLONE_PTRACE. You didn't say what version > of GDB you were using; you may want to try a newer one. > > -- > Daniel Jacobowitz > I have tried this with GDB 6.0 and 6.1. -Ali From drow at false.org Mon May 17 21:00:40 2004 From: drow at false.org (Daniel Jacobowitz) Date: Mon, 17 May 2004 17:00:40 -0400 Subject: Debugging and NPTL In-Reply-To: <1084827570.40a927b2e09cf@binish.com> References: <1084821105.40a90e71376a1@binish.com> <20040517203217.GA27279@nevyn.them.org> <1084827570.40a927b2e09cf@binish.com> Message-ID: <20040517210040.GA28326@nevyn.them.org> On Mon, May 17, 2004 at 04:59:30PM -0400, Ali Ijaz Sheikh wrote: > Quoting Daniel Jacobowitz : > > > On Mon, May 17, 2004 at 03:11:45PM -0400, Ali Ijaz Sheikh wrote: > > > > > > Hi, > > > > > > I have recently started seeing some problems with debugging of > > multithreaded > > > applications with NPTL on 2.6 series kernels. It seems that GDB is no > > longer > > > being informed of the events occurring in the child threads because > > > create_thread (nptl/sysdeps/pthread/create_thread.c) routine does not pass > > the > > > CLONE_PTRACE flag to the clone system call. For example, if the child > > thread > > > gets a SEGV, the whole thread group is terminated without GDB ever being > > told. > > > > > > When creating a thread in a thread group that is being ptraced, shouldn't > > the > > > child thread be created with a CLONE_PTRACE? It this a nptl bug? Or is > > this > > > GDB's fault? > > > > > > A simple program that creates a thread and does raise(SIGSEGV) in the child > > > thread can be used to reproduce this problem. Try running that in gdb. > > > > No, it should not be using CLONE_PTRACE. You didn't say what version > > of GDB you were using; you may want to try a newer one. > > > > -- > > Daniel Jacobowitz > > > > I have tried this with GDB 6.0 and 6.1. GDB 6.1 should support NPTL out of the box. -- Daniel Jacobowitz From roland at redhat.com Mon May 17 21:24:27 2004 From: roland at redhat.com (Roland McGrath) Date: Mon, 17 May 2004 14:24:27 -0700 Subject: Debugging and NPTL In-Reply-To: Ali Ijaz Sheikh's message of Monday, 17 May 2004 15:11:45 -0400 <1084821105.40a90e71376a1@binish.com> Message-ID: <200405172124.i4HLORMv010700@magilla.sf.frob.com> As Daniel alluded to, there have been a variety of bugs in gdb relating to this, but also in libthread_db and libpthread. So you should make sure you have the latest versions of both gdb and glibc installed before fretting. From drepper at redhat.com Tue May 18 00:06:16 2004 From: drepper at redhat.com (Ulrich Drepper) Date: Mon, 17 May 2004 17:06:16 -0700 Subject: [PATCH] thread cancellation via C++ exception In-Reply-To: <20040511201704.GA7908@kolpackov.net> References: <20040511201704.GA7908@kolpackov.net> Message-ID: <40A95378.10606@redhat.com> This is not only not going to be added to glibc, it's also not guaranteed to work (probably doesn't work today) and can break in interesting ways at any time. Cancellation, as the word already suggests, is final. There mustn't be any catch without rethrow. The thread library does, and will probably even more so in future, alter the state of the library once a thread is canceled and this is not reversible. -- ? Ulrich Drepper ? Red Hat, Inc. ? 444 Castro St ? Mountain View, CA ? From boris at kolpackov.net Mon May 17 21:30:56 2004 From: boris at kolpackov.net (Boris Kolpackov) Date: Mon, 17 May 2004 16:30:56 -0500 Subject: [PATCH] thread cancellation via C++ exception In-Reply-To: References: <20040511201704.GA7908@kolpackov.net> Message-ID: <20040517213056.GA18411@kolpackov.net> Scott Lamb writes: > A couple questions: > > 1) Can it be caught and rethrown? Yes but can't finalize it (in other words the catch block should exit via `throw;'). > I read an earlier thread in which someone mentioned using > boost::python. He wanted to catch the cancellation, throw an equivalent > Python exception, and rethrow the C++ exception at the other end. This > is not allowed currently in NPTL. Right, it is not allowed with my patch either. I agree it would be nice to allow 'native' exceptions to propagate through corresponding parts of call stack. It is not clear, however, how to detect 'cancellation refusal' in such cases. > I'd like to be able to do something similar with C code that is not > cancellation-safe. OpenSSL, for example. It would be prohibitively > difficult to modify these libraries to use cancellation and get the > patches integrated upstream, but much easier to propogate a C error > code through then rethrow the exception at the other end. No changes to > the C code would then be required. Same problem - no way to enforce cancellation. > 2) What happens if the thread is canceled while a C++ exception is > already active? terminate() will be called. > Unless my test is flawed (it's at > test_cancellation_while_throwing.cc>) or NPTL's behavior has changed > since the version I tested, it will abort with "terminate called > without an active exception". With my patch it prints terminate called after throwing a `(anonymous namespace)::pthread_canceled' what(): N37_GLOBAL__N__ZNSt15thread_canceledD2Ev16pthread_canceledE Aborted which is what's expected. > I think the ideal behavior would be to defer the cancellation until > the exception is handled. Well, you can do it already in your dtor: if you are going to call a cancellation point from your dtor (close() comes to mind) then disable cancellation. > I probably wouldn't use it, even if your patch allowed me to do these > things. I've given up on pthread cancellation, due to bugs and the lack > of standardization w.r.t. C++. This new behavior might be helpful for > code intended to run solely under that environment, but for portable > code new behaviors can only make things worse. I stopped worrying about portability and feel noticeably better now ;-) > Instead, I'm working on implementing my own thing on top of my sigsafe > library. None of the standard library functions will be cancellation > points to my code (just sigsafe_XXX() system call wrappers and code > that uses them), but that's life. Are they still going to be cancellation points? For example, if I call your sigsafe_mutex_lock() and then cancel this thread (perhaps through sigsafe_cancel()) will it still work? Note that according to the SUS pthread_mutex_lock "shall not return an error code of [EINTR]". hth, -boris -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 652 bytes Desc: Digital signature URL: From slamb at slamb.org Tue May 18 03:14:08 2004 From: slamb at slamb.org (Scott Lamb) Date: Mon, 17 May 2004 22:14:08 -0500 Subject: [PATCH] thread cancellation via C++ exception In-Reply-To: <20040517213056.GA18411@kolpackov.net> References: <20040511201704.GA7908@kolpackov.net> <20040517213056.GA18411@kolpackov.net> Message-ID: <6D192BC2-A879-11D8-B907-000A95891440@slamb.org> On 17 May 2004, at 4:30 PM, Boris Kolpackov wrote: > Right, it is not allowed with my patch either. I agree it would be nice > to allow 'native' exceptions to propagate through corresponding parts > of call stack. It is not clear, however, how to detect 'cancellation > refusal' in such cases. I'm not sure why this is necessary. Ulrich, you've stated that threads must not refuse cancellation. Okay; then any such program is Seriously Broken(TM) and its behavior is undefined. But it's already impossible to detect all broken programs. And here the attempt to do so seems harmful - if libc didn't try, then the situations I mentioned would be possible. >> I think the ideal behavior would be to defer the cancellation until >> the exception is handled. > > Well, you can do it already in your dtor: if you are going to call > a cancellation point from your dtor (close() comes to mind) then > disable cancellation. Okay. > I stopped worrying about portability and feel noticeably better now ;-) That must be nice. :/ >> Instead, I'm working on implementing my own thing on top of my sigsafe >> library. None of the standard library functions will be cancellation >> points to my code (just sigsafe_XXX() system call wrappers and code >> that uses them), but that's life. > > Are they still going to be cancellation points? For example, if I > call your sigsafe_mutex_lock() and then cancel this thread (perhaps > through sigsafe_cancel()) will it still work? Note that according to > the SUS pthread_mutex_lock "shall not return an error code of [EINTR]". I'll send you a private email about this; I'm sure my library is boring to Ulrich and folks. Thanks, Scott From dgunigun at in.ibm.com Tue May 18 07:10:54 2004 From: dgunigun at in.ibm.com (Dinakar Guniguntala) Date: Tue, 18 May 2004 12:40:54 +0530 Subject: pthread_cond_broadcast and FUTEX_REQUEUE Message-ID: Ulrich, I noticed that pthread_cond_broadcast still uses the FUTEX_REQUEUE functionality in the latest CVS sources whereas this has been removed in RHEL 3.0 update 2. Since there seems to be a testcase that demonstrates this problem, (http://bugme.osdl.org/show_bug.cgi?id=2364) I was wondering if the fix will get into CVS as well. I had also previously noted that another fix for this problem would be to continue to use FUTEX_REQUEUE without releasing the internal condvar lock to prevent corruption of the counters. What are your thoughts on this Regards, Dinakar From jakub at redhat.com Tue May 18 08:50:41 2004 From: jakub at redhat.com (Jakub Jelinek) Date: Tue, 18 May 2004 04:50:41 -0400 Subject: pthread_cond_broadcast and FUTEX_REQUEUE In-Reply-To: References: Message-ID: <20040518085041.GA30909@devserv.devel.redhat.com> On Tue, May 18, 2004 at 12:40:54PM +0530, Dinakar Guniguntala wrote: > I noticed that pthread_cond_broadcast still uses the FUTEX_REQUEUE > functionality in the latest CVS sources whereas this has been > removed in RHEL 3.0 update 2. Since there seems to be a testcase > that demonstrates this problem, > (http://bugme.osdl.org/show_bug.cgi?id=2364) > I was wondering if the fix will get into CVS as well. > > I had also previously noted that another fix for this problem would be to > continue to use FUTEX_REQUEUE without releasing the internal > condvar lock to prevent corruption of the counters. There are actually 2 different problems with current pthread_cond_broadcast: https://www.redhat.com/archives/phil-list/2004-April/msg00002.html http://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=115349 I'm aware of. The latter is fixed by changes Ulrich wrote during the last days and are currently in testing, the former can be solved by adding a new futex(2) operation, FUTEX_CMP_REQUEUE, plus corresponding glibc changes. Please wait a few days until these changes get enough testing, then at least the #115349 fix can go in immediately, the latter needs to wait for kernel people buy-in. Jakub From boris at kolpackov.net Tue May 18 15:25:10 2004 From: boris at kolpackov.net (Boris Kolpackov) Date: Tue, 18 May 2004 10:25:10 -0500 Subject: [PATCH] thread cancellation via C++ exception In-Reply-To: <40A95378.10606@redhat.com> References: <20040511201704.GA7908@kolpackov.net> <40A95378.10606@redhat.com> Message-ID: <20040518152510.GB18609@kolpackov.net> Ulrich Drepper writes: > This is not only not going to be added to glibc, No illusions about that. > it's also not guaranteed to work (probably doesn't work today) and > can break in interesting ways at any time. Are you talking about my patch or about the idea of finalizing the exception? > Cancellation, as the word already suggests, is final. There mustn't be > any catch without rethrow. The thread library does, and will probably > even more so in future, alter the state of the library once a thread is > canceled and this is not reversible. Agree. My patch prevents exception finalization in about the same way as the original nptl code does. -boris -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 652 bytes Desc: Digital signature URL: From jakub at redhat.com Thu May 20 08:53:51 2004 From: jakub at redhat.com (Jakub Jelinek) Date: Thu, 20 May 2004 04:53:51 -0400 Subject: tst-cond18 hang analysis Message-ID: <20040520085351.GT30909@devserv.devel.redhat.com> Hi! This is posted mainly for archival purposes. It documents a nptl/tst-cond18.c hang with NPTL CVS as of 2004-05-16. This ought to be fixed in current CVS (after the 2004-05-18 CVS commits to nptl/) by introducing broadcast_seq. thr1 thr2 thr3 thr4 thr5 thr6 pthread_mutex_lock (&m); pthread_cond_wait (&c, &m); pthread_mutex_lock (&m); pthread_cond_wait (&c, &m); pthread_mutex_lock (&m); pthread_mutex_lock (&m); pthread_mutex_lock (&m); pthread_mutex_lock (&m); pthread_cond_broadcast (&c); pthread_mutex_unlock (&m); pthread_cond_wait (&c, &m); pthread_cond_wait (&c, &m); pthread_cond_signal (&c); pthread_mutex_unlock (&m); pthread_mutex_lock (&m); pthread_mutex_lock (&m); [hang] Detailed: tao thread action 000 1 locks m 000 1 enters cond_wait 000 1 locks c->__data.__lock 000 1 unlocks m 100 1 ++total_seq, thr1's seq = 0 100 1 unlocks c->__data.__lock 100 1 futex_wait (&wakeup_seq) 100 2 locks m 100 2 enters cond_wait 100 2 locks c->__data.__lock 100 2 unlocks m 200 2 ++total_seq, thr2's seq = 0 200 2 unlocks c->__data.__lock 200 2 futex_wait (&wakeup_seq) 200 3 locks m 200 4 attempts to lock m 200 4 futex_wait (&m->__data.__lock) 200 5 attempts to lock m 200 5 futex_wait (&m->__data.__lock) 200 6 attempts to lock m 200 6 futex_wait (&m->__data.__lock) 200 3 enters cond_broadcast 200 3 locks c->__data.__lock 220 3 wakeup_seq = total_seq 220 3 unlocks c->__data.__lock 220 3 futex_requeue (&wakeup_seq) [ thr1 awaken, thr2 requeued to mutex ] 220 3 leaves cond_broadcast 220 1 locks c->__data.__lock 220 1 val = 2; val != seq (0) && val != woken_seq (0), no looping 221 1 ++woken_seq 221 1 unlocks c->__data.__lock 221 1 attempts to lock m 221 1 futex_wait (&m->__data.__lock) 221 3 unlocks m 221 3 futex_wake (&m->__data.__lock) [ thr4 awaken ] 221 4 enters cond_wait 221 4 locks c->__data.__lock 221 4 unlocks m 221 4 futex_wake (&m->__data.__lock) [ thr5 awaken ] 321 4 ++total_seq, thr4's seq = 2 321 4 unlocks c->__data.__lock 321 5 enters cond_wait 321 5 locks c->__data.__lock 321 5 unlocks m 321 5 futex_wake (&m->__data.__lock) [ thr6 awaken ] 421 5 ++total_seq, thr5's seq = 2 421 5 unlocks c->__data.__lock 421 6 enters cond_broadcast 421 6 locks c->__data.__lock 431 6 ++wakeup_seq 431 6 futex_wake (&wakeup_seq) [ nobody awaken ] 431 6 unlocks c->__data.__lock 431 4 futex_wait (&wakeup_seq), returns -EWOULDBLOCK immediately 431 4 locks c->__data.__lock 431 4 val = 3; val != seq (2) && val != woken_seq (1), no looping 432 4 ++woken_seq 432 4 unlocks c->__data.__lock 432 4 attempts to lock m 432 4 futex_wait (&m->__data.__lock) 432 5 futex_wait (&wakeup_seq), returns -EWOULDBLOCK immediately 432 4 locks c->__data.__lock 432 4 val = 3; val != seq (2) && val != woken_seq (2), no looping 433 4 ++woken_seq 433 4 unlocks c->__data.__lock 433 4 attempts to lock m 433 4 futex_wait (&m->__data.__lock) 433 6 unlocks m 433 6 futex_wake (&m->__data.__lock) [ thr2 awaken ] 433 2 locks c->__data.__lock 433 2 val = 3; val != seq (0), but val == woken_seq (3), therefore loop 433 2 unlocks c->__data.__lock 433 2 futex_wait (&wakeup_seq) 433 3 attempts to lock m 433 3 futex_wait (&m->__data.__lock) 433 6 attempts to lock m 433 6 futex_wait (&m->__data.__lock) [ hang ] # thr{1,3,4,5,6} waiting on m->__data.__lock, thr2 waiting on wakeup_seq Legend: tao - total_seq/wakeup_seq/woken_seq Jakub From jakub at redhat.com Thu May 20 08:58:17 2004 From: jakub at redhat.com (Jakub Jelinek) Date: Thu, 20 May 2004 04:58:17 -0400 Subject: tst-cond16 hang analysis Message-ID: <20040520085817.GU30909@devserv.devel.redhat.com> Hi! This is posted mainly for archival purposes. It describes what happens with NPTL CVS as of 2004-05-19 (i.e. after broadcast_seq has been added; the analysis would be slightly different before broadcast_seq has been introduced, but the hang has been there as well (simply remove the b column, ", bc_seq = N" assignments, ++broadcast_seq line and bc_seq == broadcast_seq comparison). thr1 thr2 thr3 pthread_mutex_lock (&m); pthread_cond_wait (&c, &m); pthread_mutex_lock (&m); pthread_mutex_unlock (&m); pthread_cond_broadcast (&c); pthread_mutex_lock (&m); pthread_cond_wait (&c); pthread_mutex_lock &m); pthread_cond_wait (&c, &m); [ hang ] # Normally following would happen afterwards: pthread_mutex_unlock (&m); pthread_mutex_lock (&m); pthread_mutex_unlock (&m); pthread_cond_broadcast (&c); and the waiters would be awaken. Detailed: taob thread action 0000 1 locks m 0000 1 enters cond_wait 0000 1 locks c->__data.__lock 0000 1 unlocks m 1000 1 ++total_seq, thr1's seq = 0, bc_seq = 0 1000 1 unlocks c->__data.__lock 1000 2 locks m 1000 2 unlocks m 1000 2 enters cond_broadcast 1000 2 locks c->__data.__lock 1110 2 wakeup_seq = woken_seq = total_seq 1111 2 ++broadcast_seq 1111 2 unlocks c->__data.__lock 1111 3 locks m 1111 3 enters cond_wait 1111 3 locks c->__data.__lock 1111 3 unlocks m 2111 3 ++total_seq, thr3's seq = 1, bc_seq = 1 2111 3 unlocks c->__data.__lock 2111 3 futex_wait (&wakeup_seq) 2111 1 futex_wait (&wakeup_seq) 2111 2 futex_requeue [ thr3 awaken, thr1 requeued to mutex ] 2111 3 locks c->__data.__lock 2111 3 bc_seq (1) == broadcast_seq, no early exit 2111 3 val = 1; val == seq (1), val (1) == woken_seq (1), therefore loop 2111 3 unlocks c->__data.__lock 2111 3 futex_wait (&wakeup_seq) 2111 2 locks m [ note, m->__data.__lock went from 0 to 1 ] 2111 2 enters cond_wait 2111 2 locks c->__data.__lock 2111 2 unlocks m [ note, m->__data.__lock went from 1 to 0, so thr1 has not been awaken ] 3111 2 ++total_seq, thr1's seq = 1, bc_seq = 1 3111 2 unlocks c->__data.__lock 3111 1 futex_wait (&wakeup_seq) [ hang ] Legend: taob total_seq/wakeup_seq/woken_seq/broadcast_seq Jakub From jakub at redhat.com Thu May 20 09:01:29 2004 From: jakub at redhat.com (Jakub Jelinek) Date: Thu, 20 May 2004 05:01:29 -0400 Subject: [PATCH] tst-cond16 fix - kernel part Message-ID: <20040520090129.GV30909@devserv.devel.redhat.com> Hi! This is the kernel part of tst-cond16 fix. --- linux-2.6.5/include/linux/futex.h.jj 2004-04-04 05:37:36.000000000 +0200 +++ linux-2.6.5/include/linux/futex.h 2004-05-05 09:57:09.200306101 +0200 @@ -8,9 +8,10 @@ #define FUTEX_WAKE (1) #define FUTEX_FD (2) #define FUTEX_REQUEUE (3) - +#define FUTEX_CMP_REQUEUE (4) long do_futex(unsigned long uaddr, int op, int val, - unsigned long timeout, unsigned long uaddr2, int val2); + unsigned long timeout, unsigned long uaddr2, int val2, + int val3); #endif --- linux-2.6.5/kernel/futex.c.jj 2004-04-04 05:36:52.000000000 +0200 +++ linux-2.6.5/kernel/futex.c 2004-05-05 12:23:33.481048623 +0200 @@ -96,6 +96,7 @@ struct futex_q { */ struct futex_hash_bucket { spinlock_t lock; + unsigned int nqueued; struct list_head chain; }; @@ -318,13 +319,14 @@ out: * physical page. */ static int futex_requeue(unsigned long uaddr1, unsigned long uaddr2, - int nr_wake, int nr_requeue) + int nr_wake, int nr_requeue, int *valp) { union futex_key key1, key2; struct futex_hash_bucket *bh1, *bh2; struct list_head *head1; struct futex_q *this, *next; int ret, drop_count = 0; + unsigned int nqueued; down_read(¤t->mm->mmap_sem); @@ -338,12 +340,33 @@ static int futex_requeue(unsigned long u bh1 = hash_futex(&key1); bh2 = hash_futex(&key2); + nqueued = bh1->nqueued; + if (likely (valp != NULL)) { + int curval; + + smp_mb (); + + if (get_user(curval, (int *)uaddr1) != 0) { + ret = -EFAULT; + goto out; + } + if (curval != *valp) { + ret = -EAGAIN; + goto out; + } + } + if (bh1 < bh2) spin_lock(&bh1->lock); spin_lock(&bh2->lock); if (bh1 > bh2) spin_lock(&bh1->lock); + if (unlikely (nqueued != bh1->nqueued && valp != NULL)) { + ret = -EAGAIN; + goto out_unlock; + } + head1 = &bh1->chain; list_for_each_entry_safe(this, next, head1, list) { if (!match_futex (&this->key, &key1)) @@ -365,6 +388,7 @@ static int futex_requeue(unsigned long u } } +out_unlock: spin_unlock(&bh1->lock); if (bh1 != bh2) spin_unlock(&bh2->lock); @@ -398,6 +422,7 @@ static void queue_me(struct futex_q *q, q->lock_ptr = &bh->lock; spin_lock(&bh->lock); + bh->nqueued++; list_add_tail(&q->list, &bh->chain); spin_unlock(&bh->lock); } @@ -625,7 +650,7 @@ out: } long do_futex(unsigned long uaddr, int op, int val, unsigned long timeout, - unsigned long uaddr2, int val2) + unsigned long uaddr2, int val2, int val3) { int ret; @@ -641,7 +666,10 @@ long do_futex(unsigned long uaddr, int o ret = futex_fd(uaddr, val); break; case FUTEX_REQUEUE: - ret = futex_requeue(uaddr, uaddr2, val, val2); + ret = futex_requeue(uaddr, uaddr2, val, val2, NULL); + break; + case FUTEX_CMP_REQUEUE: + ret = futex_requeue(uaddr, uaddr2, val, val2, &val3); break; default: ret = -ENOSYS; @@ -651,7 +679,8 @@ long do_futex(unsigned long uaddr, int o asmlinkage long sys_futex(u32 __user *uaddr, int op, int val, - struct timespec __user *utime, u32 __user *uaddr2) + struct timespec __user *utime, u32 __user *uaddr2, + int val3) { struct timespec t; unsigned long timeout = MAX_SCHEDULE_TIMEOUT; @@ -665,11 +694,11 @@ asmlinkage long sys_futex(u32 __user *ua /* * requeue parameter in 'utime' if op == FUTEX_REQUEUE. */ - if (op == FUTEX_REQUEUE) + if (op >= FUTEX_REQUEUE) val2 = (int) (long) utime; return do_futex((unsigned long)uaddr, op, val, timeout, - (unsigned long)uaddr2, val2); + (unsigned long)uaddr2, val2, val3); } static struct super_block * --- linux-2.6.5/kernel/compat.c.jj 2004-04-04 05:37:07.000000000 +0200 +++ linux-2.6.5/kernel/compat.c 2004-05-05 09:56:36.761119626 +0200 @@ -208,7 +208,7 @@ asmlinkage long compat_sys_sigprocmask(i #ifdef CONFIG_FUTEX asmlinkage long compat_sys_futex(u32 *uaddr, int op, int val, - struct compat_timespec *utime, u32 *uaddr2) + struct compat_timespec *utime, u32 *uaddr2, int val3) { struct timespec t; unsigned long timeout = MAX_SCHEDULE_TIMEOUT; @@ -219,11 +219,11 @@ asmlinkage long compat_sys_futex(u32 *ua return -EFAULT; timeout = timespec_to_jiffies(&t) + 1; } - if (op == FUTEX_REQUEUE) + if (op >= FUTEX_REQUEUE) val2 = (int) (long) utime; return do_futex((unsigned long)uaddr, op, val, timeout, - (unsigned long)uaddr2, val2); + (unsigned long)uaddr2, val2, val3); } #endif Jakub From jakub at redhat.com Thu May 20 09:20:17 2004 From: jakub at redhat.com (Jakub Jelinek) Date: Thu, 20 May 2004 05:20:17 -0400 Subject: [PATCH] tst-cond16 fix - NPTL part Message-ID: <20040520092013.GW30909@devserv.devel.redhat.com> Hi! This is the NPTL part of the tst-cond16 fix. 2004-05-20 Jakub Jelinek * Makefile (tests): Add tst-cond16. * sysdeps/unix/sysv/linux/lowlevelcond.sym (cond_futex): Add. * pthread_cond_init.c (__pthread_cond_init): Clear __data.__futex. * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h (pthread_cond_t): Add __data.__futex field, reshuffle __data.__clock. * sysdeps/unix/sysv/linux/i386/pthread_cond_signal.S (__pthread_cond_signal): Increment __futex at the same time as __wakeup_seq or __total_seq. Pass address of __futex instead of address of low 32-bits of __wakeup_seq to futex syscall. * sysdeps/unix/sysv/linux/i386/pthread_cond_wait.S (__pthread_cond_wait): Likewise. Pass __futex value from before releasing internal lock to FUTEX_WAIT. * sysdeps/unix/sysv/linux/i386/pthread_cond_timedwait.S (__pthread_cond_timedwait): Likewise. * sysdeps/unix/sysv/linux/i386/pthread_cond_broadcast.S (FUTEX_CMP_REQUEUE): Define. (__pthread_cond_broadcast): Set __futex to 2 * __total_seq. Use FUTEX_CMP_REQUEUE operation instead of FUTEX_REQUEUE. Pass __futex value from before the unlock and __futex address instead of address of low 32-bits of __wakeup_seq to futex syscall. Fallback to FUTEX_WAKE all on any errors. * sysdeps/unix/sysv/linux/alpha/lowlevellock.h (FUTEX_CMP_REQUEUE): Define. (lll_futex_requeue): Add val argument, use FUTEX_CMP_REQUEUE internally. Return non-zero if error, zero if success. * sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h (pthread_cond_t): Add __data.__futex field, reshuffle __data.__clock. * sysdeps/unix/sysv/linux/s390/lowlevellock.h (FUTEX_CMP_REQUEUE): Define. (lll_futex_requeue): Add val argument, return 1 unconditionally for the time being. * sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h (pthread_cond_t): Add __data.__futex field, reshuffle __data.__clock. * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h (FUTEX_CMP_REQUEUE): Define. (lll_futex_requeue): Add val argument, use FUTEX_CMP_REQUEUE internally. Return non-zero if error, zero if success. * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h (pthread_cond_t): Add __data.__futex field, reshuffle __data.__clock. * sysdeps/unix/sysv/linux/sparc/lowlevellock.h (FUTEX_CMP_REQUEUE): Define. (lll_futex_requeue): Add val argument, use FUTEX_CMP_REQUEUE internally. Return non-zero if error, zero if success. * sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h (pthread_cond_t): Add __data.__futex field, reshuffle __data.__clock. * sysdeps/unix/sysv/linux/ia64/lowlevellock.h (FUTEX_CMP_REQUEUE): Define. (lll_futex_requeue): Add val argument, use FUTEX_CMP_REQUEUE internally. Return non-zero if error, zero if success. * sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h (pthread_cond_t): Add __data.__futex field, reshuffle __data.__clock. * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h (pthread_cond_t): Add __data.__futex field, reshuffle __data.__clock. * sysdeps/pthread/pthread_cond_signal.c (__pthread_cond_signal): Increment __futex at the same time as __wakeup_seq or __total_seq. Pass address of __futex instead of address of low 32-bits of __wakeup_seq to futex syscall. * sysdeps/pthread/pthread_cond_wait.c (__pthread_cond_wait): Likewise. Pass __futex value from before releasing internal lock to FUTEX_WAIT. * sysdeps/pthread/pthread_cond_timedwait.c (__pthread_cond_timedwait): Likewise. Avoid unnecessary shadowing of variables. * sysdeps/pthread/pthread_cond_broadcast.c (__pthread_cond_broadcast): Set __futex to 2 * __total_seq. Pass __futex value from before the unlock and __futex address instead of address of low 32-bits of __wakeup_seq to futex_requeue macro, adjust for new return value meaning. * sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S (__pthread_cond_signal): Increment __futex at the same time as __wakeup_seq or __total_seq. Pass address of __futex instead of address of low 32-bits of __wakeup_seq to futex syscall. * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S (__pthread_cond_wait): Likewise. Pass __futex value from before releasing internal lock to FUTEX_WAIT. * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S (__pthread_cond_timedwait): Likewise. * sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S (FUTEX_CMP_REQUEUE): Define. (__pthread_cond_broadcast): Set __futex to 2 * __total_seq. Use FUTEX_CMP_REQUEUE operation instead of FUTEX_REQUEUE. Pass __futex value from before the unlock and __futex address instead of address of low 32-bits of __wakeup_seq to futex syscall. Fallback to FUTEX_WAKE all on any errors. --- libc/nptl/Makefile 2004-05-19 22:58:46.405674919 +0200 +++ libc/nptl/Makefile 2004-05-18 14:43:22.000000000 +0200 @@ -194,7 +194,7 @@ tests = tst-attr1 tst-attr2 tst-attr3 \ tst-spin1 tst-spin2 tst-spin3 \ tst-cond1 tst-cond2 tst-cond3 tst-cond4 tst-cond5 tst-cond6 tst-cond7 \ tst-cond8 tst-cond9 tst-cond10 tst-cond11 tst-cond12 tst-cond13 \ - tst-cond14 tst-cond15 tst-cond17 tst-cond18 \ + tst-cond14 tst-cond15 tst-cond16 tst-cond17 tst-cond18 \ tst-rwlock1 tst-rwlock2 tst-rwlock3 tst-rwlock4 tst-rwlock5 \ tst-rwlock6 tst-rwlock7 tst-rwlock8 tst-rwlock9 tst-rwlock10 \ tst-rwlock11 tst-rwlock12 tst-rwlock13 \ --- libc/nptl/pthread_cond_init.c 2004-05-19 22:58:46.405674919 +0200 +++ libc/nptl/pthread_cond_init.c 2004-05-18 14:43:22.000000000 +0200 @@ -31,6 +31,7 @@ __pthread_cond_init (cond, cond_attr) struct pthread_condattr *icond_attr = (struct pthread_condattr *) cond_attr; cond->__data.__lock = LLL_MUTEX_LOCK_INITIALIZER; + cond->__data.__futex = 0; cond->__data.__clock = (icond_attr == NULL ? CLOCK_REALTIME : (icond_attr->value & 0xfe) >> 1); cond->__data.__total_seq = 0; --- libc/nptl/sysdeps/pthread/pthread_cond_broadcast.c 2004-05-19 22:58:46.532652163 +0200 +++ libc/nptl/sysdeps/pthread/pthread_cond_broadcast.c 2004-05-18 14:56:08.000000000 +0200 @@ -41,31 +41,25 @@ __pthread_cond_broadcast (cond) /* Yes. Mark them all as woken. */ cond->__data.__wakeup_seq = cond->__data.__total_seq; cond->__data.__woken_seq = cond->__data.__total_seq; + cond->__data.__futex = (unsigned int) cond->__data.__total_seq * 2; + int futex_val = cond->__data.__futex; /* Signal that a broadcast happened. */ ++cond->__data.__broadcast_seq; /* We are done. */ lll_mutex_unlock (cond->__data.__lock); - /* The futex syscall operates on a 32-bit word. That is fine, - we just use the low 32 bits of the sequence counter. */ -#if BYTE_ORDER == LITTLE_ENDIAN - int *futex = ((int *) (&cond->__data.__wakeup_seq)); -#elif BYTE_ORDER == BIG_ENDIAN - int *futex = ((int *) (&cond->__data.__wakeup_seq)) + 1; -#else -# error "No valid byte order" -#endif - /* Do not use requeue for pshared condvars. */ if (cond->__data.__mutex == (void *) ~0l) goto wake_all; /* Wake everybody. */ pthread_mutex_t *mut = (pthread_mutex_t *) cond->__data.__mutex; - if (__builtin_expect (lll_futex_requeue (futex, 1, INT_MAX, - &mut->__data.__lock) == -EINVAL, - 0)) + /* lll_futex_requeue returns 0 for success and non-zero + for errors. */ + if (__builtin_expect (lll_futex_requeue (&cond->__data.__futex, 1, + INT_MAX, &mut->__data.__lock, + futex_val), 0)) { /* The requeue functionality is not available. */ wake_all: --- libc/nptl/sysdeps/pthread/pthread_cond_signal.c 2003-09-22 07:44:27.000000000 +0200 +++ libc/nptl/sysdeps/pthread/pthread_cond_signal.c 2004-05-18 14:58:04.000000000 +0200 @@ -1,4 +1,4 @@ -/* Copyright (C) 2003 Free Software Foundation, Inc. +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Martin Schwidefsky , 2003. @@ -40,19 +40,10 @@ __pthread_cond_signal (cond) { /* Yes. Mark one of them as woken. */ ++cond->__data.__wakeup_seq; - - /* The futex syscall operates on a 32-bit word. That is fine, - we just use the low 32 bits of the sequence counter. */ -#if BYTE_ORDER == LITTLE_ENDIAN - int *futex = ((int *) (&cond->__data.__wakeup_seq)); -#elif BYTE_ORDER == BIG_ENDIAN - int *futex = ((int *) (&cond->__data.__wakeup_seq)) + 1; -#else -# error "No valid byte order" -#endif + ++cond->__data.__futex; /* Wake one. */ - lll_futex_wake (futex, 1); + lll_futex_wake (&cond->__data.__futex, 1); } /* We are done. */ --- libc/nptl/sysdeps/pthread/pthread_cond_timedwait.c 2004-05-19 22:58:46.533651984 +0200 +++ libc/nptl/sysdeps/pthread/pthread_cond_timedwait.c 2004-05-18 15:05:55.000000000 +0200 @@ -66,6 +66,7 @@ __pthread_cond_timedwait (cond, mutex, a /* We have one new user of the condvar. */ ++cond->__data.__total_seq; + ++cond->__data.__futex; /* Remember the mutex we are using here. If there is already a different address store this is a bad user bug. Do not store @@ -89,27 +90,17 @@ __pthread_cond_timedwait (cond, mutex, a /* Remember the broadcast counter. */ cbuffer.bc_seq = cond->__data.__broadcast_seq; - /* The futex syscall operates on a 32-bit word. That is fine, we - just use the low 32 bits of the sequence counter. */ -#if BYTE_ORDER == LITTLE_ENDIAN - int *futex = ((int *) (&cond->__data.__wakeup_seq)); -#elif BYTE_ORDER == BIG_ENDIAN - int *futex = ((int *) (&cond->__data.__wakeup_seq)) + 1; -#else -# error "No valid byte order" -#endif - while (1) { struct timespec rt; { #ifdef __NR_clock_gettime INTERNAL_SYSCALL_DECL (err); - int val; - val = INTERNAL_SYSCALL (clock_gettime, err, 2, + int ret; + ret = INTERNAL_SYSCALL (clock_gettime, err, 2, cond->__data.__clock, &rt); # ifndef __ASSUME_POSIX_TIMERS - if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (val, err), 0)) + if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (ret, err), 0)) { struct timeval tv; (void) gettimeofday (&tv, NULL); @@ -149,15 +140,17 @@ __pthread_cond_timedwait (cond, mutex, a goto timeout; } + unsigned int futex_val = cond->__data.__futex; + /* 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 (); - /* Wait until woken by signal or broadcast. Note that we - truncate the 'val' value to 32 bits. */ - err = lll_futex_timed_wait (futex, (unsigned int) val, &rt); + /* Wait until woken by signal or broadcast. */ + err = lll_futex_timed_wait (&cond->__data.__futex, + futex_val, &rt); /* Disable asynchronous cancellation. */ __pthread_disable_asynccancel (cbuffer.oldtype); --- libc/nptl/sysdeps/pthread/pthread_cond_wait.c 2004-05-19 22:58:46.552648579 +0200 +++ libc/nptl/sysdeps/pthread/pthread_cond_wait.c 2004-05-18 15:10:07.000000000 +0200 @@ -52,20 +52,14 @@ __condvar_cleanup (void *arg) appropriately. */ ++cbuffer->cond->__data.__wakeup_seq; ++cbuffer->cond->__data.__woken_seq; + ++cbuffer->cond->__data.__futex; } /* We are done. */ lll_mutex_unlock (cbuffer->cond->__data.__lock); /* Wake everybody to make sure no condvar signal gets lost. */ -#if BYTE_ORDER == LITTLE_ENDIAN - int *futex = ((int *) (&cbuffer->cond->__data.__wakeup_seq)); -#elif BYTE_ORDER == BIG_ENDIAN - int *futex = ((int *) (&cbuffer->cond->__data.__wakeup_seq)) + 1; -#else -# error "No valid byte order" -#endif - lll_futex_wake (futex, INT_MAX); + lll_futex_wake (&cbuffer->cond->__data.__futex, INT_MAX); /* Get the mutex before returning unless asynchronous cancellation is in effect. */ @@ -95,6 +89,7 @@ __pthread_cond_wait (cond, mutex) /* We have one new user of the condvar. */ ++cond->__data.__total_seq; + ++cond->__data.__futex; /* Remember the mutex we are using here. If there is already a different address store this is a bad user bug. Do not store @@ -118,27 +113,18 @@ __pthread_cond_wait (cond, mutex) /* Remember the broadcast counter. */ cbuffer.bc_seq = cond->__data.__broadcast_seq; - /* The futex syscall operates on a 32-bit word. That is fine, we - just use the low 32 bits of the sequence counter. */ -#if BYTE_ORDER == LITTLE_ENDIAN - int *futex = ((int *) (&cond->__data.__wakeup_seq)); -#elif BYTE_ORDER == BIG_ENDIAN - int *futex = ((int *) (&cond->__data.__wakeup_seq)) + 1; -#else -# error "No valid byte order" -#endif - do { + unsigned int futex_val = cond->__data.__futex; + /* 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 (); - /* Wait until woken by signal or broadcast. Note that we - truncate the 'val' value to 32 bits. */ - lll_futex_wait (futex, (unsigned int) val); + /* Wait until woken by signal or broadcast. */ + lll_futex_wait (&cond->__data.__futex, futex_val); /* Disable asynchronous cancellation. */ __pthread_disable_asynccancel (cbuffer.oldtype); --- libc/nptl/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h 2004-05-19 22:58:46.609638366 +0200 +++ libc/nptl/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h 2004-05-18 14:44:38.000000000 +0200 @@ -76,11 +76,12 @@ typedef union struct { int __lock; - int __clock; + unsigned int __futex; unsigned long long int __total_seq; unsigned long long int __wakeup_seq; unsigned long long int __woken_seq; void *__mutex; + int __clock; unsigned int __broadcast_seq; } __data; char __size[__SIZEOF_PTHREAD_COND_T]; --- libc/nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h 2004-03-24 12:16:58.000000000 +0100 +++ libc/nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h 2004-05-18 15:13:18.000000000 +0200 @@ -30,6 +30,7 @@ #define FUTEX_WAIT 0 #define FUTEX_WAKE 1 #define FUTEX_REQUEUE 3 +#define FUTEX_CMP_REQUEUE 4 /* Initializer for compatibility lock. */ #define LLL_MUTEX_LOCK_INITIALIZER (0) @@ -61,14 +62,15 @@ INTERNAL_SYSCALL_ERROR_P (__ret, __err)? -__ret : __ret; \ }) -#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex) \ +/* Returns non-zero if error happened, zero if success. */ +#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex, val) \ ({ \ INTERNAL_SYSCALL_DECL (__err); \ long int __ret; \ - __ret = INTERNAL_SYSCALL (futex, __err, 5, \ - (futexp), FUTEX_REQUEUE, (nr_wake), (nr_move), \ - (mutex)); \ - INTERNAL_SYSCALL_ERROR_P (__ret, __err)? -__ret : __ret; \ + __ret = INTERNAL_SYSCALL (futex, __err, 6, \ + (futexp), FUTEX_CMP_REQUEUE, (nr_wake), \ + (nr_move), (mutex), (val)); \ + INTERNAL_SYSCALL_ERROR_P (__ret, __err); \ }) --- libc/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h 2004-05-19 22:58:46.610638187 +0200 +++ libc/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h 2004-05-18 14:43:22.000000000 +0200 @@ -76,11 +76,12 @@ typedef union struct { int __lock; - int __clock; + unsigned int __futex; unsigned long long int __total_seq; unsigned long long int __wakeup_seq; unsigned long long int __woken_seq; void *__mutex; + int __clock; unsigned int __broadcast_seq; } __data; char __size[__SIZEOF_PTHREAD_COND_T]; --- libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S 2004-05-19 22:58:46.611638008 +0200 +++ libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S 2004-05-18 14:43:22.000000000 +0200 @@ -32,6 +32,7 @@ #define FUTEX_WAIT 0 #define FUTEX_WAKE 1 #define FUTEX_REQUEUE 3 +#define FUTEX_CMP_REQUEUE 4 #define EINVAL 22 @@ -47,8 +48,9 @@ __pthread_cond_broadcast: pushl %ebx pushl %esi pushl %edi + pushl %ebp - movl 16(%esp), %ebx + movl 20(%esp), %ebx /* Get internal lock. */ movl $1, %edx @@ -61,29 +63,31 @@ __pthread_cond_broadcast: #endif jnz 1f -2: addl $wakeup_seq, %ebx - movl total_seq+4-wakeup_seq(%ebx), %eax - movl total_seq-wakeup_seq(%ebx), %ecx - cmpl 4(%ebx), %eax +2: addl $cond_futex, %ebx + movl total_seq+4-cond_futex(%ebx), %eax + movl total_seq-cond_futex(%ebx), %ebp + cmpl wakeup_seq+4-cond_futex(%ebx), %eax ja 3f jb 4f - cmpl (%ebx), %ecx + cmpl wakeup_seq-cond_futex(%ebx), %ebp jna 4f /* Cause all currently waiting threads to recognize they are woken up. */ -3: movl %ecx, (%ebx) - movl %eax, 4(%ebx) - movl %ecx, woken_seq-wakeup_seq(%ebx) - movl %eax, woken_seq-wakeup_seq+4(%ebx) - addl $1, broadcast_seq-wakeup_seq(%ebx) +3: movl %ebp, wakeup_seq-cond_futex(%ebx) + movl %eax, wakeup_seq-cond_futex+4(%ebx) + movl %ebp, woken_seq-cond_futex(%ebx) + movl %eax, woken_seq-cond_futex+4(%ebx) + addl %ebp, %ebp + addl $1, broadcast_seq-cond_futex(%ebx) + movl %ebp, (%ebx) /* Get the address of the mutex used. */ - movl dep_mutex-wakeup_seq(%ebx), %edi + movl dep_mutex-cond_futex(%ebx), %edi /* Unlock. */ LOCK - subl $1, cond_lock-wakeup_seq(%ebx) + subl $1, cond_lock-cond_futex(%ebx) jne 7f /* Don't use requeue for pshared condvars. */ @@ -91,7 +95,7 @@ __pthread_cond_broadcast: je 9f /* Wake up all threads. */ - movl $FUTEX_REQUEUE, %ecx + movl $FUTEX_CMP_REQUEUE, %ecx movl $SYS_futex, %eax movl $0x7fffffff, %esi movl $1, %edx @@ -99,14 +103,18 @@ __pthread_cond_broadcast: # if MUTEX_FUTEX != 0 addl $MUTEX_FUTEX, %edi # endif - ENTER_KERNEL - -#ifndef __ASSUME_FUTEX_REQUEUE - cmpl $-EINVAL, %eax - je 9f -#endif +/* FIXME: Until Ingo fixes 4G/4G vDSO, 6 arg syscalls are broken for sysenter. + ENTER_KERNEL */ + 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 + jae 9f 10: xorl %eax, %eax + popl %ebp popl %edi popl %esi popl %ebx @@ -115,10 +123,11 @@ __pthread_cond_broadcast: .align 16 /* Unlock. */ 4: LOCK - subl $1, cond_lock-wakeup_seq(%ebx) + subl $1, cond_lock-cond_futex(%ebx) jne 5f 6: xorl %eax, %eax + popl %ebp popl %edi popl %esi popl %ebx @@ -135,12 +144,12 @@ __pthread_cond_broadcast: jmp 2b /* Unlock in loop requires waekup. */ -5: leal cond_lock-wakeup_seq(%ebx), %eax +5: leal cond_lock-cond_futex(%ebx), %eax call __lll_mutex_unlock_wake jmp 6b /* Unlock in loop requires waekup. */ -7: leal cond_lock-wakeup_seq(%ebx), %eax +7: leal cond_lock-cond_futex(%ebx), %eax call __lll_mutex_unlock_wake jmp 8b --- libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S 2004-02-19 17:50:40.000000000 +0100 +++ libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S 2004-05-18 14:43:22.000000000 +0200 @@ -60,22 +60,23 @@ __pthread_cond_signal: #endif jnz 1f -2: leal wakeup_seq(%edi), %ebx +2: leal cond_futex(%edi), %ebx movl total_seq+4(%edi), %eax movl total_seq(%edi), %ecx - cmpl 4(%ebx), %eax + cmpl wakeup_seq+4(%edi), %eax #if cond_lock != 0 /* Must use leal to preserve the flags. */ leal cond_lock(%edi), %edi #endif ja 3f jb 4f - cmpl (%ebx), %ecx + cmpl wakeup_seq-cond_futex(%ebx), %ecx jbe 4f /* Bump the wakeup number. */ -3: addl $1, (%ebx) - adcl $0, 4(%ebx) +3: addl $1, wakeup_seq-cond_futex(%ebx) + adcl $0, wakeup_seq-cond_futex+4(%ebx) + addl $1, (%ebx) /* Wake up one thread. */ movl $FUTEX_WAKE, %ecx --- libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S 2004-05-19 22:58:46.612637829 +0200 +++ libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S 2004-05-18 14:43:22.000000000 +0200 @@ -82,6 +82,7 @@ __pthread_cond_timedwait: addl $1, total_seq(%ebx) adcl $0, total_seq+4(%ebx) + addl $1, cond_futex(%ebx) #define FRAME_SIZE 24 subl $FRAME_SIZE, %esp @@ -148,6 +149,8 @@ __pthread_cond_timedwait: 21: movl %ecx, 4(%esp) movl %edx, 8(%esp) + movl cond_futex(%ebx), %edi + /* Unlock. */ LOCK #if cond_lock == 0 @@ -164,12 +167,12 @@ __pthread_cond_timedwait: leal 4(%esp), %esi xorl %ecx, %ecx /* movl $FUTEX_WAIT, %ecx */ movl %edi, %edx - addl $wakeup_seq, %ebx -.Ladd_wakeup: + addl $cond_futex, %ebx +.Ladd_cond_futex: movl $SYS_futex, %eax ENTER_KERNEL - subl $wakeup_seq, %ebx -.Lsub_wakeup: + subl $cond_futex, %ebx +.Lsub_cond_futex: movl %eax, %esi movl (%esp), %eax @@ -212,6 +215,7 @@ __pthread_cond_timedwait: addl $1, wakeup_seq(%ebx) adcl $0, wakeup_seq+4(%ebx) + addl $1, cond_futex(%ebx) movl $ETIMEDOUT, %esi jmp 14f @@ -359,7 +363,7 @@ __condvar_tw_cleanup3: .size __condvar_tw_cleanup3, .-__condvar_tw_cleanup3 .type __condvar_tw_cleanup2, @function __condvar_tw_cleanup2: - subl $wakeup_seq, %ebx + subl $cond_futex, %ebx .size __condvar_tw_cleanup2, .-__condvar_tw_cleanup2 .type __condvar_tw_cleanup, @function __condvar_tw_cleanup: @@ -390,6 +394,8 @@ __condvar_tw_cleanup: addl $1, wakeup_seq(%ebx) adcl $0, wakeup_seq+4(%ebx) + addl $1, cond_futex(%ebx) + addl $1, woken_seq(%ebx) adcl $0, woken_seq+4(%ebx) @@ -409,7 +415,7 @@ __condvar_tw_cleanup: call __lll_mutex_unlock_wake /* Wake up all waiters to make sure no signal gets lost. */ -2: addl $wakeup_seq, %ebx +2: addl $cond_futex, %ebx movl $FUTEX_WAKE, %ecx movl $SYS_futex, %eax movl $0x7fffffff, %edx @@ -435,7 +441,7 @@ __condvar_tw_cleanup: .uleb128 .Lcstend-.Lcstbegin .Lcstbegin: .long .LcleanupSTART-.LSTARTCODE - .long .Ladd_wakeup-.LcleanupSTART + .long .Ladd_cond_futex-.LcleanupSTART .long __condvar_tw_cleanup-.LSTARTCODE .uleb128 0 .long .LebxmovedUR-.LSTARTCODE @@ -443,15 +449,15 @@ __condvar_tw_cleanup: .long __condvar_tw_cleanup3-.LSTARTCODE .uleb128 0 .long .LebxmovedUR-.LSTARTCODE - .long .Ladd_wakeup-.LebxmovedUR + .long .Ladd_cond_futex-.LebxmovedUR .long __condvar_tw_cleanup-.LSTARTCODE .uleb128 0 - .long .Ladd_wakeup-.LSTARTCODE - .long .Lsub_wakeup-.Ladd_wakeup + .long .Ladd_cond_futex-.LSTARTCODE + .long .Lsub_cond_futex-.Ladd_cond_futex .long __condvar_tw_cleanup2-.LSTARTCODE .uleb128 0 - .long .Lsub_wakeup-.LSTARTCODE - .long .LcleanupEND-.Lsub_wakeup + .long .Lsub_cond_futex-.LSTARTCODE + .long .LcleanupEND-.Lsub_cond_futex .long __condvar_tw_cleanup-.LSTARTCODE .uleb128 0 .long .LcallUR-.LSTARTCODE --- libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S 2004-05-19 22:58:46.613637649 +0200 +++ libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S 2004-05-18 14:43:22.000000000 +0200 @@ -79,6 +79,7 @@ __pthread_cond_wait: addl $1, total_seq(%ebx) adcl $0, total_seq+4(%ebx) + addl $1, cond_futex(%ebx) #define FRAME_SIZE 16 subl $FRAME_SIZE, %esp @@ -92,8 +93,10 @@ __pthread_cond_wait: movl %edx, 8(%esp) movl %eax, 12(%esp) +8: movl cond_futex(%ebx), %edi + /* Unlock. */ -8: LOCK + LOCK #if cond_lock == 0 subl $1, (%ebx) #else @@ -107,12 +110,12 @@ __pthread_cond_wait: movl %esi, %ecx /* movl $FUTEX_WAIT, %ecx */ movl %edi, %edx - addl $wakeup_seq, %ebx -.Ladd_wakeup: + addl $cond_futex, %ebx +.Ladd_cond_futex: movl $SYS_futex, %eax ENTER_KERNEL - subl $wakeup_seq, %ebx -.Lsub_wakeup: + subl $cond_futex, %ebx +.Lsub_cond_futex: movl (%esp), %eax call __pthread_disable_asynccancel @@ -246,7 +249,7 @@ versioned_symbol (libpthread, __pthread_ .type __condvar_w_cleanup2, @function __condvar_w_cleanup2: - subl $wakeup_seq, %ebx + subl $cond_futex, %ebx .size __condvar_w_cleanup2, .-__condvar_w_cleanup2 .LSbl4: .type __condvar_w_cleanup, @function @@ -278,6 +281,8 @@ __condvar_w_cleanup: addl $1, wakeup_seq(%ebx) adcl $0, wakeup_seq+4(%ebx) + addl $1, cond_futex(%ebx) + addl $1, woken_seq(%ebx) adcl $0, woken_seq+4(%ebx) @@ -297,7 +302,7 @@ __condvar_w_cleanup: call __lll_mutex_unlock_wake /* Wake up all waiters to make sure no signal gets lost. */ -2: addl $wakeup_seq, %ebx +2: addl $cond_futex, %ebx movl $FUTEX_WAKE, %ecx movl $SYS_futex, %eax movl $0x7fffffff, %edx @@ -323,15 +328,15 @@ __condvar_w_cleanup: .uleb128 .Lcstend-.Lcstbegin .Lcstbegin: .long .LcleanupSTART-.LSTARTCODE - .long .Ladd_wakeup-.LcleanupSTART + .long .Ladd_cond_futex-.LcleanupSTART .long __condvar_w_cleanup-.LSTARTCODE .uleb128 0 - .long .Ladd_wakeup-.LSTARTCODE - .long .Lsub_wakeup-.Ladd_wakeup + .long .Ladd_cond_futex-.LSTARTCODE + .long .Lsub_cond_futex-.Ladd_cond_futex .long __condvar_w_cleanup2-.LSTARTCODE .uleb128 0 - .long .Lsub_wakeup-.LSTARTCODE - .long .LcleanupEND-.Lsub_wakeup + .long .Lsub_cond_futex-.LSTARTCODE + .long .LcleanupEND-.Lsub_cond_futex .long __condvar_w_cleanup-.LSTARTCODE .uleb128 0 .long .LcallUR-.LSTARTCODE --- libc/nptl/sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h 2004-05-19 22:58:46.614637470 +0200 +++ libc/nptl/sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h 2004-05-18 14:46:13.000000000 +0200 @@ -76,11 +76,12 @@ typedef union struct { int __lock; - int __clock; + unsigned int __futex; unsigned long long int __total_seq; unsigned long long int __wakeup_seq; unsigned long long int __woken_seq; void *__mutex; + int __clock; unsigned int __broadcast_seq; } __data; char __size[__SIZEOF_PTHREAD_COND_T]; --- libc/nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.h 2004-03-24 12:16:59.000000000 +0100 +++ libc/nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.h 2004-05-18 15:27:23.000000000 +0200 @@ -30,6 +30,7 @@ #define FUTEX_WAIT 0 #define FUTEX_WAKE 1 #define FUTEX_REQUEUE 3 +#define FUTEX_CMP_REQUEUE 4 /* Delay in spinlock loop. */ #define BUSY_WAIT_NOP asm ("hint @pause") @@ -52,11 +53,13 @@ _r10 == -1 ? -_retval : _retval; \ }) -#define lll_futex_requeue(ftx, nr_wake, nr_move, mutex) \ +/* Returns non-zero if error happened, zero if success. */ +#define lll_futex_requeue(ftx, nr_wake, nr_move, mutex, val) \ ({ \ - DO_INLINE_SYSCALL(futex, 5, (long) (ftx), FUTEX_REQUEUE, (int) (nr_wake), \ - (int) (nr_move), (long) (mutex)); \ - _r10 == -1 ? -_retval : _retval; \ + DO_INLINE_SYSCALL(futex, 6, (long) (ftx), FUTEX_CMP_REQUEUE, \ + (int) (nr_wake), (int) (nr_move), (long) (mutex), \ + (int) val); \ + _r10 == -1; \ }) --- libc/nptl/sysdeps/unix/sysv/linux/lowlevelcond.sym 2004-05-19 22:58:46.588642129 +0200 +++ libc/nptl/sysdeps/unix/sysv/linux/lowlevelcond.sym 2004-05-18 14:43:22.000000000 +0200 @@ -4,6 +4,7 @@ -- cond_lock offsetof (pthread_cond_t, __data.__lock) +cond_futex offsetof (pthread_cond_t, __data.__futex) cond_clock offsetof (pthread_cond_t, __data.__clock) total_seq offsetof (pthread_cond_t, __data.__total_seq) wakeup_seq offsetof (pthread_cond_t, __data.__wakeup_seq) --- libc/nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h 2004-05-19 22:58:46.623635858 +0200 +++ libc/nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h 2004-05-18 14:45:21.000000000 +0200 @@ -96,11 +96,12 @@ typedef union struct { int __lock; - int __clock; + unsigned int __futex; unsigned long long int __total_seq; unsigned long long int __wakeup_seq; unsigned long long int __woken_seq; void *__mutex; + int __clock; unsigned int __broadcast_seq; } __data; char __size[__SIZEOF_PTHREAD_COND_T]; --- libc/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h 2004-04-13 10:42:53.000000000 +0200 +++ libc/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h 2004-05-18 15:19:01.000000000 +0200 @@ -30,6 +30,7 @@ #define FUTEX_WAIT 0 #define FUTEX_WAKE 1 #define FUTEX_REQUEUE 3 +#define FUTEX_CMP_REQUEUE 4 /* Initializer for compatibility lock. */ #define LLL_MUTEX_LOCK_INITIALIZER (0) @@ -64,15 +65,16 @@ INTERNAL_SYSCALL_ERROR_P (__ret, __err) ? -__ret : __ret; \ }) -#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex) \ +/* Returns non-zero if error happened, zero if success. */ +#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex, val) \ ({ \ INTERNAL_SYSCALL_DECL (__err); \ long int __ret; \ \ - __ret = INTERNAL_SYSCALL (futex, __err, 5, \ - (futexp), FUTEX_REQUEUE, (nr_wake), (nr_move), \ - (mutex)); \ - INTERNAL_SYSCALL_ERROR_P (__ret, __err) ? -__ret : __ret; \ + __ret = INTERNAL_SYSCALL (futex, __err, 6, \ + (futexp), FUTEX_CMP_REQUEUE, (nr_wake), \ + (nr_move), (mutex), (val)); \ + INTERNAL_SYSCALL_ERROR_P (__ret, __err); \ }) #ifdef UP --- libc/nptl/sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h 2004-05-19 22:58:46.628634962 +0200 +++ libc/nptl/sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h 2004-05-18 14:44:56.000000000 +0200 @@ -95,11 +95,12 @@ typedef union struct { int __lock; - int __clock; + unsigned int __futex; unsigned long long int __total_seq; unsigned long long int __wakeup_seq; unsigned long long int __woken_seq; void *__mutex; + int __clock; unsigned int __broadcast_seq; } __data; char __size[__SIZEOF_PTHREAD_COND_T]; --- libc/nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h 2004-03-24 12:17:00.000000000 +0100 +++ libc/nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h 2004-05-18 15:16:44.000000000 +0200 @@ -29,6 +29,7 @@ #define FUTEX_WAIT 0 #define FUTEX_WAKE 1 #define FUTEX_REQUEUE 3 +#define FUTEX_CMP_REQUEUE 4 /* Initializer for compatibility lock. */ #define LLL_MUTEX_LOCK_INITIALIZER (0) @@ -82,22 +83,29 @@ }) -#define lll_futex_requeue(futex, nr_wake, nr_move, mutex) \ +/* Returns non-zero if error happened, zero if success. */ +#if 0 +/* FIXME: s390 only supports up to 5 argument syscalls. Once FUTEX_CMP_REQUEUE + kernel interface for s390 is finalized, adjust this. */ +#define lll_futex_requeue(futex, nr_wake, nr_move, mutex, val) \ ({ \ - register unsigned long int __r2 asm ("2") = (unsigned long int) (futex); \ - register unsigned long int __r3 asm ("3") = FUTEX_REQUEUE; \ - register unsigned long int __r4 asm ("4") = (long int) (nr_wake); \ - register unsigned long int __r5 asm ("5") = (long int) (nr_move); \ - register unsigned long int __r6 asm ("6") = (unsigned long int) (mutex); \ - register unsigned long __result asm ("2"); \ + register unsigned long int __r2 asm ("2") = (unsigned long int) (futex); \ + register unsigned long int __r3 asm ("3") = FUTEX_CMP_REQUEUE; \ + register unsigned long int __r4 asm ("4") = (long int) (nr_wake); \ + register unsigned long int __r5 asm ("5") = (long int) (nr_move); \ + register unsigned long int __r6 asm ("6") = (unsigned long int) (mutex); \ + register unsigned long __result asm ("2"); \ \ __asm __volatile ("svc %b1" \ : "=d" (__result) \ : "i" (SYS_futex), "0" (__r2), "d" (__r3), \ "d" (__r4), "d" (__r5), "d" (__r6) \ : "cc", "memory" ); \ - __result; \ + __result > -4096UL; \ }) +#else +#define lll_futex_requeue(futex, nr_wake, nr_move, mutex, val) 1 +#endif #define lll_compare_and_swap(futex, oldval, newval, operation) \ --- libc/nptl/sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h 2004-05-19 22:58:46.637633349 +0200 +++ libc/nptl/sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h 2004-05-18 14:45:41.000000000 +0200 @@ -96,11 +96,12 @@ typedef union struct { int __lock; - int __clock; + unsigned int __futex; unsigned long long int __total_seq; unsigned long long int __wakeup_seq; unsigned long long int __woken_seq; void *__mutex; + int __clock; unsigned int __broadcast_seq; } __data; char __size[__SIZEOF_PTHREAD_COND_T]; --- libc/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h 2004-03-24 12:17:00.000000000 +0100 +++ libc/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h 2004-05-18 15:21:43.000000000 +0200 @@ -29,6 +29,7 @@ #define FUTEX_WAIT 0 #define FUTEX_WAKE 1 #define FUTEX_REQUEUE 3 +#define FUTEX_CMP_REQUEUE 4 /* Initializer for compatibility lock. */ #define LLL_MUTEX_LOCK_INITIALIZER (0) @@ -63,15 +64,16 @@ __ret; \ }) -#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex) \ +/* Returns non-zero if error happened, zero if success. */ +#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex, val) \ ({ \ INTERNAL_SYSCALL_DECL (__err); \ long int __ret; \ \ - __ret = INTERNAL_SYSCALL (futex, __err, 5, \ - (futexp), FUTEX_REQUEUE, (nr_wake), (nr_move), \ - (mutex)); \ - __ret; \ + __ret = INTERNAL_SYSCALL (futex, __err, 6, \ + (futexp), FUTEX_CMP_REQUEUE, (nr_wake), \ + (nr_move), (mutex), (val)); \ + INTERNAL_SYSCALL_ERROR_P (__ret, __err); \ }) #ifdef __sparc32_atomic_do_lock --- libc/nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h 2004-05-19 22:58:46.739615073 +0200 +++ libc/nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h 2004-05-18 14:46:25.000000000 +0200 @@ -76,11 +76,12 @@ typedef union struct { int __lock; - int __clock; + unsigned int __futex; unsigned long long int __total_seq; unsigned long long int __wakeup_seq; unsigned long long int __woken_seq; void *__mutex; + int __clock; unsigned int __broadcast_seq; } __data; char __size[__SIZEOF_PTHREAD_COND_T]; --- libc/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S 2004-05-19 22:58:46.651630841 +0200 +++ libc/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S 2004-05-18 17:35:15.000000000 +0200 @@ -32,6 +32,7 @@ #define FUTEX_WAIT 0 #define FUTEX_WAKE 1 #define FUTEX_REQUEUE 3 +#define FUTEX_CMP_REQUEUE 4 #define EINVAL 22 @@ -55,39 +56,42 @@ __pthread_cond_broadcast: #endif jnz 1f -2: addq $wakeup_seq, %rdi - movq total_seq-wakeup_seq(%rdi), %rcx - cmpq (%rdi), %rcx +2: addq $cond_futex, %rdi + movq total_seq-cond_futex(%rdi), %r9 + cmpq wakeup_seq-cond_futex(%rdi), %r9 jna 4f /* Cause all currently waiting threads to recognize they are woken up. */ - movq %rcx, (%rdi) - movq %rcx, woken_seq-wakeup_seq(%rdi) - incl broadcast_seq-wakeup_seq(%rdi) + movq %r9, wakeup_seq-cond_futex(%rdi) + movq %r9, woken_seq-cond_futex(%rdi) + addq %r9, %r9 + movl %r9d, (%rdi) + incl broadcast_seq-cond_futex(%rdi) /* Get the address of the mutex used. */ - movq dep_mutex-wakeup_seq(%rdi), %r8 + movq dep_mutex-cond_futex(%rdi), %r8 /* Unlock. */ LOCK - decl cond_lock-wakeup_seq(%rdi) + decl cond_lock-cond_futex(%rdi) jne 7f 8: cmpq $-1, %r8 je 9f /* Wake up all threads. */ - movq $FUTEX_REQUEUE, %rsi + movq $FUTEX_CMP_REQUEUE, %rsi movq $SYS_futex, %rax movl $1, %edx movq $0x7fffffff, %r10 syscall -#ifndef __ASSUME_FUTEX_REQUEUE - cmpq $-EINVAL, %rax - je 9f -#endif + /* 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 + jae 9f 10: xorl %eax, %eax retq @@ -95,7 +99,7 @@ __pthread_cond_broadcast: .align 16 /* Unlock. */ 4: LOCK - decl cond_lock-wakeup_seq(%rdi) + decl cond_lock-cond_futex(%rdi) jne 5f 6: xorl %eax, %eax @@ -113,14 +117,14 @@ __pthread_cond_broadcast: jmp 2b /* Unlock in loop requires wakeup. */ -5: addq $cond_lock-wakeup_seq, %rdi +5: addq $cond_lock-cond_futex, %rdi callq __lll_mutex_unlock_wake jmp 6b /* Unlock in loop requires wakeup. */ -7: addq $cond_lock-wakeup_seq, %rdi +7: addq $cond_lock-cond_futex, %rdi callq __lll_mutex_unlock_wake - subq $cond_lock-wakeup_seq, %rdi + subq $cond_lock-cond_futex, %rdi jmp 8b 9: /* The futex requeue functionality is not available. */ --- libc/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S 2003-09-22 06:40:38.000000000 +0200 +++ libc/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S 2004-05-18 16:26:43.000000000 +0200 @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2002. @@ -56,13 +56,14 @@ __pthread_cond_signal: #endif jnz 1f -2: addq $wakeup_seq, %rdi +2: addq $cond_futex, %rdi movq total_seq(%r8), %rcx - cmpq (%rdi), %rcx + cmpq wakeup_seq(%r8), %rcx jbe 4f /* Bump the wakeup number. */ - addq $1, (%rdi) + addq $1, wakeup_seq(%r8) + addl $1, (%rdi) /* Wake up one thread. */ movq $FUTEX_WAKE, %rsi @@ -95,11 +96,7 @@ __pthread_cond_signal: /* Unlock in loop requires wakeup. */ 5: -#if cond_lock != 0 - addq $cond_lock-wakeup_seq, %rdi -#else movq %r8, %rdi -#endif callq __lll_mutex_unlock_wake jmp 6b .size __pthread_cond_signal, .-__pthread_cond_signal --- libc/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S 2004-05-19 22:58:46.652630661 +0200 +++ libc/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S 2004-05-18 16:18:52.000000000 +0200 @@ -105,6 +105,7 @@ __pthread_cond_timedwait: movq 8(%rsp), %rdi incq total_seq(%rdi) + incl cond_futex(%rdi) /* Install cancellation handler. */ #ifdef PIC @@ -118,9 +119,9 @@ __pthread_cond_timedwait: /* Get and store current wakeup_seq value. */ movq 8(%rsp), %rdi - movq wakeup_seq(%rdi), %r12 + movq wakeup_seq(%rdi), %r9 movl broadcast_seq(%rdi), %edx - movq %r12, 40(%rsp) + movq %r9, 40(%rsp) movl %edx, 4(%rsp) /* Get the current time. */ @@ -172,6 +173,8 @@ __pthread_cond_timedwait: 21: movq %rcx, 24(%rsp) movq %rdx, 32(%rsp) + movl cond_futex(%rdi), %r12d + /* Unlock. */ LOCK #if cond_lock == 0 @@ -187,7 +190,7 @@ __pthread_cond_timedwait: leaq 24(%rsp), %r10 xorq %rsi, %rsi /* movq $FUTEX_WAIT, %rsi */ movq %r12, %rdx - addq $wakeup_seq-cond_lock, %rdi + addq $cond_futex, %rdi movq $SYS_futex, %rax syscall movq %rax, %r14 @@ -211,21 +214,22 @@ __pthread_cond_timedwait: movq woken_seq(%rdi), %rax - movq wakeup_seq(%rdi), %r12 + movq wakeup_seq(%rdi), %r9 cmpl 4(%rsp), %edx jne 23f - cmpq 40(%rsp), %r12 + cmpq 40(%rsp), %r9 jbe 15f - cmpq %rax, %r12 + cmpq %rax, %r9 ja 9f 15: cmpq $-ETIMEDOUT, %r14 jne 8b 13: incq wakeup_seq(%rdi) + incl cond_futex(%rdi) movq $ETIMEDOUT, %r14 jmp 14f --- libc/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S 2004-05-19 22:58:46.739615073 +0200 +++ libc/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S 2004-05-18 17:47:31.000000000 +0200 @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2002. @@ -69,6 +69,8 @@ __condvar_cleanup: incq woken_seq(%rdi) + incl cond_futex(%rdi) + 3: LOCK #if cond_lock == 0 decl (%rdi) @@ -82,7 +84,7 @@ __condvar_cleanup: callq __lll_mutex_unlock_wake /* Wake up all waiters to make sure no signal gets lost. */ -2: addq $wakeup_seq, %rdi +2: addq $cond_futex, %rdi movq $FUTEX_WAKE, %rsi movl $0x7fffffff, %edx movq $SYS_futex, %rax @@ -154,6 +156,7 @@ __pthread_cond_wait: movq 8(%rsp), %rdi incq total_seq(%rdi) + incl cond_futex(%rdi) /* Install cancellation handler. */ #ifdef PIC @@ -167,13 +170,14 @@ __pthread_cond_wait: /* Get and store current wakeup_seq value. */ movq 8(%rsp), %rdi - movq wakeup_seq(%rdi), %r12 + movq wakeup_seq(%rdi), %r9 movl broadcast_seq(%rdi), %edx - movq %r12, 24(%rsp) + movq %r9, 24(%rsp) movl %edx, 4(%rsp) /* Unlock. */ -8: LOCK +8: movl cond_futex(%rdi), %r12d + LOCK #if cond_lock == 0 decl (%rdi) #else @@ -187,7 +191,7 @@ __pthread_cond_wait: movq 8(%rsp), %rdi xorq %r10, %r10 movq %r12, %rdx - addq $wakeup_seq-cond_lock, %rdi + addq $cond_futex-cond_lock, %rdi movq $SYS_futex, %rax movq %r10, %rsi /* movq $FUTEX_WAIT, %rsi */ syscall @@ -211,15 +215,15 @@ __pthread_cond_wait: movq woken_seq(%rdi), %rax - movq wakeup_seq(%rdi), %r12 + movq wakeup_seq(%rdi), %r9 cmpl 4(%rsp), %edx jne 16f - cmpq 24(%rsp), %r12 + cmpq 24(%rsp), %r9 jbe 8b - cmpq %rax, %r12 + cmpq %rax, %r9 jna 8b incq woken_seq(%rdi) @@ -359,8 +363,8 @@ versioned_symbol (libpthread, __pthread_ .byte 0x40+.Lsubq-.Lpush_r12 # DW_CFA_advance_loc+N .byte 14 # DW_CFA_def_cfa_offset .uleb128 16+FRAME_SIZE - .byte 2 # DW_CFA_advance_loc1 - .byte .Laddq-.Lsubq + .byte 3 # DW_CFA_advance_loc2 + .2byte .Laddq-.Lsubq .byte 14 # DW_CFA_def_cfa_offset .uleb128 16 .byte 0x40+.Lpop_r12-.Laddq # DW_CFA_advance_loc+N Jakub From kukuk at suse.de Fri May 21 06:41:39 2004 From: kukuk at suse.de (Thorsten Kukuk) Date: Fri, 21 May 2004 08:41:39 +0200 Subject: [PATCH] tst-cond16 fix - NPTL part In-Reply-To: <20040520092013.GW30909@devserv.devel.redhat.com> References: <20040520092013.GW30909@devserv.devel.redhat.com> Message-ID: <20040521064139.GA13381@suse.de> On Thu, May 20, Jakub Jelinek wrote: > Hi! > > This is the NPTL part of the tst-cond16 fix. For PPC (and some other architectures) I need the attached patch for compiling. But while on ix86 the patch alone (without fixed kernel) solves the problem, it does not do so on PPC. Thorsten --- nptl/sysdeps/pthread/pthread_cond_broadcast.c +++ nptl/sysdeps/pthread/pthread_cond_broadcast.c 2004/05/20 20:50:39 @@ -63,7 +63,7 @@ { /* The requeue functionality is not available. */ wake_all: - lll_futex_wake (futex, INT_MAX); + lll_futex_wake (&cond->__data.__futex, INT_MAX); } /* That's all. */ -- Thorsten Kukuk http://www.suse.de/~kukuk/ kukuk at suse.de SuSE Linux AG Maxfeldstr. 5 D-90409 Nuernberg -------------------------------------------------------------------- Key fingerprint = A368 676B 5E1B 3E46 CFCE 2D97 F8FD 4E23 56C6 FB4B From jakub at redhat.com Fri May 21 07:55:48 2004 From: jakub at redhat.com (Jakub Jelinek) Date: Fri, 21 May 2004 03:55:48 -0400 Subject: [PATCH] tst-cond16 fix - NPTL part In-Reply-To: <20040521064139.GA13381@suse.de> References: <20040520092013.GW30909@devserv.devel.redhat.com> <20040521064139.GA13381@suse.de> Message-ID: <20040521075548.GH30909@devserv.devel.redhat.com> On Fri, May 21, 2004 at 08:41:39AM +0200, Thorsten Kukuk wrote: > On Thu, May 20, Jakub Jelinek wrote: > > > Hi! > > > > This is the NPTL part of the tst-cond16 fix. > > For PPC (and some other architectures) I need the attached patch > for compiling. But while on ix86 the patch alone (without fixed > kernel) solves the problem, it does not do so on PPC. Ok, I admit I have only tested this on i386 (4xHT) and x86_64 (UP only) so far. On PPC, is tst-cond16 the only test that fails with this patch? Are you using a kernel without FUTEX_CMP_REQUEUE there as well? Can you see with say strace if FUTEX_CMP_REQUEUE returns an error in all cases that it is run and that it does the FUTEX_WAKE call afterwards? I'll test this later today on PPC (without FUTEX_CMP_REQUEUE in the kernel). Jakub From kukuk at suse.de Fri May 21 07:58:53 2004 From: kukuk at suse.de (Thorsten Kukuk) Date: Fri, 21 May 2004 09:58:53 +0200 Subject: [PATCH] tst-cond16 fix - NPTL part In-Reply-To: <20040521075548.GH30909@devserv.devel.redhat.com> References: <20040520092013.GW30909@devserv.devel.redhat.com> <20040521064139.GA13381@suse.de> <20040521075548.GH30909@devserv.devel.redhat.com> Message-ID: <20040521075853.GA6835@suse.de> On Fri, May 21, Jakub Jelinek wrote: > On Fri, May 21, 2004 at 08:41:39AM +0200, Thorsten Kukuk wrote: > > On Thu, May 20, Jakub Jelinek wrote: > > > > > Hi! > > > > > > This is the NPTL part of the tst-cond16 fix. > > > > For PPC (and some other architectures) I need the attached patch > > for compiling. But while on ix86 the patch alone (without fixed > > kernel) solves the problem, it does not do so on PPC. > > Ok, I admit I have only tested this on i386 (4xHT) and x86_64 (UP only) > so far. > On PPC, is tst-cond16 the only test that fails with this patch? It seems so. > Are you using a kernel without FUTEX_CMP_REQUEUE there as well? Yes, our build machines aren't updated yet. > Can you see with say strace if FUTEX_CMP_REQUEUE returns an error in all > cases that it is run and that it does the FUTEX_WAKE call afterwards? I will try it now. Thorsten -- Thorsten Kukuk http://www.suse.de/~kukuk/ kukuk at suse.de SuSE Linux AG Maxfeldstr. 5 D-90409 Nuernberg -------------------------------------------------------------------- Key fingerprint = A368 676B 5E1B 3E46 CFCE 2D97 F8FD 4E23 56C6 FB4B From jakub at redhat.com Fri May 21 08:02:46 2004 From: jakub at redhat.com (Jakub Jelinek) Date: Fri, 21 May 2004 04:02:46 -0400 Subject: [PATCH] tst-cond16 fix - NPTL part In-Reply-To: <20040521075853.GA6835@suse.de> References: <20040520092013.GW30909@devserv.devel.redhat.com> <20040521064139.GA13381@suse.de> <20040521075548.GH30909@devserv.devel.redhat.com> <20040521075853.GA6835@suse.de> Message-ID: <20040521080246.GI30909@devserv.devel.redhat.com> On Fri, May 21, 2004 at 09:58:53AM +0200, Thorsten Kukuk wrote: > > Are you using a kernel without FUTEX_CMP_REQUEUE there as well? > > Yes, our build machines aren't updated yet. > > > Can you see with say strace if FUTEX_CMP_REQUEUE returns an error in all > > cases that it is run and that it does the FUTEX_WAKE call afterwards? > > I will try it now. BTW: there seems to be a forgotten ++cond->__data.__futex; in timedwait: timeout: /* Yep. Adjust the counters. */ ++cond->__data.__wakeup_seq; + ++cond->__data.__futex; /* The error value. */ result = ETIMEDOUT; break; but that should have no effect on tst-cond18 which doesn't use timedwait. (i486 and x86_64 assembly seems to handle this right). Jakub From kukuk at suse.de Fri May 21 11:37:11 2004 From: kukuk at suse.de (Thorsten Kukuk) Date: Fri, 21 May 2004 13:37:11 +0200 Subject: [PATCH] tst-cond16 fix - NPTL part In-Reply-To: <20040521075548.GH30909@devserv.devel.redhat.com> References: <20040520092013.GW30909@devserv.devel.redhat.com> <20040521064139.GA13381@suse.de> <20040521075548.GH30909@devserv.devel.redhat.com> Message-ID: <20040521113711.GA31078@suse.de> On Fri, May 21, Jakub Jelinek wrote: > On Fri, May 21, 2004 at 08:41:39AM +0200, Thorsten Kukuk wrote: > > On Thu, May 20, Jakub Jelinek wrote: > > > > > Hi! > > > > > > This is the NPTL part of the tst-cond16 fix. > > > > For PPC (and some other architectures) I need the attached patch > > for compiling. But while on ix86 the patch alone (without fixed > > kernel) solves the problem, it does not do so on PPC. > > Ok, I admit I have only tested this on i386 (4xHT) and x86_64 (UP only) > so far. > On PPC, is tst-cond16 the only test that fails with this patch? > Are you using a kernel without FUTEX_CMP_REQUEUE there as well? > Can you see with say strace if FUTEX_CMP_REQUEUE returns an error in all > cases that it is run and that it does the FUTEX_WAKE call afterwards? Yes, it Calls FUTEX_CMP_REQUEUE, which fails and than it calls FUTEX WAKE: 26413 futex(0x10011bf4, 0x4 /* FUTEX_??? */, 1 26413 <... futex resumed> ) = -1 ENOSYS (Function not implemented) 26413 futex(0x10011bf4, FUTEX_WAKE, 2147483647 26413 <... futex resumed> ) = 2 Thorsten -- Thorsten Kukuk http://www.suse.de/~kukuk/ kukuk at suse.de SuSE Linux AG Maxfeldstr. 5 D-90409 Nuernberg -------------------------------------------------------------------- Key fingerprint = A368 676B 5E1B 3E46 CFCE 2D97 F8FD 4E23 56C6 FB4B From jakub at redhat.com Fri May 21 15:44:42 2004 From: jakub at redhat.com (Jakub Jelinek) Date: Fri, 21 May 2004 11:44:42 -0400 Subject: [PATCH] tst-cond16 fix - NPTL part (take 2) In-Reply-To: <20040521075853.GA6835@suse.de> References: <20040520092013.GW30909@devserv.devel.redhat.com> <20040521064139.GA13381@suse.de> <20040521075548.GH30909@devserv.devel.redhat.com> <20040521075853.GA6835@suse.de> Message-ID: <20040521154442.GM30909@devserv.devel.redhat.com> On Fri, May 21, 2004 at 09:58:53AM +0200, Thorsten Kukuk wrote: > > Can you see with say strace if FUTEX_CMP_REQUEUE returns an error in all > > cases that it is run and that it does the FUTEX_WAKE call afterwards? > > I will try it now. I think the fix I just posted to libc-hacker should fix this (unrelated to FUTEX_CMP_REQUEUE). Here is the updated FUTEX_CMP_REQUEUE NPTL patch. 2004-05-21 Jakub Jelinek * Makefile (tests): Add tst-cond16. * sysdeps/unix/sysv/linux/lowlevelcond.sym (cond_futex): Add. * pthread_cond_init.c (__pthread_cond_init): Clear __data.__futex. * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h (pthread_cond_t): Add __data.__futex field, reshuffle __data.__clock. * sysdeps/unix/sysv/linux/i386/pthread_cond_signal.S (__pthread_cond_signal): Increment __futex at the same time as __wakeup_seq or __total_seq. Pass address of __futex instead of address of low 32-bits of __wakeup_seq to futex syscall. * sysdeps/unix/sysv/linux/i386/pthread_cond_wait.S (__pthread_cond_wait): Likewise. Pass __futex value from before releasing internal lock to FUTEX_WAIT. * sysdeps/unix/sysv/linux/i386/pthread_cond_timedwait.S (__pthread_cond_timedwait): Likewise. * sysdeps/unix/sysv/linux/i386/pthread_cond_broadcast.S (FUTEX_CMP_REQUEUE): Define. (__pthread_cond_broadcast): Set __futex to 2 * __total_seq. Use FUTEX_CMP_REQUEUE operation instead of FUTEX_REQUEUE. Pass __futex value from before the unlock and __futex address instead of address of low 32-bits of __wakeup_seq to futex syscall. Fallback to FUTEX_WAKE all on any errors. * sysdeps/unix/sysv/linux/alpha/lowlevellock.h (FUTEX_CMP_REQUEUE): Define. (lll_futex_requeue): Add val argument, use FUTEX_CMP_REQUEUE internally. Return non-zero if error, zero if success. * sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h (pthread_cond_t): Add __data.__futex field, reshuffle __data.__clock. * sysdeps/unix/sysv/linux/s390/lowlevellock.h (FUTEX_CMP_REQUEUE): Define. (lll_futex_requeue): Add val argument, return 1 unconditionally for the time being. * sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h (pthread_cond_t): Add __data.__futex field, reshuffle __data.__clock. * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h (FUTEX_CMP_REQUEUE): Define. (lll_futex_requeue): Add val argument, use FUTEX_CMP_REQUEUE internally. Return non-zero if error, zero if success. * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h (pthread_cond_t): Add __data.__futex field, reshuffle __data.__clock. * sysdeps/unix/sysv/linux/sparc/lowlevellock.h (FUTEX_CMP_REQUEUE): Define. (lll_futex_requeue): Add val argument, use FUTEX_CMP_REQUEUE internally. Return non-zero if error, zero if success. * sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h (pthread_cond_t): Add __data.__futex field, reshuffle __data.__clock. * sysdeps/unix/sysv/linux/ia64/lowlevellock.h (FUTEX_CMP_REQUEUE): Define. (lll_futex_requeue): Add val argument, use FUTEX_CMP_REQUEUE internally. Return non-zero if error, zero if success. * sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h (pthread_cond_t): Add __data.__futex field, reshuffle __data.__clock. * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h (pthread_cond_t): Add __data.__futex field, reshuffle __data.__clock. * sysdeps/pthread/pthread_cond_signal.c (__pthread_cond_signal): Increment __futex at the same time as __wakeup_seq or __total_seq. Pass address of __futex instead of address of low 32-bits of __wakeup_seq to futex syscall. * sysdeps/pthread/pthread_cond_wait.c (__pthread_cond_wait): Likewise. Pass __futex value from before releasing internal lock to FUTEX_WAIT. * sysdeps/pthread/pthread_cond_timedwait.c (__pthread_cond_timedwait): Likewise. Avoid unnecessary shadowing of variables. * sysdeps/pthread/pthread_cond_broadcast.c (__pthread_cond_broadcast): Set __futex to 2 * __total_seq. Pass __futex value from before the unlock and __futex address instead of address of low 32-bits of __wakeup_seq to futex_requeue macro, adjust for new return value meaning. * sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S (__pthread_cond_signal): Increment __futex at the same time as __wakeup_seq or __total_seq. Pass address of __futex instead of address of low 32-bits of __wakeup_seq to futex syscall. * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S (__pthread_cond_wait): Likewise. Pass __futex value from before releasing internal lock to FUTEX_WAIT. * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S (__pthread_cond_timedwait): Likewise. * sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S (FUTEX_CMP_REQUEUE): Define. (__pthread_cond_broadcast): Set __futex to 2 * __total_seq. Use FUTEX_CMP_REQUEUE operation instead of FUTEX_REQUEUE. Pass __futex value from before the unlock and __futex address instead of address of low 32-bits of __wakeup_seq to futex syscall. Fallback to FUTEX_WAKE all on any errors. --- libc/nptl/Makefile 2004-05-19 22:58:46.405674919 +0200 +++ libc/nptl/Makefile 2004-05-18 14:43:22.000000000 +0200 @@ -194,7 +194,7 @@ tests = tst-attr1 tst-attr2 tst-attr3 \ tst-spin1 tst-spin2 tst-spin3 \ tst-cond1 tst-cond2 tst-cond3 tst-cond4 tst-cond5 tst-cond6 tst-cond7 \ tst-cond8 tst-cond9 tst-cond10 tst-cond11 tst-cond12 tst-cond13 \ - tst-cond14 tst-cond15 tst-cond17 tst-cond18 \ + tst-cond14 tst-cond15 tst-cond16 tst-cond17 tst-cond18 \ tst-rwlock1 tst-rwlock2 tst-rwlock3 tst-rwlock4 tst-rwlock5 \ tst-rwlock6 tst-rwlock7 tst-rwlock8 tst-rwlock9 tst-rwlock10 \ tst-rwlock11 tst-rwlock12 tst-rwlock13 \ --- libc/nptl/pthread_cond_init.c 2004-05-19 22:58:46.405674919 +0200 +++ libc/nptl/pthread_cond_init.c 2004-05-18 14:43:22.000000000 +0200 @@ -31,6 +31,7 @@ __pthread_cond_init (cond, cond_attr) struct pthread_condattr *icond_attr = (struct pthread_condattr *) cond_attr; cond->__data.__lock = LLL_MUTEX_LOCK_INITIALIZER; + cond->__data.__futex = 0; cond->__data.__clock = (icond_attr == NULL ? CLOCK_REALTIME : (icond_attr->value & 0xfe) >> 1); cond->__data.__total_seq = 0; --- libc/nptl/sysdeps/pthread/pthread_cond_broadcast.c 2004-05-19 22:58:46.532652163 +0200 +++ libc/nptl/sysdeps/pthread/pthread_cond_broadcast.c 2004-05-18 14:56:08.000000000 +0200 @@ -41,35 +41,29 @@ __pthread_cond_broadcast (cond) /* Yes. Mark them all as woken. */ cond->__data.__wakeup_seq = cond->__data.__total_seq; cond->__data.__woken_seq = cond->__data.__total_seq; + cond->__data.__futex = (unsigned int) cond->__data.__total_seq * 2; + int futex_val = cond->__data.__futex; /* Signal that a broadcast happened. */ ++cond->__data.__broadcast_seq; /* We are done. */ lll_mutex_unlock (cond->__data.__lock); - /* The futex syscall operates on a 32-bit word. That is fine, - we just use the low 32 bits of the sequence counter. */ -#if BYTE_ORDER == LITTLE_ENDIAN - int *futex = ((int *) (&cond->__data.__wakeup_seq)); -#elif BYTE_ORDER == BIG_ENDIAN - int *futex = ((int *) (&cond->__data.__wakeup_seq)) + 1; -#else -# error "No valid byte order" -#endif - /* Do not use requeue for pshared condvars. */ if (cond->__data.__mutex == (void *) ~0l) goto wake_all; /* Wake everybody. */ pthread_mutex_t *mut = (pthread_mutex_t *) cond->__data.__mutex; - if (__builtin_expect (lll_futex_requeue (futex, 1, INT_MAX, - &mut->__data.__lock) == -EINVAL, - 0)) + /* lll_futex_requeue returns 0 for success and non-zero + for errors. */ + if (__builtin_expect (lll_futex_requeue (&cond->__data.__futex, 1, + INT_MAX, &mut->__data.__lock, + futex_val), 0)) { /* The requeue functionality is not available. */ wake_all: - lll_futex_wake (futex, INT_MAX); + lll_futex_wake (&cond->__data.__futex, INT_MAX); } /* That's all. */ --- libc/nptl/sysdeps/pthread/pthread_cond_signal.c 2003-09-22 07:44:27.000000000 +0200 +++ libc/nptl/sysdeps/pthread/pthread_cond_signal.c 2004-05-18 14:58:04.000000000 +0200 @@ -1,4 +1,4 @@ -/* Copyright (C) 2003 Free Software Foundation, Inc. +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Martin Schwidefsky , 2003. @@ -40,19 +40,10 @@ __pthread_cond_signal (cond) { /* Yes. Mark one of them as woken. */ ++cond->__data.__wakeup_seq; - - /* The futex syscall operates on a 32-bit word. That is fine, - we just use the low 32 bits of the sequence counter. */ -#if BYTE_ORDER == LITTLE_ENDIAN - int *futex = ((int *) (&cond->__data.__wakeup_seq)); -#elif BYTE_ORDER == BIG_ENDIAN - int *futex = ((int *) (&cond->__data.__wakeup_seq)) + 1; -#else -# error "No valid byte order" -#endif + ++cond->__data.__futex; /* Wake one. */ - lll_futex_wake (futex, 1); + lll_futex_wake (&cond->__data.__futex, 1); } /* We are done. */ --- libc/nptl/sysdeps/pthread/pthread_cond_timedwait.c 2004-05-19 22:58:46.533651984 +0200 +++ libc/nptl/sysdeps/pthread/pthread_cond_timedwait.c 2004-05-18 15:05:55.000000000 +0200 @@ -66,6 +66,7 @@ __pthread_cond_timedwait (cond, mutex, a /* We have one new user of the condvar. */ ++cond->__data.__total_seq; + ++cond->__data.__futex; /* Remember the mutex we are using here. If there is already a different address store this is a bad user bug. Do not store @@ -89,27 +90,17 @@ __pthread_cond_timedwait (cond, mutex, a /* Remember the broadcast counter. */ cbuffer.bc_seq = cond->__data.__broadcast_seq; - /* The futex syscall operates on a 32-bit word. That is fine, we - just use the low 32 bits of the sequence counter. */ -#if BYTE_ORDER == LITTLE_ENDIAN - int *futex = ((int *) (&cond->__data.__wakeup_seq)); -#elif BYTE_ORDER == BIG_ENDIAN - int *futex = ((int *) (&cond->__data.__wakeup_seq)) + 1; -#else -# error "No valid byte order" -#endif - while (1) { struct timespec rt; { #ifdef __NR_clock_gettime INTERNAL_SYSCALL_DECL (err); - int val; - val = INTERNAL_SYSCALL (clock_gettime, err, 2, + int ret; + ret = INTERNAL_SYSCALL (clock_gettime, err, 2, cond->__data.__clock, &rt); # ifndef __ASSUME_POSIX_TIMERS - if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (val, err), 0)) + if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (ret, err), 0)) { struct timeval tv; (void) gettimeofday (&tv, NULL); @@ -149,15 +140,17 @@ __pthread_cond_timedwait (cond, mutex, a goto timeout; } + unsigned int futex_val = cond->__data.__futex; + /* 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 (); - /* Wait until woken by signal or broadcast. Note that we - truncate the 'val' value to 32 bits. */ - err = lll_futex_timed_wait (futex, (unsigned int) val, &rt); + /* Wait until woken by signal or broadcast. */ + err = lll_futex_timed_wait (&cond->__data.__futex, + futex_val, &rt); /* Disable asynchronous cancellation. */ __pthread_disable_asynccancel (cbuffer.oldtype); @@ -180,6 +173,7 @@ __pthread_cond_timedwait (cond, mutex, a timeout: /* Yep. Adjust the counters. */ ++cond->__data.__wakeup_seq; + ++cond->__data.__futex; /* The error value. */ result = ETIMEDOUT; --- libc/nptl/sysdeps/pthread/pthread_cond_wait.c 2004-05-19 22:58:46.552648579 +0200 +++ libc/nptl/sysdeps/pthread/pthread_cond_wait.c 2004-05-18 15:10:07.000000000 +0200 @@ -52,20 +52,14 @@ __condvar_cleanup (void *arg) appropriately. */ ++cbuffer->cond->__data.__wakeup_seq; ++cbuffer->cond->__data.__woken_seq; + ++cbuffer->cond->__data.__futex; } /* We are done. */ lll_mutex_unlock (cbuffer->cond->__data.__lock); /* Wake everybody to make sure no condvar signal gets lost. */ -#if BYTE_ORDER == LITTLE_ENDIAN - int *futex = ((int *) (&cbuffer->cond->__data.__wakeup_seq)); -#elif BYTE_ORDER == BIG_ENDIAN - int *futex = ((int *) (&cbuffer->cond->__data.__wakeup_seq)) + 1; -#else -# error "No valid byte order" -#endif - lll_futex_wake (futex, INT_MAX); + lll_futex_wake (&cbuffer->cond->__data.__futex, INT_MAX); /* Get the mutex before returning unless asynchronous cancellation is in effect. */ @@ -95,6 +89,7 @@ __pthread_cond_wait (cond, mutex) /* We have one new user of the condvar. */ ++cond->__data.__total_seq; + ++cond->__data.__futex; /* Remember the mutex we are using here. If there is already a different address store this is a bad user bug. Do not store @@ -118,27 +113,18 @@ __pthread_cond_wait (cond, mutex) /* Remember the broadcast counter. */ cbuffer.bc_seq = cond->__data.__broadcast_seq; - /* The futex syscall operates on a 32-bit word. That is fine, we - just use the low 32 bits of the sequence counter. */ -#if BYTE_ORDER == LITTLE_ENDIAN - int *futex = ((int *) (&cond->__data.__wakeup_seq)); -#elif BYTE_ORDER == BIG_ENDIAN - int *futex = ((int *) (&cond->__data.__wakeup_seq)) + 1; -#else -# error "No valid byte order" -#endif - do { + unsigned int futex_val = cond->__data.__futex; + /* 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 (); - /* Wait until woken by signal or broadcast. Note that we - truncate the 'val' value to 32 bits. */ - lll_futex_wait (futex, (unsigned int) val); + /* Wait until woken by signal or broadcast. */ + lll_futex_wait (&cond->__data.__futex, futex_val); /* Disable asynchronous cancellation. */ __pthread_disable_asynccancel (cbuffer.oldtype); --- libc/nptl/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h 2004-05-19 22:58:46.609638366 +0200 +++ libc/nptl/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h 2004-05-18 14:44:38.000000000 +0200 @@ -76,11 +76,12 @@ typedef union struct { int __lock; - int __clock; + unsigned int __futex; unsigned long long int __total_seq; unsigned long long int __wakeup_seq; unsigned long long int __woken_seq; void *__mutex; + int __clock; unsigned int __broadcast_seq; } __data; char __size[__SIZEOF_PTHREAD_COND_T]; --- libc/nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h 2004-03-24 12:16:58.000000000 +0100 +++ libc/nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h 2004-05-18 15:13:18.000000000 +0200 @@ -30,6 +30,7 @@ #define FUTEX_WAIT 0 #define FUTEX_WAKE 1 #define FUTEX_REQUEUE 3 +#define FUTEX_CMP_REQUEUE 4 /* Initializer for compatibility lock. */ #define LLL_MUTEX_LOCK_INITIALIZER (0) @@ -61,14 +62,15 @@ INTERNAL_SYSCALL_ERROR_P (__ret, __err)? -__ret : __ret; \ }) -#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex) \ +/* Returns non-zero if error happened, zero if success. */ +#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex, val) \ ({ \ INTERNAL_SYSCALL_DECL (__err); \ long int __ret; \ - __ret = INTERNAL_SYSCALL (futex, __err, 5, \ - (futexp), FUTEX_REQUEUE, (nr_wake), (nr_move), \ - (mutex)); \ - INTERNAL_SYSCALL_ERROR_P (__ret, __err)? -__ret : __ret; \ + __ret = INTERNAL_SYSCALL (futex, __err, 6, \ + (futexp), FUTEX_CMP_REQUEUE, (nr_wake), \ + (nr_move), (mutex), (val)); \ + INTERNAL_SYSCALL_ERROR_P (__ret, __err); \ }) --- libc/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h 2004-05-19 22:58:46.610638187 +0200 +++ libc/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h 2004-05-18 14:43:22.000000000 +0200 @@ -76,11 +76,12 @@ typedef union struct { int __lock; - int __clock; + unsigned int __futex; unsigned long long int __total_seq; unsigned long long int __wakeup_seq; unsigned long long int __woken_seq; void *__mutex; + int __clock; unsigned int __broadcast_seq; } __data; char __size[__SIZEOF_PTHREAD_COND_T]; --- libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S 2004-05-19 22:58:46.611638008 +0200 +++ libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S 2004-05-18 14:43:22.000000000 +0200 @@ -32,6 +32,7 @@ #define FUTEX_WAIT 0 #define FUTEX_WAKE 1 #define FUTEX_REQUEUE 3 +#define FUTEX_CMP_REQUEUE 4 #define EINVAL 22 @@ -47,8 +48,9 @@ __pthread_cond_broadcast: pushl %ebx pushl %esi pushl %edi + pushl %ebp - movl 16(%esp), %ebx + movl 20(%esp), %ebx /* Get internal lock. */ movl $1, %edx @@ -61,29 +63,31 @@ __pthread_cond_broadcast: #endif jnz 1f -2: addl $wakeup_seq, %ebx - movl total_seq+4-wakeup_seq(%ebx), %eax - movl total_seq-wakeup_seq(%ebx), %ecx - cmpl 4(%ebx), %eax +2: addl $cond_futex, %ebx + movl total_seq+4-cond_futex(%ebx), %eax + movl total_seq-cond_futex(%ebx), %ebp + cmpl wakeup_seq+4-cond_futex(%ebx), %eax ja 3f jb 4f - cmpl (%ebx), %ecx + cmpl wakeup_seq-cond_futex(%ebx), %ebp jna 4f /* Cause all currently waiting threads to recognize they are woken up. */ -3: movl %ecx, (%ebx) - movl %eax, 4(%ebx) - movl %ecx, woken_seq-wakeup_seq(%ebx) - movl %eax, woken_seq-wakeup_seq+4(%ebx) - addl $1, broadcast_seq-wakeup_seq(%ebx) +3: movl %ebp, wakeup_seq-cond_futex(%ebx) + movl %eax, wakeup_seq-cond_futex+4(%ebx) + movl %ebp, woken_seq-cond_futex(%ebx) + movl %eax, woken_seq-cond_futex+4(%ebx) + addl %ebp, %ebp + addl $1, broadcast_seq-cond_futex(%ebx) + movl %ebp, (%ebx) /* Get the address of the mutex used. */ - movl dep_mutex-wakeup_seq(%ebx), %edi + movl dep_mutex-cond_futex(%ebx), %edi /* Unlock. */ LOCK - subl $1, cond_lock-wakeup_seq(%ebx) + subl $1, cond_lock-cond_futex(%ebx) jne 7f /* Don't use requeue for pshared condvars. */ @@ -91,7 +95,7 @@ __pthread_cond_broadcast: je 9f /* Wake up all threads. */ - movl $FUTEX_REQUEUE, %ecx + movl $FUTEX_CMP_REQUEUE, %ecx movl $SYS_futex, %eax movl $0x7fffffff, %esi movl $1, %edx @@ -99,14 +103,18 @@ __pthread_cond_broadcast: # if MUTEX_FUTEX != 0 addl $MUTEX_FUTEX, %edi # endif - ENTER_KERNEL - -#ifndef __ASSUME_FUTEX_REQUEUE - cmpl $-EINVAL, %eax - je 9f -#endif +/* FIXME: Until Ingo fixes 4G/4G vDSO, 6 arg syscalls are broken for sysenter. + ENTER_KERNEL */ + 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 + jae 9f 10: xorl %eax, %eax + popl %ebp popl %edi popl %esi popl %ebx @@ -115,10 +123,11 @@ __pthread_cond_broadcast: .align 16 /* Unlock. */ 4: LOCK - subl $1, cond_lock-wakeup_seq(%ebx) + subl $1, cond_lock-cond_futex(%ebx) jne 5f 6: xorl %eax, %eax + popl %ebp popl %edi popl %esi popl %ebx @@ -135,12 +144,12 @@ __pthread_cond_broadcast: jmp 2b /* Unlock in loop requires waekup. */ -5: leal cond_lock-wakeup_seq(%ebx), %eax +5: leal cond_lock-cond_futex(%ebx), %eax call __lll_mutex_unlock_wake jmp 6b /* Unlock in loop requires waekup. */ -7: leal cond_lock-wakeup_seq(%ebx), %eax +7: leal cond_lock-cond_futex(%ebx), %eax call __lll_mutex_unlock_wake jmp 8b --- libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S 2004-02-19 17:50:40.000000000 +0100 +++ libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S 2004-05-18 14:43:22.000000000 +0200 @@ -60,22 +60,23 @@ __pthread_cond_signal: #endif jnz 1f -2: leal wakeup_seq(%edi), %ebx +2: leal cond_futex(%edi), %ebx movl total_seq+4(%edi), %eax movl total_seq(%edi), %ecx - cmpl 4(%ebx), %eax + cmpl wakeup_seq+4(%edi), %eax #if cond_lock != 0 /* Must use leal to preserve the flags. */ leal cond_lock(%edi), %edi #endif ja 3f jb 4f - cmpl (%ebx), %ecx + cmpl wakeup_seq-cond_futex(%ebx), %ecx jbe 4f /* Bump the wakeup number. */ -3: addl $1, (%ebx) - adcl $0, 4(%ebx) +3: addl $1, wakeup_seq-cond_futex(%ebx) + adcl $0, wakeup_seq-cond_futex+4(%ebx) + addl $1, (%ebx) /* Wake up one thread. */ movl $FUTEX_WAKE, %ecx --- libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S 2004-05-19 22:58:46.612637829 +0200 +++ libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S 2004-05-18 14:43:22.000000000 +0200 @@ -82,6 +82,7 @@ __pthread_cond_timedwait: addl $1, total_seq(%ebx) adcl $0, total_seq+4(%ebx) + addl $1, cond_futex(%ebx) #define FRAME_SIZE 24 subl $FRAME_SIZE, %esp @@ -148,6 +149,8 @@ __pthread_cond_timedwait: 21: movl %ecx, 4(%esp) movl %edx, 8(%esp) + movl cond_futex(%ebx), %edi + /* Unlock. */ LOCK #if cond_lock == 0 @@ -164,12 +167,12 @@ __pthread_cond_timedwait: leal 4(%esp), %esi xorl %ecx, %ecx /* movl $FUTEX_WAIT, %ecx */ movl %edi, %edx - addl $wakeup_seq, %ebx -.Ladd_wakeup: + addl $cond_futex, %ebx +.Ladd_cond_futex: movl $SYS_futex, %eax ENTER_KERNEL - subl $wakeup_seq, %ebx -.Lsub_wakeup: + subl $cond_futex, %ebx +.Lsub_cond_futex: movl %eax, %esi movl (%esp), %eax @@ -212,6 +215,7 @@ __pthread_cond_timedwait: addl $1, wakeup_seq(%ebx) adcl $0, wakeup_seq+4(%ebx) + addl $1, cond_futex(%ebx) movl $ETIMEDOUT, %esi jmp 14f @@ -359,7 +363,7 @@ __condvar_tw_cleanup3: .size __condvar_tw_cleanup3, .-__condvar_tw_cleanup3 .type __condvar_tw_cleanup2, @function __condvar_tw_cleanup2: - subl $wakeup_seq, %ebx + subl $cond_futex, %ebx .size __condvar_tw_cleanup2, .-__condvar_tw_cleanup2 .type __condvar_tw_cleanup, @function __condvar_tw_cleanup: @@ -390,6 +394,8 @@ __condvar_tw_cleanup: addl $1, wakeup_seq(%ebx) adcl $0, wakeup_seq+4(%ebx) + addl $1, cond_futex(%ebx) + addl $1, woken_seq(%ebx) adcl $0, woken_seq+4(%ebx) @@ -409,7 +415,7 @@ __condvar_tw_cleanup: call __lll_mutex_unlock_wake /* Wake up all waiters to make sure no signal gets lost. */ -2: addl $wakeup_seq, %ebx +2: addl $cond_futex, %ebx movl $FUTEX_WAKE, %ecx movl $SYS_futex, %eax movl $0x7fffffff, %edx @@ -435,7 +441,7 @@ __condvar_tw_cleanup: .uleb128 .Lcstend-.Lcstbegin .Lcstbegin: .long .LcleanupSTART-.LSTARTCODE - .long .Ladd_wakeup-.LcleanupSTART + .long .Ladd_cond_futex-.LcleanupSTART .long __condvar_tw_cleanup-.LSTARTCODE .uleb128 0 .long .LebxmovedUR-.LSTARTCODE @@ -443,15 +449,15 @@ __condvar_tw_cleanup: .long __condvar_tw_cleanup3-.LSTARTCODE .uleb128 0 .long .LebxmovedUR-.LSTARTCODE - .long .Ladd_wakeup-.LebxmovedUR + .long .Ladd_cond_futex-.LebxmovedUR .long __condvar_tw_cleanup-.LSTARTCODE .uleb128 0 - .long .Ladd_wakeup-.LSTARTCODE - .long .Lsub_wakeup-.Ladd_wakeup + .long .Ladd_cond_futex-.LSTARTCODE + .long .Lsub_cond_futex-.Ladd_cond_futex .long __condvar_tw_cleanup2-.LSTARTCODE .uleb128 0 - .long .Lsub_wakeup-.LSTARTCODE - .long .LcleanupEND-.Lsub_wakeup + .long .Lsub_cond_futex-.LSTARTCODE + .long .LcleanupEND-.Lsub_cond_futex .long __condvar_tw_cleanup-.LSTARTCODE .uleb128 0 .long .LcallUR-.LSTARTCODE --- libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S 2004-05-19 22:58:46.613637649 +0200 +++ libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S 2004-05-18 14:43:22.000000000 +0200 @@ -79,6 +79,7 @@ __pthread_cond_wait: addl $1, total_seq(%ebx) adcl $0, total_seq+4(%ebx) + addl $1, cond_futex(%ebx) #define FRAME_SIZE 16 subl $FRAME_SIZE, %esp @@ -92,8 +93,10 @@ __pthread_cond_wait: movl %edx, 8(%esp) movl %eax, 12(%esp) +8: movl cond_futex(%ebx), %edi + /* Unlock. */ -8: LOCK + LOCK #if cond_lock == 0 subl $1, (%ebx) #else @@ -107,12 +110,12 @@ __pthread_cond_wait: movl %esi, %ecx /* movl $FUTEX_WAIT, %ecx */ movl %edi, %edx - addl $wakeup_seq, %ebx -.Ladd_wakeup: + addl $cond_futex, %ebx +.Ladd_cond_futex: movl $SYS_futex, %eax ENTER_KERNEL - subl $wakeup_seq, %ebx -.Lsub_wakeup: + subl $cond_futex, %ebx +.Lsub_cond_futex: movl (%esp), %eax call __pthread_disable_asynccancel @@ -246,7 +249,7 @@ versioned_symbol (libpthread, __pthread_ .type __condvar_w_cleanup2, @function __condvar_w_cleanup2: - subl $wakeup_seq, %ebx + subl $cond_futex, %ebx .size __condvar_w_cleanup2, .-__condvar_w_cleanup2 .LSbl4: .type __condvar_w_cleanup, @function @@ -278,6 +281,8 @@ __condvar_w_cleanup: addl $1, wakeup_seq(%ebx) adcl $0, wakeup_seq+4(%ebx) + addl $1, cond_futex(%ebx) + addl $1, woken_seq(%ebx) adcl $0, woken_seq+4(%ebx) @@ -297,7 +302,7 @@ __condvar_w_cleanup: call __lll_mutex_unlock_wake /* Wake up all waiters to make sure no signal gets lost. */ -2: addl $wakeup_seq, %ebx +2: addl $cond_futex, %ebx movl $FUTEX_WAKE, %ecx movl $SYS_futex, %eax movl $0x7fffffff, %edx @@ -323,15 +328,15 @@ __condvar_w_cleanup: .uleb128 .Lcstend-.Lcstbegin .Lcstbegin: .long .LcleanupSTART-.LSTARTCODE - .long .Ladd_wakeup-.LcleanupSTART + .long .Ladd_cond_futex-.LcleanupSTART .long __condvar_w_cleanup-.LSTARTCODE .uleb128 0 - .long .Ladd_wakeup-.LSTARTCODE - .long .Lsub_wakeup-.Ladd_wakeup + .long .Ladd_cond_futex-.LSTARTCODE + .long .Lsub_cond_futex-.Ladd_cond_futex .long __condvar_w_cleanup2-.LSTARTCODE .uleb128 0 - .long .Lsub_wakeup-.LSTARTCODE - .long .LcleanupEND-.Lsub_wakeup + .long .Lsub_cond_futex-.LSTARTCODE + .long .LcleanupEND-.Lsub_cond_futex .long __condvar_w_cleanup-.LSTARTCODE .uleb128 0 .long .LcallUR-.LSTARTCODE --- libc/nptl/sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h 2004-05-19 22:58:46.614637470 +0200 +++ libc/nptl/sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h 2004-05-18 14:46:13.000000000 +0200 @@ -76,11 +76,12 @@ typedef union struct { int __lock; - int __clock; + unsigned int __futex; unsigned long long int __total_seq; unsigned long long int __wakeup_seq; unsigned long long int __woken_seq; void *__mutex; + int __clock; unsigned int __broadcast_seq; } __data; char __size[__SIZEOF_PTHREAD_COND_T]; --- libc/nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.h 2004-03-24 12:16:59.000000000 +0100 +++ libc/nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.h 2004-05-18 15:27:23.000000000 +0200 @@ -30,6 +30,7 @@ #define FUTEX_WAIT 0 #define FUTEX_WAKE 1 #define FUTEX_REQUEUE 3 +#define FUTEX_CMP_REQUEUE 4 /* Delay in spinlock loop. */ #define BUSY_WAIT_NOP asm ("hint @pause") @@ -52,11 +53,13 @@ _r10 == -1 ? -_retval : _retval; \ }) -#define lll_futex_requeue(ftx, nr_wake, nr_move, mutex) \ +/* Returns non-zero if error happened, zero if success. */ +#define lll_futex_requeue(ftx, nr_wake, nr_move, mutex, val) \ ({ \ - DO_INLINE_SYSCALL(futex, 5, (long) (ftx), FUTEX_REQUEUE, (int) (nr_wake), \ - (int) (nr_move), (long) (mutex)); \ - _r10 == -1 ? -_retval : _retval; \ + DO_INLINE_SYSCALL(futex, 6, (long) (ftx), FUTEX_CMP_REQUEUE, \ + (int) (nr_wake), (int) (nr_move), (long) (mutex), \ + (int) val); \ + _r10 == -1; \ }) --- libc/nptl/sysdeps/unix/sysv/linux/lowlevelcond.sym 2004-05-19 22:58:46.588642129 +0200 +++ libc/nptl/sysdeps/unix/sysv/linux/lowlevelcond.sym 2004-05-18 14:43:22.000000000 +0200 @@ -4,6 +4,7 @@ -- cond_lock offsetof (pthread_cond_t, __data.__lock) +cond_futex offsetof (pthread_cond_t, __data.__futex) cond_clock offsetof (pthread_cond_t, __data.__clock) total_seq offsetof (pthread_cond_t, __data.__total_seq) wakeup_seq offsetof (pthread_cond_t, __data.__wakeup_seq) --- libc/nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h 2004-05-19 22:58:46.623635858 +0200 +++ libc/nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h 2004-05-18 14:45:21.000000000 +0200 @@ -96,11 +96,12 @@ typedef union struct { int __lock; - int __clock; + unsigned int __futex; unsigned long long int __total_seq; unsigned long long int __wakeup_seq; unsigned long long int __woken_seq; void *__mutex; + int __clock; unsigned int __broadcast_seq; } __data; char __size[__SIZEOF_PTHREAD_COND_T]; --- libc/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h 2004-04-13 10:42:53.000000000 +0200 +++ libc/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h 2004-05-18 15:19:01.000000000 +0200 @@ -30,6 +30,7 @@ #define FUTEX_WAIT 0 #define FUTEX_WAKE 1 #define FUTEX_REQUEUE 3 +#define FUTEX_CMP_REQUEUE 4 /* Initializer for compatibility lock. */ #define LLL_MUTEX_LOCK_INITIALIZER (0) @@ -64,15 +65,16 @@ INTERNAL_SYSCALL_ERROR_P (__ret, __err) ? -__ret : __ret; \ }) -#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex) \ +/* Returns non-zero if error happened, zero if success. */ +#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex, val) \ ({ \ INTERNAL_SYSCALL_DECL (__err); \ long int __ret; \ \ - __ret = INTERNAL_SYSCALL (futex, __err, 5, \ - (futexp), FUTEX_REQUEUE, (nr_wake), (nr_move), \ - (mutex)); \ - INTERNAL_SYSCALL_ERROR_P (__ret, __err) ? -__ret : __ret; \ + __ret = INTERNAL_SYSCALL (futex, __err, 6, \ + (futexp), FUTEX_CMP_REQUEUE, (nr_wake), \ + (nr_move), (mutex), (val)); \ + INTERNAL_SYSCALL_ERROR_P (__ret, __err); \ }) #ifdef UP --- libc/nptl/sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h 2004-05-19 22:58:46.628634962 +0200 +++ libc/nptl/sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h 2004-05-18 14:44:56.000000000 +0200 @@ -95,11 +95,12 @@ typedef union struct { int __lock; - int __clock; + unsigned int __futex; unsigned long long int __total_seq; unsigned long long int __wakeup_seq; unsigned long long int __woken_seq; void *__mutex; + int __clock; unsigned int __broadcast_seq; } __data; char __size[__SIZEOF_PTHREAD_COND_T]; --- libc/nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h 2004-03-24 12:17:00.000000000 +0100 +++ libc/nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h 2004-05-18 15:16:44.000000000 +0200 @@ -29,6 +29,7 @@ #define FUTEX_WAIT 0 #define FUTEX_WAKE 1 #define FUTEX_REQUEUE 3 +#define FUTEX_CMP_REQUEUE 4 /* Initializer for compatibility lock. */ #define LLL_MUTEX_LOCK_INITIALIZER (0) @@ -82,22 +83,29 @@ }) -#define lll_futex_requeue(futex, nr_wake, nr_move, mutex) \ +/* Returns non-zero if error happened, zero if success. */ +#if 0 +/* FIXME: s390 only supports up to 5 argument syscalls. Once FUTEX_CMP_REQUEUE + kernel interface for s390 is finalized, adjust this. */ +#define lll_futex_requeue(futex, nr_wake, nr_move, mutex, val) \ ({ \ - register unsigned long int __r2 asm ("2") = (unsigned long int) (futex); \ - register unsigned long int __r3 asm ("3") = FUTEX_REQUEUE; \ - register unsigned long int __r4 asm ("4") = (long int) (nr_wake); \ - register unsigned long int __r5 asm ("5") = (long int) (nr_move); \ - register unsigned long int __r6 asm ("6") = (unsigned long int) (mutex); \ - register unsigned long __result asm ("2"); \ + register unsigned long int __r2 asm ("2") = (unsigned long int) (futex); \ + register unsigned long int __r3 asm ("3") = FUTEX_CMP_REQUEUE; \ + register unsigned long int __r4 asm ("4") = (long int) (nr_wake); \ + register unsigned long int __r5 asm ("5") = (long int) (nr_move); \ + register unsigned long int __r6 asm ("6") = (unsigned long int) (mutex); \ + register unsigned long __result asm ("2"); \ \ __asm __volatile ("svc %b1" \ : "=d" (__result) \ : "i" (SYS_futex), "0" (__r2), "d" (__r3), \ "d" (__r4), "d" (__r5), "d" (__r6) \ : "cc", "memory" ); \ - __result; \ + __result > -4096UL; \ }) +#else +#define lll_futex_requeue(futex, nr_wake, nr_move, mutex, val) 1 +#endif #define lll_compare_and_swap(futex, oldval, newval, operation) \ --- libc/nptl/sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h 2004-05-19 22:58:46.637633349 +0200 +++ libc/nptl/sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h 2004-05-18 14:45:41.000000000 +0200 @@ -96,11 +96,12 @@ typedef union struct { int __lock; - int __clock; + unsigned int __futex; unsigned long long int __total_seq; unsigned long long int __wakeup_seq; unsigned long long int __woken_seq; void *__mutex; + int __clock; unsigned int __broadcast_seq; } __data; char __size[__SIZEOF_PTHREAD_COND_T]; --- libc/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h 2004-03-24 12:17:00.000000000 +0100 +++ libc/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h 2004-05-18 15:21:43.000000000 +0200 @@ -29,6 +29,7 @@ #define FUTEX_WAIT 0 #define FUTEX_WAKE 1 #define FUTEX_REQUEUE 3 +#define FUTEX_CMP_REQUEUE 4 /* Initializer for compatibility lock. */ #define LLL_MUTEX_LOCK_INITIALIZER (0) @@ -63,15 +64,16 @@ __ret; \ }) -#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex) \ +/* Returns non-zero if error happened, zero if success. */ +#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex, val) \ ({ \ INTERNAL_SYSCALL_DECL (__err); \ long int __ret; \ \ - __ret = INTERNAL_SYSCALL (futex, __err, 5, \ - (futexp), FUTEX_REQUEUE, (nr_wake), (nr_move), \ - (mutex)); \ - __ret; \ + __ret = INTERNAL_SYSCALL (futex, __err, 6, \ + (futexp), FUTEX_CMP_REQUEUE, (nr_wake), \ + (nr_move), (mutex), (val)); \ + INTERNAL_SYSCALL_ERROR_P (__ret, __err); \ }) #ifdef __sparc32_atomic_do_lock --- libc/nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h 2004-05-19 22:58:46.739615073 +0200 +++ libc/nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h 2004-05-18 14:46:25.000000000 +0200 @@ -76,11 +76,12 @@ typedef union struct { int __lock; - int __clock; + unsigned int __futex; unsigned long long int __total_seq; unsigned long long int __wakeup_seq; unsigned long long int __woken_seq; void *__mutex; + int __clock; unsigned int __broadcast_seq; } __data; char __size[__SIZEOF_PTHREAD_COND_T]; --- libc/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S 2004-05-19 22:58:46.651630841 +0200 +++ libc/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S 2004-05-18 17:35:15.000000000 +0200 @@ -32,6 +32,7 @@ #define FUTEX_WAIT 0 #define FUTEX_WAKE 1 #define FUTEX_REQUEUE 3 +#define FUTEX_CMP_REQUEUE 4 #define EINVAL 22 @@ -55,39 +56,42 @@ __pthread_cond_broadcast: #endif jnz 1f -2: addq $wakeup_seq, %rdi - movq total_seq-wakeup_seq(%rdi), %rcx - cmpq (%rdi), %rcx +2: addq $cond_futex, %rdi + movq total_seq-cond_futex(%rdi), %r9 + cmpq wakeup_seq-cond_futex(%rdi), %r9 jna 4f /* Cause all currently waiting threads to recognize they are woken up. */ - movq %rcx, (%rdi) - movq %rcx, woken_seq-wakeup_seq(%rdi) - incl broadcast_seq-wakeup_seq(%rdi) + movq %r9, wakeup_seq-cond_futex(%rdi) + movq %r9, woken_seq-cond_futex(%rdi) + addq %r9, %r9 + movl %r9d, (%rdi) + incl broadcast_seq-cond_futex(%rdi) /* Get the address of the mutex used. */ - movq dep_mutex-wakeup_seq(%rdi), %r8 + movq dep_mutex-cond_futex(%rdi), %r8 /* Unlock. */ LOCK - decl cond_lock-wakeup_seq(%rdi) + decl cond_lock-cond_futex(%rdi) jne 7f 8: cmpq $-1, %r8 je 9f /* Wake up all threads. */ - movq $FUTEX_REQUEUE, %rsi + movq $FUTEX_CMP_REQUEUE, %rsi movq $SYS_futex, %rax movl $1, %edx movq $0x7fffffff, %r10 syscall -#ifndef __ASSUME_FUTEX_REQUEUE - cmpq $-EINVAL, %rax - je 9f -#endif + /* 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 + jae 9f 10: xorl %eax, %eax retq @@ -95,7 +99,7 @@ __pthread_cond_broadcast: .align 16 /* Unlock. */ 4: LOCK - decl cond_lock-wakeup_seq(%rdi) + decl cond_lock-cond_futex(%rdi) jne 5f 6: xorl %eax, %eax @@ -113,14 +117,14 @@ __pthread_cond_broadcast: jmp 2b /* Unlock in loop requires wakeup. */ -5: addq $cond_lock-wakeup_seq, %rdi +5: addq $cond_lock-cond_futex, %rdi callq __lll_mutex_unlock_wake jmp 6b /* Unlock in loop requires wakeup. */ -7: addq $cond_lock-wakeup_seq, %rdi +7: addq $cond_lock-cond_futex, %rdi callq __lll_mutex_unlock_wake - subq $cond_lock-wakeup_seq, %rdi + subq $cond_lock-cond_futex, %rdi jmp 8b 9: /* The futex requeue functionality is not available. */ --- libc/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S 2003-09-22 06:40:38.000000000 +0200 +++ libc/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S 2004-05-18 16:26:43.000000000 +0200 @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2002. @@ -56,13 +56,14 @@ __pthread_cond_signal: #endif jnz 1f -2: addq $wakeup_seq, %rdi +2: addq $cond_futex, %rdi movq total_seq(%r8), %rcx - cmpq (%rdi), %rcx + cmpq wakeup_seq(%r8), %rcx jbe 4f /* Bump the wakeup number. */ - addq $1, (%rdi) + addq $1, wakeup_seq(%r8) + addl $1, (%rdi) /* Wake up one thread. */ movq $FUTEX_WAKE, %rsi @@ -95,11 +96,7 @@ __pthread_cond_signal: /* Unlock in loop requires wakeup. */ 5: -#if cond_lock != 0 - addq $cond_lock-wakeup_seq, %rdi -#else movq %r8, %rdi -#endif callq __lll_mutex_unlock_wake jmp 6b .size __pthread_cond_signal, .-__pthread_cond_signal --- libc/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S 2004-05-19 22:58:46.652630661 +0200 +++ libc/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S 2004-05-18 16:18:52.000000000 +0200 @@ -105,6 +105,7 @@ __pthread_cond_timedwait: movq 8(%rsp), %rdi incq total_seq(%rdi) + incl cond_futex(%rdi) /* Install cancellation handler. */ #ifdef PIC @@ -118,9 +119,9 @@ __pthread_cond_timedwait: /* Get and store current wakeup_seq value. */ movq 8(%rsp), %rdi - movq wakeup_seq(%rdi), %r12 + movq wakeup_seq(%rdi), %r9 movl broadcast_seq(%rdi), %edx - movq %r12, 40(%rsp) + movq %r9, 40(%rsp) movl %edx, 4(%rsp) /* Get the current time. */ @@ -172,6 +173,8 @@ __pthread_cond_timedwait: 21: movq %rcx, 24(%rsp) movq %rdx, 32(%rsp) + movl cond_futex(%rdi), %r12d + /* Unlock. */ LOCK #if cond_lock == 0 @@ -187,7 +190,7 @@ __pthread_cond_timedwait: leaq 24(%rsp), %r10 xorq %rsi, %rsi /* movq $FUTEX_WAIT, %rsi */ movq %r12, %rdx - addq $wakeup_seq-cond_lock, %rdi + addq $cond_futex, %rdi movq $SYS_futex, %rax syscall movq %rax, %r14 @@ -211,21 +214,22 @@ __pthread_cond_timedwait: movq woken_seq(%rdi), %rax - movq wakeup_seq(%rdi), %r12 + movq wakeup_seq(%rdi), %r9 cmpl 4(%rsp), %edx jne 23f - cmpq 40(%rsp), %r12 + cmpq 40(%rsp), %r9 jbe 15f - cmpq %rax, %r12 + cmpq %rax, %r9 ja 9f 15: cmpq $-ETIMEDOUT, %r14 jne 8b 13: incq wakeup_seq(%rdi) + incl cond_futex(%rdi) movq $ETIMEDOUT, %r14 jmp 14f --- libc/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S 2004-05-19 22:58:46.739615073 +0200 +++ libc/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S 2004-05-18 17:47:31.000000000 +0200 @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2002. @@ -69,6 +69,8 @@ __condvar_cleanup: incq woken_seq(%rdi) + incl cond_futex(%rdi) + 3: LOCK #if cond_lock == 0 decl (%rdi) @@ -82,7 +84,7 @@ __condvar_cleanup: callq __lll_mutex_unlock_wake /* Wake up all waiters to make sure no signal gets lost. */ -2: addq $wakeup_seq, %rdi +2: addq $cond_futex, %rdi movq $FUTEX_WAKE, %rsi movl $0x7fffffff, %edx movq $SYS_futex, %rax @@ -154,6 +156,7 @@ __pthread_cond_wait: movq 8(%rsp), %rdi incq total_seq(%rdi) + incl cond_futex(%rdi) /* Install cancellation handler. */ #ifdef PIC @@ -167,13 +170,14 @@ __pthread_cond_wait: /* Get and store current wakeup_seq value. */ movq 8(%rsp), %rdi - movq wakeup_seq(%rdi), %r12 + movq wakeup_seq(%rdi), %r9 movl broadcast_seq(%rdi), %edx - movq %r12, 24(%rsp) + movq %r9, 24(%rsp) movl %edx, 4(%rsp) /* Unlock. */ -8: LOCK +8: movl cond_futex(%rdi), %r12d + LOCK #if cond_lock == 0 decl (%rdi) #else @@ -187,7 +191,7 @@ __pthread_cond_wait: movq 8(%rsp), %rdi xorq %r10, %r10 movq %r12, %rdx - addq $wakeup_seq-cond_lock, %rdi + addq $cond_futex-cond_lock, %rdi movq $SYS_futex, %rax movq %r10, %rsi /* movq $FUTEX_WAIT, %rsi */ syscall @@ -211,15 +215,15 @@ __pthread_cond_wait: movq woken_seq(%rdi), %rax - movq wakeup_seq(%rdi), %r12 + movq wakeup_seq(%rdi), %r9 cmpl 4(%rsp), %edx jne 16f - cmpq 24(%rsp), %r12 + cmpq 24(%rsp), %r9 jbe 8b - cmpq %rax, %r12 + cmpq %rax, %r9 jna 8b incq woken_seq(%rdi) @@ -359,8 +363,8 @@ versioned_symbol (libpthread, __pthread_ .byte 0x40+.Lsubq-.Lpush_r12 # DW_CFA_advance_loc+N .byte 14 # DW_CFA_def_cfa_offset .uleb128 16+FRAME_SIZE - .byte 2 # DW_CFA_advance_loc1 - .byte .Laddq-.Lsubq + .byte 3 # DW_CFA_advance_loc2 + .2byte .Laddq-.Lsubq .byte 14 # DW_CFA_def_cfa_offset .uleb128 16 .byte 0x40+.Lpop_r12-.Laddq # DW_CFA_advance_loc+N Jakub From Sebastien.Decugis at Ext.Bull.Net Thu May 27 14:23:39 2004 From: Sebastien.Decugis at Ext.Bull.Net (Sebastien DECUGIS) Date: Thu, 27 May 2004 16:23:39 +0200 Subject: Erroneous behavior Message-ID: <1085667819.2156.150.camel@decugiss.frec.bull.fr> Hi, I've run into an issue with pthread_cond_timedwait() and clock_settime(). The basics of my attached test is: clock_gettime() -> time in ts create a thread [thread] pthread_cond_timedwait() with timeout = ts + 20sec [main]clock_settime() with new ts > timeout In this situation, the POSIX IEEE 1003.1 (2004) standard states that the behavior of the thread should be as if the time had runned out (please refer to the clock_settime() reference, ?4). But when I run my test with a fresh nptl (cvs from monday), I have to wait for the timeout as if the clock had not been changed. Please note that even if I signal the condition, I get the ETIMEDOUT error code return (which is normal). I think this is due to the absolute timeout parameter being tranformed into a relative timeout in the pthread_cond_timedwait routine. Is this operation unavoidable? Maybe a workaround would be to wake every threads waiting (in pthread_cond_timedwait) on a given clock when this clock is set forward. At worst, it results in a legal spurious wakeup, if the time out is not expired. Please let me know if this is a kernel issue? Thank you, Sebastien. -- S?bastien DECUGIS Bull S.A. NPTL Tests & Trace project http://nptl.bullopensource.org/phpBB/ -------------- next part -------------- A non-text attachment was scrubbed... Name: test.tar.gz Type: application/x-compressed-tar Size: 9363 bytes Desc: not available URL: