@@ -341,13 +341,15 @@ enum IsCurrentExecutorCheckMode : unsigned {
341
341
342
342
// Shimming call to Swift runtime because Swift Embedded does not have
343
343
// these symbols defined.
344
- bool __swift_bincompat_useLegacyNonCrashingExecutorChecks () {
344
+ swift_task_is_current_executor_flag
345
+ __swift_bincompat_useLegacyNonCrashingExecutorChecks () {
345
346
#if !SWIFT_CONCURRENCY_EMBEDDED
346
- return swift::runtime::bincompat::
347
- swift_bincompat_useLegacyNonCrashingExecutorChecks ();
348
- # else
349
- return false ;
347
+ if ( swift::runtime::bincompat::
348
+ swift_bincompat_useLegacyNonCrashingExecutorChecks ()) {
349
+ return swift_task_is_current_executor_flag::None;
350
+ }
350
351
#endif
352
+ return swift_task_is_current_executor_flag::Assert;
351
353
}
352
354
353
355
// Shimming call to Swift runtime because Swift Embedded does not have
@@ -364,22 +366,40 @@ const char *__swift_runtime_env_useLegacyNonCrashingExecutorChecks() {
364
366
365
367
// Done this way because of the interaction with the initial value of
366
368
// 'unexpectedExecutorLogLevel'
367
- bool swift_bincompat_useLegacyNonCrashingExecutorChecks () {
368
- bool legacyMode = __swift_bincompat_useLegacyNonCrashingExecutorChecks ();
369
+ swift_task_is_current_executor_flag swift_bincompat_useLegacyNonCrashingExecutorChecks () {
370
+ swift_task_is_current_executor_flag options =
371
+ __swift_bincompat_useLegacyNonCrashingExecutorChecks ();
369
372
370
373
// Potentially, override the platform detected mode, primarily used in tests.
371
374
if (const char *modeStr =
372
375
__swift_runtime_env_useLegacyNonCrashingExecutorChecks ()) {
376
+ SWIFT_TASK_DEBUG_LOG (" executor checking: SWIFT_IS_CURRENT_EXECUTOR_LEGACY_MODE_OVERRIDE = '%s'" , modeStr);
373
377
if (strcmp (modeStr, " nocrash" ) == 0 ||
374
378
strcmp (modeStr, " legacy" ) == 0 ) {
375
- return true ;
379
+ SWIFT_TASK_DEBUG_LOG (" executor checking: SWIFT_IS_CURRENT_EXECUTOR_LEGACY_MODE_OVERRIDE = %s => NONE; options = %d" ,
380
+ modeStr, options);
381
+ options = swift_task_is_current_executor_flag (
382
+ swift_task_is_current_executor_flag::None);
383
+ }
384
+
385
+ if (strcmp (modeStr, " swift62" ) == 0 ) {
386
+ options = swift_task_is_current_executor_flag (
387
+ options | swift_task_is_current_executor_flag::HasIsIsolatingCurrentContext);
388
+ // When we're using the isIsolatingCurrentContext we don't want to use crashing APIs,
389
+ // so disable it explicitly.
390
+ options = swift_task_is_current_executor_flag (
391
+ options & ~swift_task_is_current_executor_flag::Assert);
392
+ SWIFT_TASK_DEBUG_LOG (" executor checking: SWIFT_IS_CURRENT_EXECUTOR_LEGACY_MODE_OVERRIDE = %s => 6.2; options = %d" , modeStr, options);
376
393
} else if (strcmp (modeStr, " crash" ) == 0 ||
377
394
strcmp (modeStr, " swift6" ) == 0 ) {
378
- return false ; // don't use the legacy mode
395
+ options = swift_task_is_current_executor_flag (
396
+ options | swift_task_is_current_executor_flag::Assert);
397
+ SWIFT_TASK_DEBUG_LOG (" executor checking: SWIFT_IS_CURRENT_EXECUTOR_LEGACY_MODE_OVERRIDE = %s => 6.9; options = %d" , modeStr, options);
379
398
} // else, just use the platform detected mode
380
399
} // no override, use the default mode
381
400
382
- return legacyMode;
401
+ SWIFT_TASK_DEBUG_LOG (" executor checking: options = %d" , options);
402
+ return options;
383
403
}
384
404
385
405
// Implemented in Swift to avoid some annoying hard-coding about
@@ -407,6 +427,13 @@ static bool swift_task_isCurrentExecutorWithFlagsImpl(
407
427
swift_task_is_current_executor_flag flags) {
408
428
auto options = SwiftTaskIsCurrentExecutorOptions (flags);
409
429
auto current = ExecutorTrackingInfo::current ();
430
+ SWIFT_TASK_DEBUG_LOG (" executor checking: current task %p" , current);
431
+ #ifndef NDEBUG
432
+ if (options.contains (swift_task_is_current_executor_flag::Assert))
433
+ SWIFT_TASK_DEBUG_LOG (" executor checking: active option = Assert (%d)" , flags);
434
+ if (options.contains (swift_task_is_current_executor_flag::HasIsIsolatingCurrentContext))
435
+ SWIFT_TASK_DEBUG_LOG (" executor checking: active option = HasIsIsolatingCurrentContext (%d)" , flags);
436
+ #endif
410
437
411
438
if (!current) {
412
439
// We have no current executor, i.e. we are running "outside" of Swift
@@ -416,15 +443,30 @@ static bool swift_task_isCurrentExecutorWithFlagsImpl(
416
443
417
444
// Special handling the main executor by detecting the main thread.
418
445
if (expectedExecutor.isMainExecutor () && isExecutingOnMainThread ()) {
446
+ SWIFT_TASK_DEBUG_LOG (" executor checking: expected is main executor & current thread is main thread => pass" , nullptr );
419
447
return true ;
420
448
}
421
449
422
450
// We cannot use 'complexEquality' as it requires two executor instances,
423
451
// and we do not have a 'current' executor here.
424
452
453
+ if (options.contains (swift_task_is_current_executor_flag::HasIsIsolatingCurrentContext)) {
454
+ SWIFT_TASK_DEBUG_LOG (" executor checking mode option: HasIsIsolatingCurrentContext; invoke (%p).isIsolatingCurrentContext" ,
455
+ expectedExecutor.getIdentity ());
456
+ // The executor has the most recent 'isIsolatingCurrentContext' API
457
+ // so available so we prefer calling that to 'checkIsolated'.
458
+ auto result = swift_task_isIsolatingCurrentContext (expectedExecutor);
459
+
460
+ SWIFT_TASK_DEBUG_LOG (" executor checking mode option: HasIsIsolatingCurrentContext; invoke (%p).isIsolatingCurrentContext => %s" ,
461
+ expectedExecutor.getIdentity (), result ? " pass" : " fail" );
462
+ return result;
463
+ }
464
+
425
465
// Otherwise, as last resort, let the expected executor check using
426
466
// external means, as it may "know" this thread is managed by it etc.
427
467
if (options.contains (swift_task_is_current_executor_flag::Assert)) {
468
+ SWIFT_TASK_DEBUG_LOG (" executor checking mode option: Assert; invoke (%p).expectedExecutor" ,
469
+ expectedExecutor.getIdentity ());
428
470
swift_task_checkIsolated (expectedExecutor); // will crash if not same context
429
471
430
472
// checkIsolated did not crash, so we are on the right executor, after all!
@@ -436,16 +478,23 @@ static bool swift_task_isCurrentExecutorWithFlagsImpl(
436
478
}
437
479
438
480
SerialExecutorRef currentExecutor = current->getActiveExecutor ();
481
+ SWIFT_TASK_DEBUG_LOG (" executor checking: current executor %p %s" ,
482
+ currentExecutor.getIdentity (), currentExecutor.getIdentityDebugName ());
439
483
440
484
// Fast-path: the executor is exactly the same memory address;
441
485
// We assume executors do not come-and-go appearing under the same address,
442
486
// and treat pointer equality of executors as good enough to assume the executor.
443
487
if (currentExecutor == expectedExecutor) {
488
+ SWIFT_TASK_DEBUG_LOG (" executor checking: current executor %p, equal to expected executor => pass" ,
489
+ currentExecutor.getIdentity ());
444
490
return true ;
445
491
}
446
492
447
493
// Fast-path, specialize the common case of comparing two main executors.
448
494
if (currentExecutor.isMainExecutor () && expectedExecutor.isMainExecutor ()) {
495
+ SWIFT_TASK_DEBUG_LOG (" executor checking: current executor %p is main executor, and expected executor (%p) is main executor => pass" ,
496
+ currentExecutor.getIdentity (),
497
+ expectedExecutor.getIdentity ());
449
498
return true ;
450
499
}
451
500
@@ -463,8 +512,16 @@ static bool swift_task_isCurrentExecutorWithFlagsImpl(
463
512
// or confirm we actually are on the main queue; or the custom expected
464
513
// executor has a chance to implement a similar queue check.
465
514
if (!options.contains (swift_task_is_current_executor_flag::Assert)) {
466
- if ((expectedExecutor.isMainExecutor () && !currentExecutor.isMainExecutor ()) ||
467
- (!expectedExecutor.isMainExecutor () && currentExecutor.isMainExecutor ())) {
515
+ if ((expectedExecutor.isMainExecutor () && !currentExecutor.isMainExecutor ())) {
516
+ SWIFT_TASK_DEBUG_LOG (" executor checking: expected executor %p%s is main executor, and current executor %p%s is NOT => fail" ,
517
+ expectedExecutor.getIdentity (), expectedExecutor.getIdentityDebugName (),
518
+ currentExecutor.getIdentity (), currentExecutor.getIdentityDebugName ());
519
+ return false ;
520
+ }
521
+ if ((!expectedExecutor.isMainExecutor () && currentExecutor.isMainExecutor ())) {
522
+ SWIFT_TASK_DEBUG_LOG (" executor checking: expected executor %p%s is NOT main executor, and current executor %p%s is => fail" ,
523
+ expectedExecutor.getIdentity (), expectedExecutor.getIdentityDebugName (),
524
+ currentExecutor.getIdentity (), currentExecutor.getIdentityDebugName ());
468
525
return false ;
469
526
}
470
527
}
@@ -487,6 +544,8 @@ static bool swift_task_isCurrentExecutorWithFlagsImpl(
487
544
currentExecutor.getSerialExecutorWitnessTable ()),
488
545
reinterpret_cast <const WitnessTable *>(
489
546
expectedExecutor.getSerialExecutorWitnessTable ()))) {
547
+ SWIFT_TASK_DEBUG_LOG (" executor checking: can check isComplexEquality (%p, and %p)" ,
548
+ expectedExecutor.getIdentity (), currentExecutor.getIdentity ());
490
549
491
550
auto isSameExclusiveExecutionContextResult =
492
551
_task_serialExecutor_isSameExclusiveExecutionContext (
@@ -498,11 +557,25 @@ static bool swift_task_isCurrentExecutorWithFlagsImpl(
498
557
// it and return; if it was false, we need to give checkIsolated another
499
558
// chance to check.
500
559
if (isSameExclusiveExecutionContextResult) {
560
+ SWIFT_TASK_DEBUG_LOG (" executor checking: isComplexEquality (%p, and %p) is true => pass" ,
561
+ expectedExecutor.getIdentity (), currentExecutor.getIdentity ());
501
562
return true ;
502
563
} // else, we must give 'checkIsolated' a last chance to verify isolation
503
564
}
504
565
}
505
566
567
+ if (options.contains (swift_task_is_current_executor_flag::HasIsIsolatingCurrentContext)) {
568
+ // We can invoke the 'isIsolatingCurrentContext' function.
569
+ SWIFT_TASK_DEBUG_LOG (" executor checking: can call (%p).isIsolatingCurrentContext" ,
570
+ expectedExecutor.getIdentity ());
571
+
572
+ bool checkResult = swift_task_isIsolatingCurrentContext (expectedExecutor);
573
+
574
+ SWIFT_TASK_DEBUG_LOG (" executor checking: can call (%p).isIsolatingCurrentContext => %p" ,
575
+ expectedExecutor.getIdentity (), checkResult ? " pass" : " fail" );
576
+ return checkResult;
577
+ }
578
+
506
579
// This provides a last-resort check by giving the expected SerialExecutor the
507
580
// chance to perform a check using some external knowledge if perhaps we are,
508
581
// after all, on this executor, but the Swift concurrency runtime was just not
@@ -524,9 +597,13 @@ static bool swift_task_isCurrentExecutorWithFlagsImpl(
524
597
// synchronous, and will not cause suspensions, as that would require the
525
598
// presence of a Task.
526
599
if (options.contains (swift_task_is_current_executor_flag::Assert)) {
600
+ SWIFT_TASK_DEBUG_LOG (" executor checking: call (%p).checkIsolated" ,
601
+ expectedExecutor.getIdentity ());
527
602
swift_task_checkIsolated (expectedExecutor); // will crash if not same context
528
603
529
604
// The checkIsolated call did not crash, so we are on the right executor.
605
+ SWIFT_TASK_DEBUG_LOG (" executor checking: call (%p).checkIsolated passed => pass" ,
606
+ expectedExecutor.getIdentity ());
530
607
return true ;
531
608
}
532
609
@@ -538,12 +615,23 @@ static bool swift_task_isCurrentExecutorWithFlagsImpl(
538
615
539
616
// Check override of executor checking mode.
540
617
static void swift_task_setDefaultExecutorCheckingFlags (void *context) {
541
- bool useLegacyMode = swift_bincompat_useLegacyNonCrashingExecutorChecks ();
542
- auto checkMode = static_cast <swift_task_is_current_executor_flag *>(context);
543
- if (!useLegacyMode) {
544
- *checkMode = swift_task_is_current_executor_flag (
545
- *checkMode | swift_task_is_current_executor_flag::Assert);
546
- }
618
+ SWIFT_TASK_DEBUG_LOG (" executor checking: swift_task_setDefaultExecutorCheckingFlags = %d" , nullptr );
619
+ auto useLegacyMode = swift_bincompat_useLegacyNonCrashingExecutorChecks ();
620
+ SWIFT_TASK_DEBUG_LOG (" executor checking: use legacy mode = %d" , useLegacyMode);
621
+ auto *options = static_cast <swift_task_is_current_executor_flag *>(context);
622
+ SWIFT_TASK_DEBUG_LOG (" executor checking: options = %d" , *options);
623
+ // if (!useLegacyMode) {
624
+ // *options = swift_task_is_current_executor_flag(
625
+ // *options | swift_task_is_current_executor_flag::Assert);
626
+ // }
627
+ *options = useLegacyMode;
628
+ SWIFT_TASK_DEBUG_LOG (" executor checking: resulting options = %d" , *options);
629
+ SWIFT_TASK_DEBUG_LOG (" executor checking: option Assert = %d" ,
630
+ SwiftTaskIsCurrentExecutorOptions (*options).
631
+ contains (swift_task_is_current_executor_flag::Assert));
632
+ SWIFT_TASK_DEBUG_LOG (" executor checking: option HasIsIsolatingCurrentContext = %d" ,
633
+ SwiftTaskIsCurrentExecutorOptions (*options).
634
+ contains (swift_task_is_current_executor_flag::HasIsIsolatingCurrentContext));
547
635
}
548
636
549
637
SWIFT_CC (swift)
@@ -2294,8 +2382,7 @@ static void swift_task_switchImpl(SWIFT_ASYNC_CONTEXT AsyncContext *resumeContex
2294
2382
currentTaskExecutor.getIdentity (),
2295
2383
currentTaskExecutor.isDefined () ? " " : " (undefined)" ,
2296
2384
newTaskExecutor.getIdentity (),
2297
- newTaskExecutor.isDefined () ? " " : " (undefined)" ,
2298
- trackingInfo->isSynchronousStart () ? " [synchronous start]" : " " );
2385
+ newTaskExecutor.isDefined () ? " " : " (undefined)" );
2299
2386
2300
2387
// If the current executor is compatible with running the new executor,
2301
2388
// we can just immediately continue running with the resume function
0 commit comments