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.
|