From nobody Tue Dec 23 13:45:57 2003 X-From-Line: imap Fri Oct 10 00:06:00 2003 Return-Path: Received: from pobox.corp.redhat.com ([unix socket]) by pobox.corp.redhat.com (Cyrus v2.1.12) with LMTP; Fri, 10 Oct 2003 00:18:13 -0400 X-Sieve: CMU Sieve 2.2 Received: from int-mx1.corp.redhat.com (int-mx1.corp.redhat.com [172.16.52.254]) by pobox.corp.redhat.com (8.12.8/8.12.8) with ESMTP id h9A4ID95005655 for ; Fri, 10 Oct 2003 00:18:13 -0400 Received: from myware.akkadia.org (drepper.cipe.redhat.com [10.0.1.84]) by int-mx1.corp.redhat.com (8.11.6/8.11.6) with ESMTP id h9A4IBc24844 for ; Fri, 10 Oct 2003 00:18:11 -0400 Received: from redhat.com (drepper@myware.akkadia.org [192.168.7.70]) by myware.akkadia.org (8.12.10/8.12.10) with ESMTP id h9A4IAdb002566 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Thu, 9 Oct 2003 21:18:10 -0700 X-Gnus-Mail-Source: imap:localhost:INBOX Message-ID: <3F8632FB.70909@redhat.com> Date: Thu, 09 Oct 2003 21:18:03 -0700 From: Ulrich Drepper Organization: Red Hat, Inc. User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20030925 Thunderbird/0.3 X-Accept-Language: en-us, en MIME-Version: 1.0 To: Jim Blandy Subject: Re: signals and memory synchronization References: In-Reply-To: X-Enigmail-Version: 0.81.7.0 X-Enigmail-Supports: pgp-inline, pgp-mime Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Lines: 105 Xref: zenia.home mail.misc:51261 -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Jim Blandy wrote: > There is no function (that I can see) that is both async-safe and > memory-synchronizing, to allow a thread's signal handler to wait for > some other thread's permission to continue. Shouldn't there be some > way for a handler to pause until some other thread gives the go-ahead, > that also ensures that the waiting thread will see the notifying > thread's changes to memory? Not with the POSIX model in mind. Signals are something special, signal handlers are executed in exceptional situations. They are not meant to be general purpose environments. This is important since signals are sometimes used to implement other parts of the runtime. Look at LinuxThreads, which basically implemented all locking with signals. This made other uses of signals everything but reliable and without the restrictions on which interfaces can be used in signal handlers imposed by POSIX it wouldn't be possible at all. > I'm implementing a multi-threaded, precise garbage collector. I don't > want my collector's C API to require its users to call checkpoint > functions periodically to indicate when it's safe to GC, Well, you probably know how other GCs work. Just to make sure: most GCs have a special page somewhere in the address space which is usually writable. If a thread wants to make sure that memory allocation is OK it first writes to this page. There is also probably some way for the thread to signal that it has finished the work. If the GC wants memory operations to be stopped it makes the page unwritable or unreadable or both. Any access will lead to a segfault which can be caught. The worker threads can determine from the segfault address whether this is caused by access to this special page or not. There are lots of bells and whistles and possible pitfalls, but this mechanism is pretty fast. Just one or two memory accesses which usually are fast. Well, they are fast if you can assure that the processors don't play ping-pong with the cache lines. > because that > requirement is sometimes impossible to meet when working with > third-party code. Well, third-party Java code goes through the JNI which means entry and exit of the native code can be monitored. From outside the JRE memory can only be accessed via special interfaces, which can have the checks built in. There is usually no need to preemptively stop all threads. If you have pure computing threads, why should they be stopped. > Each mutator thread, in its signal handler, posts to > that semphore when it's ready to pause. This works great, because > sem_post is async-safe, and synchronizes memory, so the collecting > thread will see the mutators' work. Yes, that works. But there is no interface to wait for one of a set of semaphores. I guess if you really need full synchronization this isn't important. > Then, the mutator threads need to > pause until the collecting thread says it's done --- but there's no > async-safe, memory-synchronizing wait primitive. > > That's what I think is missing from POSIX. Or am I missing something? There is no such interface, and for good reason as explained above. The 'P' in POSIX stands for portable and there is no way to get all parties interested in POSIX to agree to something like this. The best you can hope for are OS-specific methods. For recent Linux systems you can easily use futexes. Since you can use futexes to implement a condition variable-like behavior you wouldn't even have to wake all threads individually. One FUTEX_WAKE call would be sufficient. Also, the wakeup of the GC thread can be done better with futexes. Semaphores aren't ideal since you need a semaphore for each working thread. If you instead can have something where the waiter is only woken after all the threads it signaled arrive at the sync point, this would be more efficient. Easily doable with futexes. I would certainly try to take advantage of the features a system provides and only fall back to a generic method if there is no better way. - -- - --------------. ,-. 444 Castro Street Ulrich Drepper \ ,-----------------' \ Mountain View, CA 94041 USA Red Hat `--' drepper at redhat.com `--------------------------- -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.2.2 (GNU/Linux) iD8DBQE/hjMB2ijCOnn/RHQRAsN4AJwNz6Ar5oZ5cgboahReVzMsqbVoZACfTmM7 E3yJsDRFBJlHngrTEGlOPOM= =THpz -----END PGP SIGNATURE-----