Commit Graph

5 Commits

Author SHA1 Message Date
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
19a7fa6625 [SILGen] Put actor data-race checking behind a flag.
Introduce flags `-enable-actor-data-race-checks` and
`-disable-actor-data-race-checks` to enable/disable emission of code
that checks that we are on the correct actor. Default to `false` for
now but make it easy to enable in the future.
2021-04-20 22:30:53 -07:00
Doug Gregor
4d6f07ee66 [SILGen] Don't emit executor checks for @_unsafeMainActor closures.
Narrow fix for rdar://76860623.
2021-04-20 22:30:53 -07:00
Doug Gregor
24399546f7 [Concurrency] Don't check for data races in an actor's deinit.
An actor's deinit can be invoked from any thread, and does not
(cannot!) synchronize to the actor. However, because "self" is
by definition unique and cannot escape, don't perform data race
checking in it or any local functions/closures within the initializer.

This is an imperfect approximation, because one could introduce a data
race by invoking a concurrent algorithm on "self" that does not
escape the closure but subverts @Sendable checking and concurrently
accesses actor state. However, for the moment we accept this false
negative because the false positives from performing this checking are
much more prevalent.
2021-04-12 21:39:54 -07:00
Doug Gregor
e77a27e8ed [Concurrency] Introduce runtime detection of data races.
Through various means, it is possible for a synchronous actor-isolated
function to escape to another concurrency domain and be called from
outside the actor. The problem existed previously, but has become far
easier to trigger now that `@escaping` closures and local functions
can be actor-isolated.

Introduce runtime detection of such data races, where a synchronous
actor-isolated function ends up being called from the wrong executor.
Do this by emitting an executor check in actor-isolated synchronous
functions, where we query the executor in thread-local storage and
ensure that it is what we expect. If it isn't, the runtime complains.
The runtime's complaints can be controlled with the environment
variable `SWIFT_UNEXPECTED_EXECUTOR_LOG_LEVEL`:

  0 - disable checking
  1 - warn when a data race is detected
  2 - error and abort when a data race is detected

At an implementation level, this introduces a new concurrency runtime
entry point `_checkExpectedExecutor` that checks the given executor
(on which the function should always have been called) against the
executor on which is called (which is in thread-local storage). There
is a special carve-out here for `@MainActor` code, where we check
against the OS's notion of "main thread" as well, so that `@MainActor`
code can be called via (e.g.) the Dispatch library's
`DispatchQueue.main.async`.

The new SIL instruction `extract_executor` performs the lowering of an
actor down to its executor, which is implicit in the `hop_to_executor`
instruction. Extend the LowerHopToExecutor pass to perform said
lowering.
2021-04-12 15:19:51 -07:00