Commit Graph

630 Commits

Author SHA1 Message Date
John McCall
2ff171921e Fix -latomic condition, include android 2021-07-20 16:21:44 -04:00
Doug Gregor
e2d97af4bf Add availability gating for async function and actor type definitions.
Implements rdar://80098709.
2021-07-20 11:28:23 -07:00
John McCall
871ee794bc Link the concurrency runtime against libatomic on Linux.
We mostly get away without this because we're fairly disciplined
about using constant memory orderings, and apparently that's
usually good enough to get inline accesses and avoid needing to
link atomic.  However, we have a few places with the task status
atomic that use a non-constant load ordering with load and
compare_exchange_weak, and my recent change to make that atomic
a double-word was apparently sufficient on some (but not all)
Linux distributions to get the compiler to call the runtime
function.  Regardless, we shouldn't be playing around in the
margins here: Linux requires us to link libatomic, so we should.
2021-07-20 01:57:26 -04: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
48b8780e58 Merge pull request #38386 from rjmccall/track-task-is-running
Track whether a task is actively running
2021-07-15 16:22:44 -04:00
Konrad `ktoso` Malawski
716a0255c0 [Distributed] Move to ActorIdentity protocol (#38362) 2021-07-15 21:13:55 +09:00
John McCall
264e4ace12 Clear the active task immediately when suspending. 2021-07-14 20:24:01 -04:00
John McCall
bd451f9f08 Remove the hooking for swift_task_getCurrent().
This is very performance-sensitive and unreasonable to change.
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
John McCall
930c72aee2 Fix DispatchQueueShim to work correctly in a debug build.
The self object isn't actually a Swift object, so we can neither
do class dispatch on it nor retain it with swift_retain.

Some of the credit goes to Mike Ash on this one.  All the
blame is mine, of course.
2021-07-14 15:50:10 -04:00
Andrew Trick
982b47d829 Add Builtin.hopToActor to the feature list.
This builtin never occurs in @inlinable code. But apparently we still
need to add a language feature for every builtin. This must allow
older compilers to reparse the library source (though I don't know why
that would ever happen!)

Fixes rdar://80525569 error: module 'Builtin' has no member named 'hopToActor')
2021-07-13 16:28:38 -07:00
Philippe Hausler
6a80196da3 Allow AsyncSequence operators to be inlined in their construction (#38310) 2021-07-09 09:23:39 -07:00
Mike Ash
9d3cd5ea7e Merge pull request #38290 from mikeash/frame-pointer-mask-symbol
[Concurrency] Add an exported symbol on Darwin that contains the frame pointer flag bit for async frames.
2021-07-09 09:36:32 -04:00
Doug Gregor
57e22bb92f Merge pull request #38306 from DougGregor/structured-concurrency-review-4
[SE-0304] Align Task API implementation with the fourth revision of the proposal
2021-07-08 22:07:42 -07:00
Doug Gregor
121e34fa04 Reimplement Task.sleep(nanoseconds:) without the raciness.
The prior implementation of `Task.sleep()` effectively had two
different atomic words to capture the state, which could lead to cases
where cancelling before a sleep operation started would fail to
throw `CancellationError`. Reimplement the logic for the cancellable
sleep with a more traditional lock-free approach by
packing all of the state information into a single word, where we
always load, figure out what to do, then compare-and-swap.
2021-07-08 17:26:55 -07:00
Doug Gregor
1a024e96c8 Remove UnownedJob.run(). It never did anything anyway 2021-07-08 13:23:42 -07:00
Doug Gregor
4a0723f68c [SE-0304] Add UnsafeCurrentTask.cancel(). 2021-07-08 13:22:33 -07:00
Doug Gregor
7ba63cf53c [SE-0304] Clarify documentation of Task.sleep(nanoseconds:) slightly 2021-07-08 13:21:56 -07:00
Doug Gregor
59d1e61ac4 [SE-0304] Implement cancellable Task.sleep(nanoseconds:). 2021-07-08 09:46:07 -07:00
Doug Gregor
20c8bd12e8 [SE-0304] Add (Throwing)?TaskGroup.waitForAll()
Do this as a staged change to the ABI, introducing an underscored
`@usableFromInline` implementation to the ABI that we can rely on
later, and an `@_alwaysEmitIntoClient` version we can inline now.
2021-07-07 20:49:33 -07:00
Doug Gregor
b7e2136e4a [SE-0304] Rename Task.yield() to Task.suspend() 2021-07-07 20:30:57 -07:00
Doug Gregor
f692faea6a [SE-0304] Rename TaskPriority.default to medium 2021-07-07 18:06:52 -07:00
Doug Gregor
04dd840ba3 [SE-0304] Replace the async operations in (Throwing)TaskGroup with addTask 2021-07-07 17:04:52 -07: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
Mike Ash
2d6a6927e9 Merge pull request #38162 from mikeash/concurrency-constant-pthread-keys
[Concurrency] Use pthread_specific for thread-local storage on Darwin.
2021-07-02 13:22:15 -04:00
Konrad `ktoso` Malawski
bb16d734f3 [Concurrency] add TaskLocal::Item:iisParentPointer for cleaner API 2021-07-02 11:53:50 +09:00
Konrad `ktoso` Malawski
cd0708b315 [Concurrency] task local must not copy null values 2021-07-02 11:36:20 +09:00
Mike Ash
190d3fd22e [Concurrency] Use pthread_specific for thread-local storage on Darwin.
The pthread_specific APIs are better than C++ thread_local storage on Darwin since we can use Swift's reserved pthread keys there.

rdar://79504652
2021-06-29 16:56:59 -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
swift-ci
00a1e9119c Merge pull request #38097 from CodaFi/checkerboard 2021-06-24 23:35:39 -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
Robert Widmann
15a552f11e [Gardening] Match Parameter Names To Doc Comments
Keep these names in sync so the documentation for these parameters
actually shows up in the IDE.
2021-06-24 20:30:44 -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
ec367ce3b6 Drop overridable entry point for swift_asyncLet_start.
This entry point is a small shim over `swift_task_create_common`, which
is overridable. We don't need a separate override point here.
2021-06-24 07:53:19 -07:00
Doug Gregor
819615eab1 Make Swift task-creation entry points always-emit-into-client.
The `swift_task_create` entry point is our general runtime ABI for
launching tasks. Make the various Swift APIs sitting on top of it
always-emit-into-client to take them out of the ABI. This reduces the
number of ABI entry points and allows us to make more ABI-compatible
changes to the Swift side.
2021-06-24 07:53:19 -07:00
Doug Gregor
ba0644cf81 Move priority adjustments for async task creation into the runtime.
We're not actually performing the adjustments at the moment due to an
unrelated bug, and will want to perform them within
`swift_task_create_common` based on inheritContext and the given
priority.
2021-06-24 07:53:18 -07:00
Doug Gregor
7def279cdb Drop task options from the createAsyncTask SIL builtin.
We'll keep the task options entirely as a contract between IRGen and
the concurrency runtime, so Swift code need not deal with them.
2021-06-24 07:53:18 -07:00
Doug Gregor
e7e922ea77 Introduce a createAsyncTaskInGroup SIL builtin.
Rather than using group task options constructed from the Swift parts
of the _Concurrency library and passed through `createAsyncTask`'s
options, introduce a separate builtin that always takes a group. Move
the responsibility for creating the options structure into IRGen, so
we don't need to expose the TaskGroupTaskOptionRecord type in Swift.
2021-06-24 07:53:18 -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
29b45a3087 Use withUnsafePointer(to:) rather than withUnsafeBytes(of:) 2021-06-24 07:53:18 -07:00
Doug Gregor
a4af1a71f6 Use withUnsafeBytes(of:) properly for getting the address of a local variable 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