RE: JavaMemoryModel: Re: "Double-Checked Locking is Broken"

From: TEREKHOV@de.ibm.com
Date: Tue Mar 27 2001 - 12:41:40 EST


Hi, "Boehm, Hans" <hans_boehm@hp.com> wrote:

> Interesting.
>
> > In POSIX, I'm not sure how to do allocation, cleanup, and management
> > of TSD. These could be problems, especially for singletons in dlls.
> > (Or maybe not. I hope someone else knows.) Otherwise, so long as you
> > aren't using very large numbers of singletons and threads, this looks
> > like a competitive option.

> I would guess you call pthread_key_create in a constructor for a static.
> This does feel a bit like you're pushing the problem into creating the
> singleton thread-specific data object, which you somehow handle through
> other run-time mechanisms.

umm.. how about eager initialization for tsd keys (before thread(s)
creation) and later, lazy initialization for singletons using previously
initialized tsd keys (sub-{sub-}keys - please see the message below).

> >
> > > Note that it would be sufficient to have a processor specific flag
> > > (instead of thread specific flag) but AFAIK there is no portable
> > > way for doing it...
> >
> > Right. Maybe we need "CPULocals" in Java.

> Does that really buy you performance at user level? Unlike thread
locals,
> the semantics of "CPULocals" seem nontrivial, since you can ge preempted
> halfway through an update ...

that should not be a problem for atomic writes to pre-allocated storage.
and i also think that there should not be any problem to add full mutex
based synchronization (still atomic writes but to dynamically allocated
storage using internal DCL w/o memory barriers) so that get/lookup calls
would still _not_ need any synchronization / memory barriers - that is
what really buys performance. however, it is really important that set()
after get() should not assume that it updates the same CPULocal variable
which was checked via get() - CPU may change - a thread could be running
on a different CPU after get() (fortunately that will make _no_
difference with respect to memory visibility).

regards,
alexander.

----

From: Alexander Terekhov <terekhov@web.de> Newsgroups: comp.programming.threads Subject: Re: DCL -- is there a FAQ? Date: Tue, 27 Mar 2001 13:38:35 +0200

Dave Butenhof wrote:

[...]

> The problem is that TSD isn't free either, and there may be a limited > quantity (PTHREAD_KEYS_MAX, which need be no higher than 128). To make this work at > all in general, you'd need some standard way (e.g., a language feature) to > consolidate these "application keys" into a smaller number of actual POSIX keys. > Compiler support for syntax such as the Microsoft "TLS" __declspec(__thread), layered > on top of POSIX TSD, can do that, but needn't. (And even reducing the TLS key usage > to one per shared library isn't necessarily enough to ensure all possible [or even > reasonable] applications will be able to run.)

umm.. why not try to reduce TLS key usage to just one per _all_ shared libraries, so that each shared library would get one sub-key assigned to it (part of library init) and would itself manage multiple sub-sub-keys for each singleton (just one more level of indirection) ??

as for language feature, i would prefer:

Singleton* Singleton::get_instance() { synch static Singleton theSingleton( _..._ ); return &theSingleton; }

which is similar to PTHREAD's:

static Singleton* theSingleton; static pthread_once_t singleton_init_once_control = PTHREAD_ONCE_INIT;

static void singleton_init_once() { static Singleton _theSingleton( _..._ ); theSingleton = &_theSingleton; }

Singleton* Singleton::get_instance() { pthread_once( &singleton_init_once_control,singleton_init_once ); return theSingleton; }

but that a) "synch" would be simply ignored (by compiler) for ST programs and b) it would _not_ internally use any TSD on UPs/MPs w/o memory reads reordering and c) it would _conditionally_ use TSD if running on processors with memory reads reordering (uniprocessor - no need for TSD, multiprocessor - use TSD -> just one more "if" -- could be even controlled by some compiler option to make "server" code always use TSD - version w/o "if")

btw, linux pthreads (GLIBC):

int __pthread_once(pthread_once_t * once_control, void (*init_routine)(void)) { /* flag for doing the condition broadcast outside of mutex */ int state_changed;

/* Test without locking first for speed */ if (*once_control == DONE) return 0; . . .

seems to be incorrect (for MPs with memory reads reordering). <?> (because it uses "broken" DCL and hence violates "On return from pthread_once(), it is guaranteed that init_routine() has completed. " with respect to memory visibility on MPs with memory reads reordering)

or am i missing something why __pthread_once above should work anyway?

regards, alexander.

"Boehm, Hans" <hans_boehm@hp.com> on 03/26/2001 09:50:40 PM

Please respond to "Boehm, Hans" <hans_boehm@hp.com>

To: "'dl@cs.oswego.edu'" <dl@cs.oswego.edu>, Alexander Terekhov/Germany/IBM@IBMDE cc: dfb@watson.ibm.com, bogda@cs.ucsb.edu, paul@paulhaahr.com, tom@go2net.com, jmaessen@MIT.EDU, pugh@cs.umd.edu, egs@cs.washington.edu, schmidt@cs.wustl.edu, javaMemoryModel@cs.umd.edu Subject: RE: JavaMemoryModel: Re: "Double-Checked Locking is Broken"

Interesting.

> In POSIX, I'm not sure how to do allocation, cleanup, and management > of TSD. These could be problems, especially for singletons in dlls. > (Or maybe not. I hope someone else knows.) Otherwise, so long as you > aren't using very large numbers of singletons and threads, this looks > like a competitive option. I would guess you call pthread_key_create in a constructor for a static. This does feel a bit like you're pushing the problem into creating the singleton thread-specific data object, which you somehow handle through other run-time mechanisms. > > > Note that it would be sufficient to have a processor specific flag > > (instead of thread specific flag) but AFAIK there is no portable > > way for doing it... > > Right. Maybe we need "CPULocals" in Java. Does that really buy you performance at user level? Unlike thread locals, the semantics of "CPULocals" seem nontrivial, since you can ge preempted halfway through an update ...

Hans

------------------------------- JavaMemoryModel mailing list - http://www.cs.umd.edu/~pugh/java/memoryModel



This archive was generated by hypermail 2b29 : Thu Oct 13 2005 - 07:00:30 EDT