<div dir="ltr"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><span style="font-size:12.8px">Correct me if I'm wrong, but basically what you are saying is that hotspot does not perform advanced enough analysis to see that 'this' is actually unnecessary after the call to unsafe.</span></blockquote><div><br></div><div>In which case? In DBB, `this` is still necessary after the Unsafe call since it needs to update position.  In theory, it could move position update prior to calling Bits.copyToArray() but it would have to prove that it's safe to do so.  Part of that safety check would require it to reason about memory effects, side effects, and failure cases (i.e. position update isn't reached if there's an exception, it would need to preserve that effect, also taking into account that it may not be able to speculatively write to memory and then undo those effects in case of exception).  So the answer is probably "yes" to your question above, in a theoretical sense only.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><span style="font-size:12.8px">What about the standard get() methods of DBB? Since they do not update the state of the buffer after the call, are they also protected in some way at the practical level? Or is it unlikely (impossible?) to have a GC safepoint just at the end of the ix(int) method? I guess even if this happen, you would need to be very very unlucky to have the reference handler clean the Cleaners fast enough...</span></blockquote><div><br></div><div>I think the reasoning here is similar to the above.  ByteBuffer.get() is invoked on a DBB instance, compiler sees a call to Unsafe.getXXX at some point.  The "natural" lifetime of the instance survives until the instance method returns.  So if compiler now wanted to shorten this by observing that `this` is unreachable sooner than method exit, it has to prove a bunch of things like I mentioned above.</div><div><br></div><div>Mind you, this is just my understanding -- I'm not speaking to this in any authoritative manner :).</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Dec 7, 2015 at 1:36 PM, Alexandre De Champeaux <span dir="ltr"><<a href="mailto:adc@quartetfs.com" target="_blank">adc@quartetfs.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Ok thanks.<div>Correct me if I'm wrong, but basically what you are saying is that hotspot does not perform advanced enough analysis to see that 'this' is actually unnecessary after the call to unsafe. So there is no practical risk to read invalid data/crash, but only a theoretical one.</div><div>What about the standard get() methods of DBB? Since they do not update the state of the buffer after the call, are they also protected in some way at the practical level? Or is it unlikely (impossible?) to have a GC safepoint just at the end of the ix(int) method? I guess even if this happen, you would need to be very very unlucky to have the reference handler clean the Cleaners fast enough...</div><div><br></div></div><div class="gmail_extra"><div><div class="h5"><br><div class="gmail_quote">On Mon, Dec 7, 2015 at 7:03 PM, Vitaly Davidovich <span dir="ltr"><<a href="mailto:vitalyd@gmail.com" target="_blank">vitalyd@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Ok, good :).<div><br></div><div>So the difference between your original case and what DBB has is that the "natural" lifetime of your SimpleBuffer ends prior to the unsafe operation.  Once you "detach" a piece of unmanaged memory from a managed wrapper (e.g. take the long address and start passing it around without the wrapper), all bets are off.  But while the managed wrapper is "naturally" live (i.e. as interpreter would treat it, or at least without subsequent compiler optimizations) I'd expect (hope!) that the wrapper does not become unreachable while those ops are in flight.</div></div><div><div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Dec 7, 2015 at 12:46 PM, Alexandre De Champeaux <span dir="ltr"><<a href="mailto:adc@quartetfs.com" target="_blank">adc@quartetfs.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Yep things are fine if I add a call to a method similar to the position() method of DBB after calling copyToArray(). </div><div class="gmail_extra"><div><div><br><div class="gmail_quote">On Mon, Dec 7, 2015 at 6:23 PM, Vitaly Davidovich <span dir="ltr"><<a href="mailto:vitalyd@gmail.com" target="_blank">vitalyd@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Can you more closely mirror DBB by updating some state of your SimpleBuffer after calling copyToArray()? DBB returns 'this' from its get(byte[], ...) and also sets position after the Bits.copyToArray() method.</div><div><div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Dec 7, 2015 at 12:08 PM, Alexandre De Champeaux <span dir="ltr"><<a href="mailto:adc@quartetfs.com" target="_blank">adc@quartetfs.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div>I have actually written a test class that reproduces a segfault. It uses an structure similar to DBB and an updated version of the Bits.copyToArray method which forces a GC and waits a bit from within it to simulate a safepoint stop and a GC, and leaves time to the reference handler to clean up.</div><div>Is this test too far away from the DBB code to actually simulate a possible behavior of DBB? Or is hotspot only able to not mark as unreachable vanilla java DBB, but not customer classes?</div><div><br></div><div>Here is the test class:</div><div><br></div><div><br></div><div><div>import sun.misc.Cleaner;<br></div><div>import sun.misc.Unsafe;</div><div><br></div><div>/**</div><div> * This test checks whether or not the JVM will dereference "this" and destroy the buffer while</div><div> * accessing it.</div><div> * <p></div><div> * Run the main method of this class to run the test.</div><div> * <p></div><div> * Note that the test segfaults each time if using a JNI call to mmap/munmap to do the memory</div><div> * management but not as often using Unsafe (malloc recycling memory?).</div><div> * <p></div><div> * Example output of a failure:</div><div> *</div><div> * <pre></div><div><span style="white-space:pre-wrap">               </span>TestGcThisAndDestroyBuffer.main() 0 -- 0</div><div><span style="white-space:pre-wrap">         </span>TestGcThisAndDestroyBuffer.main() 0 -- 1</div><div><span style="white-space:pre-wrap">         </span>TestGcThisAndDestroyBuffer.main() 0 -- 2</div><div><span style="white-space:pre-wrap">         </span>TestGcThisAndDestroyBuffer.main() 0 -- 3</div><div><span style="white-space:pre-wrap">         </span>TestGcThisAndDestroyBuffer.main() 0 -- 4</div><div><span style="white-space:pre-wrap">         </span>TestGcThisAndDestroyBuffer.main() 0 -- 5</div><div><span style="white-space:pre-wrap">         </span>TestGcThisAndDestroyBuffer.main() 0 -- 6</div><div><span style="white-space:pre-wrap">         </span>TestGcThisAndDestroyBuffer.main() 0 -- 7</div><div><span style="white-space:pre-wrap">         </span>TestGcThisAndDestroyBuffer.main() 0 -- 8</div><div><span style="white-space:pre-wrap">         </span>TestGcThisAndDestroyBuffer.main() 0 -- 9</div><div><span style="white-space:pre-wrap">         </span>TestGcThisAndDestroyBuffer.main() 0 -- 10</div><div><span style="white-space:pre-wrap">                </span>TestGcThisAndDestroyBuffer.main() 0 -- 11</div><div><span style="white-space:pre-wrap">                </span>TestGcThisAndDestroyBuffer.main() 0 -- 12</div><div><span style="white-space:pre-wrap">                </span>TestGcThisAndDestroyBuffer.main() 0 -- 13</div><div><span style="white-space:pre-wrap">                </span>TestGcThisAndDestroyBuffer.main() 0 -- 14</div><div><span style="white-space:pre-wrap">                </span>Must be compiled now, start doing some GCs 30001</div><div><span style="white-space:pre-wrap">         </span>#</div><div><span style="white-space:pre-wrap">                </span># A fatal error has been detected by the Java Runtime Environment:</div><div><span style="white-space:pre-wrap">               </span>#</div><div><span style="white-space:pre-wrap">                </span>#  SIGSEGV (0xb) at pc=0x00007f489fb86220, pid=16949, tid=139949914818304</div><div><span style="white-space:pre-wrap">               </span>#</div><div><span style="white-space:pre-wrap">                </span># JRE version: Java(TM) SE Runtime Environment (8.0_60-b27) (build 1.8.0_60-b27)</div><div><span style="white-space:pre-wrap">         </span># Java VM: Java HotSpot(TM) 64-Bit Server VM (25.60-b23 mixed mode linux-amd64 compressed oops)</div><div><span style="white-space:pre-wrap">          </span># Problematic frame:</div><div><span style="white-space:pre-wrap">             </span># V  [libjvm.so+0x7f7220]</div><div><span style="white-space:pre-wrap">               </span>#</div><div><span style="white-space:pre-wrap">                </span># Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again</div><div><span style="white-space:pre-wrap">               </span>#</div><div><span style="white-space:pre-wrap">                </span># An error report file with more information is saved as:</div><div><span style="white-space:pre-wrap">                </span># /SSDhome/alexandre/ActivePivot5/scripts/adc/java_tests/hs_err_pid16949.log</div><div><span style="white-space:pre-wrap">             </span>Compiled method (nm)   10180   18     n 0       sun.misc.Unsafe::copyMemory (native)</div><div><span style="white-space:pre-wrap">              </span> total in heap  [0x00007f488910f2d0,0x00007f488910f640] = 880</div><div><span style="white-space:pre-wrap">           </span> relocation     [0x00007f488910f3f8,0x00007f488910f440] = 72</div><div><span style="white-space:pre-wrap">           </span> main code      [0x00007f488910f440,0x00007f488910f640] = 512</div><div><span style="white-space:pre-wrap">         </span>Compiled method (nm)   10180   18     n 0       sun.misc.Unsafe::copyMemory (native)</div><div><span style="white-space:pre-wrap">              </span> total in heap  [0x00007f488910f2d0,0x00007f488910f640] = 880</div><div><span style="white-space:pre-wrap">           </span> relocation     [0x00007f488910f3f8,0x00007f488910f440] = 72</div><div><span style="white-space:pre-wrap">           </span> main code      [0x00007f488910f440,0x00007f488910f640] = 512</div><div><span style="white-space:pre-wrap">         </span>#</div><div><span style="white-space:pre-wrap">                </span># If you would like to submit a bug report, please visit:</div><div><span style="white-space:pre-wrap">                </span>#   <a href="http://bugreport.java.com/bugreport/crash.jsp" target="_blank">http://bugreport.java.com/bugreport/crash.jsp</a></div><div><span style="white-space:pre-wrap">           </span>#</div><div> * </pre></div><div> */</div><div>@SuppressWarnings("restriction")</div><div>public class TestGcThisAndDestroyBuffer {</div><div><br></div><div><span style="white-space:pre-wrap">    </span>/** The threshold found in Bits.copyMemory */</div><div><span style="white-space:pre-wrap">    </span>static final long UNSAFE_COPY_THRESHOLD = 1024L * 1024L;</div><div><span style="white-space:pre-wrap"> </span>private static final Unsafe unsafe = retrieveUnsafe();</div><div><br></div><div><span style="white-space:pre-wrap">  </span>static long ctr = 0;</div><div><br></div><div><span style="white-space:pre-wrap">    </span>// The tested method</div><div><span style="white-space:pre-wrap">     </span>// See the method in Bits.copyToArray</div><div><span style="white-space:pre-wrap">    </span>/* For Bits.copyToArray to segfault we need:</div><div><span style="white-space:pre-wrap">     </span> *</div><div><span style="white-space:pre-wrap">       </span> * 1) The buffer to be garbage collected while calling the method, for that we need:</div><div><span style="white-space:pre-wrap">     </span> * <span style="white-space:pre-wrap">             </span>- A safepoint exist in the method</div><div><span style="white-space:pre-wrap">        </span> * <span style="white-space:pre-wrap">             </span>- The buffer needs to not be held, so JIT compil must have occured,</div><div><span style="white-space:pre-wrap">      </span> * <span style="white-space:pre-wrap">             </span> and JIT must have dereferenced the DBB at the time of the call</div><div><span style="white-space:pre-wrap">  </span> * 2) The reference handler thread to have run the associated cleaner</div><div><span style="white-space:pre-wrap">    </span> */</div><div><span style="white-space:pre-wrap">      </span>static void copyToArray(long srcAddr, Object dst, long dstBaseOffset, long dstPos, long length) {</div><div><span style="white-space:pre-wrap">                </span>long offset = dstBaseOffset + dstPos;</div><div><span style="white-space:pre-wrap">            </span>while (length > 0) {</div><div><span style="white-space:pre-wrap">                  </span>// Code differing from Bits.</div><div><span style="white-space:pre-wrap">                     </span>if (ctr++ >= 30_000) {</div><div><span style="white-space:pre-wrap">                                </span>// Counter is there to wait for JIT compilation</div><div><span style="white-space:pre-wrap">                          </span>System.out.println("Must be compiled now, start doing some GCs " + ctr);</div><div><span style="white-space:pre-wrap">                               </span>// Here we simulate a safepoint, and a GC at this safepoint</div><div><span style="white-space:pre-wrap">                              </span>System.gc();</div><div><span style="white-space:pre-wrap">                             </span>try {</div><div><span style="white-space:pre-wrap">                                    </span>// And here we wait for the reference handler to perform the cleaning to simulate a fast cleaning.</div><div><span style="white-space:pre-wrap">                                       </span>Thread.sleep(1000);</div><div><span style="white-space:pre-wrap">                              </span>} catch (InterruptedException e) {</div><div><span style="white-space:pre-wrap">                                       </span>Thread.currentThread().interrupt();</div><div><span style="white-space:pre-wrap">                              </span>}</div><div><span style="white-space:pre-wrap">                        </span>}</div><div><br></div><div><span style="white-space:pre-wrap">                       </span>long size = (length > UNSAFE_COPY_THRESHOLD) ? UNSAFE_COPY_THRESHOLD : length;</div><div><span style="white-space:pre-wrap">                        </span>unsafe.copyMemory(null, srcAddr, dst, offset, size);</div><div><span style="white-space:pre-wrap">                     </span>length -= size;</div><div><span style="white-space:pre-wrap">                  </span>srcAddr += size;</div><div><span style="white-space:pre-wrap">                 </span>offset += size;</div><div><span style="white-space:pre-wrap">          </span>}</div><div><span style="white-space:pre-wrap">        </span>}</div><div><br></div><div><span style="white-space:pre-wrap">       </span>// A basic class inspired from java.nio.DirectByteBuffer</div><div><span style="white-space:pre-wrap"> </span>static class SimpleBuffer {</div><div><span style="white-space:pre-wrap">              </span>static int SIZE = (int) (2 * UNSAFE_COPY_THRESHOLD);</div><div><span style="white-space:pre-wrap">             </span>static final long arrayBaseOffset = (long) unsafe.arrayBaseOffset(byte[].class);</div><div><br></div><div><span style="white-space:pre-wrap">                </span>final long addr;</div><div><br></div><div><span style="white-space:pre-wrap">                </span>public SimpleBuffer() {</div><div><span style="white-space:pre-wrap">                  </span>addr = unsafe.allocateMemory(SIZE);</div><div><span style="white-space:pre-wrap">                      </span>unsafe.setMemory(addr, SIZE, (byte) 0);</div><div><span style="white-space:pre-wrap">                  </span>Cleaner.create(this, new Deallocator(addr));</div><div><span style="white-space:pre-wrap">             </span>}</div><div><br></div><div><span style="white-space:pre-wrap">               </span>public byte[] copy() {</div><div><span style="white-space:pre-wrap">                   </span>final byte[] a = new byte[SIZE];</div><div><span style="white-space:pre-wrap">                 </span>copyToArray(addr, a, arrayBaseOffset, 0, SIZE);</div><div><span style="white-space:pre-wrap">                  </span>return a;</div><div><span style="white-space:pre-wrap">                </span>}</div><div><br></div><div><span style="white-space:pre-wrap">               </span>private static class Deallocator implements Runnable {</div><div><br></div><div><span style="white-space:pre-wrap">                  </span>private long address;</div><div><br></div><div><span style="white-space:pre-wrap">                   </span>private Deallocator(long address) {</div><div><span style="white-space:pre-wrap">                              </span>assert (address != 0);</div><div><span style="white-space:pre-wrap">                           </span>this.address = address;</div><div><span style="white-space:pre-wrap">                  </span>}</div><div><br></div><div><span style="white-space:pre-wrap">                       </span>@Override</div><div><span style="white-space:pre-wrap">                        </span>public void run() {</div><div><span style="white-space:pre-wrap">                              </span>if (address == 0) {</div><div><span style="white-space:pre-wrap">                                      </span>// Paranoia</div><div><span style="white-space:pre-wrap">                                      </span>return;</div><div><span style="white-space:pre-wrap">                          </span>}</div><div><span style="white-space:pre-wrap">                                </span>unsafe.freeMemory(address);</div><div><span style="white-space:pre-wrap">                              </span>address = 0;</div><div><span style="white-space:pre-wrap">                     </span>}</div><div><br></div><div><span style="white-space:pre-wrap">               </span>}</div><div><br></div><div><span style="white-space:pre-wrap">       </span>}</div><div><br></div><div><span style="white-space:pre-wrap">       </span>static byte[] aBunchOfCopies() {</div><div><span style="white-space:pre-wrap">         </span>byte[] res = null;</div><div><span style="white-space:pre-wrap">               </span>for (int i = 0; i < 1000; ++i) {</div><div><span style="white-space:pre-wrap">                      </span>res = new SimpleBuffer().copy();</div><div><span style="white-space:pre-wrap">                 </span>if (res[0] == -1) {</div><div><span style="white-space:pre-wrap">                              </span>return res;</div><div><span style="white-space:pre-wrap">                      </span>}</div><div><span style="white-space:pre-wrap">                </span>}</div><div><span style="white-space:pre-wrap">                </span>return res;</div><div><span style="white-space:pre-wrap">      </span>}</div><div><br></div><div><span style="white-space:pre-wrap">       </span>public static void main(String[] args) {</div><div><span style="white-space:pre-wrap">         </span>int i = 0;</div><div><span style="white-space:pre-wrap">               </span>while (true) {</div><div><span style="white-space:pre-wrap">                   </span>final byte[] res = aBunchOfCopies();</div><div><span style="white-space:pre-wrap">                     </span>System.out.println("TestGcThisAndDestroyBuffer.main() " + res[0] + " -- " + i++);</div><div><span style="white-space:pre-wrap">            </span>}</div><div><span style="white-space:pre-wrap">        </span>}</div><div><br></div><div><span style="white-space:pre-wrap">       </span>private static final sun.misc.Unsafe retrieveUnsafe() {</div><div><span style="white-space:pre-wrap">          </span>try {</div><div><span style="white-space:pre-wrap">                    </span>return sun.misc.Unsafe.getUnsafe();</div><div><span style="white-space:pre-wrap">              </span>} catch (SecurityException se) {</div><div><span style="white-space:pre-wrap">                 </span>try {</div><div><span style="white-space:pre-wrap">                            </span>return java.security.AccessController</div><div><span style="white-space:pre-wrap">                                            </span>.doPrivileged(new java.security.PrivilegedExceptionAction<sun.misc.Unsafe>() {</div><div><span style="white-space:pre-wrap">                                                     </span>@Override</div><div><span style="white-space:pre-wrap">                                                        </span>public sun.misc.Unsafe run() throws Exception {</div><div><span style="white-space:pre-wrap">                                                          </span>java.lang.reflect.Field f = sun.misc.Unsafe.class.getDeclaredField("theUnsafe");</div><div><span style="white-space:pre-wrap">                                                               </span>f.setAccessible(true);</div><div><span style="white-space:pre-wrap">                                                           </span>return (sun.misc.Unsafe) f.get(null);</div><div><span style="white-space:pre-wrap">                                                    </span>}</div><div><span style="white-space:pre-wrap">                                                </span>});</div><div><span style="white-space:pre-wrap">                      </span>} catch (java.security.PrivilegedActionException e) {</div><div><span style="white-space:pre-wrap">                            </span>throw new RuntimeException("Could not initialize intrinsics", e.getCause());</div><div><span style="white-space:pre-wrap">                   </span>}</div><div><span style="white-space:pre-wrap">                </span>}</div><div><span style="white-space:pre-wrap">        </span>}</div><div><br></div><div>}</div></div><div><br></div></div><div class="gmail_extra"><div><div><br><div class="gmail_quote">On Mon, Dec 7, 2015 at 4:15 PM, Vitaly Davidovich <span dir="ltr"><<a href="mailto:vitalyd@gmail.com" target="_blank">vitalyd@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><p dir="ltr">JIT knows about Unsafe operations, and it also knows the type of memory being accessed (or sometimes knows it doesn't know :)).  So I don't think it'll mark a DBB as unreachable while these operations are in-flight.</p>
<p dir="ltr">Peter's scenario is unique to WeakReference since it's intentionally not considered a strong reference and there's otherwise plain java code in his example (that JIT can reason about easily otherwise).</p>
<p dir="ltr">sent from my phone</p>
<div class="gmail_quote"><div><div>On Dec 7, 2015 8:10 AM, "Alexandre De Champeaux" <<a href="mailto:adc@quartetfs.com" target="_blank">adc@quartetfs.com</a>> wrote:<br type="attribution"></div></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div><div dir="ltr"><span style="color:rgb(0,0,0);font-size:12.8px">Hi all,</span><div style="color:rgb(0,0,0);font-size:12.8px"><br></div><div style="color:rgb(0,0,0);font-size:12.8px">I recently had a look at the discussion started by Peter Levart on October 21 (<a href="http://cs.oswego.edu/pipermail/concurrency-interest/2015-October/014493.html" target="_blank">http://cs.oswego.edu/pipermail/concurrency-interest/2015-October/014493.html</a>).</div><div style="color:rgb(0,0,0);font-size:12.8px"><br></div><div style="color:rgb(0,0,0);font-size:12.8px">It was a very insightful discussion, and made me aware that the "this" object could be garbage collected while being inside a call of one of its method.</div><div style="color:rgb(0,0,0);font-size:12.8px"><br></div><div style="color:rgb(0,0,0);font-size:12.8px">However, this got me concerned about the java.nio.DirectByteBuffer read and write methods:</div><div style="color:rgb(0,0,0);font-size:12.8px"><span style="font-size:12.8px">If the "this" object is garbage collected when making a call like ByteBuffer.allocateDirect(int)</span><span style="font-size:12.8px">.someGetOrPutMethod(), the native pointer that is passed to sun.misc.Unsafe might be freed, and accessing it will cause the read/write to occur in an invalid memory area, which might lead to a segfault, or other major issues.</span></div><div style="color:rgb(0,0,0);font-size:12.8px"><span style="font-size:12.8px">This would be quite unlikely: JIT compilation needs to occur while keeping a safepoint, then a GC must happen, and finally the ReferenceHandler thread needs to perform its cleanup fast enough.</span><br></div><div style="color:rgb(0,0,0);font-size:12.8px"><br></div><div style="color:rgb(0,0,0);font-size:12.8px">I am particularly concerned by the get(byte[] dst, int offset, int length) method, that in turns calls Bits.copyToArray, which purposely splits its calls to Unsafe.copyMemory to allow for safepoints to sneak in.</div><div style="color:rgb(0,0,0);font-size:12.8px"><br></div><div style="color:rgb(0,0,0);font-size:12.8px">Am I correct, or does the JVM performs specific protection for instances of DirectByteBuffer?</div><div style="color:rgb(0,0,0);font-size:12.8px"><br></div><div style="color:rgb(0,0,0);font-size:12.8px">Regards,<span style="font-size:small;color:rgb(34,34,34)">  </span></div><div style="color:rgb(0,0,0);font-size:12.8px"><span style="font-size:small;color:rgb(34,34,34)"><br></span></div><div style="color:rgb(0,0,0);font-size:12.8px"><span style="font-size:small;color:rgb(34,34,34)">Alexandre de Champeaux</span></div>
</div>
<br></div></div>_______________________________________________<br>
Concurrency-interest mailing list<br>
<a href="mailto:Concurrency-interest@cs.oswego.edu" target="_blank">Concurrency-interest@cs.oswego.edu</a><br>
<a href="http://cs.oswego.edu/mailman/listinfo/concurrency-interest" rel="noreferrer" target="_blank">http://cs.oswego.edu/mailman/listinfo/concurrency-interest</a><br>
<br></blockquote></div>
</blockquote></div><br><br clear="all"><div><br></div></div></div><span><font color="#888888">-- <br><div><div dir="ltr"><div>Alexandre</div></div></div>
</font></span></div>
</blockquote></div><br></div>
</div></div></blockquote></div><br><br clear="all"><div><br></div></div></div><span><font color="#888888">-- <br><div><div dir="ltr"><div>Alexandre</div></div></div>
</font></span></div>
</blockquote></div><br></div>
</div></div></blockquote></div><br><br clear="all"><div><br></div></div></div><span class="HOEnZb"><font color="#888888">-- <br><div><div dir="ltr"><div>Alexandre</div></div></div>
</font></span></div>
</blockquote></div><br></div>