Commit Graph

59 Commits

Author SHA1 Message Date
Mike Ash
fe7e13bba5 [Runtime][IRGen] Sign type context descriptor pointers.
Ensure that context descriptor pointers are signed in the runtime by putting the ptrauth_struct attribute on the types.

We use the new __builtin_ptrauth_struct_key/disc to conditionally apply ptrauth_struct to TrailingObjects based on the signing of the base type, so that pointers to TrailingObjects get signed when used with a context descriptor pointer.

We add new runtime entrypoints that take signed pointers where appropriate, and have the compiler emit calls to the new entrypoints when targeting a sufficiently new OS.

rdar://111480914
2023-07-07 18:10:35 -04:00
Evan Wilde
1bd1c468a0 Concurrency: Task.startOnMainActor
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.
2023-03-06 13:33:22 -08:00
Evan Wilde
841fda5dbe Add asyncMainDrainQueue hook
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".
2023-03-01 22:16:23 -08:00
Evan Wilde
ec7a926148 Fix asyncMainDrainQueue noreturn warning
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`.
2023-03-01 17:08:41 -08:00
Evan Wilde
00af28cd6e Merge pull request #63705 from etcwilde/ewilde/swift5ever-compat-override-sections 2023-02-16 17:28:56 -08:00
Evan Wilde
f023bdeee9 Base override section names on swift version
This patch automates maintaining the right compatibility override
section names so we don't need to remember to update them by hand with
each version.

The expansions look like
'"__swift" "5" "9" "_hooks"' and
'"__s" "5" "9" "async_hook"'.

Note: The section names can only grow to be 16 characters long. If we
      see explosions regarding these names, that could be why.
2023-02-15 19:43:57 -08:00
Rokhini Prabhu
62852262b4 Remove dead code with task nearest deadline logic
Radar-Id: rdar://problem/88093007
2023-02-07 14:34:29 -08:00
Konrad `ktoso` Malawski
6f38910058 DiscardingTaskGroup now shares some implementation with "Accumulating" TaskGroup 2023-01-09 11:35:04 +09:00
Konrad `ktoso` Malawski
e37b998c56 implement simple rethrowing logic, however body throw always wins 2023-01-05 21:42:20 +09:00
Konrad `ktoso` Malawski
7ac5b407a6 move to DiscardingTaskGroup 2023-01-05 16:19:05 +09:00
Konrad `ktoso` Malawski
2652862229 prepare for cancellation handling 2023-01-05 16:19:05 +09:00
Konrad `ktoso` Malawski
54dec38a34 initial complete impl 2023-01-05 16:19:05 +09:00
Konrad `ktoso` Malawski
f8b85015c1 prepare flags
wip on options

implement discardResults as a flag passed to grout init
2023-01-05 16:19:05 +09:00
John McCall
7f737d235d Synchronize with cancellation when removing a task from a task group
We were detaching the child by just modifying the list, but the cancellation path was assuming that that would not be done without holding the task status lock.

This patch just fixes the current runtime; the back-deployment side is complicated.

Fixes rdar://88398824
2022-10-29 00:10:28 -04:00
Doug Gregor
3c892a153c Update runtime compatibility hooks to version 5.8 2022-07-05 10:07:52 -07:00
Rokhini Prabhu
66d4af0b01 Task priority escalation on Apple platforms
A task can be in one of 4 states over its lifetime:

    (a) suspended
    (b) enqueued
    (c) running
    (d) completed

This change provides priority inversion avoidance support if a task gets
escalated when it is in state (a), (c), (d).

Radar-Id: rdar://problem/76127624
2022-02-07 16:34:46 -08:00
Joey
44728a98eb Update CompatibilityOverride.cpp 2022-02-01 00:34:54 +08:00
Joey
74eccd3b3d Fix typo in CompatibilityOverride.h 2022-01-30 20:38:03 +08:00
Joey
67ee2f69af Fix typo in CompatibilityOverride.cpp 2022-01-30 20:37:58 +08:00
Rokhini Prabhu
e35eba06d2 Remove old addChild and detachChild stuff from files
Radar-Id: rdar://problem/86347801
2021-12-31 03:23:52 -08: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
Kuba (Brecka) Mracek
b48e148fed Merge pull request #40204 from kubamracek/swift_stdlib_support_back_deployment
Rename SWIFT_ENABLE_COMPATIBILITY_OVERRIDES -> SWIFT_STDLIB_SUPPORT_BACK_DEPLOYMENT and avoid building more back-deployment stdlib parts when not set
2021-12-15 07:03:56 -08:00
Rokhini
cb17173c22 Merge pull request #40520 from apple/rokhinip/synchronize-group-child-creation-and-cancellation
Synchronize adding a child task to a TaskGroup with parent task's TaskStatusRecord lock
2021-12-15 05:45:37 +08:00
Kuba Mracek
d441f85358 Rename SWIFT_ENABLE_COMPATIBILITY_OVERRIDES -> SWIFT_STDLIB_SUPPORT_BACK_DEPLOYMENT and avoid building more back-deployment stdlib parts when not set 2021-12-14 09:59:44 -08:00
Rokhini Prabhu
4bcaa2e7d9 There is no inherent synchronization in the TaskGroupStatusRecord so
when a task is adding adding new children to a task group, we need to
synchronize with the task status record lock of the parent task that has the
task group, to prevent races with concurrent cancellation and escalation.

Radar-Id: rdar://problem/86311782
2021-12-10 20:17:24 -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
Mishal Shah
afdae45cd2 Update the Swift runtime hooks version to 5.6 2021-10-05 16:46:31 -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
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
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
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
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
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
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
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
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
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
Konrad `ktoso` Malawski
82e91b7785 [TaskLocals] Enable sync functions to bind task-locals; Keep Storage in TLS 2021-05-11 11:06:16 +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
swift-ci
e152c14c0a Merge pull request #37162 from DougGregor/spawn-let 2021-04-30 02:19:16 -07: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
Konrad `ktoso` Malawski
58ea749304 [TaskLocal] Crash on inapropriate use within task group 2021-04-29 15:48:22 +09:00
Konrad `ktoso` Malawski
3d96d05546 [TaskLocals] property wrapper keys 2021-04-29 15:48:09 +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