@@ -353,13 +353,15 @@ enum IsCurrentExecutorCheckMode : unsigned {
353
353
354
354
// Shimming call to Swift runtime because Swift Embedded does not have
355
355
// these symbols defined.
356
- bool __swift_bincompat_useLegacyNonCrashingExecutorChecks () {
356
+ swift_task_is_current_executor_flag
357
+ __swift_bincompat_useLegacyNonCrashingExecutorChecks () {
357
358
#if !SWIFT_CONCURRENCY_EMBEDDED
358
- return swift::runtime::bincompat::
359
- swift_bincompat_useLegacyNonCrashingExecutorChecks ();
360
- # else
361
- return false ;
359
+ if ( swift::runtime::bincompat::
360
+ swift_bincompat_useLegacyNonCrashingExecutorChecks ()) {
361
+ return swift_task_is_current_executor_flag::None;
362
+ }
362
363
#endif
364
+ return swift_task_is_current_executor_flag::Assert;
363
365
}
364
366
365
367
// Shimming call to Swift runtime because Swift Embedded does not have
@@ -376,22 +378,40 @@ const char *__swift_runtime_env_useLegacyNonCrashingExecutorChecks() {
376
378
377
379
// Done this way because of the interaction with the initial value of
378
380
// 'unexpectedExecutorLogLevel'
379
- bool swift_bincompat_useLegacyNonCrashingExecutorChecks () {
380
- bool legacyMode = __swift_bincompat_useLegacyNonCrashingExecutorChecks ();
381
+ swift_task_is_current_executor_flag swift_bincompat_useLegacyNonCrashingExecutorChecks () {
382
+ swift_task_is_current_executor_flag options =
383
+ __swift_bincompat_useLegacyNonCrashingExecutorChecks ();
381
384
382
385
// Potentially, override the platform detected mode, primarily used in tests.
383
386
if (const char *modeStr =
384
387
__swift_runtime_env_useLegacyNonCrashingExecutorChecks ()) {
388
+ SWIFT_TASK_DEBUG_LOG (" executor checking: SWIFT_IS_CURRENT_EXECUTOR_LEGACY_MODE_OVERRIDE = '%s'" , modeStr);
385
389
if (strcmp (modeStr, " nocrash" ) == 0 ||
386
390
strcmp (modeStr, " legacy" ) == 0 ) {
387
- return true ;
391
+ SWIFT_TASK_DEBUG_LOG (" executor checking: SWIFT_IS_CURRENT_EXECUTOR_LEGACY_MODE_OVERRIDE = %s => NONE; options = %d" ,
392
+ modeStr, options);
393
+ options = swift_task_is_current_executor_flag (
394
+ swift_task_is_current_executor_flag::None);
395
+ }
396
+
397
+ if (strcmp (modeStr, " swift62" ) == 0 ) {
398
+ options = swift_task_is_current_executor_flag (
399
+ options | swift_task_is_current_executor_flag::HasIsIsolatingCurrentContext);
400
+ // When we're using the isIsolatingCurrentContext we don't want to use crashing APIs,
401
+ // so disable it explicitly.
402
+ options = swift_task_is_current_executor_flag (
403
+ options & ~swift_task_is_current_executor_flag::Assert);
404
+ SWIFT_TASK_DEBUG_LOG (" executor checking: SWIFT_IS_CURRENT_EXECUTOR_LEGACY_MODE_OVERRIDE = %s => 6.2; options = %d" , modeStr, options);
388
405
} else if (strcmp (modeStr, " crash" ) == 0 ||
389
406
strcmp (modeStr, " swift6" ) == 0 ) {
390
- return false ; // don't use the legacy mode
407
+ options = swift_task_is_current_executor_flag (
408
+ options | swift_task_is_current_executor_flag::Assert);
409
+ SWIFT_TASK_DEBUG_LOG (" executor checking: SWIFT_IS_CURRENT_EXECUTOR_LEGACY_MODE_OVERRIDE = %s => 6.9; options = %d" , modeStr, options);
391
410
} // else, just use the platform detected mode
392
411
} // no override, use the default mode
393
412
394
- return legacyMode;
413
+ SWIFT_TASK_DEBUG_LOG (" executor checking: options = %d" , options);
414
+ return options;
395
415
}
396
416
397
417
// Implemented in Swift to avoid some annoying hard-coding about
@@ -419,6 +439,13 @@ static bool swift_task_isCurrentExecutorWithFlagsImpl(
419
439
swift_task_is_current_executor_flag flags) {
420
440
auto options = SwiftTaskIsCurrentExecutorOptions (flags);
421
441
auto current = ExecutorTrackingInfo::current ();
442
+ SWIFT_TASK_DEBUG_LOG (" executor checking: current task %p" , current);
443
+ #ifndef NDEBUG
444
+ if (options.contains (swift_task_is_current_executor_flag::Assert))
445
+ SWIFT_TASK_DEBUG_LOG (" executor checking: active option = Assert (%d)" , flags);
446
+ if (options.contains (swift_task_is_current_executor_flag::HasIsIsolatingCurrentContext))
447
+ SWIFT_TASK_DEBUG_LOG (" executor checking: active option = HasIsIsolatingCurrentContext (%d)" , flags);
448
+ #endif
422
449
423
450
if (!current) {
424
451
// We have no current executor, i.e. we are running "outside" of Swift
@@ -428,15 +455,30 @@ static bool swift_task_isCurrentExecutorWithFlagsImpl(
428
455
429
456
// Special handling the main executor by detecting the main thread.
430
457
if (expectedExecutor.isMainExecutor () && isExecutingOnMainThread ()) {
458
+ SWIFT_TASK_DEBUG_LOG (" executor checking: expected is main executor & current thread is main thread => pass" , nullptr );
431
459
return true ;
432
460
}
433
461
434
462
// We cannot use 'complexEquality' as it requires two executor instances,
435
463
// and we do not have a 'current' executor here.
436
464
465
+ if (options.contains (swift_task_is_current_executor_flag::HasIsIsolatingCurrentContext)) {
466
+ SWIFT_TASK_DEBUG_LOG (" executor checking mode option: HasIsIsolatingCurrentContext; invoke (%p).isIsolatingCurrentContext" ,
467
+ expectedExecutor.getIdentity ());
468
+ // The executor has the most recent 'isIsolatingCurrentContext' API
469
+ // so available so we prefer calling that to 'checkIsolated'.
470
+ auto result = swift_task_isIsolatingCurrentContext (expectedExecutor);
471
+
472
+ SWIFT_TASK_DEBUG_LOG (" executor checking mode option: HasIsIsolatingCurrentContext; invoke (%p).isIsolatingCurrentContext => %s" ,
473
+ expectedExecutor.getIdentity (), result ? " pass" : " fail" );
474
+ return result;
475
+ }
476
+
437
477
// Otherwise, as last resort, let the expected executor check using
438
478
// external means, as it may "know" this thread is managed by it etc.
439
479
if (options.contains (swift_task_is_current_executor_flag::Assert)) {
480
+ SWIFT_TASK_DEBUG_LOG (" executor checking mode option: Assert; invoke (%p).expectedExecutor" ,
481
+ expectedExecutor.getIdentity ());
440
482
swift_task_checkIsolated (expectedExecutor); // will crash if not same context
441
483
442
484
// checkIsolated did not crash, so we are on the right executor, after all!
@@ -448,16 +490,23 @@ static bool swift_task_isCurrentExecutorWithFlagsImpl(
448
490
}
449
491
450
492
SerialExecutorRef currentExecutor = current->getActiveExecutor ();
493
+ SWIFT_TASK_DEBUG_LOG (" executor checking: current executor %p %s" ,
494
+ currentExecutor.getIdentity (), currentExecutor.getIdentityDebugName ());
451
495
452
496
// Fast-path: the executor is exactly the same memory address;
453
497
// We assume executors do not come-and-go appearing under the same address,
454
498
// and treat pointer equality of executors as good enough to assume the executor.
455
499
if (currentExecutor == expectedExecutor) {
500
+ SWIFT_TASK_DEBUG_LOG (" executor checking: current executor %p, equal to expected executor => pass" ,
501
+ currentExecutor.getIdentity ());
456
502
return true ;
457
503
}
458
504
459
505
// Fast-path, specialize the common case of comparing two main executors.
460
506
if (currentExecutor.isMainExecutor () && expectedExecutor.isMainExecutor ()) {
507
+ SWIFT_TASK_DEBUG_LOG (" executor checking: current executor %p is main executor, and expected executor (%p) is main executor => pass" ,
508
+ currentExecutor.getIdentity (),
509
+ expectedExecutor.getIdentity ());
461
510
return true ;
462
511
}
463
512
@@ -475,8 +524,16 @@ static bool swift_task_isCurrentExecutorWithFlagsImpl(
475
524
// or confirm we actually are on the main queue; or the custom expected
476
525
// executor has a chance to implement a similar queue check.
477
526
if (!options.contains (swift_task_is_current_executor_flag::Assert)) {
478
- if ((expectedExecutor.isMainExecutor () && !currentExecutor.isMainExecutor ()) ||
479
- (!expectedExecutor.isMainExecutor () && currentExecutor.isMainExecutor ())) {
527
+ if ((expectedExecutor.isMainExecutor () && !currentExecutor.isMainExecutor ())) {
528
+ SWIFT_TASK_DEBUG_LOG (" executor checking: expected executor %p%s is main executor, and current executor %p%s is NOT => fail" ,
529
+ expectedExecutor.getIdentity (), expectedExecutor.getIdentityDebugName (),
530
+ currentExecutor.getIdentity (), currentExecutor.getIdentityDebugName ());
531
+ return false ;
532
+ }
533
+ if ((!expectedExecutor.isMainExecutor () && currentExecutor.isMainExecutor ())) {
534
+ SWIFT_TASK_DEBUG_LOG (" executor checking: expected executor %p%s is NOT main executor, and current executor %p%s is => fail" ,
535
+ expectedExecutor.getIdentity (), expectedExecutor.getIdentityDebugName (),
536
+ currentExecutor.getIdentity (), currentExecutor.getIdentityDebugName ());
480
537
return false ;
481
538
}
482
539
}
@@ -499,6 +556,8 @@ static bool swift_task_isCurrentExecutorWithFlagsImpl(
499
556
currentExecutor.getSerialExecutorWitnessTable ()),
500
557
reinterpret_cast <const WitnessTable *>(
501
558
expectedExecutor.getSerialExecutorWitnessTable ()))) {
559
+ SWIFT_TASK_DEBUG_LOG (" executor checking: can check isComplexEquality (%p, and %p)" ,
560
+ expectedExecutor.getIdentity (), currentExecutor.getIdentity ());
502
561
503
562
auto isSameExclusiveExecutionContextResult =
504
563
_task_serialExecutor_isSameExclusiveExecutionContext (
@@ -510,11 +569,25 @@ static bool swift_task_isCurrentExecutorWithFlagsImpl(
510
569
// it and return; if it was false, we need to give checkIsolated another
511
570
// chance to check.
512
571
if (isSameExclusiveExecutionContextResult) {
572
+ SWIFT_TASK_DEBUG_LOG (" executor checking: isComplexEquality (%p, and %p) is true => pass" ,
573
+ expectedExecutor.getIdentity (), currentExecutor.getIdentity ());
513
574
return true ;
514
575
} // else, we must give 'checkIsolated' a last chance to verify isolation
515
576
}
516
577
}
517
578
579
+ if (options.contains (swift_task_is_current_executor_flag::HasIsIsolatingCurrentContext)) {
580
+ // We can invoke the 'isIsolatingCurrentContext' function.
581
+ SWIFT_TASK_DEBUG_LOG (" executor checking: can call (%p).isIsolatingCurrentContext" ,
582
+ expectedExecutor.getIdentity ());
583
+
584
+ bool checkResult = swift_task_isIsolatingCurrentContext (expectedExecutor);
585
+
586
+ SWIFT_TASK_DEBUG_LOG (" executor checking: can call (%p).isIsolatingCurrentContext => %p" ,
587
+ expectedExecutor.getIdentity (), checkResult ? " pass" : " fail" );
588
+ return checkResult;
589
+ }
590
+
518
591
// This provides a last-resort check by giving the expected SerialExecutor the
519
592
// chance to perform a check using some external knowledge if perhaps we are,
520
593
// after all, on this executor, but the Swift concurrency runtime was just not
@@ -536,9 +609,13 @@ static bool swift_task_isCurrentExecutorWithFlagsImpl(
536
609
// synchronous, and will not cause suspensions, as that would require the
537
610
// presence of a Task.
538
611
if (options.contains (swift_task_is_current_executor_flag::Assert)) {
612
+ SWIFT_TASK_DEBUG_LOG (" executor checking: call (%p).checkIsolated" ,
613
+ expectedExecutor.getIdentity ());
539
614
swift_task_checkIsolated (expectedExecutor); // will crash if not same context
540
615
541
616
// The checkIsolated call did not crash, so we are on the right executor.
617
+ SWIFT_TASK_DEBUG_LOG (" executor checking: call (%p).checkIsolated passed => pass" ,
618
+ expectedExecutor.getIdentity ());
542
619
return true ;
543
620
}
544
621
@@ -550,12 +627,23 @@ static bool swift_task_isCurrentExecutorWithFlagsImpl(
550
627
551
628
// Check override of executor checking mode.
552
629
static void swift_task_setDefaultExecutorCheckingFlags (void *context) {
553
- bool useLegacyMode = swift_bincompat_useLegacyNonCrashingExecutorChecks ();
554
- auto checkMode = static_cast <swift_task_is_current_executor_flag *>(context);
555
- if (!useLegacyMode) {
556
- *checkMode = swift_task_is_current_executor_flag (
557
- *checkMode | swift_task_is_current_executor_flag::Assert);
558
- }
630
+ SWIFT_TASK_DEBUG_LOG (" executor checking: swift_task_setDefaultExecutorCheckingFlags = %d" , nullptr );
631
+ auto useLegacyMode = swift_bincompat_useLegacyNonCrashingExecutorChecks ();
632
+ SWIFT_TASK_DEBUG_LOG (" executor checking: use legacy mode = %d" , useLegacyMode);
633
+ auto *options = static_cast <swift_task_is_current_executor_flag *>(context);
634
+ SWIFT_TASK_DEBUG_LOG (" executor checking: options = %d" , *options);
635
+ // if (!useLegacyMode) {
636
+ // *options = swift_task_is_current_executor_flag(
637
+ // *options | swift_task_is_current_executor_flag::Assert);
638
+ // }
639
+ *options = useLegacyMode;
640
+ SWIFT_TASK_DEBUG_LOG (" executor checking: resulting options = %d" , *options);
641
+ SWIFT_TASK_DEBUG_LOG (" executor checking: option Assert = %d" ,
642
+ SwiftTaskIsCurrentExecutorOptions (*options).
643
+ contains (swift_task_is_current_executor_flag::Assert));
644
+ SWIFT_TASK_DEBUG_LOG (" executor checking: option HasIsIsolatingCurrentContext = %d" ,
645
+ SwiftTaskIsCurrentExecutorOptions (*options).
646
+ contains (swift_task_is_current_executor_flag::HasIsIsolatingCurrentContext));
559
647
}
560
648
561
649
SWIFT_CC (swift)
@@ -2306,8 +2394,7 @@ static void swift_task_switchImpl(SWIFT_ASYNC_CONTEXT AsyncContext *resumeContex
2306
2394
currentTaskExecutor.getIdentity (),
2307
2395
currentTaskExecutor.isDefined () ? " " : " (undefined)" ,
2308
2396
newTaskExecutor.getIdentity (),
2309
- newTaskExecutor.isDefined () ? " " : " (undefined)" ,
2310
- trackingInfo->isSynchronousStart () ? " [synchronous start]" : " " );
2397
+ newTaskExecutor.isDefined () ? " " : " (undefined)" );
2311
2398
2312
2399
// If the current executor is compatible with running the new executor,
2313
2400
// we can just immediately continue running with the resume function
0 commit comments