Commit Graph

129 Commits

Author SHA1 Message Date
Konrad `ktoso` Malawski
e37b998c56 implement simple rethrowing logic, however body throw always wins 2023-01-05 21:42:20 +09:00
Konrad `ktoso` Malawski
2eaaf352de complete impl, except body throws 2023-01-05 20:13:05 +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
Konrad `ktoso` Malawski
1a3403524c [Concurrency] Optimize Void task group, to not store completed tasks anymore 2023-01-05 16:19:05 +09:00
Erik Eckstein
525550644c concurrency runtime: fix unused variable/label warnings 2022-11-21 19:50:39 +01: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
Rokhini Prabhu
a606892155 Task group children should be executed on parent task at time of await 2022-09-01 10:02:25 -07:00
Alastair Houghton
0e9318cec5 [Threading] Put everything through git clang-format.
Just formatting changes.

rdar://90776105
2022-06-07 07:39:53 +01:00
Alastair Houghton
f5bdb858e0 [Threading] Create new threading library and use it.
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
2022-06-07 07:39:51 +01:00
Alastair Houghton
0cf687aa2b [Build][Runtime] Replace SWIFT_STDLIB_SINGLE_THREADED_RUNTIME.
SWIFT_STDLIB_SINGLE_THREADED_RUNTIME is too much of a blunt instrument here.
It covers both the Concurrency runtime and the rest of the runtime, but we'd
like to be able to have e.g. a single-threaded Concurrency runtime while
the rest of the runtime is still thread safe (for instance).

So: rename it to SWIFT_STDLIB_SINGLE_THREADED_CONCURRENCY and make it just
control the Concurrency runtime, then add a SWIFT_STDLIB_THREADING_PACKAGE
setting at the CMake/build-script level, which defines
SWIFT_STDLIB_THREADING_xxx where xxx depends on the chosen threading package.

This is especially useful on systems where there may be a choice of threading
package that you could use.

rdar://90776105
2022-06-07 07:39:51 +01:00
Alex Hoppen
4aa2bbbf06 Revert "Merge pull request #42447 from al45tair/eng/PR-90776105"
This reverts commit 8bcb71140f, reversing
changes made to c4dd271d36.
2022-06-02 18:03:23 +02:00
Alastair Houghton
b5bd267ff1 [Threading] Put everything through git clang-format.
Just formatting changes.

rdar://90776105
2022-05-24 14:57:41 +01:00
Alastair Houghton
63a09007a1 [Threading] Create new threading library and use it.
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
2022-05-24 14:57:39 +01:00
Alastair Houghton
dadcb04ae2 [Build][Runtime] Replace SWIFT_STDLIB_SINGLE_THREADED_RUNTIME.
SWIFT_STDLIB_SINGLE_THREADED_RUNTIME is too much of a blunt instrument here.
It covers both the Concurrency runtime and the rest of the runtime, but we'd
like to be able to have e.g. a single-threaded Concurrency runtime while
the rest of the runtime is still thread safe (for instance).

So: rename it to SWIFT_STDLIB_SINGLE_THREADED_CONCURRENCY and make it just
control the Concurrency runtime, then add a SWIFT_STDLIB_THREADING_PACKAGE
setting at the CMake/build-script level, which defines
SWIFT_STDLIB_THREADING_xxx where xxx depends on the chosen threading package.

This is especially useful on systems where there may be a choice of threading
package that you could use.

rdar://90776105
2022-05-24 14:57:38 +01:00
Saleem Abdulrasool
a8b0ee24dc runtime: blanket application of namespacing and inclusion of new
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.
2022-04-14 14:21:12 -07:00
Rokhini Prabhu
a5fa349f88 Merge pull request #41281 from apple/rokhinip/88600541-task-priority-escalation-arm64_32
Task Escalation support on arm64_32 Apple platforms
2022-02-10 17:02:38 -08:00
Rokhini Prabhu
6beb11ed7d Rename flagAsEnqueuedOnExecutor to flagAsAndEnqueueOnExecutor to reflect
what it actually does.

Radar-Id: rdar://problem/88600541
2022-02-10 11:50:31 -08:00
Kuba (Brecka) Mracek
a395db680a [Concurrency] Avoid #include-ing dlfcn.h when not available (#41276) 2022-02-09 09:41:04 -08: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
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
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
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
Rokhini Prabhu
835f274183 Make sure that cancelling a task group does not invoke cancellation
handler of parent task that created the group

Change comment in TaskGroup.swift to enforce that only parent task can
call cancelAll on the group

Add tests to verify mutating of task group in child tasks will fail

Radar-Id: rdar://problem/86346865
2021-12-17 18:35:39 -08:00
Alastair Houghton
0e5a620917 Merge pull request #40331 from al45tair/problem/84393438
[Runtime] Don't use threading APIs when building single threaded.
2021-12-14 22:19:20 +00: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
Alastair Houghton
e08fd330f1 [Runtime] Tidy up locking/unlocking conditionals.
Rather than conditionalising all the calls to mutex.lock() and mutex.unlock(),
centralise the logic.

rdar://84393438
2021-12-02 15:02:06 +00:00
Alastair Houghton
2d335062e2 [Runtime] Don't use threading related APIs when building single threaded.
Mostly this consists of #if-ing out code that we don't need when running
single threaded.

rdar://84393438
2021-11-30 16:18:26 +00:00
Kavon Farvardin
69e80a1201 use compare_exchange_strong to protect agianst spurious failures
A `compare_exchange_weak` can spuriously return false, regardless of
whether a concurrent access happened. This was causing a null-pointer
dereference in TaskGroupImpl::poll in a narrow circumstance.

The dereference failure only appears when using the `arm64`
slice of the runtime library, since Clang will use `ldxr/stxr` for
synchronization on such targets. The weak form does not retry on a
spurious failure, but the strong version will.

resolves rdar://84192672
2021-11-18 16:37:04 -08: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
Konrad `ktoso` Malawski
11943005c3 [Concurrency] Call TaskGroupImpl destructor; stop leaking groups 2021-09-14 13:41:44 +09:00
Konrad `ktoso` Malawski
f336404ae9 [Concurrency] TaskGroup children remove their records as they complete
If we didn't do this (and we didn't), the tasks get released as we
perform the next() impl, and move the value from the ready task to the
waiting task. Then, the ready task gets destroyed.

But as the task group exists, it performs a cancelAll() and that
iterates over all records. Those records were not removed previously
(!!!) which meant we were pointing at now deallocated tasks.

Previously this worked because we didn't deallocate the tasks, so they
leaked, but we didn't crash. With the memory leak fixed, this began to
crash since we'd attempt to cancel already destroyed tasks.

Solution:
- Remove task records whenever they complete a waiting task.
- This can ONLY be done by the "group owning task" itself, becuause
  the contract of ONLY this task being allowed to modify records. o
  It MUST NOT be done by the completing tasks as they complete, as it
  would race with the owning task modifying this linked list of child
  tasks in the group record.
2021-09-04 20:09:55 +09: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
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
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
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
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
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
Konrad `ktoso` Malawski
dd10132b12 [Concurrency] Cancelled group should only spawn already cancelled tasks 2021-06-24 09:22:45 +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
Saleem Abdulrasool
420e85d634 Concurrency: silence some -Wmicrosoft-extension warnings (NFC)
Explicitly namespace the friend type to avoid the warning.
2021-06-03 17:53:54 -07:00
Konrad `ktoso` Malawski
ba615029c7 [Concurrency] Store child record when async let child task spawned 2021-04-19 10:06:23 +09:00
swift-ci
63b4cf0c9a Merge pull request #36689 from apple/tsan-task-groups 2021-04-09 18:23:38 -07:00
Julian Lettner
29107180e5 Teach TSan about TaskGroups
`TaskGroup::offer(completedTask)`:
* Called from `AsyncTask::completeFuture()` which already takes care of
  `release(completedTask)`.  No additional edge is required if no task
  is waiting and completed task is stored so it can be retrieved by
  `group.poll()`.
* If group has waiting task, it will be dequeued and scheduled, add
  `acquire(waitingTask)`.

`TaskGroupImpl::poll(waitingTask)`:
* If no pending tasks, do nothing.
* If returning finished task, `acquire(finishedTask)`.
* If enqueuing waiting task, `release(waitingTask)`.

Note: `release()` should go before, and `acquire()` after the annotated
      synchronization operation.

Radar-Id: rdar://75910632
2021-04-09 14:44:53 -07:00