[LLVMdev] Finding safe thread suspension points while JIT-ing
Philip Reames
listmail at philipreames.com
Thu May 15 15:31:28 PDT 2014
Slight nitpick: control of *what*?
Your comment should read something like "transfer control of the current
thread" or something similar.
Otherwise, LGTM.
Philip
On 05/15/2014 01:43 PM, Juergen Ributzka wrote:
> The addition about the undefined state of the current context is a
> very good point. Although I wouldn’t like to shut the door completely
> and allow for future extensions to relax this constraint for APIs that
> explicitly state that they are safe to use during a yield callback.
>
> I agree with Andy that we shouldn’t mention multi-threaded context at
> all in the API docs, because we are not even supporting it right now.
> I think this feature should be opt-in anyways, so extending the API
> documentation once we support it should be sufficient.
>
> What I would like to see of course is that we would still be able to
> support this callback for a multi-threaded context/pass manager design
> in such a way, that it is possible to suspend any thread at a
> suspension point and it won’t block any other thread even in the same
> context. But I don’t want to write this in stone now. This gives us
> all the flexibility we need for developing a good concurrent design.
>
> Having the ability to dynamically add and remove threads from an
> active compilation would be a nice feature that we should try to
> incorporate when possible and that would work nicely with the yield
> callback.
>
> Anyways, I am digressing to much. As I said before we should only
> specify the multi-threaded context constrains in the API doc once they
> are actually available. For now this is simply undefined behavior and
> not even supported.
>
> I extended the API with Philip’s suggestions and updated the doc.
> Please ignore proper 80col formatting for now ;-)
>
> Does this look good to everyone?
>
> -Juergen
>
> Core.h:
> typedef void (*LLVMYieldCallback)(LLVMContextRef, void *);
>
> /**
> * Set the yield callback function for this context.
> *
> * @see LLVMContext::setYieldCallback()
> */
> void LLVMContextSetYieldCallback(LLVMContextRef C,
> LLVMYieldCallback Callback,
> void *OpaqueHandle);
>
> LLVMContext.h:
> /// \brief Registers a yield callback with the given context.
> ///
> /// The yield callback function may be called by LLVM to transfer
> /// control back to the client that invoked the LLVM compilation. This can
> /// be used to yield control of the thread, or perform periodic work
> needed
> /// by the client. There is no guaranteed frequency at which
> callbacks must
> /// occur; in fact, the client is not guaranteed to ever receive this
> callback.
> /// It is at the sole discretion of LLVM to do so and only if it
> can guarantee
> /// that suspending the thread won't block any forward progress in
> other LLVM
> /// contexts in the same process.
> ///
> /// At a suspend point, the state of the current LLVM context is
> intentionally
> /// undefined. No assumptions about it can or should be made. Only
> LLVM context
> /// API calls that explicitly state that they can be used during a
> yield callback
> /// are allowed to be used. Any other API calls into the context are
> not supported
> /// until the yield callback function returns control to LLVM. Other
> LLVM contexts
> /// are unaffected by this restriction.
> void setYieldCallback(YieldCallbackTy Callback, void *OpaqueHandle);
>
> /// \brief Calls the yield callback (if applicable).
> ///
> /// This transfers control back to the client, which may suspend the
> current
> /// thread. Only call this method when LLVM doesn't hold any global
> mutex or
> /// cannot block the execution in another LLVM context.
> void yieldToClient();
>
>
> On May 15, 2014, at 11:32 AM, Andrew Trick <atrick at apple.com
> <mailto:atrick at apple.com>> wrote:
>
>>
>> On May 15, 2014, at 9:50 AM, Philip Reames <listmail at philipreames.com
>> <mailto:listmail at philipreames.com>> wrote:
>>
>>> Given the use case (user mode scheduling), I'm not going to oppose
>>> this proposal. I would like to see a couple of things clarified
>>> documentation wise:
>>> - When is this interface valid? (i.e. the single thread case)
>>> - If a context does have multiple threads, is this called once per
>>> thread? Or once per thread group after internal coordination? (you
>>> can write this out of scope if desired)
>>> - If we later introduce multiple threads, and this mechanism doesn't
>>> support it, what will happen? Will the function just not be called?
>>> - You hint at this already, but clarifying the state of the current
>>> context at a suspend point would be helpful.
>>>
>>> Here's a possible draft that includes the above:
>>> The may-suspend callback function may be called by LLVM to transfer
>>> control back to the client that invoked the LLVM compilation. This
>>> can be used to yield control of the thread, or perform periodic work
>>> needed by the client. There is no guaranteed frequency at which
>>> callbacks must occur; in fact, the client is not guaranteed to ever
>>> receive this callback. It is at the sole discretion of LLVM to do so
>>> and only if it can guarantee that suspending the thread won't block
>>> any forward progress in other LLVM contexts.
>>>
>>> At a suspend point, the state of the current LLVM context is
>>> intentionally undefined. No assumptions about it can or should be
>>> made. In particular, call backs into the context are not supported
>>> until the suspend function returns control to LLVM. Other LLVM
>>> contexts are unaffected.
>>
>> Great.
>>
>>> Currently, LLVM assumes one thread per LLVM context. If, or when,
>>> we introduce multiple threads, this interface will not be available
>>> for contexts which opt-in to the thread pool model. We may extend
>>> this interface at a later time to support thread pools, but for the
>>> moment, that use case is explicitly unsupported.
>>
>> Correct. We should avoid mentioning multi-thread contexts in the API
>> docs. It is very misleading to describe a feature that LLVM does not
>> support. We can instead add a statement to the docs explaining that
>> the callback is only synchronous with respect to the calling thread
>> and places no guarantee on the state of other threads, regardless of
>> their context.
>>
>>> p.s. Bikeshed wise, might "yield" be a better term than "suspend" here?
>>
>> I personally like calling it “yield” because it is more intuitive and
>> describes the use case. I proposed maySuspend because I wanted to be
>> accurate. It is really the client deciding what to do with the
>> callback. LLVM should make no assumption that it’s actually yielding.
>>
>> Chandler likes “yield” too, so lets go with that unless anyone else
>> wants to weigh in.
>>
>> On the commits list, Juergen introduced our current use case, along
>> with a couple other future use cases for this API. I’m sorry I
>> neglected to clearly reiterate our usage, but when it comes to
>> documenting the C API I intentionally try not to limit its potential
>> to a narrow use case.
>>
>> -Andy
>>
>>> Philip
>>>
>>> On 05/13/2014 11:49 AM, Juergen Ributzka wrote:
>>>> Sounds good. Lets get started by nailing down the C API and
>>>> semantics for this first.
>>>>
>>>> I mirrored the C API for the LLVM context diagnostic handler and
>>>> used Andy’s suggested name for the callback.
>>>> The opaque handle was suggested by Duncan and can provide optional
>>>> user specified information that is
>>>> provided back during the callback (i.e. barrier, etc).
>>>>
>>>> Cheers,
>>>> Juergen
>>>>
>>>> Core.h:
>>>> typedef void (*LLVMMaySuspendCallback)(LLVMContextRef, void *);
>>>>
>>>> /**
>>>> * Set the may-suspend callback function for this context.
>>>> *
>>>> * @see LLVMContext::setMaySuspendCallback()
>>>> */
>>>> void LLVMContextSetMaySuspendCallback(LLVMContextRef C,
>>>> LLVMMaySuspendCallback Callback,
>>>> void *OpaqueHandle);
>>>>
>>>> LLVMContext.h:
>>>> /// \brief Registers a may-suspend callback with the context.
>>>> ///
>>>> /// The may-suspend callback function may be called by LLVM to transfer
>>>> /// control back to the client that invoked the LLVM compilation.
>>>> The client
>>>> /// is not garantueed to ever receive this callback. It is at the sole
>>>> /// discretion of LLVM to do so and only if it can guarantee that
>>>> suspending
>>>> /// the thread won't block any forward progress in other LLVM contexts.
>>>> void setMaySuspendCallback(MaySuspendCallbackTy Callback, void
>>>> *OpaqueHandle);
>>>>
>>>> /// \brief Calls the may-suspend callback (if applicable).
>>>> ///
>>>> /// This transfers control back to the client, which may suspend
>>>> the current
>>>> /// thread. Only call this method when LLVM doesn't hold any global
>>>> mutex or
>>>> /// cannot block the execution in another LLVM context.
>>>> void callMaySuspendCallback();
>>>>
>>>> On May 12, 2014, at 5:26 PM, Nick Lewycky <nlewycky at google.com
>>>> <mailto:nlewycky at google.com>> wrote:
>>>>
>>>>> 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.
>>>>>
>>>>>
>>>>> 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.
>>>>>
>>>>> 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.
>>>>>
>>>>> Nick
>>>>
>>>>
>>>>
>>>> _______________________________________________
>>>> LLVM Developers mailing list
>>>> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu
>>>> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
>>>
>>> _______________________________________________
>>> LLVM Developers mailing list
>>> LLVMdev at cs.uiuc.edu
>>> <mailto:LLVMdev at cs.uiuc.edu>http://llvm.cs.uiuc.edu
>>> <http://llvm.cs.uiuc.edu/>
>>> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20140515/a0bbbd17/attachment.html>
More information about the llvm-dev
mailing list