Commit Graph

149 Commits

Author SHA1 Message Date
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
Mike Ash
0d6721214d [Concurrency] Add an exported symbol on Darwin that contains the frame pointer flag bit for async frames.
The symbol is swift_async_extendedFramePointerFlags. Since the value doesn't need to be dynamically computed, we save a level of indirection by emitting a fake global variable whose address is the value we want, similar to objc_absolute_packed_isa_class_mask.

This bit is mixed in to the frame pointer address stored on the stack to signal that a frame is an async frame. The compiler can emit code that ORs in the address of this symbol to apply the appropriate flag when it doesn't know the flag statically.

rdar://80277146
2021-07-07 14:46:58 -04:00
Julian Lettner
558a0cc605 Add tsan_release edge on task creation (#38074)
* Synchronize both versions of actor_counters.swift test

* Synchronize on Job address

Make sure to synchronize on Job address (AsyncTasks are Jobs, but not
all Jobs are AsyncTasks).

* Add fprintf debug output for TSan acquire/release

* Add tsan_release edge on task creation

without this, we are getting false data races between when a task
is created and immediately scheduled on a different thread.

False positive for `Sanitizers/tsan/actor_counters.swift` test:
```
WARNING: ThreadSanitizer: data race (pid=81452)
  Read of size 8 at 0x7b2000000560 by thread T5:
    #0 Counter.next() <null>:2 (a.out:x86_64+0x1000047f8)
    #1 (1) suspend resume partial function for worker(identity:counters:numIterations:) <null>:2 (a.out:x86_64+0x100005961)
    #2 swift::runJobInEstablishedExecutorContext(swift::Job*) <null>:2 (libswift_Concurrency.dylib:x86_64+0x280ef)

  Previous write of size 8 at 0x7b2000000560 by main thread:
    #0 Counter.init(maxCount:) <null>:2 (a.out:x86_64+0x1000046af)
    #1 Counter.__allocating_init(maxCount:) <null>:2 (a.out:x86_64+0x100004619)
    #2 runTest(numCounters:numWorkers:numIterations:) <null>:2 (a.out:x86_64+0x100006d2e)
    #3 swift::runJobInEstablishedExecutorContext(swift::Job*) <null>:2 (libswift_Concurrency.dylib:x86_64+0x280ef)
    #4 main <null>:2 (a.out:x86_64+0x10000a175)
```

New edge with this change:
```
[4357150208] allocate task 0x7b3800000000, parent = 0x0
[4357150208] creating task 0x7b3800000000 with parent 0x0
[4357150208] tsan_release on 0x7b3800000000    <<< new release edge
[139088221442048] tsan_acquire on 0x7b3800000000
[139088221442048] trying to switch from executor 0x0 to 0x7ff85e2d9a00
[139088221442048] switch failed, task 0x7b3800000000 enqueued on executor 0x7ff85e2d9a00
[139088221442048] enqueue job 0x7b3800000000 on executor 0x7ff85e2d9a00
[139088221442048] tsan_release on 0x7b3800000000
[139088221442048] tsan_release on 0x7b3800000000
[4357150208] tsan_acquire on 0x7b3800000000
counters: 1, workers: 1, iterations: 1
[4357150208] allocate task 0x7b3c00000000, parent = 0x0
[4357150208] creating task 0x7b3c00000000 with parent 0x0
[4357150208] tsan_release on 0x7b3c00000000    <<< new release edge
[139088221442048] tsan_acquire on 0x7b3c00000000
[4357150208] task 0x7b3800000000 waiting on task 0x7b3c00000000, going to sleep
[4357150208] tsan_release on 0x7b3800000000
[4357150208] tsan_release on 0x7b3800000000
[139088221442048] getting current executor 0x0
[139088221442048] tsan_release on 0x7b3c00000000
...
```

rdar://78932849

* Add static_cast<Job *>()

* Move TSan release edge to swift_task_enqueueGlobal()

Move the TSan release edge from `swift_task_create_commonImpl()` to
`swift_task_enqueueGlobalImpl()`.  Task creation itself is not an event
that needs synchronization, but rather that task creation "happens
before" execution of that task on another thread.

This edge is usually added when the task is scheduled via
`swift_task_enqueue()` (which then usually calls
`swift_task_enqueueGlobal()`).  However, not all task scheduling goes
through the `swift_task_enqueue()` funnel as some places call the more
specific `swift_task_enqueueGlobal()` directly.  So let's annotate this
function (duplicate edges aren't harmful) to ensure we cover all
schedule events, including newly-created tasks (our original problem
here).

rdar://78932849

Co-authored-by: Julian Lettner <julian.lettner@apple.com>
2021-06-25 18:40:53 -07:00
Arnold Schwaighofer
481d8ba00e Merge pull request #38089 from aschwaighofer/workaround_armv7k_async_lowering_bug
Runtime: Workaround armv7k code lowering bug
2021-06-24 22:43:04 -07:00
Arnold Schwaighofer
9263f61062 Runtime: Workaround armv7k code lowering bug
This is to workaround a bug in llvm's codegen when emitting the
callee-pop stack adjustment on a regular return from a swiftasync
function (vs. a tail call).

Without the workaround we fail to emit the callee-pop stack adjustment
leading to a mis-aligned stack on return.

```
  pop     {r7, pc}
  add     sp, #16
```

Workaround for rdar://79726989
2021-06-24 13:45:58 -07:00
Doug Gregor
f2d65c1506 Fix priority propagation when creating new tasks 2021-06-24 07:53:19 -07:00
Doug Gregor
931116071c Eliminate swift_task_create_f.
It's a tiny shim over `swift_task_create_common` that is rarely used.
Switch all of the former callers over the common API.
2021-06-24 07:53:18 -07:00
Doug Gregor
95e38839ab Hollow out swift_asyncLet_startImpl to just a swift_task_create call.
Introduce a task option record to capture the async-let storage, so
that `swift_task_create` can perform the appropriate initialization.
2021-06-24 07:53:18 -07:00
Doug Gregor
e94c8271d0 Remove swift_task_create_async_let_future.
This is a small shim over `swift_task_create`. Use that instead.
2021-06-24 07:53:18 -07:00
Doug Gregor
76959b1d4f Remove CreateAsyncTaskGroupFuture and swift_task_create_group_future.
We've moved everything over to `CreateAsyncTask` now.
2021-06-24 07:53:18 -07:00
Doug Gregor
8388a92ee9 Correct naming of "CopyThreadLocals" to "CopyTaskLocals" 2021-06-24 07:53:18 -07:00
Doug Gregor
dafb574a35 Switch task group child task creation over to Builtin.createAsyncTask().
Extend the behavior of `swift_task_create_common` to also encompass
adding the pending group task (when requested) and attaching it to the
group.
2021-06-24 07:53:18 -07:00
Doug Gregor
a61adace85 Remove CreateAsyncTaskFuture and swift_task_create_future.
We no longer need these entry points.
2021-06-24 07:53:18 -07:00
Doug Gregor
c7edfa3ba9 Centralize non-group task creation on swift_task_create[_f].
Introduce a builtin `createAsyncTask` that maps to `swift_task_create`,
and use that for the non-group task creation operations based on the
task-creation flags. `swift_task_create` and the thin function version
`swift_task_create_f` go through the dynamically-replaceable
`swift_task_create_common`, where all of the task creation logic is
present.

While here, move copying of task locals and the initial scheduling of
the task into `swift_task_create_common`, enabling by separate flags.
2021-06-24 07:53:17 -07:00
Doug Gregor
3727db2fe2 Create a separate set of task creation flags for swift_task_create.
The flags that are useful for task creation are a bit different from
the flags that go on a job. Create a separate flag set for task
creation and use that in the API for `swift_task_create`. For now,
have the callers do the remapping.
2021-06-24 07:53:17 -07:00
Doug Gregor
51d9db6404 Simplify swift_task_create_group_future_common API and rename it.
Collapse the `group` parameter of this API into the task options, and
have existing callers set up the options appropriately. The goal for
this function is to become the centralized entry point for all task
creation, with an extensible interface.
2021-06-24 07:53:17 -07:00
Konrad `ktoso` Malawski
dd10132b12 [Concurrency] Cancelled group should only spawn already cancelled tasks 2021-06-24 09:22:45 +09:00
Konrad `ktoso` Malawski
f37ae3d277 [Concurrency] move isAsyncTask into flags of task creation 2021-06-21 21:17:48 +09:00
Konrad `ktoso` Malawski
8536100354 [Concurrency] introduce task options, and change ABI to accept them
introduce new options parameter to all task spawning

[Concurrency] ABI for asynclet start to accept options

[Concurrency] fix unittest usages of changed task creation ABI

[Concurrency] introduce constants for parameter indexes in ownership

[Concurrency] fix test/SILOptimizer/closure_lifetime_fixup_concurrency.swift
2021-06-21 13:03:50 +09:00
John McCall
ca62a79079 Use &_dispatch_main_q as the identity of the main actor.
I added Builtin.buildMainActorExecutor before, but because I never
implemented it correctly in IRGen, it's not okay to use it on old
versions, so I had to introduce a new feature only for it.

The shim dispatch queue class in the Concurrency runtime is rather
awful, but I couldn't think of a reasonable alternative without
just entirely hard-coding the witness table in the runtime.
It's not ABI, at least.
2021-06-17 05:04:30 -04:00
Arnold Schwaighofer
0b8e7169e3 swift_task_future_waitImpl: Sink context intialization into slow path 2021-06-10 12:43:08 -07:00
Arnold Schwaighofer
10e3d2e3af Change _wait(_throwing) ABIs to reduce code size
Changes the task, taskGroup, asyncLet wait funtion call ABIs.

To reduce code size pass the context parameters and resumption function
as arguments to the wait function.

This means that the suspend point does not need to store parent context
and resumption to the suspend point's context.

```
  void swift_task_future_wait_throwing(
    OpaqueValue * result,
    SWIFT_ASYNC_CONTEXT AsyncContext *callerContext,
    AsyncTask *task,
    ThrowingTaskFutureWaitContinuationFunction *resume,
    AsyncContext *callContext);
```

The runtime passes the caller context to the resume entry point saving
the load of the parent context in the resumption function.

This patch adds a `Metadata *` field to `GroupImpl`. The await entry
pointer no longer pass the metadata pointer and there is a path through
the runtime where the task future is no longer available.
2021-06-08 10:41:26 -07:00
Saleem Abdulrasool
d09d4b960b Concurrency: add Windows support to SWIFT_TASK_PRINTF_DEBUG
`pthread_self` is not portable to all platforms.  Introduce a
`_swift_get_current_thread_id` to abstract over accessing the current
thread ID.  On Windows, the thread ID and thread handle are two separate
entities, unlike POSIX threads which treats them the same.
2021-06-05 14:01:02 -07:00
Saleem Abdulrasool
d39ca422ad Concurrency: remove unused variable (NFC) 2021-06-03 17:55:21 -07:00
John McCall
db3967f41d Future-proof the layout of AsyncTask. 2021-05-20 15:30:48 -04:00
Mike Ash
e4a1d2bbed [Concurrency] Expose Job's metadata as a debug variable 2021-05-13 15:57:03 -04:00
Fred Riss
bbda706393 [Concurrency] Add a unique Task ID to AsyncTask
This commit changes JobFlags storage to be 32bits, but leaves the runtime
API expressed in terms of size_t. This allows us to pack an Id in the
32bits we freed up.

The offset of this Id in the AsyncTask is an ABI constant. This way
introspection tools can extract the currently running task identifier
without any need for special APIs.
2021-05-11 08:28:17 -07:00
Konrad `ktoso` Malawski
6cbb792f92 [TaskLocals] Propagate task-locals through async{} 2021-05-11 11:06:17 +09:00
Dario Rexin
efe6973293 [Concurrency] Reduce overhead of Task.yield and Task.sleep (#37090)
* [Concurrency] Reduce overhead of Task.yield and Task.sleep

Instead of creating a new task, we create a simple job that wraps a Builtin.RawUnsafeContinuation and resumes the continuation when it is executed. The job instance is allocated on the task local allocator, meaning we don't malloc anything.

* Update stdlib/public/Concurrency/Task.swift

Co-authored-by: Konrad `ktoso` Malawski <konrad.malawski@project13.pl>

Co-authored-by: Konrad `ktoso` Malawski <konrad.malawski@project13.pl>
2021-05-10 11:51:20 -07:00
Doug Gregor
220e29d674 Reinstate "async let", with "spawn let" as an alias. 2021-05-07 00:13:56 -07:00
Max Desiatov
7be99e4cbf Merge pull request #37084 from kateinoigakukun/katei/share-fatalerror-concurrency
Rename duplicated `swift::fatalError` in `swiftRuntime` and `swift_Concurrency`.

Both `swiftRuntime` and `swift_Concurrency` had `swift::fatalError` implementation, but it causes symbol conflict with the `-static-stdlib` flag.

This patch removes one of the implementations in `swift_Concurrency` to avoid conflicts. Also added a test case to ensure that linking the Concurrency module with `-static-stdlib` works.

This issue was found by SwiftWasm test cases.
2021-05-06 09:46:15 +01:00
John McCall
cc2863c136 Merge pull request #36878 from rjmccall/custom-executors
Introduce basic support for custom executors
2021-04-30 13:54:02 -04:00
swift-ci
e152c14c0a Merge pull request #37162 from DougGregor/spawn-let 2021-04-30 02:19:16 -07:00
John McCall
186c53000d Introduce basic support for custom executors.
- Introduce an UnownedSerialExecutor type into the concurrency library.
- Create a SerialExecutor protocol which allows an executor type to
  change how it executes jobs.
- Add an unownedExecutor requirement to the Actor protocol.
- Change the ABI for ExecutorRef so that it stores a SerialExecutor
  witness table pointer in the implementation field.  This effectively
  makes ExecutorRef an `unowned(unsafe) SerialExecutor`, except that
  default actors are represented without a witness table pointer (just
  a bit-pattern).
- Synthesize the unownedExecutor method for default actors (i.e. actors
  that don't provide an unownedExecutor property).
- Make synthesized unownedExecutor properties `final`, and give them
  a semantics attribute specifying that they're for default actors.
- Split `Builtin.buildSerialExecutorRef` into a few more precise
  builtins.  We're not using the main-actor one yet, though.

Pitch thread:
  https://forums.swift.org/t/support-custom-executors-in-swift-concurrency/44425
2021-04-30 03:11:56 -04:00
Doug Gregor
5d8174da57 [Concurrency] Introduce spawn let 2021-04-29 22:42:40 -07:00
Konrad `ktoso` Malawski
6f3dac190a [TaskLocals] remove TaskLocalInheritance, we'll introduce when needed 2021-04-29 15:48:22 +09:00
Yuta Saito
709359cfab Rename duplicated swift::fatalError definition in swiftRuntime and swift_Concurrency
Both swiftRuntime and swift_Concurrency had swift::fatalError
implementation, but it causes symbol conflict when -static-stdlib.

This patch renames one of the impl in swift_Concurrency to avoid
conflict.
2021-04-28 23:52:18 +09:00
Erik Eckstein
075ad87a40 Concurrency: allocate an async-let task with its parent's stack allocator.
Also, do this for the initial slab for the task's allocator itself.
This avoids memory allocations for async-lets.
In case the async-task's memory demand does not exceed the initial slab size, it is now completely malloc-free.

The refcount bits of an async-let task are initialized to "immortal" so that ARC operations don't have an effect on the task.
2021-04-26 13:07:32 +02:00
Erik Eckstein
93367ed587 concurrency: make the startAsyncLet closure no-escaping
The closure does not escape the startAsyncLet - endAsyncLet scope. Even though it's (potentially) running on a different thread.

The substantial change in the runtime is to not call swift_release on the closure context if it's a non-escaping closure.
2021-04-20 21:57:19 +02:00
Konrad `ktoso` Malawski
d3c5ebc9b7 [AsyncLet] reimplemented with new ABI and builtins 2021-04-19 10:06:23 +09:00
Konrad `ktoso` Malawski
ba615029c7 [Concurrency] Store child record when async let child task spawned 2021-04-19 10:06:23 +09:00
Arnold Schwaighofer
ae2a4cca14 Merge pull request #36842 from aschwaighofer/fix_withCancellationHandler_arm64e_windows
Fix with cancellation handler arm64e windows
2021-04-10 14:10:12 -07:00
Arnold Schwaighofer
141634aae7 Fix withCancellationHandler on arm64e 2021-04-09 05:30:24 -07:00