This has been the behavior of the runtime since the initial release.
Initially, it was thought that task executors would provide similar
functionality, so they naturally took over the enumerator. After that
changed, we forgot to change it back. Fortunately, we haven't released
any versions of Swift with the task executors feature yet, so it's not
too late to fix this.
The function is marked `noreturn` but the compiler was not able to reason
statically about whether this constraint is met. From code inspection it's
clear that the call to `swift_task_donateThreadToGlobalExecutorUntil()` does
not return, so `swift_unreachable()` can be used to suppress the warning.
Since https://github.com/apple/swift/pull/65613, DiscardingTG started to
accept `() -> Void` instead of `() -> T`, but it also changed the number
of arguments accepted by the closure from 3 to 2. So it should use
`non_future_adapter` instead of `future_adapter` to avoid runtime signature
mismatch.
startOnMainActor checked the current executor directly, which in some
cases came back as a `nullptr`. This happens with older API which don't
know to set the current executor. `swift_task_isCurrentExecutor` knows
how to check for the current dispatch queue and the main thread though,
so switching the main-executor check to use that API instead.
This patch adds an SPI to run the first partial function of a MainActor
asynchronous function on the MainActor synchronously. This is
effectively like the asynchronous program entrypoint behavior. The first
partial function is run synchronously. Following continuations are
enqueued for execution like any other asynchronous function.
The swift_task_asyncMainDrainQueue function acts as the entrypoint into
driving the main queues, ultimately running the whole program and acting
as the backing driver of the main actor. Making the function hookable
means that custom concurrency runtimes can implement their own async
entrypoints, allowing async top-level code and async-main to "just
work".
The async main drain queue function is noreturn, but was emitting a
warning due to the override compatibility returning the result of the
overridden function in the wrapper override function. To work around
this, I've added the `OVERRIDE_TASK_NORETURN` macro, which provides an
override point for noreturn functions in the concurrency library that
doesn't return the result from the wrapped function, avoiding the
warning. In the event that the function is not set, the macro is set to
the normal `OVERRIDE` with the return type set to `void`.
status record that is already registered with the task. Provide more
versatile removeStatusRecord functions and update clients to use them
Radar-Id: rdar://problem/101864092
rdar://105837040
* WIP: Store layout string in type metadata
* WIP: More cases working
* WIP: Layout strings almost working
* Add layout string pointer to struct metadata
* Fetch bytecode layout strings from metadata in runtime
* More efficient bytecode layout
* Add support for interpreted generics in layout strings
* Layout string instantiation, take and more
* Remove duplicate information from layout strings
* Include size of previous object in next objects offset to reduce number of increments at runtime
* Add support for existentials
* Build type layout strings with StructBuilder to support target sizes and metadata pointers
* Add support for resilient types
* Properly cache layout strings in compiler
* Generic resilient types working
* Non-generic resilient types working
* Instantiate resilient type in layout when possible
* Fix a few issues around alignment and signing
* Disable generics, fix static alignment
* Fix MultiPayloadEnum size when no extra tag is necessary
* Fixes after rebase
* Cleanup
* Fix most tests
* Fix objcImplementattion and non-Darwin builds
* Fix BytecodeLayouts on non-Darwin
* Fix Linux build
* Fix sizes in linux tests
* Sign layout string pointers
* Use nullptr instead of debug value
done the load or who need the oldStatus information after adding the
status record.
Change some of the memory barrier logic since we can take advantage of
load-through HW address dependency.
Radar-Id: rdar://problem/105634683
field of an ActiveTaskStatus can also be modified while the
TaskStatusRecord list is being modified. Make the StatusRecordLock
reentrant.
Radar-Id: rdar://problem/88093007
other threads/tasks which have a reference to the task might need to
access parts of it even if the task itself is completed.
Radar-Id: rdar://problem/88093007
When a completed task updates the queue head to announce
that it's been completed, it only did an acquire exchange.
By also having it also do a release, we will ensure that
prior writes done by the completed task, before the task is
marked completed, will be correctly ordered as happening
before any subsequent reads by tasks waiting on that
completion status.
Co-authored-by: John McCall <rjmccall@apple.com>
Replace the `assert(false)` with `swift_unreachable`.
This is more robust in release builds where the `assert(false)` is a no-op and would result in a wrong fall-though to the next switch case.
Fixes a warning in release builds.
This is done using a condition variable upon which the awaiting thread
will block if the continuation has not be resumed by the point of await.
The resuming thread will signal this condition variable, thereby
unblocking the awaiting thread.
Rdar://99977665
The new intrinsic, exposed via static functions on Task<T, Never> and
Task<T, Error> (rethrowing), begins an asynchronous context within a
synchronous caller's context. This is only available for use under the
task-to-thread concurrency model, and even then only under SPI.
Previously getAsyncClosureEntryPointAndContextSize took both a pointer
for a function and a closure context. That was a relic of a temporary
ABI where async function pointers were not used in all cases. Now that
that ABI is long gone, async function pointers are always used.
Consequently, the closure context argument was unused. Here, the
closure context argument is removed.
As soon as the waiting task is successfully enqueued on the blocking
task, both tasks have to be considered invalidated because the
blocking task can concurrently complete and resume its waiters:
- The waiting task ensures that the blocking task is valid while
it's waiting. However, that's measured from the perspective of
the waiting task, not from the perspective of the thread that was
previously executing it. As soon as the waiting task is resumed,
the wait call completes and the validity guarantee on the blocking
task disappears, so the blocking task must be treated as
invalidated.
- The waiting task ensures that it is valid as long as it isn't
complete. Since it's trying to wait, it must not be complete.
However, as soon we resume it, it can complete, so the waiting
task must also be treated as invalidated.
This is one of those things that's not really easy to test, and the
need for a fix is pretty urgent, so I'm submitting this patch without
a test. I'll try to land a race test that demonstrates the bug in
the next few days.
@kavon deserves all the credit here for some truly heroic debugging
and finally recognizing the flaw in the code; I'm just popping in
at the last minute to sheepishly patch the bug.
Fixes rdar://92666987
Moved all the threading code to one place. Added explicit support for
Darwin, Linux, Pthreads, C11 threads and Win32 threads, including new
implementations of Once for Linux, Pthreads, C11 and Win32.
rdar://90776105
Moved all the threading code to one place. Added explicit support for
Darwin, Linux, Pthreads, C11 threads and Win32 threads, including new
implementations of Once for Linux, Pthreads, C11 and Win32.
rdar://90776105
Change continuation signposts to emit an interval for init/resume.
Fix task_create to take the decoded flags as separate parameters, matching other calls.
Move job_run trace calls into runJobInEstablishedExecutorContext. swift_job_runImpl didn't catch everything.
rdar://92149411
Apply a blanket pass of including `new` for the placement new allocation
and namespacing the call to the global placement new allocator. This
should repair the Android ARMv7 builds.
Decode all fields from the various flags values, pass each field as a separate argument to the various signposts. We were just passing the raw value of the flags and requiring the signpost client to decode them, which was ugly and required the client to know details they shouldn't need to know.
Strip ptrauth bits from the task resume function when signposting, when ptrauth is supported.
Add signpost events for continuation init/await/resume events.
We also make task_wait into an interval, rather than a single event. The interval ends when the task resumes. As part of this change, we also skip emitting the interval when the wait completed immediately and the task didn't have to suspend.
While we're in there, clean up a few SWIFT_TASK_DEBUG_LOG lines that emitted warnings when built with the logging enabled.
rdar://88658803
Generated code has never actually initialized this field, so we
might as well remove it. Doing so mostly doesn't impact the ABI
since we don't store anything for arguments or results in the
context as part of the normal call sequence. We do need to adjust
some of the hard-coded contexts, however, such as continuation
contexts and the statically-sized context for special runtime
async functions.