|
41 | 41 | #include "swift/Runtime/Portability.h"
|
42 | 42 | #include "swift/Strings.h"
|
43 | 43 | #include "swift/Threading/Mutex.h"
|
| 44 | +#include "swift/Threading/ThreadSanitizer.h" |
44 | 45 | #include "llvm/ADT/StringExtras.h"
|
45 | 46 | #include <algorithm>
|
46 | 47 | #include <cctype>
|
@@ -7977,10 +7978,28 @@ void *MetadataAllocator::Allocate(size_t size, size_t alignment) {
|
7977 | 7978 | Tag);
|
7978 | 7979 | }
|
7979 | 7980 |
|
| 7981 | + // If we allocated a new page, then we need to do a store-release to ensure |
| 7982 | + // the initialization writes are properly ordered when viewed from other |
| 7983 | + // threads that read from the new page. If we did not allocate a new page, |
| 7984 | + // then we need a load-consume to cover the other side of that. |
| 7985 | + std::memory_order successOrder = allocatedNewPage |
| 7986 | + ? std::memory_order_release |
| 7987 | + : SWIFT_MEMORY_ORDER_CONSUME; |
| 7988 | + |
7980 | 7989 | // Swap in the new state.
|
7981 | 7990 | if (AllocationPool.compare_exchange_weak(curState, newState,
|
7982 |
| - std::memory_order_relaxed, |
| 7991 | + successOrder, |
7983 | 7992 | std::memory_order_relaxed)) {
|
| 7993 | + // If the program is using Thread Sanitizer, it can't see our memory |
| 7994 | + // ordering, so inform it manually. TSan will track the consume ordering |
| 7995 | + // in __swift_instantiateConcreteTypeFromMangledName so we register the |
| 7996 | + // correct ordering with threads that get a metadata pointer from a cache |
| 7997 | + // variable too. |
| 7998 | + if (allocatedNewPage) |
| 7999 | + swift::tsan::release(&AllocationPool); |
| 8000 | + else |
| 8001 | + swift::tsan::acquire(&AllocationPool); |
| 8002 | + |
7984 | 8003 | // If that succeeded, we've successfully allocated.
|
7985 | 8004 | __msan_allocated_memory(allocation, sizeWithHeader);
|
7986 | 8005 | __asan_unpoison_memory_region(allocation, sizeWithHeader);
|
|
0 commit comments