<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On 12 May 2014 17:20, Andrew Trick <span dir="ltr"><<a href="mailto:atrick@apple.com" target="_blank">atrick@apple.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div style="word-wrap:break-word"><br><div><div class=""><div>On May 12, 2014, at 3:52 PM, Philip Reames <<a href="mailto:listmail@philipreames.com" target="_blank">listmail@philipreames.com</a>> wrote:</div><br><blockquote type="cite">
<div bgcolor="#FFFFFF" text="#000000">
I don't have a strong opinion on this topic at the moment, but given
that it is potentially GC related, I figured I'd speak up. <br>
<br>
I see two unspoken assumptions in the thread so far:<br>
- The runtime needs a means to bring all threads to a stop to
perform some action. In particular, no thread can be excepted.<br></div></blockquote><div><br></div></div><div>The *only* assumption that we want client to make of this API is that a compiler thread can be suspended at this point without blocking other non-compiler threads in the same process, or blocking other compiler threads associated with a *different* LLVM context.</div>
<div><br></div><div>There will be no assumption about the state of the suspended thread’s LLVM context and no assumption that other threads in the same context will continue executing (if there were such a thing).</div><div class="">
<div><br></div><blockquote type="cite"><div bgcolor="#FFFFFF" text="#000000">
- A single LLVM library call takes longer to complete than the
runtime is willing to wait for the thread stoppage to occur. <br></div></blockquote><div><br></div></div><div>I’m not sure what you mean by this.</div><div class=""><div><br></div><blockquote type="cite"><div bgcolor="#FFFFFF" text="#000000">
Both are entirely reasonable; I'm just spelling them out since they
might not be obvious to everyone. The second is particularly
noteworthy since it's entirely new in LLVM. <br>
<br>
I largely agree with Andy at the moment that the existing interface
assumes one thread per context. I don't see the issue with
continuing with this assumption, particular since no one t.m.k. has
put forward any serious plans to change this. If this does happen,
having it occur in an opt-in manner will be a matter of practical
necessity. <br></div></blockquote><div><br></div></div><div>I don’t think this API makes any assumption about LLVM’s threading model. I don’t even see how this API assumes one thread per context. However, I will concede that it does if it helps focus this discussion. Either way, the JIT should determine the threading model and be given a C API that allows configuring and scheduling those threads. As you correctly said, if we hypothetically implement a parallel pass manager mode that breaks some JITs, then clients will need to opt-in. We are not beholden to implement this callback in that mode. We just need to make that clear.</div>
<div class=""><div><br></div><blockquote type="cite"><div bgcolor="#FFFFFF" text="#000000">
I find myself somewhat uncertain of the choice to leverage the pass
manager for this purpose though. It's the entirely logical place to
start, but is it enough? What if a single pass takes too long to
complete? Do we start scattering these call backs throughout large
parts of LLVM? Also, how does this interact with something like the
hoped for parallel LTO? <br>
<br>
Like Chandler, I believe there needs to be a fully thought out
proposal and discussion on this list. I would weakly oppose the
change in it's current form solely on this basis.<br></div></blockquote><div><br></div></div><div>Would you (or anyone) oppose a simple maySuspendContext() callback API? It would mean nothing more than the thread(s) for a given LLVM context can be suspended independent from other contexts.</div>
</div></div></blockquote><div><br></div><div>I think this is the right approach. So a given thread hits a safe point, it optionally calls a "suspend check" or "i an safe to suspend right now" callback if set. It doesn't stop other threads, it doesn't continue until the function returns.</div>
<div><br></div><div>If you want to stop all threads then the user callback may contain a barrier and count down how many threads have stopped until it sees all of them.</div><div><br></div><div>Nick</div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div style="word-wrap:break-word"><div><div class=""><blockquote type="cite"><div bgcolor="#FFFFFF" text="#000000">Andy, Juergen - Can you start by providing a bit more background
information? What do you need the thread yield call back for?
Garbage collection? Other VM tasks? User mode scheduling of
threads? Something else entirely?<br></div></blockquote><div><br></div></div>The thread yield API is primarily for user mode scheduling of threads. </div><div><br></div><div>A JIT could certainly use it for GC and other VM tasks. That isn’t necessary for us because those tasks can run concurrent with the LLVM thread until it completes. It would only be a problem if there are resource constraints.</div>
<div><br></div><div>-Andy</div><div><div class="h5"><div><br><blockquote type="cite"><div bgcolor="#FFFFFF" text="#000000">
<br>
Yours,<br>
Philip<br>
<br>
<br>
<br>
<div>On 05/10/2014 11:11 AM, Juergen
Ributzka wrote:<br>
</div>
<blockquote type="cite">
<br>
<div>
<div>On May 9, 2014, at 7:36 PM, Andrew Trick <<a href="mailto:atrick@apple.com" target="_blank">atrick@apple.com</a>>
wrote:</div>
<br>
<blockquote type="cite">
<div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">
<div><br>
On May 9, 2014, at 6:33 PM, Chandler Carruth <<a href="mailto:chandlerc@google.com" target="_blank">chandlerc@google.com</a>>
wrote:</div>
<br>
<blockquote type="cite">
<div dir="ltr">So, I'm bringing a discussion that has thus
far been on llvm-commits to llvmdev because I finally
(and thanks for helping me understand this Andy)
understand what is *really* going on, and I think lots
of others need to be aware of this and involved to
figure out the right path forward.
<div><br>
</div>
<div>You can find the full review thread and more
context under the subject "[PATCH][PM] Add pass run
listeners to the pass manager.", but here is the
important bit from Juergen's initial email:</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-family:arial,sans-serif;font-size:13px">this patch provides
the necessary C/C++ APIs and infastructure to enable
fine-<br>
</span><span style="font-family:arial,sans-serif;font-size:13px">grain progress report and safe
suspension points after each </span><span style="font-family:arial,sans-serif;font-size:13px;background-color:rgb(255,255,204);background-repeat:initial initial">pass</span><span style="font-family:arial,sans-serif;font-size:13px"> in the </span><span style="font-family:arial,sans-serif;font-size:13px;background-color:rgb(255,255,204);background-repeat:initial initial">pass<br>
</span><span style="font-family:arial,sans-serif;font-size:13px">manager.</span> </blockquote>
<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"> </blockquote>
<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-family:arial,sans-serif;font-size:13px">Clients can provide a
callback function to the </span><span style="font-family:arial,sans-serif;font-size:13px">pass</span><span style="font-family:arial,sans-serif;font-size:13px"> manager to call after
each<br>
</span><span style="font-family:arial,sans-serif;font-size:13px">pass</span><span style="font-family:arial,sans-serif;font-size:13px">. This can be used in a variety of ways
(progress report, dumping of IR<br>
</span><span style="font-family:arial,sans-serif;font-size:13px">between passes, safe suspension of
threads, etc).</span></blockquote>
<div><br>
</div>
<div>I had wrongly (perhaps because of the
implementation, but still, wrongly) focused on the
progress report and IR dumping use cases. It sounds
(from talking to Andy offline, sorry for that
confusion) like the real use case is safe suspension
of threads. The idea is that we would have a callback
from the pass manager into the LLVMContext which would
be used to recognize safe points at which the entire
LLVMContext could be suspended, and to expose these
callbacks through C API to JIT users.</div>
</div>
</blockquote>
<div><br>
</div>
<div>Good. Let’s table the discussion of how to report
passes and just focus on the thread suspension API. It
never occurred to me that a client using the new API for
thread scheduling would not *already* be making an
assumption about one thread per context. I believe
anything else will break these clients regardless of the
API. So I didn’t see this API as imposing a new
restriction. The more explicit we can be about this, the
better.</div>
</div>
</blockquote>
<div><br>
</div>
<div>They not only have to make the assumption of one thread per
context, but they actually have to enforce it. According to
the comments in LLVMContext there is no locking guarantee and
the user/client has to be careful to use one context per
thread. This is the current C API and that is how clients are
using it right now.</div>
<div><br>
</div>
<div>Any future extension to the LLVMContext and to the pass
manager that change this requirement - namely running in
parallel - should be backwards compatible. Although I don’t
see how this could or should be an issue to begin with as long
we default to the current single-threaded execution model per
LLVMContext. Anything that changes this behavior should and
have to be explicitly requested by the client. That means
there has to be a new C API call to communicate this
information. For now all the threads are created by the client
and I think this should also stay so in the future.</div>
<br>
<blockquote type="cite">
<div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">
<blockquote type="cite">
<div dir="ltr">Increasingly, I can't fathom a way to get a
good design for safe suspension of JIT-ing threads using
callbacks tied to when passes run today. I think it is a
huge mistake to bake this into the C API at this point.
If you need this functionality in the C API, with a
design we can use going forward, I'd like to see a
*really* careful write up of exactly what the suspension
point requirements are and a design for achieving them.
I think it should be completely independent from any
infrastructure for reporting or dumping IR in pass
managers.</div>
</blockquote>
<div><br>
</div>
<div>Yes, there absolutely needs to be a way to expose
functionality within LLVM in its current form through the
C API. We can say that the API works under some explicit
set of rules. If some future LLVM can be configured in a
way that breaks the rules, you don’t get the callback in
that case.</div>
</div>
</blockquote>
<div><br>
</div>
<div>It is already a conscious choice of the client if and how
to use threads. This choice already affects how callbacks that
we already have are implemented by the client. The same would
apply for the proposed callback. The client knows exactly the
conditions, because it is in full control of setting up the
environment.</div>
<br>
<blockquote type="cite">
<div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">
<br>
<blockquote type="cite">
<div dir="ltr">
<div>I think something much simpler than this might work
outside of the C API, where we can essentially change
how it works when we start designing how multiple
threads will actually work within an LLVMContext.
Would that work? Is there a way to make progress more
rapidly there?</div>
<div><br>
</div>
<div>Ultimately, this is opening a huge can of worms if
we put it into the C API, as I think it is going to
fundamentally impact what options we actually have for
parallelizing parts of LLVM in the future. If we want
to go there, we need be *incredibly* explicit about
what assumptions are being made here.</div>
</div>
</blockquote>
</div>
</blockquote>
<div><br>
</div>
<div>Yes, this will definitely impact the design, but only in a
positive way :D There is only one big requirement and that is
a given: The thread cannot hold a global mutex when making
this call. This would deadlock everything - even other
concurrent running contexts in todays implementation.</div>
<div><br>
</div>
<div>When a thread group is running concurrently in the future
pass manager then it clear that the suspension of any thread
in this thread group might deadlock the remaining threads in
the thread group and that is perfectly fine. Also having this
callback being fired concurrently is fine too. The client
created a parallel pass manager and has to write the callback
thread-safe.</div>
<div><br>
</div>
<div>The important thing here is that LLVM is holding the thread
hostage and we need the control back to safely suspend it. It
is possible suspend the thread from outside, but then it might
be inside a system call or library call that holds a mutex.
This could deadlock the whole application. By giving the
control back to the client via the call back we know that this
cannot happen. We know that LLVM might hold some mutex local
to the context, but that is fine and won’t deadlock the whole
application.</div>
<div><br>
</div>
<div>-Juergen</div>
<br>
<blockquote type="cite">
<div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">
<br>
</div>
<div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">
Let’s be
explicit then.</div>
<div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">
<br>
</div>
<div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">
We will
always need to be able to configure LLVM with one thread per
context. Always. So it’s not like we’re adding something
that could become unusable in the future. Does anyone
disagree?</div>
<div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">
<br>
</div>
<div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">
Incidentally,
I have no idea why the callback would not work with parallel
context. If you suspend a thread within a thread group, it
is totally expected that the other threads will also
eventually block.</div>
<div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">
<br>
</div>
<div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">
Tangentially,
how many other places do we assume that an LLVMContext
corresponds to a thread?</div>
<div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">
<br>
</div>
<div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">
-Andy</div>
</blockquote>
</div>
<br>
<br>
<fieldset></fieldset>
<br>
<pre>_______________________________________________
LLVM Developers mailing list
<a href="mailto:LLVMdev@cs.uiuc.edu" target="_blank">LLVMdev@cs.uiuc.edu</a> <a href="http://llvm.cs.uiuc.edu/" target="_blank">http://llvm.cs.uiuc.edu</a>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev</a>
</pre>
</blockquote>
<br>
</div>
</blockquote></div><br></div></div></div><br>_______________________________________________<br>
LLVM Developers mailing list<br>
<a href="mailto:LLVMdev@cs.uiuc.edu">LLVMdev@cs.uiuc.edu</a> <a href="http://llvm.cs.uiuc.edu" target="_blank">http://llvm.cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev</a><br>
<br></blockquote></div><br></div></div>