<div dir="ltr">
<div>Hi Marc,</div><div><br></div><div>Below some questions about sequential consistency and critical sections in SMP Gambit.</div><div><br></div><div>
<div>The Sutter slides below illustrate the problematique addressed beautifully.<br></div></div><div><br></div><div> * Please have a look at the below and confirm that this is what Gambit does?<br></div><div><br></div><div> *
In thread-local code does Gambit internally do any optimizations that
alters the execution order? In C-compiled code I presume the C compiler
can make such optimizations, and that in itself pulls Gambit to need to address this problem domain.<br></div><div><br></div><div> * The
baseline constraint on Gambit's as well as any C compiler's
optimizations are that optimizations that alter order will not span
module-external calls, isn't it?</div><div>
<div><br></div><div> * Does Gambit
offer any low level primitives for (critical sections for) doing low
level in-module sequentially consistent operations between cores?</div><div><br></div><div> I.e. anything lower level than thread-send/receive and mutex-lock/unlock.<br></div><div><br></div><div> What about fence, acquire/read fence, release/write fence.<br></div><div><br></div>
</div><div> * Does Gambit guarantee that newly allocated objects have some initialization when accessed from any CPU core, or if malloc() gave trash then may a Gambit thread see trash?</div><div><br></div><div> Example:</div><div><br></div><div> Context: (define x #f) (##fence!)<br></div><div> Core A: (set! x (vector 1 2))</div><div> Core B: (let loop () (let ((v x)) (if v (print (##vector-ref v 0))) (loop)))</div><div><br></div><div> Which are all possible values that may be printed?<br></div><br><div>C/C++ standardized SMP/memory model in the C11/C++11 specs. It's great to see Gambit spec the same now.<br></div><div><br></div><div>Thanks,</div><div>Adam<br></div><div><br></div><div><br></div><div>Re
critical sections, do you have primitives in SMP Gambit to force the
compiler to respect them, and then in the code output produce assembly
instructions that honor them?</div><div><br></div>
<div>Today in SMP Gambit, I presume thread-send/receive and
mutex-lock/unlock will abstract away the underlying architecture's
memory model, and ensure that thread-receive will have access to the
whole structure that thread-send sent.</div><div><br></div><div>Example:<br></div><div style="margin-left:40px"><br></div><div style="margin-left:40px">GVM processor A:<br></div><div style="margin-left:40px"><br></div><div style="margin-left:40px">(thread-send B (list 1 2))</div><div style="margin-left:40px"><br></div><div style="margin-left:40px">(define l (list 3 4))</div><div style="margin-left:40px">(set-car! l 5)</div><div style="margin-left:40px">
(thread-send B (list 1 2))</div><div style="margin-left:40px"><br></div><div style="margin-left:40px"><br></div><div style="margin-left:40px">GVM processor B:<br></div><div style="margin-left:40px">(let loop () (for-each print (thread-receive) (loop))<br></div><div style="margin-left:40px"><br></div><div>This
is to illustrate that thread-send/receive ensures that the list
elements will be accessible (= read correctly) at the receiving site. In
this case on any architecture, four print calls are done, each with the
respectove argument: 1, 2, 5, 4.<br></div><div><br></div><div><br></div><div>I
guess that design feature is helped by that the Gambit compiler will
not do optimizations that garble the code order, over module-external
procedure calls, and thread-send/receive & mutex-lock/unlock count
as procedures.</div><div><br></div><div><br></div><div>I presume on strongly ordered architectures the following will make 2 3 go through:</div><div><br></div><div style="margin-left:40px">GVM processor A:</div><div style="margin-left:40px">(define l (list 1 2))</div><div style="margin-left:40px">(thread-send B l)</div><div style="margin-left:40px">(set-car! l 3)</div><br><div style="margin-left:40px">GVM processor B:<br></div><div style="margin-left:40px">(define m (thread-receive))</div><div style="margin-left:40px">(let loop ((i 0)) (if (not (eqv? (expt 3 12) i)) (loop (+ i 1)))<br></div><div style="margin-left:40px">(for-each print m)<br></div><div style="margin-left:40px"><br></div><div>On a weakly ordered architecture the code would not SIGSEGV nor throw exception, but the first value could be 1 or 3.</div><div><br></div><div><br></div><div>Importantly
on a weakly ordered architecture the code would never cause a SIGSEGV,
because Gambit's memory management ensures that pending memory bus
transactions are flushed before it initiates collection of a dead
object.</div><div><br></div><div>Similarly any allocated object's space is immediately accessible on all cores:</div><div><br></div><div style="margin-left:40px">Common workup:</div><div style="margin-left:40px">(define s #f)</div><div style="margin-left:40px"><br></div><div style="margin-left:40px">GVM processor A:</div><div style="margin-left:40px">(set! s (make-u8vector 5))</div><div style="margin-left:40px"><br></div><div style="margin-left:40px">GVM processor B:<br></div><div style="margin-left:40px">(let loop () (let ((v s)) (if v (##u8vector-ref v 1)) (loop))<br></div><div><br></div><div>The
promise is limited to that the content is accessible only though - on a
weakly ordered architecture, it may not have been initialized yet and
therefore the type and range check in (u8vector-ref v 1) could fail,
(##u8vector-ref v 1) do not do that though and while it may return junk,
at least it will not crash.<br></div><div><br></div><div>The above two described behaviors are is in symmetry with any host OS' malloc/free.</div><div><br></div><div><br></div><div>Important references:</div><div><br></div><div>Sutter slides:<a href="https://1drv.ms/b/s!Aq0V7yDPsIZOgcI0y2P8R-VifbnTtw">https://1drv.ms/b/s!Aq0V7yDPsIZOgcI0y2P8R-VifbnTtw</a></div><div><br></div><div>Sutter videos:<br></div><div>
<div><div><a href="https://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-1-of-2" target="_blank">https://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-1-of-2</a> /</div></div><div><a href="https://www.youtube.com/watch?v=A8eCGOqgvH4" target="_blank">https://www.youtube.com/watch?v=A8eCGOqgvH4</a></div><div>and</div><div><a href="https://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-2-of-2" target="_blank">https://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-2-of-2</a> / <br></div><div><a href="https://www.youtube.com/watch?v=KeLBd2EJLOU" target="_blank">https://www.youtube.com/watch?v=KeLBd2EJLOU</a></div>
</div><div><br></div><div><br></div>
</div>