[M3devel] race conditions in lock-free code...

Tony Hosking hosking at cs.purdue.edu
Tue Aug 28 05:21:40 CEST 2012


Indeed, a lock is overkill.  In general any constructor (initializer) will need a StoreStore barrier (see http://g.oswego.edu/dl/jmm/cookbook.html) before returning a pointer to the constructed storage.

Sent from my iPad

On Aug 27, 2012, at 10:45 PM, Jay <jay.krell at cornell.edu> wrote:

> Alpha may be declining in relevance but MIPS and SPARC are still around and ARM is widespread & growing.

SPARC is TSO. So not necessary.  StoreStore = nop.

ARM needs dmb-st.

Alpha needs wmb.

I don't know what a StoreStore barrier looks like on MIPS.


> 
> A lock is much more than is needed. Just a "fence" or "barrier" before the write into the global like I showed should suffice.
> 
> Compiler should warn...? For writes to globals in the absence of locks or fences/barriers? Including knowing the call graph...

Overkill. Don't scare the horses unnecessarily.  Concurrent programmers must always beware.

> 
> - Jay (briefly/pocket-sized-computer-aka-phone)
> 
> On Aug 27, 2012, at 5:40 PM, Tony Hosking <hosking at cs.purdue.edu> wrote:
> 
>> On Intel we should be OK: x86-TSO causes the write to x^ to appear before the write to global on all cores.
>> 
>> Yes, I think it may have been problematic on Alpha and may still be on PowerPC.  To make the character write visible one would need a fence after the assignment to x^ before returning x.
>> 
>> It would be straightforward to fix this using a LOCK statement around the allocation and initialization.  Or alternatively, if we assume all constructors include an implicit fence then using a constructor would do the trick.
>> 
>> Antony Hosking | Associate Professor | Computer Science | Purdue University
>> 305 N. University Street | West Lafayette | IN 47907 | USA
>> Mobile +1 765 427 5484
>> 
>> 
>> 
>> 
>> 
>> On Aug 27, 2012, at 2:34 PM, Mika Nystrom <mika at async.caltech.edu> wrote:
>> 
>>> 
>>> yeah I agree.
>>> 
>>> processor 1 performs...
>>> 
>>> x  := alloc_new_text
>>> x^ := character
>>> return x
>>> global := x
>>> 
>>> processor 2 performs
>>> 
>>> IF global # NIL THEN use(global) END 
>>> 
>>> now if out of all this, x^ := character is held back, e.g., in a processor
>>> write buffer, and if use(global) involves performing global^, the value
>>> of global^ will be the value of global^ just after x := alloc_new_text
>>> and before x^ := character.
>>> 
>>> I believe very aggressive architectures such as Alpha permit reordering
>>> to that extent.  If memory serves, on Alpha, if you do not perform a
>>> Memory Barrier, pretty much nothing can be inferred on one processor
>>> about the ordering of operations on another.
>>> 
>>> X86 I am not sure is that aggressive.  In a hardware-synchronized
>>> multiprocessor environment without barrier operations using e.g. the
>>> Illinois/MESI protocol (doesn't X86?), at the point x^ := character is
>>> performed, the cache coherence protocol has to guarantee the cache line
>>> is in state Exclusive, which means it has to be evicted from the cache
>>> in processor 2 and when use(global) comes around the protocol will
>>> have to ensure it is in Shared state on processor 2.  (Or Exclusive,
>>> if P1 writes it back and invalidates.)  This would guarantee that you
>>> could not actually see a very old value for global^ at the same time
>>> as a newer value for global.  The protocol guarantees that the relative
>>> ordering of writes is maintained across processors.
>>> 
>>> Of course I don't know whether Alphas are actually that aggressive in
>>> practice.  I'd suspect that a multiprocessor 21264 could be.  But I do
>>> agree it's a bug relative to the Alpha Architecture Manual.  A very nasty
>>> one at that.
>>> 
>>>  Mika
>>> 
>>> 
>>> Jay K writes:
>>>> --_5c33c9ca-3a7d-4c39-ab66-ab9c151d1539_
>>>> Content-Type: text/plain; charset="iso-8859-1"
>>>> Content-Transfer-Encoding: quoted-printable
>>>> 
>>>> It is NOT benign.
>>>> The global can be written before the initialization of what it points to is=
>>>> done.
>>>> The result is wrong.
>>>> 
>>>> 
>>>> It IS benign if multiple threads go and allocate separate multiple initiali=
>>>> zed TEXTs.
>>>> That's not the problem.
>>>> 
>>>> 
>>>> - Jay
>>>> 
>>>> 
>>>>> CC: jay.krell at cornell.edu=3B m3devel at elegosoft.com
>>>>> From: hosking at cs.purdue.edu
>>>>> Subject: Re: [M3devel] race conditions in lock-free code...
>>>>> Date: Mon=2C 27 Aug 2012 09:27:38 -0400
>>>>> To: mika at async.caltech.edu
>>>>> =20
>>>>> So why is this anything other than benign? It's a cache and there's no pr=
>>>> oblem if different threads get different texts. Don't cripple performance u=
>>>> nnecessarily.  The collector will reclaim any unreachable text.
>>>>> =20
>>>>> Sent from my iPad
>>>>> =20
>>>>> On Aug 27=2C 2012=2C at 3:17 AM=2C Mika Nystrom <mika at async.caltech.edu> =
>>>> wrote:
>>>>> =20
>>>>>> Oh I see now.
>>>>>> =20
>>>>>> It's not that the processor reorders in any tricky way.  It is that the
>>>>>> write performed by Text8.New could be sitting around processor 1's cach=
>>>> e
>>>>>> indefinitely without actually getting written back to main memory.
>>>>>> Processor 2 might see the new pointer=2C but when reading the memory po=
>>>> inted
>>>>>> to=2C would get uninitialized memory.  I think this can happen on Alpha=
>>>> but
>>>>>> maybe not X86 (without further reorderings anyhow)?
>>>>>> =20
>>>>>> Any chance any of the pthreads bugs could be of this nature?  How are t=
>>>> he
>>>>>> pthreads doing?  I gathered some bugs were fixed but I haven't tried th=
>>>> e
>>>>>> system for a while.
>>>>>> =20
>>>>>>  Mika
>>>>>> =20
>>>>>> =20
>>>>>> Jay K writes:
>>>>>>> --_86f22d85-5540-4565-bf73-232aaafdc94b_
>>>>>>> Content-Type: text/plain=3B charset=3D"iso-8859-1"
>>>>>>> Content-Transfer-Encoding: quoted-printable
>>>>>>> =20
>>>>>>> The processor can reorder. Across call/ret at least in general.
>>>>>>> =20
>>>>>>> =20
>>>>>>> The compiler can also reorder=3D2C if you have whole-program-optimizat=
>>>> ion=3D2C =3D
>>>>>>> link-time-code-gen (Microsoft "LTCG")=3D2C link-time-optimization (gcc=
>>>> "LTO")=3D
>>>>>>> . (We don't=3D2C but real world systems certainly do.)
>>>>>>> =20
>>>>>>> =20
>>>>>>> - Jay
>>>>>>> =20
>>>>>>> =20
>>>>>>>> To: jay.krell at cornell.edu=3D3B m3devel at elegosoft.com=3D3B mika at async.=
>>>> caltech.=3D
>>>>>>> edu
>>>>>>>> Subject: Re: [M3devel] race conditions in lock-free code...
>>>>>>>> Date: Sun=3D2C 26 Aug 2012 22:32:48 -0700
>>>>>>>> From: mika at async.caltech.edu
>>>>>>>> =3D20
>>>>>>>> Sorry=3D2C I can't seem to quote your message.
>>>>>>>> =3D20
>>>>>>>> You say that Text8.New's result can be assigned to fromCharCache[c]
>>>>>>>> before Text8.New is done running.  How is that possible?  Surely
>>>>>>>> Text8.New has to calculate its result before it can be assigned
>>>>>>>> anywhere.  Yes possibly FromChar allocates space for the result of
>>>>>>>> Text8.New but the assignment of whatever appears in that space can't
>>>>>>>> happen until *after* Text8.New has run.  Unless you are saying that
>>>>>>>> the running of Text8.New and FromChar are intertwined somehow..?
>>>>>>>> I know compilers do some odd things but that doesn't sound right...
>>>>>>>> =3D20
>>>>>>>> If Text8.New took fromCharCache[c] as a VAR parameter you might be
>>>>>>>> right=3D2C though.  But it doesn't...
>>>>>>>> =3D20
>>>>>>>> Am I missing something?
>>>>>>>> =3D20
>>>>>>>>  Mika
>>>>>>>> =3D20
>>>>>>>> Mika Nystrom writes:
>>>>>>>>> =20
>>>>>>>>> Yeah it's a race condition=3D2C in theory.  But is it important?  If=
>>>> you g=3D
>>>>>>> et
>>>>>>>>> the wrong copy=3D2C there will be two TEXTs representing one CHAR.  =
>>>> But no
>>>>>>>>> one ever said FromChar was guaranteed to return the same pointer whe=
>>>> n
>>>>>>>>> you call it with the same CHAR...
>>>>>>>>> =20
>>>>>>>>> Mika
>>>>>>>>> =20
>>>>>>>>> Jay K writes:
>>>>>>>>>> --_5f23896e-68ee-44da-82dd-311cd8c58979_
>>>>>>>>>> Content-Type: text/plain=3D3B charset=3D3D"iso-8859-1"
>>>>>>>>>> Content-Transfer-Encoding: quoted-printable
>>>>>>>>>> =20
>>>>>>>>>> We have race conditions=3D3D2C like this=3D3D2C m3core/src/Text.m3:
>>>>>>>>>> =20
>>>>>>>>>> =20
>>>>>>>>>> VAR fromCharCache :=3D3D3D ARRAY CHAR OF T {NIL=3D3D2C ..}=3D3D3B (=
>>>> * 1-char t=3D
>>>>>>> exts *)
>>>>>>>>>> =20
>>>>>>>>>> =20
>>>>>>>>>> PROCEDURE FromChar (c: CHAR): T =3D3D3D
>>>>>>>>>> VAR buf: ARRAY [0..0] OF CHAR=3D3D3B
>>>>>>>>>> BEGIN
>>>>>>>>>> IF fromCharCache [c] =3D3D3D NIL THEN
>>>>>>>>>>  buf [0] :=3D3D3D c=3D3D3B
>>>>>>>>>>  fromCharCache[c] :=3D3D3D Text8.New (buf)=3D3D3B
>>>>>>>>>> END=3D3D3B
>>>>>>>>>> RETURN fromCharCache [c]
>>>>>>>>>> END FromChar=3D3D3B
>>>>>>>>>> =20
>>>>>>>>>> =20
>>>>>>>>>> It should be:
>>>>>>>>>> =20
>>>>>>>>>> =20
>>>>>>>>>> PROCEDURE FromChar (c: CHAR): T =3D3D3D
>>>>>>>>>> =3D3D0A=3D3D
>>>>>>>>>> VAR buf: ARRAY [0..0] OF CHAR=3D3D3B
>>>>>>>>>> =3D3D0A=3D3D
>>>>>>>>>> BEGIN
>>>>>>>>>> =3D3D0A=3D3D
>>>>>>>>>> IF fromCharCache [c] =3D3D3D NIL THEN
>>>>>>>>>> =3D3D0A=3D3D
>>>>>>>>>>  buf [0] :=3D3D3D c=3D3D3B
>>>>>>>>>> =3D3D0A=3D3D
>>>>>>>>>>  WITH a =3D3D3D Text8.New (buf) DO
>>>>>>>>>>    MemoryBarrier()=3D3D3B
>>>>>>>>>>    fromCharCache[c] :=3D3D3D a=3D3D3B
>>>>>>>>>> END=3D3D3B
>>>>>>>>>> =3D3D0A=3D3D
>>>>>>>>>> END=3D3D3B
>>>>>>>>>> =3D3D0A=3D3D
>>>>>>>>>> RETURN fromCharCache [c]
>>>>>>>>>> =3D3D0A=3D3D
>>>>>>>>>> END FromChar=3D3D3B
>>>>>>>>>> =3D3D0A=3D3D
>>>>>>>>>> =20
>>>>>>>>>> =20
>>>>>>>>>> to ensure that all of Text8.New() finishes before the assignment to=
>>>> fro=3D
>>>>>>> mCha=3D3D
>>>>>>>>>> rCache[c] is made.
>>>>>>>>>> =20
>>>>>>>>>> =20
>>>>>>>>>> Can the compiler somehow catch these?
>>>>>>>>>> I fear they are a small epidemic.
>>>>>>>>>> For a long time people didn't realize where all the compiler and pr=
>>>> oces=3D
>>>>>>> sor =3D3D
>>>>>>>>>> could reorder.
>>>>>>>>>> =20
>>>>>>>>>> =20
>>>>>>>>>> Do we have the right constructs by now to fix them?
>>>>>>>>>> I think we do.
>>>>>>>>>> =20
>>>>>>>>>> =20
>>>>>>>>>> - Jay
>>>>>>>>>>                      =3D3D
>>>>>>>>>> =20
>>>>>>>>>> --_5f23896e-68ee-44da-82dd-311cd8c58979_
>>>>>>>>>> Content-Type: text/html=3D3B charset=3D3D"iso-8859-1"
>>>>>>>>>> Content-Transfer-Encoding: quoted-printable
>>>>>>>>>> =20
>>>>>>>>>> <html>
>>>>>>>>>> <head>
>>>>>>>>>> <style><!--
>>>>>>>>>> .hmmessage P
>>>>>>>>>> {
>>>>>>>>>> margin:0px=3D3D3B
>>>>>>>>>> padding:0px
>>>>>>>>>> }
>>>>>>>>>> body.hmmessage
>>>>>>>>>> {
>>>>>>>>>> font-size: 12pt=3D3D3B
>>>>>>>>>> font-family:Calibri
>>>>>>>>>> }
>>>>>>>>>> --></style></head>
>>>>>>>>>> <body class=3D3D3D'hmmessage'><div dir=3D3D3D'ltr'>We have race con=
>>>> ditions=3D
>>>>>>> =3D3D2C like =3D3D
>>>>>>>>>> this=3D3D2C m3core/src/Text.m3:<br><br><br>VAR fromCharCache :=3D3D=
>>>> 3D ARRAY=3D
>>>>>>> CHAR OF=3D3D
>>>>>>>>>> T {NIL=3D3D2C ..}=3D3D3B (* 1-char texts *)<br><br><br>PROCEDURE Fr=
>>>> omChar =3D
>>>>>>> (c: CHAR=3D3D
>>>>>>>>>> ): T =3D3D3D<br>&nbsp=3D3D3B VAR buf: ARRAY [0..0] OF CHAR=3D3D3B<b=
>>>> r>&nbsp=3D3D=3D
>>>>>>> 3B BEGIN<br>=3D3D
>>>>>>>>>> &nbsp=3D3D3B&nbsp=3D3D3B&nbsp=3D3D3B IF fromCharCache [c] =3D3D3D N=
>>>> IL THEN<br>&=3D
>>>>>>> nbsp=3D3D3B&nbsp=3D3D
>>>>>>>>>> =3D3D3B&nbsp=3D3D3B&nbsp=3D3D3B&nbsp=3D3D3B buf [0] :=3D3D3D c=3D3D=
>>>> 3B<br>&nbsp=3D3D3B=3D
>>>>>>> &nbsp=3D3D3B&nbsp=3D3D3B&n=3D3D
>>>>>>>>>> bsp=3D3D3B&nbsp=3D3D3B fromCharCache[c] :=3D3D3D Text8.New (buf)=3D=
>>>> 3D3B<br>&nbs=3D
>>>>>>> p=3D3D3B&nbsp=3D3D3B=3D3D
>>>>>>>>>> &nbsp=3D3D3B END=3D3D3B<br>&nbsp=3D3D3B&nbsp=3D3D3B&nbsp=3D3D3B RET=
>>>> URN fromCharCa=3D
>>>>>>> che [c]<br>&nb=3D3D
>>>>>>>>>> sp=3D3D3B END FromChar=3D3D3B<br><br><br>It should be:<br><br><br>P=
>>>> ROCEDURE=3D
>>>>>>> FromCha=3D3D
>>>>>>>>>> r (c: CHAR): T =3D3D3D<br>=3D3D0A=3D3D
>>>>>>>>>> &nbsp=3D3D3B VAR buf: ARRAY [0..0] OF CHAR=3D3D3B<br>=3D3D0A=3D3D
>>>>>>>>>> &nbsp=3D3D3B BEGIN<br>=3D3D0A=3D3D
>>>>>>>>>> &nbsp=3D3D3B&nbsp=3D3D3B&nbsp=3D3D3B IF fromCharCache [c] =3D3D3D N=
>>>> IL THEN<br>=3D
>>>>>>> =3D3D0A=3D3D
>>>>>>>>>> &nbsp=3D3D3B&nbsp=3D3D3B&nbsp=3D3D3B&nbsp=3D3D3B&nbsp=3D3D3B buf [0=
>>>> ] :=3D3D3D c=3D3D3=3D
>>>>>>> B<br>=3D3D0A=3D3D
>>>>>>>>>> &nbsp=3D3D3B&nbsp=3D3D3B&nbsp=3D3D3B&nbsp=3D3D3B&nbsp=3D3D3B WITH a=
>>>> =3D3D3D Text8.N=3D
>>>>>>> ew (buf) DO<br>&=3D3D
>>>>>>>>>> nbsp=3D3D3B&nbsp=3D3D3B&nbsp=3D3D3B&nbsp=3D3D3B&nbsp=3D3D3B&nbsp=3D=
>>>> 3D3B&nbsp=3D3D3B M=3D
>>>>>>> emoryBarrier()=3D3D3B<=3D3D
>>>>>>>>>> br>&nbsp=3D3D3B&nbsp=3D3D3B&nbsp=3D3D3B&nbsp=3D3D3B&nbsp=3D3D3B&nbs=
>>>> p=3D3D3B&nbsp=3D3D=3D
>>>>>>> 3B fromCharCache[c=3D3D
>>>>>>>>>> ] :=3D3D3D a=3D3D3B<br>&nbsp=3D3D3B&nbsp=3D3D3B&nbsp=3D3D3B&nbsp=3D=
>>>> 3D3B END=3D3D3B<br=3D
>>>>>>>> =3D3D0A=3D3D
>>>>>>>>>> &nbsp=3D3D3B&nbsp=3D3D3B&nbsp=3D3D3B END=3D3D3B<br>=3D3D0A=3D3D
>>>>>>>>>> &nbsp=3D3D3B&nbsp=3D3D3B&nbsp=3D3D3B RETURN fromCharCache [c]<br>=
>>>> =3D3D0A=3D3D
>>>>>>>>>> &nbsp=3D3D3B END FromChar=3D3D3B<br>=3D3D0A=3D3D
>>>>>>>>>> <br><br>to ensure that all of Text8.New() finishes before the assig=
>>>> nmen=3D
>>>>>>> t to=3D3D
>>>>>>>>>> fromCharCache[c] is made.<br><br><br>Can the compiler somehow catch=
>>>> th=3D
>>>>>>> ese?=3D3D
>>>>>>>>>> <br>I fear they are a small epidemic.<br>For a long time people did=
>>>> n't =3D
>>>>>>> real=3D3D
>>>>>>>>>> ize where all the compiler and processor could reorder.<br><br><br>=
>>>> Do w=3D
>>>>>>> e ha=3D3D
>>>>>>>>>> ve the right constructs by now to fix them?<br>I think we do.<br><b=
>>>> r><b=3D
>>>>>>> r> -=3D3D
>>>>>>>>>> Jay<br>                         </div></body>
>>>>>>>>>> </html>=3D3D
>>>>>>>>>> =20
>>>>>>>>>> --_5f23896e-68ee-44da-82dd-311cd8c58979_--
>>>>>>>                      =3D
>>>>>>> =20
>>>>>>> --_86f22d85-5540-4565-bf73-232aaafdc94b_
>>>>>>> Content-Type: text/html=3B charset=3D"iso-8859-1"
>>>>>>> Content-Transfer-Encoding: quoted-printable
>>>>>>> =20
>>>>>>> <html>
>>>>>>> <head>
>>>>>>> <style><!--
>>>>>>> .hmmessage P
>>>>>>> {
>>>>>>> margin:0px=3D3B
>>>>>>> padding:0px
>>>>>>> }
>>>>>>> body.hmmessage
>>>>>>> {
>>>>>>> font-size: 12pt=3D3B
>>>>>>> font-family:Calibri
>>>>>>> }
>>>>>>> --></style></head>
>>>>>>> <body class=3D3D'hmmessage'><div dir=3D3D'ltr'>The processor can reord=
>>>> er. Acros=3D
>>>>>>> s call/ret at least in general.<br><br><br>The compiler can also reord=
>>>> er=3D2C=3D
>>>>>>> if you have whole-program-optimization=3D2C link-time-code-gen (Micros=
>>>> oft "L=3D
>>>>>>> TCG")=3D2C link-time-optimization (gcc "LTO"). (We don't=3D2C but real=
>>>> world sy=3D
>>>>>>> stems certainly do.)<br><br><br>&nbsp=3D3B- Jay<br><br><br><div><div i=
>>>> d=3D3D"Sk=3D
>>>>>>> yDrivePlaceholder"></div>&gt=3D3B To: jay.krell at cornell.edu=3D3B m3dev=
>>>> el at elegos=3D
>>>>>>> oft.com=3D3B mika at async.caltech.edu<br>&gt=3D3B Subject: Re: [M3devel]=
>>>> race con=3D
>>>>>>> ditions in lock-free code...<br>&gt=3D3B Date: Sun=3D2C 26 Aug 2012 22=
>>>> :32:48 -0=3D
>>>>>>> 700<br>&gt=3D3B From: mika at async.caltech.edu<br>&gt=3D3B <br>&gt=3D3B =
>>>> Sorry=3D2C I =3D
>>>>>>> can't seem to quote your message.<br>&gt=3D3B <br>&gt=3D3B You say tha=
>>>> t Text8.N=3D
>>>>>>> ew's result can be assigned to fromCharCache[c]<br>&gt=3D3B before Tex=
>>>> t8.New =3D
>>>>>>> is done running.  How is that possible?  Surely<br>&gt=3D3B Text8.New =
>>>> has to =3D
>>>>>>> calculate its result before it can be assigned<br>&gt=3D3B anywhere.  =
>>>> Yes pos=3D
>>>>>>> sibly FromChar allocates space for the result of<br>&gt=3D3B Text8.New=
>>>> but th=3D
>>>>>>> e assignment of whatever appears in that space can't<br>&gt=3D3B happe=
>>>> n until=3D
>>>>>>> *after* Text8.New has run.  Unless you are saying that<br>&gt=3D3B the=
>>>> runni=3D
>>>>>>> ng of Text8.New and FromChar are intertwined somehow..?<br>&gt=3D3B I =
>>>> know co=3D
>>>>>>> mpilers do some odd things but that doesn't sound right...<br>&gt=3D3B=
>>>> <br>&g=3D
>>>>>>> t=3D3B If Text8.New took fromCharCache[c] as a VAR parameter you might=
>>>> be<br>=3D
>>>>>>> &gt=3D3B right=3D2C though.  But it doesn't...<br>&gt=3D3B <br>&gt=3D3=
>>>> B Am I missin=3D
>>>>>>> g something?<br>&gt=3D3B <br>&gt=3D3B      Mika<br>&gt=3D3B <br>&gt=3D=
>>>> 3B Mika Nystr=3D
>>>>>>> om writes:<br>&gt=3D3B &gt=3D3B<br>&gt=3D3B &gt=3D3BYeah it's a race c=
>>>> ondition=3D2C i=3D
>>>>>>> n theory.  But is it important?  If you get<br>&gt=3D3B &gt=3D3Bthe wr=
>>>> ong copy=3D
>>>>>>> =3D2C there will be two TEXTs representing one CHAR.  But no<br>&gt=3D=
>>>> 3B &gt=3D3B=3D
>>>>>>> one ever said FromChar was guaranteed to return the same pointer when<=
>>>> br>&g=3D
>>>>>>> t=3D3B &gt=3D3Byou call it with the same CHAR...<br>&gt=3D3B &gt=3D3B<=
>>>> br>&gt=3D3B &gt=3D
>>>>>>> =3D3B     Mika<br>&gt=3D3B &gt=3D3B<br>&gt=3D3B &gt=3D3BJay K writes:<=
>>>> br>&gt=3D3B &gt=3D
>>>>>>> =3D3B&gt=3D3B--_5f23896e-68ee-44da-82dd-311cd8c58979_<br>&gt=3D3B &gt=
>>>> =3D3B&gt=3D3BCon=3D
>>>>>>> tent-Type: text/plain=3D3B charset=3D3D"iso-8859-1"<br>&gt=3D3B &gt=3D=
>>>> 3B&gt=3D3BConte=3D
>>>>>>> nt-Transfer-Encoding: quoted-printable<br>&gt=3D3B &gt=3D3B&gt=3D3B<br=
>>>>> &gt=3D3B &gt=3D
>>>>>>> =3D3B&gt=3D3BWe have race conditions=3D3D2C like this=3D3D2C m3core/sr=
>>>> c/Text.m3:<br=3D
>>>>>>>> &gt=3D3B &gt=3D3B&gt=3D3B<br>&gt=3D3B &gt=3D3B&gt=3D3B<br>&gt=3D3B &g=
>>>> t=3D3B&gt=3D3BVAR fromC=3D
>>>>>>> harCache :=3D3D3D ARRAY CHAR OF T {NIL=3D3D2C ..}=3D3D3B (* 1-char tex=
>>>> ts *)<br>&g=3D
>>>>>>> t=3D3B &gt=3D3B&gt=3D3B<br>&gt=3D3B &gt=3D3B&gt=3D3B<br>&gt=3D3B &gt=
>>>> =3D3B&gt=3D3BPROCEDURE Fr=3D
>>>>>>> omChar (c: CHAR): T =3D3D3D<br>&gt=3D3B &gt=3D3B&gt=3D3B  VAR buf: ARR=
>>>> AY [0..0] OF =3D
>>>>>>> CHAR=3D3D3B<br>&gt=3D3B &gt=3D3B&gt=3D3B  BEGIN<br>&gt=3D3B &gt=3D3B&g=
>>>> t=3D3B    IF fromCh=3D
>>>>>>> arCache [c] =3D3D3D NIL THEN<br>&gt=3D3B &gt=3D3B&gt=3D3B      buf [0]=
>>>> :=3D3D3D c=3D3D3=3D
>>>>>>> B<br>&gt=3D3B &gt=3D3B&gt=3D3B      fromCharCache[c] :=3D3D3D Text8.Ne=
>>>> w (buf)=3D3D3B<=3D
>>>>>>> br>&gt=3D3B &gt=3D3B&gt=3D3B    END=3D3D3B<br>&gt=3D3B &gt=3D3B&gt=3D3=
>>>> B    RETURN fromCha=3D
>>>>>>> rCache [c]<br>&gt=3D3B &gt=3D3B&gt=3D3B  END FromChar=3D3D3B<br>&gt=3D=
>>>> 3B &gt=3D3B&gt=3D3B=3D
>>>>>>> <br>&gt=3D3B &gt=3D3B&gt=3D3B<br>&gt=3D3B &gt=3D3B&gt=3D3BIt should be=
>>>> :<br>&gt=3D3B &gt=3D
>>>>>>> =3D3B&gt=3D3B<br>&gt=3D3B &gt=3D3B&gt=3D3B<br>&gt=3D3B &gt=3D3B&gt=3D3=
>>>> BPROCEDURE FromChar (=3D
>>>>>>> c: CHAR): T =3D3D3D<br>&gt=3D3B &gt=3D3B&gt=3D3B=3D3D0A=3D3D<br>&gt=3D=
>>>> 3B &gt=3D3B&gt=3D3B  VA=3D
>>>>>>> R buf: ARRAY [0..0] OF CHAR=3D3D3B<br>&gt=3D3B &gt=3D3B&gt=3D3B=3D3D0A=
>>>> =3D3D<br>&gt=3D3B &=3D
>>>>>>> gt=3D3B&gt=3D3B  BEGIN<br>&gt=3D3B &gt=3D3B&gt=3D3B=3D3D0A=3D3D<br>&gt=
>>>> =3D3B &gt=3D3B&gt=3D3B   =3D
>>>>>>> IF fromCharCache [c] =3D3D3D NIL THEN<br>&gt=3D3B &gt=3D3B&gt=3D3B=3D3=
>>>> D0A=3D3D<br>&gt=3D
>>>>>>> =3D3B &gt=3D3B&gt=3D3B      buf [0] :=3D3D3D c=3D3D3B<br>&gt=3D3B &gt=
>>>> =3D3B&gt=3D3B=3D3D0A=3D3D<=3D
>>>>>>> br>&gt=3D3B &gt=3D3B&gt=3D3B      WITH a =3D3D3D Text8.New (buf) DO<br=
>>>>> &gt=3D3B &gt=3D
>>>>>>> =3D3B&gt=3D3B        MemoryBarrier()=3D3D3B<br>&gt=3D3B &gt=3D3B&gt=3D=
>>>> 3B        fromCha=3D
>>>>>>> rCache[c] :=3D3D3D a=3D3D3B<br>&gt=3D3B &gt=3D3B&gt=3D3B     END=3D3D3=
>>>> B<br>&gt=3D3B &gt=3D
>>>>>>> =3D3B&gt=3D3B=3D3D0A=3D3D<br>&gt=3D3B &gt=3D3B&gt=3D3B    END=3D3D3B<b=
>>>> r>&gt=3D3B &gt=3D3B&gt=3D3B=3D
>>>>>>> =3D3D0A=3D3D<br>&gt=3D3B &gt=3D3B&gt=3D3B    RETURN fromCharCache [c]<=
>>>> br>&gt=3D3B &gt=3D
>>>>>>> =3D3B&gt=3D3B=3D3D0A=3D3D<br>&gt=3D3B &gt=3D3B&gt=3D3B  END FromChar=
>>>> =3D3D3B<br>&gt=3D3B &gt=3D
>>>>>>> =3D3B&gt=3D3B=3D3D0A=3D3D<br>&gt=3D3B &gt=3D3B&gt=3D3B<br>&gt=3D3B &gt=
>>>> =3D3B&gt=3D3B<br>&gt=3D3B &=3D
>>>>>>> gt=3D3B&gt=3D3Bto ensure that all of Text8.New() finishes before the a=
>>>> ssignment=3D
>>>>>>> to fromCha=3D3D<br>&gt=3D3B &gt=3D3B&gt=3D3BrCache[c] is made.<br>&gt=
>>>> =3D3B &gt=3D3B&gt=3D
>>>>>>> =3D3B<br>&gt=3D3B &gt=3D3B&gt=3D3B<br>&gt=3D3B &gt=3D3B&gt=3D3BCan the=
>>>> compiler somehow c=3D
>>>>>>> atch these?<br>&gt=3D3B &gt=3D3B&gt=3D3BI fear they are a small epidem=
>>>> ic.<br>&gt=3D
>>>>>>> =3D3B &gt=3D3B&gt=3D3BFor a long time people didn't realize where all =
>>>> the compile=3D
>>>>>>> r and processor =3D3D<br>&gt=3D3B &gt=3D3B&gt=3D3Bcould reorder.<br>&g=
>>>> t=3D3B &gt=3D3B&g=3D
>>>>>>> t=3D3B<br>&gt=3D3B &gt=3D3B&gt=3D3B<br>&gt=3D3B &gt=3D3B&gt=3D3BDo we =
>>>> have the right cons=3D
>>>>>>> tructs by now to fix them?<br>&gt=3D3B &gt=3D3B&gt=3D3BI think we do.<=
>>>> br>&gt=3D3B &=3D
>>>>>>> gt=3D3B&gt=3D3B<br>&gt=3D3B &gt=3D3B&gt=3D3B<br>&gt=3D3B &gt=3D3B&gt=
>>>> =3D3B - Jay<br>&gt=3D3B &=3D
>>>>>>> gt=3D3B&gt=3D3B                         =3D3D<br>&gt=3D3B &gt=3D3B&gt=
>>>> =3D3B<br>&gt=3D3B &gt=3D3B&gt=3D3B--_=3D
>>>>>>> 5f23896e-68ee-44da-82dd-311cd8c58979_<br>&gt=3D3B &gt=3D3B&gt=3D3BCont=
>>>> ent-Type: t=3D
>>>>>>> ext/html=3D3B charset=3D3D"iso-8859-1"<br>&gt=3D3B &gt=3D3B&gt=3D3BCon=
>>>> tent-Transfer-E=3D
>>>>>>> ncoding: quoted-printable<br>&gt=3D3B &gt=3D3B&gt=3D3B<br>&gt=3D3B &gt=
>>>> =3D3B&gt=3D3B&lt=3D
>>>>>>> =3D3Bhtml&gt=3D3B<br>&gt=3D3B &gt=3D3B&gt=3D3B&lt=3D3Bhead&gt=3D3B<br>=
>>>> &gt=3D3B &gt=3D3B&gt=3D3B=3D
>>>>>>> &lt=3D3Bstyle&gt=3D3B&lt=3D3B!--<br>&gt=3D3B &gt=3D3B&gt=3D3B.hmmessag=
>>>> e P<br>&gt=3D3B &gt=3D
>>>>>>> =3D3B&gt=3D3B{<br>&gt=3D3B &gt=3D3B&gt=3D3Bmargin:0px=3D3D3B<br>&gt=3D=
>>>> 3B &gt=3D3B&gt=3D3Bpadd=3D
>>>>>>> ing:0px<br>&gt=3D3B &gt=3D3B&gt=3D3B}<br>&gt=3D3B &gt=3D3B&gt=3D3Bbody=
>>>> .hmmessage<br>&gt=3D
>>>>>>> =3D3B &gt=3D3B&gt=3D3B{<br>&gt=3D3B &gt=3D3B&gt=3D3Bfont-size: 12pt=3D=
>>>> 3D3B<br>&gt=3D3B &gt=3D
>>>>>>> =3D3B&gt=3D3Bfont-family:Calibri<br>&gt=3D3B &gt=3D3B&gt=3D3B}<br>&gt=
>>>> =3D3B &gt=3D3B&gt=3D3B=3D
>>>>>>> --&gt=3D3B&lt=3D3B/style&gt=3D3B&lt=3D3B/head&gt=3D3B<br>&gt=3D3B &gt=
>>>> =3D3B&gt=3D3B&lt=3D3Bbod=3D
>>>>>>> y class=3D3D3D'hmmessage'&gt=3D3B&lt=3D3Bdiv dir=3D3D3D'ltr'&gt=3D3BWe=
>>>> have race cond=3D
>>>>>>> itions=3D3D2C like =3D3D<br>&gt=3D3B &gt=3D3B&gt=3D3Bthis=3D3D2C m3cor=
>>>> e/src/Text.m3:&lt=3D
>>>>>>> =3D3Bbr&gt=3D3B&lt=3D3Bbr&gt=3D3B&lt=3D3Bbr&gt=3D3BVAR fromCharCache :=
>>>> =3D3D3D ARRAY CHAR =3D
>>>>>>> OF=3D3D<br>&gt=3D3B &gt=3D3B&gt=3D3B T {NIL=3D3D2C ..}=3D3D3B (* 1-cha=
>>>> r texts *)&lt=3D3Bb=3D
>>>>>>> r&gt=3D3B&lt=3D3Bbr&gt=3D3B&lt=3D3Bbr&gt=3D3BPROCEDURE FromChar (c: CH=
>>>> AR=3D3D<br>&gt=3D3B=3D
>>>>>>> &gt=3D3B&gt=3D3B): T =3D3D3D&lt=3D3Bbr&gt=3D3B&amp=3D3Bnbsp=3D3D3B VAR=
>>>> buf: ARRAY [0..0]=3D
>>>>>>> OF CHAR=3D3D3B&lt=3D3Bbr&gt=3D3B&amp=3D3Bnbsp=3D3D3B BEGIN&lt=3D3Bbr&g=
>>>> t=3D3B=3D3D<br>&gt=3D
>>>>>>> =3D3B &gt=3D3B&gt=3D3B&amp=3D3Bnbsp=3D3D3B&amp=3D3Bnbsp=3D3D3B&amp=3D3=
>>>> Bnbsp=3D3D3B IF fromCha=3D
>>>>>>> rCache [c] =3D3D3D NIL THEN&lt=3D3Bbr&gt=3D3B&amp=3D3Bnbsp=3D3D3B&amp=
>>>> =3D3Bnbsp=3D3D<br>&g=3D
>>>>>>> t=3D3B &gt=3D3B&gt=3D3B=3D3D3B&amp=3D3Bnbsp=3D3D3B&amp=3D3Bnbsp=3D3D3B=
>>>> &amp=3D3Bnbsp=3D3D3B buf =3D
>>>>>>> [0] :=3D3D3D c=3D3D3B&lt=3D3Bbr&gt=3D3B&amp=3D3Bnbsp=3D3D3B&amp=3D3Bnb=
>>>> sp=3D3D3B&amp=3D3Bnbsp=3D
>>>>>>> =3D3D3B&amp=3D3Bn=3D3D<br>&gt=3D3B &gt=3D3B&gt=3D3Bbsp=3D3D3B&amp=3D3B=
>>>> nbsp=3D3D3B fromCharCac=3D
>>>>>>> he[c] :=3D3D3D Text8.New (buf)=3D3D3B&lt=3D3Bbr&gt=3D3B&amp=3D3Bnbsp=
>>>> =3D3D3B&amp=3D3Bnbsp=3D
>>>>>>> =3D3D3B=3D3D<br>&gt=3D3B &gt=3D3B&gt=3D3B&amp=3D3Bnbsp=3D3D3B END=3D3D=
>>>> 3B&lt=3D3Bbr&gt=3D3B&amp=3D
>>>>>>> =3D3Bnbsp=3D3D3B&amp=3D3Bnbsp=3D3D3B&amp=3D3Bnbsp=3D3D3B RETURN fromCh=
>>>> arCache [c]&lt=3D3B=3D
>>>>>>> br&gt=3D3B&amp=3D3Bnb=3D3D<br>&gt=3D3B &gt=3D3B&gt=3D3Bsp=3D3D3B END F=
>>>> romChar=3D3D3B&lt=3D3Bb=3D
>>>>>>> r&gt=3D3B&lt=3D3Bbr&gt=3D3B&lt=3D3Bbr&gt=3D3BIt should be:&lt=3D3Bbr&g=
>>>> t=3D3B&lt=3D3Bbr&gt=3D
>>>>>>> =3D3B&lt=3D3Bbr&gt=3D3BPROCEDURE FromCha=3D3D<br>&gt=3D3B &gt=3D3B&gt=
>>>> =3D3Br (c: CHAR): T =3D
>>>>>>> =3D3D3D&lt=3D3Bbr&gt=3D3B=3D3D0A=3D3D<br>&gt=3D3B &gt=3D3B&gt=3D3B&amp=
>>>> =3D3Bnbsp=3D3D3B VAR buf:=3D
>>>>>>> ARRAY [0..0] OF CHAR=3D3D3B&lt=3D3Bbr&gt=3D3B=3D3D0A=3D3D<br>&gt=3D3B =
>>>> &gt=3D3B&gt=3D3B&amp=3D
>>>>>>> =3D3Bnbsp=3D3D3B BEGIN&lt=3D3Bbr&gt=3D3B=3D3D0A=3D3D<br>&gt=3D3B &gt=
>>>> =3D3B&gt=3D3B&amp=3D3Bnbsp=3D
>>>>>>> =3D3D3B&amp=3D3Bnbsp=3D3D3B&amp=3D3Bnbsp=3D3D3B IF fromCharCache [c] =
>>>> =3D3D3D NIL THEN&l=3D
>>>>>>> t=3D3Bbr&gt=3D3B=3D3D0A=3D3D<br>&gt=3D3B &gt=3D3B&gt=3D3B&amp=3D3Bnbsp=
>>>> =3D3D3B&amp=3D3Bnbsp=3D3D3B=3D
>>>>>>> &amp=3D3Bnbsp=3D3D3B&amp=3D3Bnbsp=3D3D3B&amp=3D3Bnbsp=3D3D3B buf [0] :=
>>>> =3D3D3D c=3D3D3B&lt=3D
>>>>>>> =3D3Bbr&gt=3D3B=3D3D0A=3D3D<br>&gt=3D3B &gt=3D3B&gt=3D3B&amp=3D3Bnbsp=
>>>> =3D3D3B&amp=3D3Bnbsp=3D3D3B&=3D
>>>>>>> amp=3D3Bnbsp=3D3D3B&amp=3D3Bnbsp=3D3D3B&amp=3D3Bnbsp=3D3D3B WITH a =3D=
>>>> 3D3D Text8.New (buf=3D
>>>>>>> ) DO&lt=3D3Bbr&gt=3D3B&amp=3D3B=3D3D<br>&gt=3D3B &gt=3D3B&gt=3D3Bnbsp=
>>>> =3D3D3B&amp=3D3Bnbsp=3D3D3=3D
>>>>>>> B&amp=3D3Bnbsp=3D3D3B&amp=3D3Bnbsp=3D3D3B&amp=3D3Bnbsp=3D3D3B&amp=3D3B=
>>>> nbsp=3D3D3B&amp=3D3Bnbs=3D
>>>>>>> p=3D3D3B MemoryBarrier()=3D3D3B&lt=3D3B=3D3D<br>&gt=3D3B &gt=3D3B&gt=
>>>> =3D3Bbr&gt=3D3B&amp=3D3Bn=3D
>>>>>>> bsp=3D3D3B&amp=3D3Bnbsp=3D3D3B&amp=3D3Bnbsp=3D3D3B&amp=3D3Bnbsp=3D3D3B=
>>>> &amp=3D3Bnbsp=3D3D3B&am=3D
>>>>>>> p=3D3Bnbsp=3D3D3B&amp=3D3Bnbsp=3D3D3B fromCharCache[c=3D3D<br>&gt=3D3B=
>>>> &gt=3D3B&gt=3D3B] :=3D
>>>>>>> =3D3D3D a=3D3D3B&lt=3D3Bbr&gt=3D3B&amp=3D3Bnbsp=3D3D3B&amp=3D3Bnbsp=3D=
>>>> 3D3B&amp=3D3Bnbsp=3D3D3B&=3D
>>>>>>> amp=3D3Bnbsp=3D3D3B END=3D3D3B&lt=3D3Bbr&gt=3D3B=3D3D0A=3D3D<br>&gt=3D=
>>>> 3B &gt=3D3B&gt=3D3B&amp=3D
>>>>>>> =3D3Bnbsp=3D3D3B&amp=3D3Bnbsp=3D3D3B&amp=3D3Bnbsp=3D3D3B END=3D3D3B&lt=
>>>> =3D3Bbr&gt=3D3B=3D3D0A=3D3D=3D
>>>>>>> <br>&gt=3D3B &gt=3D3B&gt=3D3B&amp=3D3Bnbsp=3D3D3B&amp=3D3Bnbsp=3D3D3B&=
>>>> amp=3D3Bnbsp=3D3D3B RET=3D
>>>>>>> URN fromCharCache [c]&lt=3D3Bbr&gt=3D3B=3D3D0A=3D3D<br>&gt=3D3B &gt=3D=
>>>> 3B&gt=3D3B&amp=3D3Bnb=3D
>>>>>>> sp=3D3D3B END FromChar=3D3D3B&lt=3D3Bbr&gt=3D3B=3D3D0A=3D3D<br>&gt=3D3=
>>>> B &gt=3D3B&gt=3D3B&lt=3D
>>>>>>> =3D3Bbr&gt=3D3B&lt=3D3Bbr&gt=3D3Bto ensure that all of Text8.New() fin=
>>>> ishes before =3D
>>>>>>> the assignment to=3D3D<br>&gt=3D3B &gt=3D3B&gt=3D3B fromCharCache[c] i=
>>>> s made.&lt=3D3B=3D
>>>>>>> br&gt=3D3B&lt=3D3Bbr&gt=3D3B&lt=3D3Bbr&gt=3D3BCan the compiler somehow=
>>>> catch these?=3D
>>>>>>> =3D3D<br>&gt=3D3B &gt=3D3B&gt=3D3B&lt=3D3Bbr&gt=3D3BI fear they are a =
>>>> small epidemic.&l=3D
>>>>>>> t=3D3Bbr&gt=3D3BFor a long time people didn't real=3D3D<br>&gt=3D3B &g=
>>>> t=3D3B&gt=3D3Bize=3D
>>>>>>> where all the compiler and processor could reorder.&lt=3D3Bbr&gt=3D3B&=
>>>> lt=3D3Bbr&=3D
>>>>>>> gt=3D3B&lt=3D3Bbr&gt=3D3BDo we ha=3D3D<br>&gt=3D3B &gt=3D3B&gt=3D3Bve =
>>>> the right construct=3D
>>>>>>> s by now to fix them?&lt=3D3Bbr&gt=3D3BI think we do.&lt=3D3Bbr&gt=3D3=
>>>> B&lt=3D3Bbr&gt=3D
>>>>>>> =3D3B&lt=3D3Bbr&gt=3D3B -=3D3D<br>&gt=3D3B &gt=3D3B&gt=3D3B Jay&lt=3D3=
>>>> Bbr&gt=3D3B                         =3D
>>>>>>> &lt=3D3B/div&gt=3D3B&lt=3D3B/body&gt=3D3B<br>&gt=3D3B &gt=3D3B&gt=3D3B=
>>>> &lt=3D3B/html&gt=3D3B=3D
>>>>>>> =3D3D<br>&gt=3D3B &gt=3D3B&gt=3D3B<br>&gt=3D3B &gt=3D3B&gt=3D3B--_5f23=
>>>> 896e-68ee-44da-82dd=3D
>>>>>>> -311cd8c58979_--<br></div>                         </div></body>
>>>>>>> </html>=3D
>>>>>>> =20
>>>>>>> --_86f22d85-5540-4565-bf73-232aaafdc94b_--
>>>>                        =
>>>> 
>>>> --_5c33c9ca-3a7d-4c39-ab66-ab9c151d1539_
>>>> Content-Type: text/html; charset="iso-8859-1"
>>>> Content-Transfer-Encoding: quoted-printable
>>>> 
>>>> <html>
>>>> <head>
>>>> <style><!--
>>>> .hmmessage P
>>>> {
>>>> margin:0px=3B
>>>> padding:0px
>>>> }
>>>> body.hmmessage
>>>> {
>>>> font-size: 12pt=3B
>>>> font-family:Calibri
>>>> }
>>>> --></style></head>
>>>> <body class=3D'hmmessage'><div dir=3D'ltr'>It is NOT benign.<br>The global =
>>>> can be written before the initialization of what it points to is done.<br>T=
>>>> he result is wrong.<br><br><br>It IS benign if multiple threads go and allo=
>>>> cate separate multiple initialized TEXTs.<br>That's not the problem.<br><br=
>>>>> <br>&nbsp=3B- Jay<br><br><br><div><div id=3D"SkyDrivePlaceholder"></div>&g=
>>>> t=3B CC: jay.krell at cornell.edu=3B m3devel at elegosoft.com<br>&gt=3B From: hos=
>>>> king at cs.purdue.edu<br>&gt=3B Subject: Re: [M3devel] race conditions in lock=
>>>> -free code...<br>&gt=3B Date: Mon=2C 27 Aug 2012 09:27:38 -0400<br>&gt=3B T=
>>>> o: mika at async.caltech.edu<br>&gt=3B <br>&gt=3B So why is this anything othe=
>>>> r than benign? It's a cache and there's no problem if different threads get=
>>>> different texts. Don't cripple performance unnecessarily.  The collector w=
>>>> ill reclaim any unreachable text.<br>&gt=3B <br>&gt=3B Sent from my iPad<br=
>>>>> &gt=3B <br>&gt=3B On Aug 27=2C 2012=2C at 3:17 AM=2C Mika Nystrom &lt=3Bmi=
>>>> ka at async.caltech.edu&gt=3B wrote:<br>&gt=3B <br>&gt=3B &gt=3B Oh I see now.=
>>>> <br>&gt=3B &gt=3B <br>&gt=3B &gt=3B It's not that the processor reorders in=
>>>> any tricky way.  It is that the<br>&gt=3B &gt=3B write performed by Text8.=
>>>> New could be sitting around processor 1's cache<br>&gt=3B &gt=3B indefinite=
>>>> ly without actually getting written back to main memory.<br>&gt=3B &gt=3B P=
>>>> rocessor 2 might see the new pointer=2C but when reading the memory pointed=
>>>> <br>&gt=3B &gt=3B to=2C would get uninitialized memory.  I think this can h=
>>>> appen on Alpha but<br>&gt=3B &gt=3B maybe not X86 (without further reorderi=
>>>> ngs anyhow)?<br>&gt=3B &gt=3B <br>&gt=3B &gt=3B Any chance any of the pthre=
>>>> ads bugs could be of this nature?  How are the<br>&gt=3B &gt=3B pthreads do=
>>>> ing?  I gathered some bugs were fixed but I haven't tried the<br>&gt=3B &gt=
>>>> =3B system for a while.<br>&gt=3B &gt=3B <br>&gt=3B &gt=3B     Mika<br>&gt=
>>>> =3B &gt=3B <br>&gt=3B &gt=3B <br>&gt=3B &gt=3B Jay K writes:<br>&gt=3B &gt=
>>>> =3B&gt=3B --_86f22d85-5540-4565-bf73-232aaafdc94b_<br>&gt=3B &gt=3B&gt=3B C=
>>>> ontent-Type: text/plain=3B charset=3D"iso-8859-1"<br>&gt=3B &gt=3B&gt=3B Co=
>>>> ntent-Transfer-Encoding: quoted-printable<br>&gt=3B &gt=3B&gt=3B <br>&gt=3B=
>>>> &gt=3B&gt=3B The processor can reorder. Across call/ret at least in genera=
>>>> l.<br>&gt=3B &gt=3B&gt=3B <br>&gt=3B &gt=3B&gt=3B <br>&gt=3B &gt=3B&gt=3B T=
>>>> he compiler can also reorder=3D2C if you have whole-program-optimization=3D=
>>>> 2C =3D<br>&gt=3B &gt=3B&gt=3B link-time-code-gen (Microsoft "LTCG")=3D2C li=
>>>> nk-time-optimization (gcc "LTO")=3D<br>&gt=3B &gt=3B&gt=3B . (We don't=3D2C=
>>>> but real world systems certainly do.)<br>&gt=3B &gt=3B&gt=3B <br>&gt=3B &g=
>>>> t=3B&gt=3B <br>&gt=3B &gt=3B&gt=3B - Jay<br>&gt=3B &gt=3B&gt=3B <br>&gt=3B =
>>>> &gt=3B&gt=3B <br>&gt=3B &gt=3B&gt=3B&gt=3B To: jay.krell at cornell.edu=3D3B m=
>>>> 3devel at elegosoft.com=3D3B mika at async.caltech.=3D<br>&gt=3B &gt=3B&gt=3B edu=
>>>> <br>&gt=3B &gt=3B&gt=3B&gt=3B Subject: Re: [M3devel] race conditions in loc=
>>>> k-free code...<br>&gt=3B &gt=3B&gt=3B&gt=3B Date: Sun=3D2C 26 Aug 2012 22:3=
>>>> 2:48 -0700<br>&gt=3B &gt=3B&gt=3B&gt=3B From: mika at async.caltech.edu<br>&gt=
>>>> =3B &gt=3B&gt=3B&gt=3B =3D20<br>&gt=3B &gt=3B&gt=3B&gt=3B Sorry=3D2C I can'=
>>>> t seem to quote your message.<br>&gt=3B &gt=3B&gt=3B&gt=3B =3D20<br>&gt=3B =
>>>> &gt=3B&gt=3B&gt=3B You say that Text8.New's result can be assigned to fromC=
>>>> harCache[c]<br>&gt=3B &gt=3B&gt=3B&gt=3B before Text8.New is done running. =
>>>> How is that possible?  Surely<br>&gt=3B &gt=3B&gt=3B&gt=3B Text8.New has t=
>>>> o calculate its result before it can be assigned<br>&gt=3B &gt=3B&gt=3B&gt=
>>>> =3B anywhere.  Yes possibly FromChar allocates space for the result of<br>&=
>>>> gt=3B &gt=3B&gt=3B&gt=3B Text8.New but the assignment of whatever appears i=
>>>> n that space can't<br>&gt=3B &gt=3B&gt=3B&gt=3B happen until *after* Text8.=
>>>> New has run.  Unless you are saying that<br>&gt=3B &gt=3B&gt=3B&gt=3B the r=
>>>> unning of Text8.New and FromChar are intertwined somehow..?<br>&gt=3B &gt=
>>>> =3B&gt=3B&gt=3B I know compilers do some odd things but that doesn't sound =
>>>> right...<br>&gt=3B &gt=3B&gt=3B&gt=3B =3D20<br>&gt=3B &gt=3B&gt=3B&gt=3B If=
>>>> Text8.New took fromCharCache[c] as a VAR parameter you might be<br>&gt=3B =
>>>> &gt=3B&gt=3B&gt=3B right=3D2C though.  But it doesn't...<br>&gt=3B &gt=3B&g=
>>>> t=3B&gt=3B =3D20<br>&gt=3B &gt=3B&gt=3B&gt=3B Am I missing something?<br>&g=
>>>> t=3B &gt=3B&gt=3B&gt=3B =3D20<br>&gt=3B &gt=3B&gt=3B&gt=3B     Mika<br>&gt=
>>>> =3B &gt=3B&gt=3B&gt=3B =3D20<br>&gt=3B &gt=3B&gt=3B&gt=3B Mika Nystrom writ=
>>>> es:<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B <br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B =
>>>> Yeah it's a race condition=3D2C in theory.  But is it important?  If you g=
>>>> =3D<br>&gt=3B &gt=3B&gt=3B et<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B the wrong =
>>>> copy=3D2C there will be two TEXTs representing one CHAR.  But no<br>&gt=3B =
>>>> &gt=3B&gt=3B&gt=3B&gt=3B one ever said FromChar was guaranteed to return th=
>>>> e same pointer when<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B you call it with the=
>>>> same CHAR...<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B <br>&gt=3B &gt=3B&gt=3B&gt=
>>>> =3B&gt=3B    Mika<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B <br>&gt=3B &gt=3B&gt=
>>>> =3B&gt=3B&gt=3B Jay K writes:<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B --_5=
>>>> f23896e-68ee-44da-82dd-311cd8c58979_<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=
>>>> =3B Content-Type: text/plain=3D3B charset=3D3D"iso-8859-1"<br>&gt=3B &gt=3B=
>>>> &gt=3B&gt=3B&gt=3B&gt=3B Content-Transfer-Encoding: quoted-printable<br>&gt=
>>>> =3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B <br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=
>>>> =3B We have race conditions=3D3D2C like this=3D3D2C m3core/src/Text.m3:<br>=
>>>> &gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B <br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&g=
>>>> t=3B <br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B VAR fromCharCache :=3D3D3D A=
>>>> RRAY CHAR OF T {NIL=3D3D2C ..}=3D3D3B (* 1-char t=3D<br>&gt=3B &gt=3B&gt=3B=
>>>> exts *)<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B <br>&gt=3B &gt=3B&gt=3B&g=
>>>> t=3B&gt=3B&gt=3B <br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B PROCEDURE FromCh=
>>>> ar (c: CHAR): T =3D3D3D<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B VAR buf: A=
>>>> RRAY [0..0] OF CHAR=3D3D3B<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B BEGIN<b=
>>>> r>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B   IF fromCharCache [c] =3D3D3D NIL =
>>>> THEN<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B     buf [0] :=3D3D3D c=3D3D3B=
>>>> <br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B     fromCharCache[c] :=3D3D3D Tex=
>>>> t8.New (buf)=3D3D3B<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B   END=3D3D3B<b=
>>>> r>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B   RETURN fromCharCache [c]<br>&gt=
>>>> =3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B END FromChar=3D3D3B<br>&gt=3B &gt=3B&gt=
>>>> =3B&gt=3B&gt=3B&gt=3B <br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B <br>&gt=3B =
>>>> &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B It should be:<br>&gt=3B &gt=3B&gt=3B&gt=3B&g=
>>>> t=3B&gt=3B <br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B <br>&gt=3B &gt=3B&gt=
>>>> =3B&gt=3B&gt=3B&gt=3B PROCEDURE FromChar (c: CHAR): T =3D3D3D<br>&gt=3B &gt=
>>>> =3B&gt=3B&gt=3B&gt=3B&gt=3B =3D3D0A=3D3D<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B=
>>>> &gt=3B VAR buf: ARRAY [0..0] OF CHAR=3D3D3B<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=
>>>> =3B&gt=3B =3D3D0A=3D3D<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B BEGIN<br>&g=
>>>> t=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B =3D3D0A=3D3D<br>&gt=3B &gt=3B&gt=3B&gt=
>>>> =3B&gt=3B&gt=3B   IF fromCharCache [c] =3D3D3D NIL THEN<br>&gt=3B &gt=3B&gt=
>>>> =3B&gt=3B&gt=3B&gt=3B =3D3D0A=3D3D<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B=
>>>>  buf [0] :=3D3D3D c=3D3D3B<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B =3D=
>>>> 3D0A=3D3D<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B     WITH a =3D3D3D Text8=
>>>> .New (buf) DO<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B       MemoryBarrier(=
>>>> )=3D3D3B<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B       fromCharCache[c] :=
>>>> =3D3D3D a=3D3D3B<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B    END=3D3D3B<br>=
>>>> &gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B =3D3D0A=3D3D<br>&gt=3B &gt=3B&gt=3B&g=
>>>> t=3B&gt=3B&gt=3B   END=3D3D3B<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B =3D3=
>>>> D0A=3D3D<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B   RETURN fromCharCache [c=
>>>> ]<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B =3D3D0A=3D3D<br>&gt=3B &gt=3B&gt=
>>>> =3B&gt=3B&gt=3B&gt=3B END FromChar=3D3D3B<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=
>>>> =3B&gt=3B =3D3D0A=3D3D<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B <br>&gt=3B =
>>>> &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B <br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B to=
>>>> ensure that all of Text8.New() finishes before the assignment to fro=3D<br=
>>>>> &gt=3B &gt=3B&gt=3B mCha=3D3D<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B rCa=
>>>> che[c] is made.<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B <br>&gt=3B &gt=3B&=
>>>> gt=3B&gt=3B&gt=3B&gt=3B <br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B Can the c=
>>>> ompiler somehow catch these?<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B I fea=
>>>> r they are a small epidemic.<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B For a=
>>>> long time people didn't realize where all the compiler and proces=3D<br>&g=
>>>> t=3B &gt=3B&gt=3B sor =3D3D<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B could =
>>>> reorder.<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B <br>&gt=3B &gt=3B&gt=3B&g=
>>>> t=3B&gt=3B&gt=3B <br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B Do we have the r=
>>>> ight constructs by now to fix them?<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=
>>>> =3B I think we do.<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B <br>&gt=3B &gt=
>>>> =3B&gt=3B&gt=3B&gt=3B&gt=3B <br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B - Jay=
>>>> <br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B                         =3D3D<br>=
>>>> &gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B <br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&g=
>>>> t=3B --_5f23896e-68ee-44da-82dd-311cd8c58979_<br>&gt=3B &gt=3B&gt=3B&gt=3B&=
>>>> gt=3B&gt=3B Content-Type: text/html=3D3B charset=3D3D"iso-8859-1"<br>&gt=3B=
>>>> &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B Content-Transfer-Encoding: quoted-printable=
>>>> <br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B <br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=
>>>> =3B&gt=3B &lt=3Bhtml&gt=3B<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B &lt=3Bh=
>>>> ead&gt=3B<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B &lt=3Bstyle&gt=3B&lt=3B!=
>>>> --<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B .hmmessage P<br>&gt=3B &gt=3B&g=
>>>> t=3B&gt=3B&gt=3B&gt=3B {<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B margin:0p=
>>>> x=3D3D3B<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B padding:0px<br>&gt=3B &gt=
>>>> =3B&gt=3B&gt=3B&gt=3B&gt=3B }<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B body=
>>>> .hmmessage<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B {<br>&gt=3B &gt=3B&gt=
>>>> =3B&gt=3B&gt=3B&gt=3B font-size: 12pt=3D3D3B<br>&gt=3B &gt=3B&gt=3B&gt=3B&g=
>>>> t=3B&gt=3B font-family:Calibri<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B }<b=
>>>> r>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B --&gt=3B&lt=3B/style&gt=3B&lt=3B/he=
>>>> ad&gt=3B<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B &lt=3Bbody class=3D3D3D'h=
>>>> mmessage'&gt=3B&lt=3Bdiv dir=3D3D3D'ltr'&gt=3BWe have race conditions=3D<br=
>>>>> &gt=3B &gt=3B&gt=3B =3D3D2C like =3D3D<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&=
>>>> gt=3B this=3D3D2C m3core/src/Text.m3:&lt=3Bbr&gt=3B&lt=3Bbr&gt=3B&lt=3Bbr&g=
>>>> t=3BVAR fromCharCache :=3D3D3D ARRAY=3D<br>&gt=3B &gt=3B&gt=3B CHAR OF=3D3D=
>>>> <br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B T {NIL=3D3D2C ..}=3D3D3B (* 1-cha=
>>>> r texts *)&lt=3Bbr&gt=3B&lt=3Bbr&gt=3B&lt=3Bbr&gt=3BPROCEDURE FromChar =3D<=
>>>> br>&gt=3B &gt=3B&gt=3B (c: CHAR=3D3D<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=
>>>> =3B ): T =3D3D3D&lt=3Bbr&gt=3B&amp=3Bnbsp=3D3D3B VAR buf: ARRAY [0..0] OF C=
>>>> HAR=3D3D3B&lt=3Bbr&gt=3B&amp=3Bnbsp=3D3D=3D<br>&gt=3B &gt=3B&gt=3B 3B BEGIN=
>>>> &lt=3Bbr&gt=3B=3D3D<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B &amp=3Bnbsp=3D=
>>>> 3D3B&amp=3Bnbsp=3D3D3B&amp=3Bnbsp=3D3D3B IF fromCharCache [c] =3D3D3D NIL T=
>>>> HEN&lt=3Bbr&gt=3B&amp=3B=3D<br>&gt=3B &gt=3B&gt=3B nbsp=3D3D3B&amp=3Bnbsp=
>>>> =3D3D<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B =3D3D3B&amp=3Bnbsp=3D3D3B&am=
>>>> p=3Bnbsp=3D3D3B&amp=3Bnbsp=3D3D3B buf [0] :=3D3D3D c=3D3D3B&lt=3Bbr&gt=3B&a=
>>>> mp=3Bnbsp=3D3D3B=3D<br>&gt=3B &gt=3B&gt=3B &amp=3Bnbsp=3D3D3B&amp=3Bnbsp=3D=
>>>> 3D3B&amp=3Bn=3D3D<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B bsp=3D3D3B&amp=
>>>> =3Bnbsp=3D3D3B fromCharCache[c] :=3D3D3D Text8.New (buf)=3D3D3B&lt=3Bbr&gt=
>>>> =3B&amp=3Bnbs=3D<br>&gt=3B &gt=3B&gt=3B p=3D3D3B&amp=3Bnbsp=3D3D3B=3D3D<br>=
>>>> &gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B &amp=3Bnbsp=3D3D3B END=3D3D3B&lt=3Bbr=
>>>> &gt=3B&amp=3Bnbsp=3D3D3B&amp=3Bnbsp=3D3D3B&amp=3Bnbsp=3D3D3B RETURN fromCha=
>>>> rCa=3D<br>&gt=3B &gt=3B&gt=3B che [c]&lt=3Bbr&gt=3B&amp=3Bnb=3D3D<br>&gt=3B=
>>>> &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B sp=3D3D3B END FromChar=3D3D3B&lt=3Bbr&gt=3B=
>>>> &lt=3Bbr&gt=3B&lt=3Bbr&gt=3BIt should be:&lt=3Bbr&gt=3B&lt=3Bbr&gt=3B&lt=3B=
>>>> br&gt=3BPROCEDURE=3D<br>&gt=3B &gt=3B&gt=3B FromCha=3D3D<br>&gt=3B &gt=3B&g=
>>>> t=3B&gt=3B&gt=3B&gt=3B r (c: CHAR): T =3D3D3D&lt=3Bbr&gt=3B=3D3D0A=3D3D<br>=
>>>> &gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B &amp=3Bnbsp=3D3D3B VAR buf: ARRAY [0.=
>>>> .0] OF CHAR=3D3D3B&lt=3Bbr&gt=3B=3D3D0A=3D3D<br>&gt=3B &gt=3B&gt=3B&gt=3B&g=
>>>> t=3B&gt=3B &amp=3Bnbsp=3D3D3B BEGIN&lt=3Bbr&gt=3B=3D3D0A=3D3D<br>&gt=3B &gt=
>>>> =3B&gt=3B&gt=3B&gt=3B&gt=3B &amp=3Bnbsp=3D3D3B&amp=3Bnbsp=3D3D3B&amp=3Bnbsp=
>>>> =3D3D3B IF fromCharCache [c] =3D3D3D NIL THEN&lt=3Bbr&gt=3B=3D<br>&gt=3B &g=
>>>> t=3B&gt=3B =3D3D0A=3D3D<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B &amp=3Bnbs=
>>>> p=3D3D3B&amp=3Bnbsp=3D3D3B&amp=3Bnbsp=3D3D3B&amp=3Bnbsp=3D3D3B&amp=3Bnbsp=
>>>> =3D3D3B buf [0] :=3D3D3D c=3D3D3=3D<br>&gt=3B &gt=3B&gt=3B B&lt=3Bbr&gt=3B=
>>>> =3D3D0A=3D3D<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B &amp=3Bnbsp=3D3D3B&am=
>>>> p=3Bnbsp=3D3D3B&amp=3Bnbsp=3D3D3B&amp=3Bnbsp=3D3D3B&amp=3Bnbsp=3D3D3B WITH =
>>>> a =3D3D3D Text8.N=3D<br>&gt=3B &gt=3B&gt=3B ew (buf) DO&lt=3Bbr&gt=3B&amp=
>>>> =3B=3D3D<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B nbsp=3D3D3B&amp=3Bnbsp=3D=
>>>> 3D3B&amp=3Bnbsp=3D3D3B&amp=3Bnbsp=3D3D3B&amp=3Bnbsp=3D3D3B&amp=3Bnbsp=3D3D3=
>>>> B&amp=3Bnbsp=3D3D3B M=3D<br>&gt=3B &gt=3B&gt=3B emoryBarrier()=3D3D3B&lt=3B=
>>>> =3D3D<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B br&gt=3B&amp=3Bnbsp=3D3D3B&a=
>>>> mp=3Bnbsp=3D3D3B&amp=3Bnbsp=3D3D3B&amp=3Bnbsp=3D3D3B&amp=3Bnbsp=3D3D3B&amp=
>>>> =3Bnbsp=3D3D3B&amp=3Bnbsp=3D3D=3D<br>&gt=3B &gt=3B&gt=3B 3B fromCharCache[c=
>>>> =3D3D<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B ] :=3D3D3D a=3D3D3B&lt=3Bbr&=
>>>> gt=3B&amp=3Bnbsp=3D3D3B&amp=3Bnbsp=3D3D3B&amp=3Bnbsp=3D3D3B&amp=3Bnbsp=3D3D=
>>>> 3B END=3D3D3B&lt=3Bbr=3D<br>&gt=3B &gt=3B&gt=3B&gt=3B =3D3D0A=3D3D<br>&gt=
>>>> =3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B &amp=3Bnbsp=3D3D3B&amp=3Bnbsp=3D3D3B&amp=
>>>> =3Bnbsp=3D3D3B END=3D3D3B&lt=3Bbr&gt=3B=3D3D0A=3D3D<br>&gt=3B &gt=3B&gt=3B&=
>>>> gt=3B&gt=3B&gt=3B &amp=3Bnbsp=3D3D3B&amp=3Bnbsp=3D3D3B&amp=3Bnbsp=3D3D3B RE=
>>>> TURN fromCharCache [c]&lt=3Bbr&gt=3B=3D3D0A=3D3D<br>&gt=3B &gt=3B&gt=3B&gt=
>>>> =3B&gt=3B&gt=3B &amp=3Bnbsp=3D3D3B END FromChar=3D3D3B&lt=3Bbr&gt=3B=3D3D0A=
>>>> =3D3D<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B &lt=3Bbr&gt=3B&lt=3Bbr&gt=3B=
>>>> to ensure that all of Text8.New() finishes before the assignmen=3D<br>&gt=
>>>> =3B &gt=3B&gt=3B t to=3D3D<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B fromCha=
>>>> rCache[c] is made.&lt=3Bbr&gt=3B&lt=3Bbr&gt=3B&lt=3Bbr&gt=3BCan the compile=
>>>> r somehow catch th=3D<br>&gt=3B &gt=3B&gt=3B ese?=3D3D<br>&gt=3B &gt=3B&gt=
>>>> =3B&gt=3B&gt=3B&gt=3B &lt=3Bbr&gt=3BI fear they are a small epidemic.&lt=3B=
>>>> br&gt=3BFor a long time people didn't =3D<br>&gt=3B &gt=3B&gt=3B real=3D3D<=
>>>> br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B ize where all the compiler and pro=
>>>> cessor could reorder.&lt=3Bbr&gt=3B&lt=3Bbr&gt=3B&lt=3Bbr&gt=3BDo w=3D<br>&=
>>>> gt=3B &gt=3B&gt=3B e ha=3D3D<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B ve th=
>>>> e right constructs by now to fix them?&lt=3Bbr&gt=3BI think we do.&lt=3Bbr&=
>>>> gt=3B&lt=3Bbr&gt=3B&lt=3Bb=3D<br>&gt=3B &gt=3B&gt=3B r&gt=3B -=3D3D<br>&gt=
>>>> =3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B Jay&lt=3Bbr&gt=3B                       =
>>>> &lt=3B/div&gt=3B&lt=3B/body&gt=3B<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=
>>>> =3B &lt=3B/html&gt=3B=3D3D<br>&gt=3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B <br>&gt=
>>>> =3B &gt=3B&gt=3B&gt=3B&gt=3B&gt=3B --_5f23896e-68ee-44da-82dd-311cd8c58979_=
>>>> --<br>&gt=3B &gt=3B&gt=3B                         =3D<br>&gt=3B &gt=3B&gt=
>>>> =3B <br>&gt=3B &gt=3B&gt=3B --_86f22d85-5540-4565-bf73-232aaafdc94b_<br>&gt=
>>>> =3B &gt=3B&gt=3B Content-Type: text/html=3B charset=3D"iso-8859-1"<br>&gt=
>>>> =3B &gt=3B&gt=3B Content-Transfer-Encoding: quoted-printable<br>&gt=3B &gt=
>>>> =3B&gt=3B <br>&gt=3B &gt=3B&gt=3B &lt=3Bhtml&gt=3B<br>&gt=3B &gt=3B&gt=3B &=
>>>> lt=3Bhead&gt=3B<br>&gt=3B &gt=3B&gt=3B &lt=3Bstyle&gt=3B&lt=3B!--<br>&gt=3B=
>>>> &gt=3B&gt=3B .hmmessage P<br>&gt=3B &gt=3B&gt=3B {<br>&gt=3B &gt=3B&gt=3B =
>>>> margin:0px=3D3B<br>&gt=3B &gt=3B&gt=3B padding:0px<br>&gt=3B &gt=3B&gt=3B }=
>>>> <br>&gt=3B &gt=3B&gt=3B body.hmmessage<br>&gt=3B &gt=3B&gt=3B {<br>&gt=3B &=
>>>> gt=3B&gt=3B font-size: 12pt=3D3B<br>&gt=3B &gt=3B&gt=3B font-family:Calibri=
>>>> <br>&gt=3B &gt=3B&gt=3B }<br>&gt=3B &gt=3B&gt=3B --&gt=3B&lt=3B/style&gt=3B=
>>>> &lt=3B/head&gt=3B<br>&gt=3B &gt=3B&gt=3B &lt=3Bbody class=3D3D'hmmessage'&g=
>>>> t=3B&lt=3Bdiv dir=3D3D'ltr'&gt=3BThe processor can reorder. Acros=3D<br>&gt=
>>>> =3B &gt=3B&gt=3B s call/ret at least in general.&lt=3Bbr&gt=3B&lt=3Bbr&gt=
>>>> =3B&lt=3Bbr&gt=3BThe compiler can also reorder=3D2C=3D<br>&gt=3B &gt=3B&gt=
>>>> =3B if you have whole-program-optimization=3D2C link-time-code-gen (Microso=
>>>> ft "L=3D<br>&gt=3B &gt=3B&gt=3B TCG")=3D2C link-time-optimization (gcc "LTO=
>>>> "). (We don't=3D2C but real world sy=3D<br>&gt=3B &gt=3B&gt=3B stems certai=
>>>> nly do.)&lt=3Bbr&gt=3B&lt=3Bbr&gt=3B&lt=3Bbr&gt=3B&amp=3Bnbsp=3D3B- Jay&lt=
>>>> =3Bbr&gt=3B&lt=3Bbr&gt=3B&lt=3Bbr&gt=3B&lt=3Bdiv&gt=3B&lt=3Bdiv id=3D3D"Sk=
>>>> =3D<br>&gt=3B &gt=3B&gt=3B yDrivePlaceholder"&gt=3B&lt=3B/div&gt=3B&amp=3Bg=
>>>> t=3D3B To: jay.krell at cornell.edu=3D3B m3devel at elegos=3D<br>&gt=3B &gt=3B&gt=
>>>> =3B oft.com=3D3B mika at async.caltech.edu&lt=3Bbr&gt=3B&amp=3Bgt=3D3B Subject=
>>>> : Re: [M3devel] race con=3D<br>&gt=3B &gt=3B&gt=3B ditions in lock-free cod=
>>>> e...&lt=3Bbr&gt=3B&amp=3Bgt=3D3B Date: Sun=3D2C 26 Aug 2012 22:32:48 -0=3D<=
>>>> br>&gt=3B &gt=3B&gt=3B 700&lt=3Bbr&gt=3B&amp=3Bgt=3D3B From: mika at async.cal=
>>>> tech.edu&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &lt=3Bbr&gt=3B&amp=3Bgt=3D3B Sorry=3D2=
>>>> C I =3D<br>&gt=3B &gt=3B&gt=3B can't seem to quote your message.&lt=3Bbr&gt=
>>>> =3B&amp=3Bgt=3D3B &lt=3Bbr&gt=3B&amp=3Bgt=3D3B You say that Text8.N=3D<br>&=
>>>> gt=3B &gt=3B&gt=3B ew's result can be assigned to fromCharCache[c]&lt=3Bbr&=
>>>> gt=3B&amp=3Bgt=3D3B before Text8.New =3D<br>&gt=3B &gt=3B&gt=3B is done run=
>>>> ning.  How is that possible?  Surely&lt=3Bbr&gt=3B&amp=3Bgt=3D3B Text8.New =
>>>> has to =3D<br>&gt=3B &gt=3B&gt=3B calculate its result before it can be ass=
>>>> igned&lt=3Bbr&gt=3B&amp=3Bgt=3D3B anywhere.  Yes pos=3D<br>&gt=3B &gt=3B&gt=
>>>> =3B sibly FromChar allocates space for the result of&lt=3Bbr&gt=3B&amp=3Bgt=
>>>> =3D3B Text8.New but th=3D<br>&gt=3B &gt=3B&gt=3B e assignment of whatever a=
>>>> ppears in that space can't&lt=3Bbr&gt=3B&amp=3Bgt=3D3B happen until=3D<br>&=
>>>> gt=3B &gt=3B&gt=3B *after* Text8.New has run.  Unless you are saying that&l=
>>>> t=3Bbr&gt=3B&amp=3Bgt=3D3B the runni=3D<br>&gt=3B &gt=3B&gt=3B ng of Text8.=
>>>> New and FromChar are intertwined somehow..?&lt=3Bbr&gt=3B&amp=3Bgt=3D3B I k=
>>>> now co=3D<br>&gt=3B &gt=3B&gt=3B mpilers do some odd things but that doesn'=
>>>> t sound right...&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &lt=3Bbr&gt=3B&amp=3Bg=3D<br>&=
>>>> gt=3B &gt=3B&gt=3B t=3D3B If Text8.New took fromCharCache[c] as a VAR param=
>>>> eter you might be&lt=3Bbr&gt=3B=3D<br>&gt=3B &gt=3B&gt=3B &amp=3Bgt=3D3B ri=
>>>> ght=3D2C though.  But it doesn't...&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &lt=3Bbr&gt=
>>>> =3B&amp=3Bgt=3D3B Am I missin=3D<br>&gt=3B &gt=3B&gt=3B g something?&lt=3Bb=
>>>> r&gt=3B&amp=3Bgt=3D3B &lt=3Bbr&gt=3B&amp=3Bgt=3D3B      Mika&lt=3Bbr&gt=3B&=
>>>> amp=3Bgt=3D3B &lt=3Bbr&gt=3B&amp=3Bgt=3D3B Mika Nystr=3D<br>&gt=3B &gt=3B&g=
>>>> t=3B om writes:&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B&lt=3Bbr&gt=3B&am=
>>>> p=3Bgt=3D3B &amp=3Bgt=3D3BYeah it's a race condition=3D2C i=3D<br>&gt=3B &g=
>>>> t=3B&gt=3B n theory.  But is it important?  If you get&lt=3Bbr&gt=3B&amp=3B=
>>>> gt=3D3B &amp=3Bgt=3D3Bthe wrong copy=3D<br>&gt=3B &gt=3B&gt=3B =3D2C there =
>>>> will be two TEXTs representing one CHAR.  But no&lt=3Bbr&gt=3B&amp=3Bgt=3D3=
>>>> B &amp=3Bgt=3D3B=3D<br>&gt=3B &gt=3B&gt=3B one ever said FromChar was guara=
>>>> nteed to return the same pointer when&lt=3Bbr&gt=3B&amp=3Bg=3D<br>&gt=3B &g=
>>>> t=3B&gt=3B t=3D3B &amp=3Bgt=3D3Byou call it with the same CHAR...&lt=3Bbr&g=
>>>> t=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D<=
>>>> br>&gt=3B &gt=3B&gt=3B =3D3B     Mika&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=
>>>> =3D3B&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3BJay K writes:&lt=3Bbr&gt=3B=
>>>> &amp=3Bgt=3D3B &amp=3Bgt=3D<br>&gt=3B &gt=3B&gt=3B =3D3B&amp=3Bgt=3D3B--_5f=
>>>> 23896e-68ee-44da-82dd-311cd8c58979_&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=
>>>> =3D3B&amp=3Bgt=3D3BCon=3D<br>&gt=3B &gt=3B&gt=3B tent-Type: text/plain=3D3B=
>>>> charset=3D3D"iso-8859-1"&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B&amp=3B=
>>>> gt=3D3BConte=3D<br>&gt=3B &gt=3B&gt=3B nt-Transfer-Encoding: quoted-printab=
>>>> le&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3B&lt=3Bbr&gt=3B&a=
>>>> mp=3Bgt=3D3B &amp=3Bgt=3D<br>&gt=3B &gt=3B&gt=3B =3D3B&amp=3Bgt=3D3BWe have=
>>>> race conditions=3D3D2C like this=3D3D2C m3core/src/Text.m3:&lt=3Bbr=3D<br>=
>>>> &gt=3B &gt=3B&gt=3B&gt=3B &amp=3Bgt=3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3B&lt=3B=
>>>> br&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3B&lt=3Bbr&gt=3B&amp=3Bgt=
>>>> =3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3BVAR fromC=3D<br>&gt=3B &gt=3B&gt=3B harCa=
>>>> che :=3D3D3D ARRAY CHAR OF T {NIL=3D3D2C ..}=3D3D3B (* 1-char texts *)&lt=
>>>> =3Bbr&gt=3B&amp=3Bg=3D<br>&gt=3B &gt=3B&gt=3B t=3D3B &amp=3Bgt=3D3B&amp=3Bg=
>>>> t=3D3B&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3B&lt=3Bbr&gt=
>>>> =3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3BPROCEDURE Fr=3D<br>&gt=3B &gt=
>>>> =3B&gt=3B omChar (c: CHAR): T =3D3D3D&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=
>>>> =3D3B&amp=3Bgt=3D3B  VAR buf: ARRAY [0..0] OF =3D<br>&gt=3B &gt=3B&gt=3B CH=
>>>> AR=3D3D3B&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3B  BEGIN&l=
>>>> t=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3B    IF fromCh=3D<br>=
>>>> &gt=3B &gt=3B&gt=3B arCache [c] =3D3D3D NIL THEN&lt=3Bbr&gt=3B&amp=3Bgt=3D3=
>>>> B &amp=3Bgt=3D3B&amp=3Bgt=3D3B      buf [0] :=3D3D3D c=3D3D3=3D<br>&gt=3B &=
>>>> gt=3B&gt=3B B&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3B     =
>>>> fromCharCache[c] :=3D3D3D Text8.New (buf)=3D3D3B&lt=3B=3D<br>&gt=3B &gt=3B=
>>>> &gt=3B br&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3B    END=3D3D3B&lt=
>>>> =3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3B    RETURN fromCha=3D=
>>>> <br>&gt=3B &gt=3B&gt=3B rCache [c]&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D=
>>>> 3B&amp=3Bgt=3D3B  END FromChar=3D3D3B&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=
>>>> =3D3B&amp=3Bgt=3D3B=3D<br>&gt=3B &gt=3B&gt=3B &lt=3Bbr&gt=3B&amp=3Bgt=3D3B =
>>>> &amp=3Bgt=3D3B&amp=3Bgt=3D3B&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B&amp=
>>>> =3Bgt=3D3BIt should be:&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D<br>&gt=3B =
>>>> &gt=3B&gt=3B =3D3B&amp=3Bgt=3D3B&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B=
>>>> &amp=3Bgt=3D3B&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3BPROC=
>>>> EDURE FromChar (=3D<br>&gt=3B &gt=3B&gt=3B c: CHAR): T =3D3D3D&lt=3Bbr&gt=
>>>> =3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3B=3D3D0A=3D3D&lt=3Bbr&gt=3B&am=
>>>> p=3Bgt=3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3B  VA=3D<br>&gt=3B &gt=3B&gt=3B R bu=
>>>> f: ARRAY [0..0] OF CHAR=3D3D3B&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B&a=
>>>> mp=3Bgt=3D3B=3D3D0A=3D3D&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3B=3D<br>&gt=3B &=
>>>> gt=3B&gt=3B gt=3D3B&amp=3Bgt=3D3B  BEGIN&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=
>>>> =3Bgt=3D3B&amp=3Bgt=3D3B=3D3D0A=3D3D&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=
>>>> =3D3B&amp=3Bgt=3D3B   =3D<br>&gt=3B &gt=3B&gt=3B IF fromCharCache [c] =3D3D=
>>>> 3D NIL THEN&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3B=3D3D0A=
>>>> =3D3D&lt=3Bbr&gt=3B&amp=3Bgt=3D<br>&gt=3B &gt=3B&gt=3B =3D3B &amp=3Bgt=3D3B=
>>>> &amp=3Bgt=3D3B      buf [0] :=3D3D3D c=3D3D3B&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &=
>>>> amp=3Bgt=3D3B&amp=3Bgt=3D3B=3D3D0A=3D3D&lt=3B=3D<br>&gt=3B &gt=3B&gt=3B br&=
>>>> gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3B      WITH a =3D3D3D Text8.=
>>>> New (buf) DO&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D<br>&gt=3B &gt=3B&gt=
>>>> =3B =3D3B&amp=3Bgt=3D3B        MemoryBarrier()=3D3D3B&lt=3Bbr&gt=3B&amp=3Bg=
>>>> t=3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3B        fromCha=3D<br>&gt=3B &gt=3B&gt=
>>>> =3B rCache[c] :=3D3D3D a=3D3D3B&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B&=
>>>> amp=3Bgt=3D3B     END=3D3D3B&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D<br>&g=
>>>> t=3B &gt=3B&gt=3B =3D3B&amp=3Bgt=3D3B=3D3D0A=3D3D&lt=3Bbr&gt=3B&amp=3Bgt=3D=
>>>> 3B &amp=3Bgt=3D3B&amp=3Bgt=3D3B    END=3D3D3B&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &=
>>>> amp=3Bgt=3D3B&amp=3Bgt=3D3B=3D<br>&gt=3B &gt=3B&gt=3B =3D3D0A=3D3D&lt=3Bbr&=
>>>> gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3B    RETURN fromCharCache [c=
>>>> ]&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D<br>&gt=3B &gt=3B&gt=3B =3D3B&amp=
>>>> =3Bgt=3D3B=3D3D0A=3D3D&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B&amp=3Bgt=
>>>> =3D3B  END FromChar=3D3D3B&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D<br>&gt=
>>>> =3B &gt=3B&gt=3B =3D3B&amp=3Bgt=3D3B=3D3D0A=3D3D&lt=3Bbr&gt=3B&amp=3Bgt=3D3=
>>>> B &amp=3Bgt=3D3B&amp=3Bgt=3D3B&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B&a=
>>>> mp=3Bgt=3D3B&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3B=3D<br>&gt=3B &gt=3B&gt=3B =
>>>> gt=3D3B&amp=3Bgt=3D3Bto ensure that all of Text8.New() finishes before the =
>>>> assignment=3D<br>&gt=3B &gt=3B&gt=3B to fromCha=3D3D&lt=3Bbr&gt=3B&amp=3Bgt=
>>>> =3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3BrCache[c] is made.&lt=3Bbr&gt=3B&amp=3Bgt=
>>>> =3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D<br>&gt=3B &gt=3B&gt=3B =3D3B&lt=3Bbr&gt=3B=
>>>> &amp=3Bgt=3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3B&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &am=
>>>> p=3Bgt=3D3B&amp=3Bgt=3D3BCan the compiler somehow c=3D<br>&gt=3B &gt=3B&gt=
>>>> =3B atch these?&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3BI f=
>>>> ear they are a small epidemic.&lt=3Bbr&gt=3B&amp=3Bgt=3D<br>&gt=3B &gt=3B&g=
>>>> t=3B =3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3BFor a long time people didn't realiz=
>>>> e where all the compile=3D<br>&gt=3B &gt=3B&gt=3B r and processor =3D3D&lt=
>>>> =3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3Bcould reorder.&lt=3Bb=
>>>> r&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B&amp=3Bg=3D<br>&gt=3B &gt=3B&gt=3B t=3D=
>>>> 3B&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3B&lt=3Bbr&gt=3B&a=
>>>> mp=3Bgt=3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3BDo we have the right cons=3D<br>&g=
>>>> t=3B &gt=3B&gt=3B tructs by now to fix them?&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &a=
>>>> mp=3Bgt=3D3B&amp=3Bgt=3D3BI think we do.&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=
>>>> =3B=3D<br>&gt=3B &gt=3B&gt=3B gt=3D3B&amp=3Bgt=3D3B&lt=3Bbr&gt=3B&amp=3Bgt=
>>>> =3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3B&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D=
>>>> 3B&amp=3Bgt=3D3B - Jay&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3B=3D<br>&gt=3B &gt=
>>>> =3B&gt=3B gt=3D3B&amp=3Bgt=3D3B                         =3D3D&lt=3Bbr&gt=3B=
>>>> &amp=3Bgt=3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3B&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &am=
>>>> p=3Bgt=3D3B&amp=3Bgt=3D3B--_=3D<br>&gt=3B &gt=3B&gt=3B 5f23896e-68ee-44da-8=
>>>> 2dd-311cd8c58979_&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3BC=
>>>> ontent-Type: t=3D<br>&gt=3B &gt=3B&gt=3B ext/html=3D3B charset=3D3D"iso-885=
>>>> 9-1"&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3BContent-Transf=
>>>> er-E=3D<br>&gt=3B &gt=3B&gt=3B ncoding: quoted-printable&lt=3Bbr&gt=3B&amp=
>>>> =3Bgt=3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3B&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3B=
>>>> gt=3D3B&amp=3Bgt=3D3B&amp=3Blt=3D<br>&gt=3B &gt=3B&gt=3B =3D3Bhtml&amp=3Bgt=
>>>> =3D3B&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3B&amp=3Blt=3D3=
>>>> Bhead&amp=3Bgt=3D3B&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3=
>>>> B=3D<br>&gt=3B &gt=3B&gt=3B &amp=3Blt=3D3Bstyle&amp=3Bgt=3D3B&amp=3Blt=3D3B=
>>>> !--&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3B.hmmessage P&lt=
>>>> =3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D<br>&gt=3B &gt=3B&gt=3B =3D3B&amp=3Bg=
>>>> t=3D3B{&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3Bmargin:0px=
>>>> =3D3D3B&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3Bpadd=3D<br>=
>>>> &gt=3B &gt=3B&gt=3B ing:0px&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B&amp=
>>>> =3Bgt=3D3B}&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3Bbody.hm=
>>>> message&lt=3Bbr&gt=3B&amp=3Bgt=3D<br>&gt=3B &gt=3B&gt=3B =3D3B &amp=3Bgt=3D=
>>>> 3B&amp=3Bgt=3D3B{&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3Bf=
>>>> ont-size: 12pt=3D3D3B&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D<br>&gt=3B &g=
>>>> t=3B&gt=3B =3D3B&amp=3Bgt=3D3Bfont-family:Calibri&lt=3Bbr&gt=3B&amp=3Bgt=3D=
>>>> 3B &amp=3Bgt=3D3B&amp=3Bgt=3D3B}&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B=
>>>> &amp=3Bgt=3D3B=3D<br>&gt=3B &gt=3B&gt=3B --&amp=3Bgt=3D3B&amp=3Blt=3D3B/sty=
>>>> le&amp=3Bgt=3D3B&amp=3Blt=3D3B/head&amp=3Bgt=3D3B&lt=3Bbr&gt=3B&amp=3Bgt=3D=
>>>> 3B &amp=3Bgt=3D3B&amp=3Bgt=3D3B&amp=3Blt=3D3Bbod=3D<br>&gt=3B &gt=3B&gt=3B =
>>>> y class=3D3D3D'hmmessage'&amp=3Bgt=3D3B&amp=3Blt=3D3Bdiv dir=3D3D3D'ltr'&am=
>>>> p=3Bgt=3D3BWe have race cond=3D<br>&gt=3B &gt=3B&gt=3B itions=3D3D2C like =
>>>> =3D3D&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3Bthis=3D3D2C m=
>>>> 3core/src/Text.m3:&amp=3Blt=3D<br>&gt=3B &gt=3B&gt=3B =3D3Bbr&amp=3Bgt=3D3B=
>>>> &amp=3Blt=3D3Bbr&amp=3Bgt=3D3B&amp=3Blt=3D3Bbr&amp=3Bgt=3D3BVAR fromCharCac=
>>>> he :=3D3D3D ARRAY CHAR =3D<br>&gt=3B &gt=3B&gt=3B OF=3D3D&lt=3Bbr&gt=3B&amp=
>>>> =3Bgt=3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3B T {NIL=3D3D2C ..}=3D3D3B (* 1-char =
>>>> texts *)&amp=3Blt=3D3Bb=3D<br>&gt=3B &gt=3B&gt=3B r&amp=3Bgt=3D3B&amp=3Blt=
>>>> =3D3Bbr&amp=3Bgt=3D3B&amp=3Blt=3D3Bbr&amp=3Bgt=3D3BPROCEDURE FromChar (c: C=
>>>> HAR=3D3D&lt=3Bbr&gt=3B&amp=3Bgt=3D3B=3D<br>&gt=3B &gt=3B&gt=3B &amp=3Bgt=3D=
>>>> 3B&amp=3Bgt=3D3B): T =3D3D3D&amp=3Blt=3D3Bbr&amp=3Bgt=3D3B&amp=3Bamp=3D3Bnb=
>>>> sp=3D3D3B VAR buf: ARRAY [0..0]=3D<br>&gt=3B &gt=3B&gt=3B OF CHAR=3D3D3B&am=
>>>> p=3Blt=3D3Bbr&amp=3Bgt=3D3B&amp=3Bamp=3D3Bnbsp=3D3D3B BEGIN&amp=3Blt=3D3Bbr=
>>>> &amp=3Bgt=3D3B=3D3D&lt=3Bbr&gt=3B&amp=3Bgt=3D<br>&gt=3B &gt=3B&gt=3B =3D3B =
>>>> &amp=3Bgt=3D3B&amp=3Bgt=3D3B&amp=3Bamp=3D3Bnbsp=3D3D3B&amp=3Bamp=3D3Bnbsp=
>>>> =3D3D3B&amp=3Bamp=3D3Bnbsp=3D3D3B IF fromCha=3D<br>&gt=3B &gt=3B&gt=3B rCac=
>>>> he [c] =3D3D3D NIL THEN&amp=3Blt=3D3Bbr&amp=3Bgt=3D3B&amp=3Bamp=3D3Bnbsp=3D=
>>>> 3D3B&amp=3Bamp=3D3Bnbsp=3D3D&lt=3Bbr&gt=3B&amp=3Bg=3D<br>&gt=3B &gt=3B&gt=
>>>> =3B t=3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3B=3D3D3B&amp=3Bamp=3D3Bnbsp=3D3D3B&am=
>>>> p=3Bamp=3D3Bnbsp=3D3D3B&amp=3Bamp=3D3Bnbsp=3D3D3B buf =3D<br>&gt=3B &gt=3B&=
>>>> gt=3B [0] :=3D3D3D c=3D3D3B&amp=3Blt=3D3Bbr&amp=3Bgt=3D3B&amp=3Bamp=3D3Bnbs=
>>>> p=3D3D3B&amp=3Bamp=3D3Bnbsp=3D3D3B&amp=3Bamp=3D3Bnbsp=3D<br>&gt=3B &gt=3B&g=
>>>> t=3B =3D3D3B&amp=3Bamp=3D3Bn=3D3D&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3=
>>>> B&amp=3Bgt=3D3Bbsp=3D3D3B&amp=3Bamp=3D3Bnbsp=3D3D3B fromCharCac=3D<br>&gt=
>>>> =3B &gt=3B&gt=3B he[c] :=3D3D3D Text8.New (buf)=3D3D3B&amp=3Blt=3D3Bbr&amp=
>>>> =3Bgt=3D3B&amp=3Bamp=3D3Bnbsp=3D3D3B&amp=3Bamp=3D3Bnbsp=3D<br>&gt=3B &gt=3B=
>>>> &gt=3B =3D3D3B=3D3D&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3=
>>>> B&amp=3Bamp=3D3Bnbsp=3D3D3B END=3D3D3B&amp=3Blt=3D3Bbr&amp=3Bgt=3D3B&amp=3B=
>>>> amp=3D<br>&gt=3B &gt=3B&gt=3B =3D3Bnbsp=3D3D3B&amp=3Bamp=3D3Bnbsp=3D3D3B&am=
>>>> p=3Bamp=3D3Bnbsp=3D3D3B RETURN fromCharCache [c]&amp=3Blt=3D3B=3D<br>&gt=3B=
>>>> &gt=3B&gt=3B br&amp=3Bgt=3D3B&amp=3Bamp=3D3Bnb=3D3D&lt=3Bbr&gt=3B&amp=3Bgt=
>>>> =3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3Bsp=3D3D3B END FromChar=3D3D3B&amp=3Blt=3D=
>>>> 3Bb=3D<br>&gt=3B &gt=3B&gt=3B r&amp=3Bgt=3D3B&amp=3Blt=3D3Bbr&amp=3Bgt=3D3B=
>>>> &amp=3Blt=3D3Bbr&amp=3Bgt=3D3BIt should be:&amp=3Blt=3D3Bbr&amp=3Bgt=3D3B&a=
>>>> mp=3Blt=3D3Bbr&amp=3Bgt=3D<br>&gt=3B &gt=3B&gt=3B =3D3B&amp=3Blt=3D3Bbr&amp=
>>>> =3Bgt=3D3BPROCEDURE FromCha=3D3D&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B=
>>>> &amp=3Bgt=3D3Br (c: CHAR): T =3D<br>&gt=3B &gt=3B&gt=3B =3D3D3D&amp=3Blt=3D=
>>>> 3Bbr&amp=3Bgt=3D3B=3D3D0A=3D3D&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B&a=
>>>> mp=3Bgt=3D3B&amp=3Bamp=3D3Bnbsp=3D3D3B VAR buf:=3D<br>&gt=3B &gt=3B&gt=3B A=
>>>> RRAY [0..0] OF CHAR=3D3D3B&amp=3Blt=3D3Bbr&amp=3Bgt=3D3B=3D3D0A=3D3D&lt=3Bb=
>>>> r&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3B&amp=3Bamp=3D<br>&gt=3B &=
>>>> gt=3B&gt=3B =3D3Bnbsp=3D3D3B BEGIN&amp=3Blt=3D3Bbr&amp=3Bgt=3D3B=3D3D0A=3D3=
>>>> D&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3B&amp=3Bamp=3D3Bnb=
>>>> sp=3D<br>&gt=3B &gt=3B&gt=3B =3D3D3B&amp=3Bamp=3D3Bnbsp=3D3D3B&amp=3Bamp=3D=
>>>> 3Bnbsp=3D3D3B IF fromCharCache [c] =3D3D3D NIL THEN&amp=3Bl=3D<br>&gt=3B &g=
>>>> t=3B&gt=3B t=3D3Bbr&amp=3Bgt=3D3B=3D3D0A=3D3D&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &=
>>>> amp=3Bgt=3D3B&amp=3Bgt=3D3B&amp=3Bamp=3D3Bnbsp=3D3D3B&amp=3Bamp=3D3Bnbsp=3D=
>>>> 3D3B=3D<br>&gt=3B &gt=3B&gt=3B &amp=3Bamp=3D3Bnbsp=3D3D3B&amp=3Bamp=3D3Bnbs=
>>>> p=3D3D3B&amp=3Bamp=3D3Bnbsp=3D3D3B buf [0] :=3D3D3D c=3D3D3B&amp=3Blt=3D<br=
>>>>> &gt=3B &gt=3B&gt=3B =3D3Bbr&amp=3Bgt=3D3B=3D3D0A=3D3D&lt=3Bbr&gt=3B&amp=3B=
>>>> gt=3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3B&amp=3Bamp=3D3Bnbsp=3D3D3B&amp=3Bamp=3D=
>>>> 3Bnbsp=3D3D3B&amp=3B=3D<br>&gt=3B &gt=3B&gt=3B amp=3D3Bnbsp=3D3D3B&amp=3Bam=
>>>> p=3D3Bnbsp=3D3D3B&amp=3Bamp=3D3Bnbsp=3D3D3B WITH a =3D3D3D Text8.New (buf=
>>>> =3D<br>&gt=3B &gt=3B&gt=3B ) DO&amp=3Blt=3D3Bbr&amp=3Bgt=3D3B&amp=3Bamp=3D3=
>>>> B=3D3D&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3Bnbsp=3D3D3B&=
>>>> amp=3Bamp=3D3Bnbsp=3D3D3=3D<br>&gt=3B &gt=3B&gt=3B B&amp=3Bamp=3D3Bnbsp=3D3=
>>>> D3B&amp=3Bamp=3D3Bnbsp=3D3D3B&amp=3Bamp=3D3Bnbsp=3D3D3B&amp=3Bamp=3D3Bnbsp=
>>>> =3D3D3B&amp=3Bamp=3D3Bnbs=3D<br>&gt=3B &gt=3B&gt=3B p=3D3D3B MemoryBarrier(=
>>>> )=3D3D3B&amp=3Blt=3D3B=3D3D&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B&amp=
>>>> =3Bgt=3D3Bbr&amp=3Bgt=3D3B&amp=3Bamp=3D3Bn=3D<br>&gt=3B &gt=3B&gt=3B bsp=3D=
>>>> 3D3B&amp=3Bamp=3D3Bnbsp=3D3D3B&amp=3Bamp=3D3Bnbsp=3D3D3B&amp=3Bamp=3D3Bnbsp=
>>>> =3D3D3B&amp=3Bamp=3D3Bnbsp=3D3D3B&amp=3Bam=3D<br>&gt=3B &gt=3B&gt=3B p=3D3B=
>>>> nbsp=3D3D3B&amp=3Bamp=3D3Bnbsp=3D3D3B fromCharCache[c=3D3D&lt=3Bbr&gt=3B&am=
>>>> p=3Bgt=3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3B] :=3D<br>&gt=3B &gt=3B&gt=3B =3D3D=
>>>> 3D a=3D3D3B&amp=3Blt=3D3Bbr&amp=3Bgt=3D3B&amp=3Bamp=3D3Bnbsp=3D3D3B&amp=3Ba=
>>>> mp=3D3Bnbsp=3D3D3B&amp=3Bamp=3D3Bnbsp=3D3D3B&amp=3B=3D<br>&gt=3B &gt=3B&gt=
>>>> =3B amp=3D3Bnbsp=3D3D3B END=3D3D3B&amp=3Blt=3D3Bbr&amp=3Bgt=3D3B=3D3D0A=3D3=
>>>> D&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3B&amp=3Bamp=3D<br>=
>>>> &gt=3B &gt=3B&gt=3B =3D3Bnbsp=3D3D3B&amp=3Bamp=3D3Bnbsp=3D3D3B&amp=3Bamp=3D=
>>>> 3Bnbsp=3D3D3B END=3D3D3B&amp=3Blt=3D3Bbr&amp=3Bgt=3D3B=3D3D0A=3D3D=3D<br>&g=
>>>> t=3B &gt=3B&gt=3B &lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3B=
>>>> &amp=3Bamp=3D3Bnbsp=3D3D3B&amp=3Bamp=3D3Bnbsp=3D3D3B&amp=3Bamp=3D3Bnbsp=3D3=
>>>> D3B RET=3D<br>&gt=3B &gt=3B&gt=3B URN fromCharCache [c]&amp=3Blt=3D3Bbr&amp=
>>>> =3Bgt=3D3B=3D3D0A=3D3D&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B&amp=3Bgt=
>>>> =3D3B&amp=3Bamp=3D3Bnb=3D<br>&gt=3B &gt=3B&gt=3B sp=3D3D3B END FromChar=3D3=
>>>> D3B&amp=3Blt=3D3Bbr&amp=3Bgt=3D3B=3D3D0A=3D3D&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &=
>>>> amp=3Bgt=3D3B&amp=3Bgt=3D3B&amp=3Blt=3D<br>&gt=3B &gt=3B&gt=3B =3D3Bbr&amp=
>>>> =3Bgt=3D3B&amp=3Blt=3D3Bbr&amp=3Bgt=3D3Bto ensure that all of Text8.New() f=
>>>> inishes before =3D<br>&gt=3B &gt=3B&gt=3B the assignment to=3D3D&lt=3Bbr&gt=
>>>> =3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3B fromCharCache[c] is made.&am=
>>>> p=3Blt=3D3B=3D<br>&gt=3B &gt=3B&gt=3B br&amp=3Bgt=3D3B&amp=3Blt=3D3Bbr&amp=
>>>> =3Bgt=3D3B&amp=3Blt=3D3Bbr&amp=3Bgt=3D3BCan the compiler somehow catch thes=
>>>> e?=3D<br>&gt=3B &gt=3B&gt=3B =3D3D&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D=
>>>> 3B&amp=3Bgt=3D3B&amp=3Blt=3D3Bbr&amp=3Bgt=3D3BI fear they are a small epide=
>>>> mic.&amp=3Bl=3D<br>&gt=3B &gt=3B&gt=3B t=3D3Bbr&amp=3Bgt=3D3BFor a long tim=
>>>> e people didn't real=3D3D&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B&amp=3B=
>>>> gt=3D3Bize=3D<br>&gt=3B &gt=3B&gt=3B where all the compiler and processor c=
>>>> ould reorder.&amp=3Blt=3D3Bbr&amp=3Bgt=3D3B&amp=3Blt=3D3Bbr&amp=3B=3D<br>&g=
>>>> t=3B &gt=3B&gt=3B gt=3D3B&amp=3Blt=3D3Bbr&amp=3Bgt=3D3BDo we ha=3D3D&lt=3Bb=
>>>> r&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3Bve the right construct=3D=
>>>> <br>&gt=3B &gt=3B&gt=3B s by now to fix them?&amp=3Blt=3D3Bbr&amp=3Bgt=3D3B=
>>>> I think we do.&amp=3Blt=3D3Bbr&amp=3Bgt=3D3B&amp=3Blt=3D3Bbr&amp=3Bgt=3D<br=
>>>>> &gt=3B &gt=3B&gt=3B =3D3B&amp=3Blt=3D3Bbr&amp=3Bgt=3D3B -=3D3D&lt=3Bbr&gt=
>>>> =3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3B Jay&amp=3Blt=3D3Bbr&amp=3Bgt=
>>>> =3D3B                         =3D<br>&gt=3B &gt=3B&gt=3B &amp=3Blt=3D3B/div=
>>>> &amp=3Bgt=3D3B&amp=3Blt=3D3B/body&amp=3Bgt=3D3B&lt=3Bbr&gt=3B&amp=3Bgt=3D3B=
>>>> &amp=3Bgt=3D3B&amp=3Bgt=3D3B&amp=3Blt=3D3B/html&amp=3Bgt=3D3B=3D<br>&gt=3B=
>>>> &gt=3B&gt=3B =3D3D&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3=
>>>> B&lt=3Bbr&gt=3B&amp=3Bgt=3D3B &amp=3Bgt=3D3B&amp=3Bgt=3D3B--_5f23896e-68ee-=
>>>> 44da-82dd=3D<br>&gt=3B &gt=3B&gt=3B -311cd8c58979_--&lt=3Bbr&gt=3B&lt=3B/di=
>>>> v&gt=3B                         &lt=3B/div&gt=3B&lt=3B/body&gt=3B<br>&gt=3B=
>>>> &gt=3B&gt=3B &lt=3B/html&gt=3B=3D<br>&gt=3B &gt=3B&gt=3B <br>&gt=3B &gt=3B=
>>>> &gt=3B --_86f22d85-5540-4565-bf73-232aaafdc94b_--<br></div>                          </di=
>>>> v></body>
>>>> </html>=
>>>> 
>>>> --_5c33c9ca-3a7d-4c39-ab66-ab9c151d1539_--
>> 




More information about the M3devel mailing list