<div dir="ltr">Hi Simon,<div><br></div><div class="gmail_extra"><div class="gmail_quote">On Wed, Aug 10, 2016 at 4:24 AM, Simon Marlow <span dir="ltr"><<a href="https://mail.google.com/mail/?view=cm&fs=1&tf=1&to=marlowsd@gmail.com" target="_blank">marlowsd@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><div><div>Definining a safe subset of IO is usually  an application-specific decision, e.g. do you want to allow access to the filesystem but without allowing openFile "/dev/mem"?  It's a minefield.<br></div></div></div></div></blockquote><div><br></div><div>I respect your intuition that this is a "minefield" (and Edward's "big mess"), but I still want to unpack this further.</div><div><br></div><div>I would propose that a MemSafe app is a two-part contract that is half an OS responsibility and half language/runtime responsibility.</div><div><ol><li>OS: guarantee that all system calls (including file access) from the process do not violate the processes memory, outside of certain opt-in DMA regions.</li><li>Lang/runtime: create a binary "ensuring" that all instructions executed in the process maintain the type safety of memory and follow the memory model.  (Scare quotes due to large TCB.)</li></ol></div><div>With this division, "/dev/mem" and subprocess/ptrace are definitely the job of the OS or containerization.  Blame for a bug would fall to category 1.</div><div><br></div><div>A MemSafe app needs a launcher/harness to check that category 1 is enforced properly.  I'm not proposing that GHC needs to generate that.  It should be separate.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><div><div></div>Ryan, if you want to give an operational semantics for memory in IO, why not start from the subset of IO that you can accurately model - the basic IO structure together with a set of primitives - and define the semantics for that?  That's typically what we do when we're talking about something in the IO monad.</div></div></div></blockquote><div><br></div><div>Yes, indeed, that has been <a href="http://research.microsoft.com/en-us/um/people/simonpj/papers/concurrent-haskell.pdf" target="_blank">the</a> <a href="http://homepages.dcc.ufmg.br/~camarao/fp/articles/lazy-state.pdf" target="_blank">approach</a> for decades (and the same thing you and I do with other monads like <a href="http://research.microsoft.com/en-us/um/people/simonpj/papers/parallel/monad-par.pdf" target="_blank">Par</a>).  There's something unsatisfying here though -- we love to build model languages that include the effects we want to talk about <i>at that time</i> -- perhaps just MVars, just putChar, or just STM.  But of course there's a big leap from these small treatments to GHC, with its multitude of moving parts.  That's partly why I think SafeHaskell is so great; it's a Full Language which aims for serious, statically enforced guarantees.</div><div><br></div><div>Well, almost a full language ;-).  You can't run programs in it, unless you <i>extend</i> the TCB.  It's kind of like Rust if you were required to use an "unsafe" block to write <font face="monospace, monospace">main()</font>.</div><div><br></div><div>Anyway, here's a draft paper that does propose a small model language.  It adds a memory model to Haskell plus IORefs/STRefs/TVars, and explains how, when executed on a machine with relaxed TSO memory (store buffers), the IO writes need to be fenced, but the ST and STM ones don't:</div><div><br></div><div>   <a href="http://www.cs.indiana.edu/~rrnewton/papers/sc-haskell_draft.pdf" target="_blank">http://www.cs.indiana.edu/~rr<wbr>newton/papers/sc-haskell_draft<wbr>.pdf</a><br></div><div><br></div><div><div>Do we need a memory model?  I concur with David Terei's <a href="https://mail.haskell.org/pipermail/haskell-cafe/2011-May/091963.html" target="_blank">arguments from 5 years ago</a>.  Note however, that the implementation in this paper is TSO only.  Implementation on ARM would be a bit different, but the relationship between IO/ST and IO/STM would stay the same.</div></div><div><br></div><div>Ryan Yates & others, I'm curious if you think the treatment of STM is satisfactory.  Like ppopp05, we do not model retrying explicitly, and our goal here is to show the interaction of the different effects.</div><div><br></div><div>Cheers, </div><div>  -Ryan</div></div></div></div>