[Dwarf-discuss] Coroutines

Kyle Huey khuey@pernos.co
Tue Feb 27 21:53:39 GMT 2024


On Tue, Feb 27, 2024 at 1:07 PM Adrian Prantl <aprantl@apple.com> wrote:

>
>
> On Feb 27, 2024, at 10:32 AM, Kyle Huey <khuey@pernos.co> wrote:
>
> On Wed, Feb 21, 2024 at 9:12 AM Adrian Prantl <aprantl@apple.com> wrote:
>
>> Can you clarify what kind of information you are interested in? Are you
>> talking about representing variables inside of coroutines, function
>> pointers to coroutines, linetables for coroutines, ...?
>>
>> LLDB's Swift plugin for example supports Swift async functions (which are
>> effectively coroutines) but does so without adding any new extensions to
>> DWARF. Here's a recent talk from last year's LLVM dev meeting on that
>> topic: https://www.youtube.om/watch?v=g4fei6Vl7o8
>> <https://www.youtube.com/watch?v=g4fei6Vl7o8>
>>
>
> The async control flow parts of this (backtraces and stepping) are what I
> am particularly interested in. Variables seem straightforward since DWARF
> location expressions are already generic enough to let you point to heap
> allocated storage for variables that survive across yield points. Your talk
> is a good demo of the behavior I'd like to achieve (for Rust specifically).
> A few technical questions:
>
> How do you "identify" a particular chain of funclet invocations that go
> together? I assume this is done based on the pointer identity of the
> async_context.
>
>
> Each async_context has a continuation pointer pointing to the next funclet
> that is going to be executed when the current coroutine returns.
>

Sure, but if you have multiple async_contexts executing the same sequence
of funclets you have to condition stopping at the next funclet on having
the right async_context, no?

Put another way (forgive my pseudo code), if you have

function silly_print() {
    delay = rand();
    // Point 1
    async_sleep(delay).await;
    // Point 2
    printf("Hello" );
}

function do_stuff() {
    runtime.async_dispatch(silly_print());
    runtime.async_dispatch(silly_print());
}

When stepping from point 1 to point 2, the breakpoint on the post-await
funclet at point 2 has to be conditional on being on the async_context
being the same async_context the debugger was using at point 1, right? And
then you have to be able to determine what the "same async_context" is.

- Kyle


> And the logic to understand what the async_context is and where it's found
> at function entry points is hardcoded into the Swift plugin?
>
>
> Yes, there is a Swift-specific unwinder plugin in LLDB that does this.
> There is also a custom stepping plan there.
>
>
> How do you handle pointer reuse on async_contexts?
>
>
> If I'm understanding the question correctly: there is a heap async_context
> object for every continuation that is on the schedule at any time. I don't
> think we can prevent a later continuation to be allocated in the same place
> as a previous one, but since they can never appear at the same time, this
> also isn't a problem.
>
> -- adrian
>
>
> - Kyle
>
>
>> -- adrian
>>
>>
>>
>>
>>
>> > On Feb 20, 2024, at 11:47 AM, Kyle Huey via Dwarf-discuss <
>> dwarf-discuss@lists.dwarfstd.org> wrote:
>> >
>> > Has anyone proposed or discussed DWARF structures to represent
>> coroutines or similar constructs? I skimmed the open issues list and didn't
>> see anything relevant.
>> >
>> > - Kyle
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.dwarfstd.org/pipermail/dwarf-discuss/attachments/20240227/648124a3/attachment-0001.htm>


More information about the Dwarf-discuss mailing list