David Miller <[EMAIL PROTECTED]> writes:

> From: Ian Lance Taylor <[EMAIL PROTECTED]>
> Date: 25 Oct 2007 21:31:56 -0700
> 
> > Samuel Tardieu <[EMAIL PROTECTED]> writes:
> > 
> > > int
> > > trylock()
> > > {
> > >   int res;
> > > 
> > >   res = pthread_mutex_trylock(&mutex);
> > >   if (res == 0)
> > >     ++acquires_count;
> > > 
> > >   return res;
> > > }
>  ...
> > Code like needs to use volatile or explicit memory barriers.
> 
> I totally disagree with you, and I think POSIX does too.
> 
> Threaded programming is hard enough as it is.
> 
> What's the point of the lock if a test on whether we've obtained it or
> not can't be used to conditionalize code execution?
> 
> Any write to memory is a globally visible side effect, and even
> ignoring theading issues I bet similar cases can be constructed
> involving signals that behave equally unexpectedly and should not
> require bogus memory barriers or volatile.
> 
> I'm not sure people realize the true ramifications of this suggested
> "fix".  It is rediculious, by any measure.

Conversely, I'm not sure you realize the true ramifications of any
other fix.

The above code happens to use pthread_mutex_trylock, but there is no
need for that.  We could have a global variable "lock_is_held".  The
code could look like this:

    if (lock_is_held)
      ++still_holding;

If the earlier code should work in a multi-threaded environment, then
this code should work.

But then we see that there is nothing special about stores.  The code
could look like this:

    if (lock_is_held)
      waiting_count = threads_waiting;

    // Do something complicated, but don't call any functions.

    if (lock_is_held)
      if (threads_waiting > waiting_count)
        sched_yield();

If the earlier code should work in a multi-threaded environment, then
this code should work too.

But that means that we can't hoist the load of the global variable
threads_waiting--we have to explicitly load it twice.  And remember:
this applies to all code.

That means that if a single function loads a global variable, we must
explicitly load it twice.  And that is true even if that single
function is constructed by inlining several other functions.

At this point we are sacrificing significant optimization.

So now we have a choice: make subtle multi-threaded code, which is not
standard conformant, work as the programmer expects, or optimize
programs with global variables and inline functions.  There is a lot
more of the latter than the former.  And we do provide a way to make
the former work.  And the former is not standard conformant while the
latter is.

So I really don't think my position is all that ridiculous.

And I challenge you to find anything in POSIX which says that this
code is supposed to work.

Ian

Reply via email to