Commit Graph

191 Commits

Author SHA1 Message Date
Mike Ash
a82ea120a4 [RemoteMirror][swift-inspect] Add a command to inspect the state of the concurrency runtime.
Most of the new inspection logic is in Remote Mirror. New code in swift-inspect calls the new Remote Mirror functions and formats the resulting information for display.

Specific Remote Mirror changes:

* Add a call to check if a given metadata is an actor.
* Add calls to get information about actors and tasks.
* Add a `readObj` call to MemoryReader that combines the read and the cast, greatly simplifying code chasing pointers in the remote process.
* Add a generalized facility to the C shims that can allocate a temporary object that remains valid until at least the next call, which is used to return various temporary arrays from the new calls. Remove the existing `lastString` and `lastChunks` member variables in favor of this new facility.

Swift-inspect changes:

* Add a new dump-concurrency command.
* Add a new `ConcurrencyDumper.swift` file with the implementation. The dumper needs to do some additional work with the results from Remote Mirror to build up the task tree and this keeps it all organized.
* Extend `Inspector` to query the target's threads and fetch each thread's current task.

Concurrency runtime changes:

* Add `_swift_concurrency_debug` variables pointing to the various future adapters. Remote Mirror uses these to provide a better view of a tasks's resume pointer.

rdar://85231338
2022-02-04 09:28:32 -05:00
Rokhini Prabhu
a2a5c64d4b Change task's base and escalated priority propagation rules for
detached, unstructured and structured concurrency child tasks

Radar-Id: rdar://problem/86100376
2022-01-24 07:50:28 -08:00
Rokhini Prabhu
9df1c9a135 Track base priority separately from max priority whereby base priority
is set at creation time. Create a new API for accessing this state

Radar-Id: rdar://problem/86100376
2022-01-24 07:50:27 -08:00
Rokhini Prabhu
6d5c7b5797 NFC: Rename priority set during task creation to be RequestedPriority
Radar-Id: rdar://problem/86100376
2022-01-21 12:12:12 -08:00
Rokhini Prabhu
8f2ac188fb Make sure that currentPriority actually reads the max QoS in the active
task status instead of the Job priority which is not necessarily in sync

Radar-Id: rdar://problem/86100376
2022-01-21 12:12:12 -08:00
Max Desiatov
372ada0e24 test: add handling for Wasm/WASI (#39519)
This change adds support for WASI in stdlib tests. Some tests that expect a crash to happen had to be disabled, since there's currently no way to observe such crash from a WASI host.
2022-01-12 14:24:50 +00:00
Rokhini Prabhu
a4fe57f230 Merge pull request #40606 from apple/rokhinip/86347801-task-creation-escalation-race
Resolve race between task creation and concurrent escalation and cancellation.
2022-01-12 12:14:09 +08:00
Mike Ash
0977920217 [Concurrency] Add tracing for major operations in the concurrency runtime.
Each trace point is declared as a function in the new `Tracing.h` header. These functions are called from the appropriate places in the concurrency runtime.

On Darwin, an implementation of these functions is provided which uses the `os/signpost.h` API to emit signpost events/intervals.

When the signpost API is not available, no-op stub implementations are provided. Implementations for other OSes can be provided by providing implementations of the trace functions for that OS.

rdar://81858487
2022-01-07 11:35:40 -05:00
Rokhini Prabhu
1947102ebd Change the logic for adding new task status records to a task
This change has two parts to it:

1. Add in a new interface (addStatusRecordWithChecks) for adding task
status records that also takes in a function ref. This function ref will
be used to evaluate if current state of the parent task has any changes
that need to be propagated to the child task that has been created.

This is necessary to prevent the following race between task creation
and concurrent cancellation and escalation:

a. Parent task create child task. It does lazy relaxed loads on its own
   state while doing so and propagates this state to the child.
b. Child task is created but has not been attached to the parent
   task/task group.
c. Parent task gets cancelled by another thread.
d. Child task gets linked into the parent’s task status records but no
   reevaluation has happened to account for changes that might have happened to
   the parent after (a).

2. Move status record management functions from the
Runtime/Concurrency.h to TaskPrivate.h. Remove any corresponding
overrides that are no longer needed. Remove unused tryAddStatusRecord
method whose functionality is provided by addStatusRecordWithChecks.

Radar-Id: rdar://problem/86347801
2021-12-31 03:23:52 -08:00
Pavel Yaskevich
be594749e7 Merge pull request #40495 from xedin/improvements-to-async-signature
[Concurrency/Runtime] Implement function/continuation type generation…
2021-12-10 09:30:54 -08:00
Pavel Yaskevich
9a00b33378 [Concurrency/Runtime] Implement function/continuation type generation for AsyncSignature
`AsyncFunctionTypeImpl` has its `type` defaulted to `TaskContinuationFunction`
which is incorrect because it has to append arguments, result type and account
for throws bit.

These changes expand `AsyncSignature` with `ContinuationType` and expand `FunctionType`
to include all of the appropriate information.
2021-12-09 16:52:53 -08:00
swift-ci
83e3ae8111 Merge pull request #40265 from mikeash/task-id-64-bit 2021-12-01 10:37:36 -08:00
Saleem Abdulrasool
de1c3e6580 Concurrency: report errors on failures on Windows
The usage of libdispatch in Concurrency is dynamic - it does not
explicitly link against libdispatch and thus cannot directly invoke
`dispatch_main`.  While linking against dispatch would be ideal, this
should improve the current path.
2021-11-30 08:19:53 -08:00
Mike Ash
bac6965946 [Concurrency] Make task IDs 64-bit.
The 32-bit identifier in Job is locked down at this point, so we expand the ID by storing the top 32 bits separately inside AsyncTask::PrivateStorage.

rdar://85167409
2021-11-19 15:24:35 -05:00
Mike Ash
cf3c131e7c [Reflection] Add API for inspecting async task allocation slabs.
We remove the existing `swift_reflection_iterateAsyncTaskAllocations` API that attempts to provide all necessary information about a tasks's allocations starting from the task. Instead, we split it into two pieces: `swift_reflection_asyncTaskSlabPointer` to get the first slab for a task, and `+swift_reflection_asyncTaskSlabAllocations` to get the allocations in a slab, and a pointer to the next slab.

We also add a dummy metadata pointer to the beginning of each slab. This allows tools to identify slab allocations on the heap without needing to locate every single async task object. They can then use `swift_reflection_asyncTaskSlabAllocations` on such allocations to find out about the contents.

rdar://82549631
2021-11-18 14:15:25 -05:00
Saleem Abdulrasool
3c9c564eba Revert "[Reflection] Add API for inspecting async task allocation slabs." 2021-11-17 18:47:13 -08:00
Mike Ash
7c7dc5d5b3 [Reflection] Add API for inspecting async task allocation slabs.
We remove the existing `swift_reflection_iterateAsyncTaskAllocations` API that attempts to provide all necessary information about a tasks's allocations starting from the task. Instead, we split it into two pieces: `swift_reflection_asyncTaskSlabPointer` to get the first slab for a task, and `+swift_reflection_asyncTaskSlabAllocations` to get the allocations in a slab, and a pointer to the next slab.

We also add a dummy metadata pointer to the beginning of each slab. This allows tools to identify slab allocations on the heap without needing to locate every single async task object. They can then use `swift_reflection_asyncTaskSlabAllocations` on such allocations to find out about the contents.

rdar://82549631
2021-11-11 16:58:14 -05:00
swift-ci
95129274bb Merge pull request #39817 from AtariDreams/unsafesendable 2021-11-05 17:44:37 -07:00
Doug Gregor
26b7cbc4ae Define swift_async_extendedFramePointerFlags for the watchOS simulator 2021-10-27 12:04:20 -07:00
Doug Gregor
4aca32c0a4 Disable the definition and use of swift_async_extendedFramePointerFlags on watchOS
The asm definition of `swift_async_extendedFramePointerFlags` prevents
the use of bitcode with the back-deployment libraries, so remove the
definition and use of this symbol from watchOS binaries entirely.
Instead, always force the async frame bit to be set. This trades off
backtraces on older OS's for debuggability of newer ones. If it causes
problems, it can be disabled via the option
`-swift-async-frame-pointer=never`.

Fixes rdar://84687579.
2021-10-26 22:26:37 -07:00
Arnold Schwaighofer
68b9ccc4ad Make sure that the future fragment's storage pointer is properly aligned 2021-10-20 00:52:07 -04:00
Rose
1415739caa Remove unused variable 2021-10-19 17:17:20 -04:00
John McCall
a76b304f00 Allow building a concurrent libSwiftConcurrency without libdispatch
The goal here is not to eventually implement a concurrent thread
pool ourselves.  We're just making it easier for integrators who
have their own pool and don't want to use Dispatch to build the
Swift concurrency runtime.  Just hook the right functions and
you should be fine.

The necessary functions to hook are:
- swift_task_enqueueGlobal
- swift_task_enqueueGlobalAfterDelay

The following functions *would* be necessary to hook:
- swift_task_enqueueMainExecutor
- swift_task_asyncMainDrainQueue (only if you have an async main?)
However, this configuration does not currently properly support
the main executor, and so `@MainActor` should be avoided for now.

rdar://83513751
2021-10-01 02:15:03 -04:00
Ben Langmuir
0e507f2f24 Revert "Allow building a concurrent libSwiftConcurrency without libdispatch" 2021-09-28 10:08:46 -07:00
John McCall
1df455bc14 Allow building a concurrent libSwiftConcurrency without libdispatch
The goal here is not to eventually implement a concurrent thread
pool ourselves.  We're just making it easier for integrators who
have their own pool and don't want to use Dispatch to build the
Swift concurrency runtime.  Just hook the right functions and
you should be fine.

The necessary functions to hook are:
- swift_task_enqueueGlobal
- swift_task_enqueueGlobalAfterDelay

The following functions *would* be necessary to hook:
- swift_task_enqueueMainExecutor
- swift_task_asyncMainDrainQueue (only if you have an async main?)
However, this configuration does not currently properly support
the main executor, and so `@MainActor` should be avoided for now.

rdar://83513751
2021-09-28 02:14:26 -04:00
Doug Gregor
22551cf517 Merge pull request #39158 from ktoso/wip-fix-group-leak
[Concurrency] Stop TaskGroup from holding onto Tasks forever (leaking)
2021-09-08 08:47:10 -07:00
Doug Gregor
9a7584750a Merge pull request #39197 from DougGregor/back-deploy-concurrency-no-fp-flag 2021-09-08 06:47:45 -07:00
Konrad `ktoso` Malawski
d4ebc58754 [Concurrency] Fix group child tasks not being released
The proper handling of task group child tasks is that:
- if it completes a waiting task immediately, we don't need to retain it
  - we just move the value to the waiting task and can destroy the task
- if we need to store the ready task and wait for a waiting task (for a
  task that hits `await group.next()`) then we need to retain the ready
  task.
  - as the waiting task arrives, we move the value from the ready task
    to the waiting task, and swift_release the ready task -- it will now
    be destroyed safely.
2021-09-04 20:00:39 +09:00
Mike Ash
c4115ccbcb Merge pull request #39115 from mikeash/voucher-propagation
[Concurrency] Propagate Darwin vouchers across async tasks.
2021-09-03 11:09:27 -04:00
Doug Gregor
03956e0421 Make swift_async_extendedFramePointerFlags = 0 in back-deployed configurations.
`swift_async_extendedFramePointerFlags` is used in back-deployed
concurrency code as a mask to set the extended async frame info bit on
OS versions that understand it. Set this mask to zero in the
back-deployed libraries.
2021-09-02 16:10:51 -07:00
Mike Ash
a80a19b1e1 [Concurrency] Propagate Darwin vouchers across async tasks.
Darwin OSes support vouchers, which are key/value sets that can be adopted on a thread to influence its execution, or sent to another process. APIs like Dispatch propagate vouchers to worker threads when running async code. This change makes Swift Concurrency do the same.

The change consists of a few different parts:

1. A set of shims (in VoucherShims.h) which provides declarations for the necessary calls when they're not available from the SDK, and stub implementations for non-Darwin platforms.
2. One of Job's reserved fields is now used to store the voucher associated with a job.
3. Jobs grab the current thread's voucher when they're created.
4. A VoucherManager class manages adoption of vouchers when running a Job, and replacing vouchers in suspended tasks.
5. A VoucherManager instance is maintained in ExecutionTrackingInfo, and is updated as necessary throughout a Job/Task's lifecycle.

rdar://76080222
2021-09-02 17:45:28 -04:00
Yuta Saito
f6f756e851 [Concurrency] repair cooperative global executor (#39092)
`SWIFT_STDLIB_SINGLE_THREADED_RUNTIME` mode has been broken for a long time.

This patch guards some includes and use of libdispatch headers so that platforms
that doesn't support libdispatch can build cooperative executor runtime.
And fixed missing implementations for cooperative mode.
2021-08-31 09:31:50 +01:00
swift-ci
45eaaa2398 Merge pull request #39042 from mikeash/swift-task-debug-printf-cleanup 2021-08-25 14:30:03 -07:00
Mike Ash
d5c0469f3e [Concurrency] Replace SWIFT_TASK_PRINTF_DEBUG with a SWIFT_TASK_DEBUG_LOG macro.
This macro takes the string and parameters directly, and is conditionally defined to either call fprintf or ignore its arguments. This makes the call sites a little more pleasant (no #if scattered about) and ensures every log includes the thread ID and a newline automatically.
2021-08-25 10:47:36 -04:00
Evan Wilde
19063508cc Remove AsyncCall.h
None of the function in AsyncCall are in use anymore so we can delete
it. This contained code for implementing swift asynchronous functions in
C++.
2021-08-09 16:40:35 -07:00
Evan Wilde
77cf7c6883 Remove old runAsyncAndBlock internals
runAsyncAndBlock has long been dead, I'm pulling out the machinery that
lives in the runtime that used to support it. This is the first layer
that can go away.
2021-08-09 14:54:05 -07:00
Doug Gregor
d9e3259ff6 [SE-0304] Clean up handling of task priorities. 2021-07-30 12:53:03 -07:00
Doug Gregor
8180c26a8d Merge pull request #38600 from varungandhi-apple/vg-resume-to-generic-executor
[Runtime] Resume to the generic executor in the absence of an override.
2021-07-23 09:30:20 -07:00
Joe Groff
fc67ba57f2 Merge pull request #37938 from jckarter/async-let-multi-suspend
Handle multiple awaits and suspend-on-exit for async let tasks.
2021-07-23 07:36:54 -07:00
Varun Gandhi
d348fd90d4 Resume to the generic executor in the absence of an override.
Without this fix, we saw a crash involving URLSession where we'd hit
assertions or corruption in the runtime in various forms:
- Assertion on trying to enqueue work onto a zombie actor.
- job->SchedulerPrivate being overwritten (crash in getNextJobInQueue).
- *(job->SchedulerPrivate) being overwritten (crash in getAsPreprocessedJob
  right after call to getNextJobInQueue).

I haven't been able to create a minimal crashing example yet, but manual
testing shows this does fix the issue.

Fixes rdar://79859254.
2021-07-22 21:11:16 -07:00
Michael Gottesman
ff6b67c585 [concurrency] Add AsyncTask::flagAsCompleted() and behind SWIFT_TASK_PRINTF_DEBUG allow it to be used to log Task completion.
This should let people debug Task lifetime easier.
2021-07-22 13:25:09 -07:00
Joe Groff
439edbce1f Handle multiple awaits and suspend-on-exit for async let tasks.
Change the code generation patterns for `async let` bindings to use an ABI based on the following
functions:

- `swift_asyncLet_begin`, which starts an `async let` child task, but which additionally
  now associates the `async let` with a caller-owned buffer to receive the result of the task.
  This is intended to allow the task to emplace its result in caller-owned memory, allowing the
  child task to be deallocated after completion without invalidating the result buffer.
- `swift_asyncLet_get[_throwing]`, which replaces `swift_asyncLet_wait[_throwing]`. Instead of
  returning a copy of the value, this entry point concerns itself with populating the local buffer.
  If the buffer hasn't been populated, then it awaits completion of the task and emplaces the
  result in the buffer; otherwise, it simply returns. The caller can then read the result out of
  its owned memory. These entry points are intended to be used before every read from the
  `async let` binding, after which point the local buffer is guaranteed to contain an initialized
  value.
- `swift_asyncLet_finish`, which replaces `swift_asyncLet_end`. Unlike `_end`, this variant
  is async and will suspend the parent task after cancelling the child to ensure it finishes
  before cleaning up. The local buffer will also be deinitialized if necessary. This is intended
  to be used on exit from an `async let` scope, to handle cleaning up the local buffer if necessary
  as well as cancelling, awaiting, and deallocating the child task.
- `swift_asyncLet_consume[_throwing]`, which combines `get` and `finish`. This will await completion
  of the task, leaving the result value in the result buffer (or propagating the error, if it
  throws), while destroying and deallocating the child task. This is intended as an optimization
  for reading `async let` variables that are read exactly once by their parent task.

To avoid an epoch break with existing swiftinterfaces and ABI clients, the old builtins and entry
points are kept intact for now, but SILGen now only generates code using the new interface.

This new interface fixes several issues with the old async let codegen, including use-after-free
crashes if the `async let` was never awaited, and the inability to read from an `async let` variable
more than once.

rdar://77855176
2021-07-22 10:19:31 -07:00
Varun Gandhi
72909bdd98 Merge pull request #38427 from varungandhi-apple/vg-workaround-priority
Further workaround for priority mishandling in runtime.
2021-07-22 09:19:09 -07:00
Varun Gandhi
fa40675910 Further workaround for priority mishandling in runtime.
See rdar://79378762, SR-14802, SR-14841, SR-14875.

This doesn't resolve all hangs, such as those occurring
due to explicit usage of priorities and certain other
situations where priorities seem to be causing issues
(rdar://79823345), but it does resolve some cases.
2021-07-15 23:03:07 -07:00
swift-ci
d73d8a69d5 Merge pull request #38404 from ktoso/wip-task-cancellation-double 2021-07-15 19:12:06 -07:00
Konrad `ktoso` Malawski
e8888f7965 [Concurrency] prevent races in task cancellation 2021-07-16 08:29:00 +09:00
John McCall
264e4ace12 Clear the active task immediately when suspending. 2021-07-14 20:24:01 -04:00
John McCall
0d5fd0f520 Remove the ShouldNotDeallocateInCallee bit from AsyncContextFlags.
The original async ABI made callees deallocate the context,
which allows tail calls (at the async-function level) but
interferes with callers' ability to optimize callee frame
allocation.  The purpose of this bit was to allow callers
to do that optimization, but we've since just made callers
responsible for deallocating the context, which is overall
just a lot simpler.  So this has been dead for quite some
time.
2021-07-14 20:24:01 -04:00
John McCall
29434257dd Allow swift_continuation_await to be forced to honor an executor. 2021-07-14 20:24:01 -04:00
John McCall
3aa04db87b Track whether a task is actively running.
Tracking this as a single bit is actually largely uninteresting
to the runtime.  To handle priority escalation properly, we really
need to track this at a finer grain of detail: recording that the
task is running on a specific thread, enqueued on a specific actor,
or so on.  But starting by tracking a single bit is important for
two reasons:

- First, it's more realistic about the performance overheads of
  tasks: we're going to be doing this tracking eventually, and
  the cost of that tracking will be dominated by the atomic
  access, so doing that access now sets the baseline about right.

- Second, it ensures that we've actually got runtime involvement
  in all the right places to do this tracking.

A propos of the latter: there was no runtime involvement with
awaiting a continuation, which is a point at which the task
potentially transitions from running to suspended.  We must do
the tracking as part of this transition, rather than recognizing
in the run-loops that a task is still active and treating it as
having suspended, because the latter point potentially races with
the resumption of the task.  To do this, I've had to introduce
a runtime function, swift_continuation_await, to do this awaiting
rather than inlining the atomic operation on the continuation.

As part of doing this work, I've also fixed a bug where we failed
to load-acquire in swift_task_escalate before walking the task
status records to invoke escalation actions.

I've also fixed several places where the handling of task statuses
may have accidentally allowed the task to revert to uncancelled.
2021-07-14 20:24:01 -04:00