Skip to content

Commit c4e4e44

Browse files
authored
Merge pull request #36390 from mikeash/concurrency-compatibility-overrides
[Concurrency] Add compatibility overrides to Concurrency library.
2 parents 88a3d5c + 6aab257 commit c4e4e44

27 files changed

+922
-248
lines changed

include/swift/Runtime/Concurrency.h

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -479,14 +479,25 @@ SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
479479
void swift_MainActor_register(HeapObject *actor);
480480

481481
/// A hook to take over global enqueuing.
482-
/// TODO: figure out a better abstraction plan than this.
483-
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
484-
void (*swift_task_enqueueGlobal_hook)(Job *job);
482+
typedef SWIFT_CC(swift) void (*swift_task_enqueueGlobal_original)(Job *job);
483+
SWIFT_EXPORT_FROM(swift_Concurrency)
484+
SWIFT_CC(swift) void (*swift_task_enqueueGlobal_hook)(
485+
Job *job, swift_task_enqueueGlobal_original original);
485486

486487
/// A hook to take over global enqueuing with delay.
487-
/// TODO: figure out a better abstraction plan than this.
488-
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
489-
void (*swift_task_enqueueGlobalWithDelay_hook)(unsigned long long delay, Job *job);
488+
typedef SWIFT_CC(swift) void (*swift_task_enqueueGlobalWithDelay_original)(
489+
unsigned long long delay, Job *job);
490+
SWIFT_EXPORT_FROM(swift_Concurrency)
491+
SWIFT_CC(swift) void (*swift_task_enqueueGlobalWithDelay_hook)(
492+
unsigned long long delay, Job *job,
493+
swift_task_enqueueGlobalWithDelay_original original);
494+
495+
/// A hook to take over main executor enqueueing.
496+
typedef SWIFT_CC(swift) void (*swift_task_enqueueMainExecutor_original)(
497+
Job *job);
498+
SWIFT_EXPORT_FROM(swift_Concurrency)
499+
SWIFT_CC(swift) void (*swift_task_enqueueMainExecutor_hook)(
500+
Job *job, swift_task_enqueueMainExecutor_original original);
490501

491502
/// Initialize the runtime storage for a default actor.
492503
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)

stdlib/public/runtime/CompatibilityOverride.cpp renamed to stdlib/public/CompatibilityOverride/CompatibilityOverride.cpp

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,15 @@
1414
//
1515
//===----------------------------------------------------------------------===//
1616

17-
#ifndef SWIFT_RUNTIME_NO_COMPATIBILITY_OVERRIDES
18-
1917
#include "CompatibilityOverride.h"
2018

21-
#include "ImageInspection.h"
19+
#ifndef SWIFT_RUNTIME_NO_COMPATIBILITY_OVERRIDES
20+
21+
#include "../runtime/ImageInspection.h"
2222
#include "swift/Runtime/Once.h"
2323
#include <assert.h>
2424
#include <atomic>
25+
#include <mach-o/getsect.h>
2526
#include <type_traits>
2627

2728
using namespace swift;
@@ -42,19 +43,38 @@ struct OverrideSection {
4243

4344
#define OVERRIDE(name, ret, attrs, ccAttrs, namespace, typedArgs, namedArgs) \
4445
Override_ ## name name;
45-
#include "CompatibilityOverride.def"
46+
#include COMPATIBILITY_OVERRIDE_INCLUDE_PATH
4647
};
4748

4849
static_assert(std::is_pod<OverrideSection>::value,
4950
"OverrideSection has a set layout and must be POD.");
5051

52+
// We only support mach-o for overrides, so the implementation of lookupSection
53+
// can be mach-o specific.
54+
#if __POINTER_WIDTH__ == 64
55+
using mach_header_platform = mach_header_64;
56+
#else
57+
using mach_header_platform = mach_header;
58+
#endif
59+
60+
extern "C" mach_header_platform *_NSGetMachExecuteHeader();
61+
static void *lookupSection(const char *segment, const char *section,
62+
size_t *outSize) {
63+
unsigned long size;
64+
auto *executableHeader = _NSGetMachExecuteHeader();
65+
uint8_t *data = getsectiondata(executableHeader, segment, section, &size);
66+
if (outSize != nullptr && data != nullptr)
67+
*outSize = size;
68+
return static_cast<void *>(data);
69+
}
70+
5171
static OverrideSection *getOverrideSectionPtr() {
5272
static OverrideSection *OverrideSectionPtr;
5373
static swift_once_t Predicate;
5474
swift_once(&Predicate, [](void *) {
5575
size_t Size;
5676
OverrideSectionPtr = static_cast<OverrideSection *>(
57-
lookupSection("__DATA", "__swift54_hooks", &Size));
77+
lookupSection("__DATA", COMPATIBILITY_OVERRIDE_SECTION_NAME, &Size));
5878
if (Size < sizeof(OverrideSection))
5979
OverrideSectionPtr = nullptr;
6080
}, nullptr);
@@ -69,6 +89,6 @@ static OverrideSection *getOverrideSectionPtr() {
6989
return nullptr; \
7090
return Section->name; \
7191
}
72-
#include "CompatibilityOverride.def"
92+
#include COMPATIBILITY_OVERRIDE_INCLUDE_PATH
7393

7494
#endif // #ifndef SWIFT_RUNTIME_NO_COMPATIBILITY_OVERRIDES
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
//===--- CompatibiltyOverride.h - Back-deploying compatibility fixes --*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// Support back-deploying compatibility fixes for newer apps running on older runtimes.
14+
//
15+
//===----------------------------------------------------------------------===//
16+
17+
#ifndef COMPATIBILITY_OVERRIDE_H
18+
#define COMPATIBILITY_OVERRIDE_H
19+
20+
#include "../runtime/Private.h"
21+
#include "swift/Runtime/Concurrency.h"
22+
#include "swift/Runtime/Metadata.h"
23+
#include "swift/Runtime/Once.h"
24+
#include <type_traits>
25+
26+
namespace swift {
27+
28+
// Macro utilities.
29+
#define COMPATIBILITY_UNPAREN(...) __VA_ARGS__
30+
#define COMPATIBILITY_CONCAT2(x, y) x##y
31+
#define COMPATIBILITY_CONCAT(x, y) COMPATIBILITY_CONCAT2(x, y)
32+
33+
// This ridiculous construct will remove the parentheses from the argument and
34+
// add a trailing comma, or will produce nothing when passed no argument. For
35+
// example:
36+
// COMPATIBILITY_UNPAREN_WITH_COMMA((1, 2, 3)) -> 1, 2, 3,
37+
// COMPATIBILITY_UNPAREN_WITH_COMMA((4)) -> 4,
38+
// COMPATIBILITY_UNPAREN_WITH_COMMA() ->
39+
#define COMPATIBILITY_UNPAREN_WITH_COMMA(x) \
40+
COMPATIBILITY_CONCAT(COMPATIBILITY_UNPAREN_ADD_TRAILING_COMMA_, \
41+
COMPATIBILITY_UNPAREN_WITH_COMMA2 x)
42+
#define COMPATIBILITY_UNPAREN_WITH_COMMA2(...) PARAMS(__VA_ARGS__)
43+
#define COMPATIBILITY_UNPAREN_ADD_TRAILING_COMMA_PARAMS(...) __VA_ARGS__,
44+
#define COMPATIBILITY_UNPAREN_ADD_TRAILING_COMMA_COMPATIBILITY_UNPAREN_WITH_COMMA2
45+
46+
// This ridiculous construct will preserve the parentheses around the argument,
47+
// or will produce an empty pair of parentheses when passed no argument. For
48+
// example:
49+
// COMPATIBILITY_PAREN((1, 2, 3)) -> (1, 2, 3)
50+
// COMPATIBILITY_PAREN((4)) -> (4)
51+
// COMPATIBILITY_PAREN() -> ()
52+
#define COMPATIBILITY_PAREN(x) \
53+
COMPATIBILITY_CONCAT(COMPATIBILITY_PAREN_, COMPATIBILITY_PAREN2 x)
54+
#define COMPATIBILITY_PAREN2(...) PARAMS(__VA_ARGS__)
55+
#define COMPATIBILITY_PAREN_PARAMS(...) (__VA_ARGS__)
56+
#define COMPATIBILITY_PAREN_COMPATIBILITY_PAREN2 ()
57+
58+
// Include path computation. Code that includes this file can write
59+
// `#include COMPATIBILITY_OVERRIDE_INCLUDE_PATH` to include the appropriate
60+
// .def file for the current library.
61+
#define COMPATIBILITY_OVERRIDE_INCLUDE_PATH_swiftRuntime \
62+
"../CompatibilityOverride/CompatibilityOverrideRuntime.def"
63+
#define COMPATIBILITY_OVERRIDE_INCLUDE_PATH_swift_Concurrency \
64+
"../CompatibilityOverride/CompatibilityOverrideConcurrency.def"
65+
66+
#define COMPATIBILITY_OVERRIDE_INCLUDE_PATH \
67+
COMPATIBILITY_CONCAT(COMPATIBILITY_OVERRIDE_INCLUDE_PATH_, \
68+
SWIFT_TARGET_LIBRARY_NAME)
69+
70+
// Compatibility overrides are only supported on Darwin.
71+
#ifndef SWIFT_RUNTIME_NO_COMPATIBILITY_OVERRIDES
72+
#if !(defined(__APPLE__) && defined(__MACH__))
73+
#define SWIFT_RUNTIME_NO_COMPATIBILITY_OVERRIDES
74+
#endif
75+
#endif
76+
77+
#ifdef SWIFT_RUNTIME_NO_COMPATIBILITY_OVERRIDES
78+
79+
// Call directly through to the original implementation when we don't support
80+
// overrides.
81+
#define COMPATIBILITY_OVERRIDE(name, ret, attrs, ccAttrs, namespace, \
82+
typedArgs, namedArgs) \
83+
attrs ccAttrs ret namespace swift_##name COMPATIBILITY_PAREN(typedArgs) { \
84+
return swift_##name##Impl COMPATIBILITY_PAREN(namedArgs); \
85+
}
86+
87+
#else // #ifdef SWIFT_RUNTIME_NO_COMPATIBILITY_OVERRIDES
88+
89+
// Override section name computation. `COMPATIBILITY_OVERRIDE_SECTION_NAME` will
90+
// resolve to string literal containing the appropriate section name for the
91+
// current library.
92+
#define COMPATIBILITY_OVERRIDE_SECTION_NAME_swiftRuntime "__swift54_hooks"
93+
#define COMPATIBILITY_OVERRIDE_SECTION_NAME_swift_Concurrency "__s_async_hook"
94+
95+
#define COMPATIBILITY_OVERRIDE_SECTION_NAME \
96+
COMPATIBILITY_CONCAT(COMPATIBILITY_OVERRIDE_SECTION_NAME_, \
97+
SWIFT_TARGET_LIBRARY_NAME)
98+
99+
// Create typedefs for function pointers to call the original implementation.
100+
#define OVERRIDE(name, ret, attrs, ccAttrs, namespace, typedArgs, namedArgs) \
101+
ccAttrs typedef ret(*Original_##name) COMPATIBILITY_PAREN(typedArgs);
102+
#include COMPATIBILITY_OVERRIDE_INCLUDE_PATH
103+
104+
// Create typedefs for override function pointers.
105+
#define OVERRIDE(name, ret, attrs, ccAttrs, namespace, typedArgs, namedArgs) \
106+
ccAttrs typedef ret (*Override_##name)(COMPATIBILITY_UNPAREN_WITH_COMMA( \
107+
typedArgs) Original_##name originalImpl);
108+
#include COMPATIBILITY_OVERRIDE_INCLUDE_PATH
109+
110+
// Create declarations for getOverride functions.
111+
#define OVERRIDE(name, ret, attrs, ccAttrs, namespace, typedArgs, namedArgs) \
112+
Override_ ## name getOverride_ ## name();
113+
#include COMPATIBILITY_OVERRIDE_INCLUDE_PATH
114+
115+
/// Used to define an override point. The override point #defines the appropriate
116+
/// OVERRIDE macro from CompatibilityOverride.def to this macro, then includes
117+
/// the file to generate the override points. The original implementation of the
118+
/// functionality must be available as swift_funcNameHereImpl.
119+
#define COMPATIBILITY_OVERRIDE(name, ret, attrs, ccAttrs, namespace, \
120+
typedArgs, namedArgs) \
121+
attrs ccAttrs ret namespace swift_##name COMPATIBILITY_PAREN(typedArgs) { \
122+
static Override_##name Override; \
123+
static swift_once_t Predicate; \
124+
swift_once( \
125+
&Predicate, [](void *) { Override = getOverride_##name(); }, nullptr); \
126+
if (Override != nullptr) \
127+
return Override(COMPATIBILITY_UNPAREN_WITH_COMMA(namedArgs) \
128+
swift_##name##Impl); \
129+
return swift_##name##Impl COMPATIBILITY_PAREN(namedArgs); \
130+
}
131+
132+
#endif // #else SWIFT_RUNTIME_NO_COMPATIBILITY_OVERRIDES
133+
134+
} /* end namespace swift */
135+
136+
#endif /* COMPATIBILITY_OVERRIDE_H */

0 commit comments

Comments
 (0)