Skip to content

Commit 29db1ec

Browse files
authored
Merge pull request #80644 from mikeash/fix-task-sizes-6.2
[6.2][Concurrency] Fix task status and private storage sizes.
2 parents c689d74 + 7edc799 commit 29db1ec

File tree

13 files changed

+220
-48
lines changed

13 files changed

+220
-48
lines changed

include/swift/ABI/Task.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -301,15 +301,15 @@ class AsyncTask : public Job {
301301
#if SWIFT_CONCURRENCY_ENABLE_PRIORITY_ESCALATION && SWIFT_POINTER_IS_4_BYTES
302302
static constexpr size_t ActiveTaskStatusSize = 4 * sizeof(void *);
303303
#else
304-
static constexpr size_t ActiveTaskStatusSize = 4 * sizeof(void *);
304+
static constexpr size_t ActiveTaskStatusSize = 2 * sizeof(void *);
305305
#endif
306306

307307
// Private storage is currently 6 pointers, 16 bytes of non-pointer data,
308308
// the ActiveTaskStatus, and a RecursiveMutex.
309309
static constexpr size_t PrivateStorageSize =
310310
6 * sizeof(void *) + 16 + ActiveTaskStatusSize + sizeof(RecursiveMutex);
311311

312-
void *Storage[PrivateStorageSize];
312+
char Storage[PrivateStorageSize];
313313

314314
/// Initialize this storage during the creation of a task.
315315
void initialize(JobPriority basePri);

include/swift/RemoteInspection/ReflectionContext.h

+39-13
Original file line numberDiff line numberDiff line change
@@ -134,11 +134,13 @@ class ReflectionContext
134134
std::vector<std::tuple<RemoteAddress, RemoteAddress>> dataRanges;
135135

136136
bool setupTargetPointers = false;
137+
typename super::StoredPointer target_asyncTaskMetadata = 0;
137138
typename super::StoredPointer target_non_future_adapter = 0;
138139
typename super::StoredPointer target_future_adapter = 0;
139140
typename super::StoredPointer target_task_wait_throwing_resume_adapter = 0;
140141
typename super::StoredPointer target_task_future_wait_resume_adapter = 0;
141142
bool supportsPriorityEscalation = false;
143+
typename super::StoredSize asyncTaskSize = 0;
142144

143145
public:
144146
using super::getBuilder;
@@ -1816,16 +1818,32 @@ class ReflectionContext
18161818
ChildTask = RecordObj->FirstChild;
18171819
}
18181820

1819-
while (ChildTask) {
1821+
while (ChildTask && ChildTaskLoopCount++ < ChildTaskLimit) {
1822+
// Read the child task.
1823+
auto ChildTaskObj = readObj<AsyncTaskType>(ChildTask);
1824+
if (!ChildTaskObj)
1825+
return {std::string("found unreadable child task pointer"), Info};
1826+
18201827
Info.ChildTasks.push_back(ChildTask);
18211828

1822-
StoredPointer ChildFragmentAddr = ChildTask + sizeof(*AsyncTaskObj);
1823-
auto ChildFragmentObj =
1824-
readObj<ChildFragment<Runtime>>(ChildFragmentAddr);
1825-
if (ChildFragmentObj)
1826-
ChildTask = ChildFragmentObj->NextChild;
1827-
else
1829+
swift::JobFlags ChildJobFlags(AsyncTaskObj->Flags);
1830+
if (ChildJobFlags.task_isChildTask()) {
1831+
if (asyncTaskSize == 0)
1832+
return {std::string("target async task size unknown, unable to "
1833+
"iterate child tasks"),
1834+
Info};
1835+
1836+
StoredPointer ChildFragmentAddr = ChildTask + asyncTaskSize;
1837+
auto ChildFragmentObj =
1838+
readObj<ChildFragment<Runtime>>(ChildFragmentAddr);
1839+
if (ChildFragmentObj)
1840+
ChildTask = ChildFragmentObj->NextChild;
1841+
else
1842+
ChildTask = 0;
1843+
} else {
1844+
// No child fragment, so we're done iterating.
18281845
ChildTask = 0;
1846+
}
18291847
}
18301848

18311849
RecordPtr = RecordObj->Parent;
@@ -1927,7 +1945,7 @@ class ReflectionContext
19271945
if (setupTargetPointers)
19281946
return;
19291947

1930-
auto getFunc = [&](const std::string &name) -> StoredPointer {
1948+
auto getPointer = [&](const std::string &name) -> StoredPointer {
19311949
auto Symbol = getReader().getSymbolAddress(name);
19321950
if (!Symbol)
19331951
return 0;
@@ -1936,19 +1954,27 @@ class ReflectionContext
19361954
return 0;
19371955
return Pointer->getResolvedAddress().getAddressData();
19381956
};
1957+
target_asyncTaskMetadata =
1958+
getPointer("_swift_concurrency_debug_asyncTaskMetadata");
19391959
target_non_future_adapter =
1940-
getFunc("_swift_concurrency_debug_non_future_adapter");
1941-
target_future_adapter = getFunc("_swift_concurrency_debug_future_adapter");
1942-
target_task_wait_throwing_resume_adapter =
1943-
getFunc("_swift_concurrency_debug_task_wait_throwing_resume_adapter");
1960+
getPointer("_swift_concurrency_debug_non_future_adapter");
1961+
target_future_adapter =
1962+
getPointer("_swift_concurrency_debug_future_adapter");
1963+
target_task_wait_throwing_resume_adapter = getPointer(
1964+
"_swift_concurrency_debug_task_wait_throwing_resume_adapter");
19441965
target_task_future_wait_resume_adapter =
1945-
getFunc("_swift_concurrency_debug_task_future_wait_resume_adapter");
1966+
getPointer("_swift_concurrency_debug_task_future_wait_resume_adapter");
19461967
auto supportsPriorityEscalationAddr = getReader().getSymbolAddress(
19471968
"_swift_concurrency_debug_supportsPriorityEscalation");
19481969
if (supportsPriorityEscalationAddr) {
19491970
getReader().readInteger(supportsPriorityEscalationAddr,
19501971
&supportsPriorityEscalation);
19511972
}
1973+
auto asyncTaskSizeAddr =
1974+
getReader().getSymbolAddress("_swift_concurrency_debug_asyncTaskSize");
1975+
if (asyncTaskSizeAddr) {
1976+
getReader().readInteger(asyncTaskSizeAddr, &asyncTaskSize);
1977+
}
19521978

19531979
setupTargetPointers = true;
19541980
}

include/swift/RemoteInspection/RuntimeInternals.h

+2-5
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ template <typename Runtime> struct ConformanceCacheEntry {
6464

6565
template <typename Runtime>
6666
struct HeapObject {
67-
typename Runtime::StoredPointer Metadata;
67+
typename Runtime::StoredSignedPointer Metadata;
6868
typename Runtime::StoredSize RefCounts;
6969
};
7070

@@ -131,10 +131,7 @@ struct AsyncTask: Job<Runtime> {
131131
// On 64-bit, there's a Reserved64 after ResumeContext.
132132
typename Runtime::StoredPointer ResumeContextAndReserved[
133133
sizeof(typename Runtime::StoredPointer) == 8 ? 2 : 1];
134-
union {
135-
AsyncTaskPrivateStorage<Runtime, ActiveTaskStatus> PrivateStorage;
136-
typename Runtime::StoredPointer PrivateStorageRaw[14];
137-
};
134+
AsyncTaskPrivateStorage<Runtime, ActiveTaskStatus> PrivateStorage;
138135
};
139136

140137
template <typename Runtime>

stdlib/private/SwiftReflectionTest/SwiftReflectionTest.swift

+10
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ public enum InstanceKind: UInt8 {
209209
case Enum
210210
case EnumValue
211211
case AsyncTask
212+
case LogString
212213
}
213214

214215
/// Represents a section in a loaded image in this process.
@@ -642,6 +643,15 @@ public func reflect(asyncTask: UInt) {
642643
reflect(instanceAddress: asyncTask, kind: .AsyncTask)
643644
}
644645

646+
/// Log a string to the test's output. Use instead of print, which gets
647+
/// captured by the parent and read as commands.
648+
public func reflectionLog(str: String) {
649+
str.withCString {
650+
let addr = UInt(bitPattern: $0)
651+
reflect(instanceAddress: addr, kind: .LogString);
652+
}
653+
}
654+
645655
/// Call this function to indicate to the parent that there are
646656
/// no more instances to look at.
647657
public func doneReflecting() {

stdlib/public/Concurrency/Debug.h

+4
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ const void *const _swift_concurrency_debug_jobMetadata;
3434
SWIFT_EXPORT_FROM(swift_Concurrency)
3535
const void *const _swift_concurrency_debug_asyncTaskMetadata;
3636

37+
/// The size of an AsyncTask, in bytes.
38+
SWIFT_EXPORT_FROM(swift_Concurrency)
39+
const size_t _swift_concurrency_debug_asyncTaskSize;
40+
3741
/// A fake metadata pointer placed at the start of async task slab allocations.
3842
SWIFT_EXPORT_FROM(swift_Concurrency)
3943
const void *const _swift_concurrency_debug_asyncTaskSlabMetadata;

stdlib/public/Concurrency/Task.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,8 @@ const void *const swift::_swift_concurrency_debug_jobMetadata =
440440
const void *const swift::_swift_concurrency_debug_asyncTaskMetadata =
441441
static_cast<Metadata *>(&taskHeapMetadata);
442442

443+
const size_t swift::_swift_concurrency_debug_asyncTaskSize = sizeof(AsyncTask);
444+
443445
const HeapMetadata *swift::jobHeapMetadataPtr =
444446
static_cast<HeapMetadata *>(&jobHeapMetadata);
445447
const HeapMetadata *swift::taskHeapMetadataPtr =

stdlib/tools/swift-reflection-test/messages.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,6 @@ typedef enum InstanceKind {
2929
Closure,
3030
Enum,
3131
EnumValue,
32-
AsyncTask
32+
AsyncTask,
33+
LogString,
3334
} InstanceKind;

stdlib/tools/swift-reflection-test/swift-reflection-test.c

+97-13
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <assert.h>
2424
#include <errno.h>
2525
#include <inttypes.h>
26+
#include <stdarg.h>
2627
#include <stdint.h>
2728
#include <stdio.h>
2829
#include <stdlib.h>
@@ -84,6 +85,20 @@ static void errnoAndExit(const char *message) {
8485
#define DEBUG_LOG(fmt, ...) (void)0
8586
#endif
8687

88+
#ifdef __clang__
89+
__attribute((__format__(__printf__, 2, 3)))
90+
#endif
91+
static void
92+
indented_printf(unsigned indentLevel, const char *fmt, ...) {
93+
for (unsigned i = 0; i < indentLevel; i++)
94+
fputs(" ", stdout);
95+
96+
va_list args;
97+
va_start(args, fmt);
98+
vprintf(fmt, args);
99+
va_end(args);
100+
}
101+
87102
static const size_t ReadEnd = 0;
88103
static const size_t WriteEnd = 1;
89104

@@ -774,10 +789,40 @@ int reflectEnumValue(SwiftReflectionContextRef RC,
774789

775790
}
776791

777-
int reflectAsyncTask(SwiftReflectionContextRef RC,
778-
const PipeMemoryReader *Reader) {
779-
uintptr_t AsyncTaskInstance = PipeMemoryReader_receiveInstanceAddress(Reader);
780-
printf("Async task %#" PRIx64 "\n", (uint64_t)AsyncTaskInstance);
792+
static int reflectAsyncTaskInstance(SwiftReflectionContextRef RC,
793+
uintptr_t AsyncTaskInstance,
794+
const PipeMemoryReader *Reader,
795+
unsigned indentLevel) {
796+
indented_printf(indentLevel, "Async task %#" PRIx64 "\n",
797+
(uint64_t)AsyncTaskInstance);
798+
799+
swift_async_task_info_t TaskInfo =
800+
swift_reflection_asyncTaskInfo(RC, AsyncTaskInstance);
801+
if (TaskInfo.Error) {
802+
printf("swift_reflection_asyncTaskInfo failed: %s\n", TaskInfo.Error);
803+
} else {
804+
indented_printf(indentLevel, "id %" PRIu64 "\n", TaskInfo.Id);
805+
indented_printf(indentLevel, "enqueuePriority %u\n",
806+
TaskInfo.EnqueuePriority);
807+
if (TaskInfo.ChildTaskCount > 0) {
808+
indented_printf(indentLevel, "children = {\n");
809+
810+
// The memory for ChildTasks is only valid until the next Remote Mirror
811+
// call, so we need to copy it.
812+
swift_reflection_ptr_t *ChildTasks =
813+
calloc(TaskInfo.ChildTaskCount, sizeof(swift_reflection_ptr_t));
814+
memcpy(ChildTasks, TaskInfo.ChildTasks,
815+
TaskInfo.ChildTaskCount * sizeof(swift_reflection_ptr_t));
816+
817+
for (unsigned i = 0; i < TaskInfo.ChildTaskCount; i++)
818+
reflectAsyncTaskInstance(RC, ChildTasks[i], Reader, indentLevel + 1);
819+
820+
free(ChildTasks);
821+
indented_printf(indentLevel, "}\n");
822+
} else {
823+
indented_printf(indentLevel, "children = {}\n");
824+
}
825+
}
781826

782827
swift_async_task_slab_return_t SlabPtrResult =
783828
swift_reflection_asyncTaskSlabPointer(RC, AsyncTaskInstance);
@@ -787,33 +832,67 @@ int reflectAsyncTask(SwiftReflectionContextRef RC,
787832
} else {
788833
swift_reflection_ptr_t SlabPtr = SlabPtrResult.SlabPtr;
789834
while (SlabPtr) {
790-
printf(" Slab pointer %#" PRIx64 "\n", (uint64_t)SlabPtr);
835+
indented_printf(indentLevel, " Slab pointer %#" PRIx64 "\n",
836+
(uint64_t)SlabPtr);
791837
swift_async_task_slab_allocations_return_t AllocationsResult =
792838
swift_reflection_asyncTaskSlabAllocations(RC, SlabPtr);
793839
if (AllocationsResult.Error) {
794-
printf("swift_reflection_asyncTaskSlabAllocations failed: %s\n",
795-
AllocationsResult.Error);
840+
indented_printf(
841+
indentLevel,
842+
"swift_reflection_asyncTaskSlabAllocations failed: %s\n",
843+
AllocationsResult.Error);
796844
SlabPtr = 0;
797845
} else {
798-
printf(" Slab size %" PRIu64 "\n",
799-
(uint64_t)AllocationsResult.SlabSize);
846+
indented_printf(indentLevel, " Slab size %" PRIu64 "\n",
847+
(uint64_t)AllocationsResult.SlabSize);
800848
for (unsigned i = 0; i < AllocationsResult.ChunkCount; i++) {
801849
swift_async_task_allocation_chunk_t Chunk =
802850
AllocationsResult.Chunks[i];
803-
printf(" Chunk at %#" PRIx64 " length %u kind %u\n",
804-
(uint64_t)Chunk.Start, Chunk.Length, Chunk.Kind);
851+
indented_printf(indentLevel,
852+
" Chunk at %#" PRIx64 " length %u kind %u\n",
853+
(uint64_t)Chunk.Start, Chunk.Length, Chunk.Kind);
805854
}
806855
SlabPtr = AllocationsResult.NextSlab;
807856
}
808857
}
809858
}
810859

811-
printf("\n\n");
812-
PipeMemoryReader_sendDoneMessage(Reader);
860+
if (indentLevel == 0) {
861+
printf("\n\n");
862+
}
813863
fflush(stdout);
814864
return 1;
815865
}
816866

867+
int reflectAsyncTask(SwiftReflectionContextRef RC,
868+
const PipeMemoryReader *Reader) {
869+
uintptr_t AsyncTaskInstance = PipeMemoryReader_receiveInstanceAddress(Reader);
870+
int result = reflectAsyncTaskInstance(RC, AsyncTaskInstance, Reader, 0);
871+
PipeMemoryReader_sendDoneMessage(Reader);
872+
return result;
873+
}
874+
875+
int logString(SwiftReflectionContextRef RC, const PipeMemoryReader *Reader) {
876+
#pragma clang diagnostic push
877+
#pragma clang diagnostic ignored "-Wcast-qual"
878+
void *Context = (void *)Reader;
879+
#pragma clang diagnostic pop
880+
881+
swift_addr_t StringPointer = PipeMemoryReader_receiveInstanceAddress(Context);
882+
uint64_t StringLength =
883+
PipeMemoryReader_getStringLength(Context, StringPointer);
884+
885+
void *FreeContext;
886+
// Read length+1 bytes to get the NUL terminator too.
887+
const void *String = PipeMemoryReader_readBytes(
888+
Context, StringPointer, StringLength + 1, &FreeContext);
889+
890+
printf("%s\n", (const char *)String);
891+
PipeMemoryReader_freeBytes(Context, String, FreeContext);
892+
893+
PipeMemoryReader_sendDoneMessage(Context);
894+
return 1;
895+
}
817896

818897
int doDumpHeapInstance(const char *BinaryFilename, PipeMemoryReader *Reader) {
819898
#if defined(_WIN32)
@@ -926,6 +1005,11 @@ int doDumpHeapInstance(const char *BinaryFilename, PipeMemoryReader *Reader) {
9261005
return EXIT_SUCCESS;
9271006
break;
9281007
}
1008+
case LogString: {
1009+
if (!logString(RC, Reader))
1010+
return EXIT_SUCCESS;
1011+
break;
1012+
}
9291013
case None:
9301014
swift_reflection_destroyReflectionContext(RC);
9311015
printf("Done.\n");

0 commit comments

Comments
 (0)