1616
1717// NOTE: This should really be applied in the CMakeLists.txt. However, we do
1818// not have a way to currently specify that at the target specific level yet.
19+
1920#if defined(_WIN32)
2021#define NOMINMAX
2122#define WIN32_LEAN_AND_MEAN
@@ -65,6 +66,39 @@ static inline bool isExclusivityLoggingEnabled() {
6566 return runtime::environment::SWIFT_DEBUG_RUNTIME_EXCLUSIVITY_LOGGING ();
6667}
6768
69+ static inline void _flockfile_stderr () {
70+ #if defined(_WIN32)
71+ _lock_file (stderr);
72+ #elif defined(__wasi__)
73+ // WebAssembly/WASI doesn't support file locking yet
74+ // https://bugs.swift.org/browse/SR-12097
75+ #else
76+ flockfile (stderr);
77+ #endif
78+ }
79+
80+ static inline void _funlockfile_stderr () {
81+ #if defined(_WIN32)
82+ _unlock_file (stderr);
83+ #elif defined(__wasi__)
84+ // WebAssembly/WASI doesn't support file locking yet
85+ // https://bugs.swift.org/browse/SR-12097
86+ #else
87+ funlockfile (stderr);
88+ #endif
89+ }
90+
91+ // / Used to ensure that logging printfs are deterministic.
92+ static inline void withLoggingLock (std::function<void ()> func) {
93+ assert (isExclusivityLoggingEnabled () &&
94+ " Should only be called if exclusivity logging is enabled!" );
95+
96+ _flockfile_stderr ();
97+ func ();
98+ fflush (stderr);
99+ _funlockfile_stderr ();
100+ }
101+
68102#endif
69103
70104SWIFT_ALWAYS_INLINE
@@ -191,8 +225,10 @@ class AccessSet {
191225
192226 bool insert (Access *access, void *pc, void *pointer, ExclusivityFlags flags) {
193227#ifndef NDEBUG
194- if (isExclusivityLoggingEnabled ())
195- fprintf (stderr, " Inserting new access: %p\n " , access);
228+ if (isExclusivityLoggingEnabled ()) {
229+ withLoggingLock (
230+ [&]() { fprintf (stderr, " Inserting new access: %p\n " , access); });
231+ }
196232#endif
197233 auto action = getAccessAction (flags);
198234
@@ -216,7 +252,7 @@ class AccessSet {
216252 if (!isTracking (flags)) {
217253#ifndef NDEBUG
218254 if (isExclusivityLoggingEnabled ()) {
219- fprintf (stderr, " Not tracking!\n " );
255+ withLoggingLock ([&]() { fprintf (stderr, " Not tracking!\n " ); } );
220256 }
221257#endif
222258 return false ;
@@ -227,8 +263,10 @@ class AccessSet {
227263 Head = access;
228264#ifndef NDEBUG
229265 if (isExclusivityLoggingEnabled ()) {
230- fprintf (stderr, " Tracking!\n " );
231- swift_dumpTrackedAccesses ();
266+ withLoggingLock ([&]() {
267+ fprintf (stderr, " Tracking!\n " );
268+ swift_dumpTrackedAccesses ();
269+ });
232270 }
233271#endif
234272 return true ;
@@ -237,8 +275,10 @@ class AccessSet {
237275 void remove (Access *access) {
238276 assert (Head && " removal from empty AccessSet" );
239277#ifndef NDEBUG
240- if (isExclusivityLoggingEnabled ())
241- fprintf (stderr, " Removing access: %p\n " , access);
278+ if (isExclusivityLoggingEnabled ()) {
279+ withLoggingLock (
280+ [&]() { fprintf (stderr, " Removing access: %p\n " , access); });
281+ }
242282#endif
243283 auto cur = Head;
244284 // Fast path: stack discipline.
@@ -708,20 +748,24 @@ void swift::swift_task_enterThreadLocalContext(char *state) {
708748
709749#ifndef NDEBUG
710750 if (isExclusivityLoggingEnabled ()) {
711- fprintf (stderr,
712- " Entering Thread Local Context. Before Swizzle. Task: %p\n " ,
713- taskCtx.getTaskAddress ());
714- taskCtx.dump ();
715- swift_dumpTrackedAccesses ();
716- }
717-
718- auto logEndState = [&] {
719- if (isExclusivityLoggingEnabled ()) {
751+ withLoggingLock ([&]() {
720752 fprintf (stderr,
721- " Entering Thread Local Context. After Swizzle. Task: %p\n " ,
753+ " Entering Thread Local Context. Before Swizzle. Task: %p\n " ,
722754 taskCtx.getTaskAddress ());
723755 taskCtx.dump ();
724756 swift_dumpTrackedAccesses ();
757+ });
758+ }
759+
760+ auto logEndState = [&] {
761+ if (isExclusivityLoggingEnabled ()) {
762+ withLoggingLock ([&]() {
763+ fprintf (stderr,
764+ " Entering Thread Local Context. After Swizzle. Task: %p\n " ,
765+ taskCtx.getTaskAddress ());
766+ taskCtx.dump ();
767+ swift_dumpTrackedAccesses ();
768+ });
725769 }
726770 };
727771#else
@@ -794,20 +838,24 @@ void swift::swift_task_exitThreadLocalContext(char *state) {
794838
795839#ifndef NDEBUG
796840 if (isExclusivityLoggingEnabled ()) {
797- fprintf (stderr,
798- " Exiting Thread Local Context. Before Swizzle. Task: %p\n " ,
799- taskCtx.getTaskAddress ());
800- taskCtx.dump ();
801- swift_dumpTrackedAccesses ();
802- }
803-
804- auto logEndState = [&] {
805- if (isExclusivityLoggingEnabled ()) {
841+ withLoggingLock ([&]() {
806842 fprintf (stderr,
807- " Exiting Thread Local Context. After Swizzle. Task: %p\n " ,
843+ " Exiting Thread Local Context. Before Swizzle. Task: %p\n " ,
808844 taskCtx.getTaskAddress ());
809845 taskCtx.dump ();
810846 swift_dumpTrackedAccesses ();
847+ });
848+ }
849+
850+ auto logEndState = [&] {
851+ if (isExclusivityLoggingEnabled ()) {
852+ withLoggingLock ([&]() {
853+ fprintf (stderr,
854+ " Exiting Thread Local Context. After Swizzle. Task: %p\n " ,
855+ taskCtx.getTaskAddress ());
856+ taskCtx.dump ();
857+ swift_dumpTrackedAccesses ();
858+ });
811859 }
812860 };
813861#else
0 commit comments