Email List: Xaustin-group-lX
[All Lists]

Re: Defect in XBD 4.10

To: yyyyyyyyyyyyyyyyyyyy@xxxxxxxxxxxxxxxx
Subject: Re: Defect in XBD 4.10
From: Alexander Terekhov <yyyyyyyy@xxxxxxxxxx>
Date: Mon, 8 Nov 2004 09:35:01 +0100
Cc: yyyyyyyyyyyyyy@xxxxxxxxxxxxx
David Hopwood <yyyyyyyyyyyyyyyyyyyy@xxxxxxxxxxxxxxxx> wrote:
> 
> Alexander Terekhov wrote:
> > Action:
> >
> > Replace XBD 4.10 by something stating that
> >
> > ----
> > Applications shall ensure that access to any memory location
>
> "memory location"?

Oh yeah. See

http://www.opengroup.org/sophocles/show_mail.tpl?source=L&listname=austin-review-l&id=1133
http://www.opengroup.org/sophocles/show_mail.tpl?source=L&listname=austin-group-l&id=3988

Thus far, the resolution is at this stage:

http://google.com/groups?threadm=TJlF9.82%24f%25.43066%40newsfep2-gui
(Subject: Re: Memory isolation)

<quote>

For your information, this subject was discussed at
the last meeting of the British C++ standards panel,
and the consensus seemed to be that it was an issue
worth pursuing further. This doesn't mean it will be
dealt with by the next C++ standard, but it is one step
closer.

</quote>

In mutex_and_condvar_free_single_producer_single_consumer sketch
that I've posted in one of the XBD 4.10 threads here, I've simply
used isolated<> template. I mean

// Introspection (for bool argument below) aside for a moment
template<typename T, bool copy_ctor_or_dtor_can_mutate_object>
class mutex_and_condvar_free_single_producer_single_consumer {

  typedef isolated< aligned_storage< T > > ELEM;

  size_t           m_size; // > 1
  ELEM *           m_elem;
  atomic< ELEM * > m_head; 
  atomic< ELEM * > m_tail;

  ELEM * advance(ELEM * elem) const {
    return (++elem < m_elem + m_size) ? elem : m_elem;
  }

  ...

public:

  ...

  void producer(const T & value) {
    ELEM * tail = m_tail.load(msync::none);
    ELEM * next = advance(tail);
    while (next == m_head.load(msync::cchsb)) usleep(1000);
    new(tail) T(value);
    m_tail.store(next, msync::ssb);
  }

  T consumer() {
    ELEM * head = m_head.load(msync::none);
    while (head == m_tail.load(type_list< msync::cchlb_t, msync::ccacq_t 
>::
      element<copy_ctor_or_dtor_can_mutate_object>::type())) usleep(1000);
    T value(*head); 
    head->~T();
    m_head.store(advance(head), type_list< msync::slb_t, msync::rel_t >::
      element<copy_ctor_or_dtor_can_mutate_object>::type());
    return value;
  }

};


> > by more than one thread is restricted such that no thread can read or
> > modify a memory location while another thread of control may be 
modifying
> > it. Applications shall use functions listed below that synchronize 
thread
> > execution
> 
> Shall use them when?

When some thread(s) can read or modify a memory location while another 
thread of control may be modifying it.

> > and ensure that modifications to locations in memory are ordered with
> > respect to accesses to the same memory locations in other threads.
> 
> I see what you mean, but this is imprecise and too easily 
misinterpreted.

May be.

> Methinks:
>  - there is a complete partial order [later correction: 'strict partial 
order'] on 
>    /events/, which include accesses and sequence points in all threads;

I'm not sure what that means.

>   - every access is to a /field/ (cannot use 'object' because bits of
>     bit fields are objects, and we mean something like the smallest 
non-bit
>     object read or modified by the access). Two fields /overlap/ if they
>     have at least one common byte in their representations;

See the "Memory isolation" thread.

> 
>   - the application shall not perform two accesses in different threads
>     to overlapping fields, at least one of which is a modification, that
>     are unordered relative to each other;
> 
>   - [nonnormative] a situation in which an application would violate the
>     above requirement is called a /data-race/.

Agreed.

> This does not, of course, imply that the relative ordering of events
> in different threads needs to be deterministic in a POSIX-conforming
> application.

I'd prefer not to use the term "event".

> > There is a happens-before inter-thread ordering with respect to 
preceding
> > (in program and inter-thread order) modifications of memory locations
> > in
> 
> [snip most of the ordering constraints; they look OK to me]
> 
> Need to add:
>      a sequence point of a thread, and its next sequence point;

Isn't that already defined by the C[/C++] standard that POSIX defers to?

>      an access that occurs "previous" to a sequence point in the
>      sense of C99 5.1.2.3, and that sequence point;
> 
>      a sequence point, and an access that occurs "subsequent" to
>      that sequence point in the sense of C99 5.1.2.3.
> 
> The constraints that refer to functions should refer to the sequence
> point before or after the function call.

IIRC "sequence points" refer to "side effects". I've added "Functions 
listed above and pthread_cond_signal() and pthread_cond_broadcast() 
are all side effects." statement exactly for that reason. Of cause,
implementations still can perform "as if" optimizations/reorderings
(ones that don't change "observable behavior" [in C++ terms] and
don't break inter-thread happens-before ordering defined by high 
level MT memory model coupled with sequence point ordering defined
by the C/C++ standards).

> >   a thread calling pthread_barrier_wait() on a specified barrier
> >   and accesses to modified memory locations in another thread
> >   after another thread returns from pthread_barrier_wait() call
> 
> "after that thread returns ..." (same correction for some of the
> other constraints).

Noted.

> >   on the same specified barrier on the same or later barrier cycle;
> >
> > Functions listed above and pthread_cond_signal() and
>  > pthread_cond_broadcast() are all side effects.
> 
> Not necessary, because they do not have visible effects outside the
> process.

See above.

And thanks for the comments.

regards,
alexander.

<Prev in Thread] Current Thread [Next in Thread>