@@ -484,6 +484,18 @@ JobPriority swift::swift_task_basePriority(AsyncTask *task)
484
484
return pri;
485
485
}
486
486
487
+ static inline bool isUnspecified (JobPriority priority) {
488
+ return priority == JobPriority::Unspecified;
489
+ }
490
+
491
+ static inline bool taskIsUnstructured (JobFlags jobFlags) {
492
+ return !jobFlags.task_isAsyncLetTask () && !jobFlags.task_isGroupChildTask ();
493
+ }
494
+
495
+ static inline bool taskIsDetached (TaskCreateFlags createFlags, JobFlags jobFlags) {
496
+ return taskIsUnstructured (jobFlags) && !createFlags.copyTaskLocals ();
497
+ }
498
+
487
499
// / Implementation of task creation.
488
500
SWIFT_CC (swift)
489
501
static AsyncTaskAndContext swift_task_create_commonImpl(
@@ -492,10 +504,11 @@ static AsyncTaskAndContext swift_task_create_commonImpl(
492
504
const Metadata *futureResultType,
493
505
TaskContinuationFunction *function, void *closureContext,
494
506
size_t initialContextSize) {
507
+
495
508
TaskCreateFlags taskCreateFlags (rawTaskCreateFlags);
509
+ JobFlags jobFlags (JobKind::Task, JobPriority::Unspecified);
496
510
497
511
// Propagate task-creation flags to job flags as appropriate.
498
- JobFlags jobFlags (JobKind::Task, taskCreateFlags.getCreationPriority ());
499
512
jobFlags.task_setIsChildTask (taskCreateFlags.isChildTask ());
500
513
if (futureResultType) {
501
514
jobFlags.task_setIsFuture (true );
@@ -548,34 +561,85 @@ static AsyncTaskAndContext swift_task_create_commonImpl(
548
561
}
549
562
550
563
AsyncTask *parent = nullptr ;
564
+ AsyncTask *currentTask = swift_task_getCurrent ();
551
565
if (jobFlags.task_isChildTask ()) {
552
- parent = swift_task_getCurrent () ;
566
+ parent = currentTask ;
553
567
assert (parent != nullptr && " creating a child task with no active task" );
554
568
}
555
569
556
- // Inherit the priority of the currently-executing task if unspecified and
557
- // we want to inherit.
558
- if (jobFlags.getPriority () == JobPriority::Unspecified &&
559
- (jobFlags.task_isChildTask () || taskCreateFlags.inheritContext ())) {
560
- AsyncTask *currentTask = parent;
561
- if (!currentTask)
562
- currentTask = swift_task_getCurrent ();
563
-
564
- if (currentTask)
565
- jobFlags.setPriority (currentTask->getPriority ());
566
- else if (taskCreateFlags.inheritContext ())
567
- jobFlags.setPriority (swift_task_getCurrentThreadPriority ());
570
+ // Start with user specified priority at creation time (if any)
571
+ JobPriority basePriority = (taskCreateFlags.getRequestedPriority ());
572
+
573
+ if (taskIsDetached (taskCreateFlags, jobFlags)) {
574
+ SWIFT_TASK_DEBUG_LOG (" Creating a detached task from %p" , currentTask);
575
+ // Case 1: No priority specified
576
+ // Base priority = UN
577
+ // Escalated priority = UN
578
+ // Case 2: Priority specified
579
+ // Base priority = user specified priority
580
+ // Escalated priority = UN
581
+ //
582
+ // Task will be created with max priority = max(base priority, UN) = base
583
+ // priority. We shouldn't need to do any additional manipulations here since
584
+ // basePriority should already be the right value
585
+
586
+ } else if (taskIsUnstructured (jobFlags)) {
587
+ SWIFT_TASK_DEBUG_LOG (" Creating an unstructured task from %p" , currentTask);
588
+
589
+ if (isUnspecified (basePriority)) {
590
+ // Case 1: No priority specified
591
+ // Base priority = Base priority of parent with a UI -> IN downgrade
592
+ // Escalated priority = UN
593
+ if (currentTask) {
594
+ basePriority = currentTask->_private ().BasePriority ;
595
+ } else {
596
+ basePriority = swift_task_getCurrentThreadPriority ();
597
+ }
598
+ basePriority = withUserInteractivePriorityDowngrade (basePriority);
599
+ } else {
600
+ // Case 2: User specified a priority
601
+ // Base priority = user specified priority
602
+ // Escalated priority = UN
603
+ }
604
+
605
+ // Task will be created with max priority = max(base priority, UN) = base
606
+ // priority
607
+ } else {
608
+ // Is a structured concurrency child task. Must have a parent.
609
+ assert ((asyncLet || group) && parent);
610
+ SWIFT_TASK_DEBUG_LOG (" Creating an structured concurrency task from %p" , currentTask);
611
+
612
+ if (isUnspecified (basePriority)) {
613
+ // Case 1: No priority specified
614
+ // Base priority = Base priority of parent with a UI -> IN downgrade
615
+ // Escalated priority = Escalated priority of parent with a UI -> IN
616
+ // downgrade
617
+ JobPriority parentBasePri = parent->_private ().BasePriority ;
618
+ basePriority = withUserInteractivePriorityDowngrade (parentBasePri);
619
+ } else {
620
+ // Case 2: User priority specified
621
+ // Base priority = User specified priority
622
+ // Escalated priority = Escalated priority of parent with a UI -> IN
623
+ // downgrade
624
+ }
625
+
626
+ // Task will be created with escalated priority = base priority. We will
627
+ // update the escalated priority with the right rules in
628
+ // updateNewChildWithParentAndGroupState when we link the child into
629
+ // the parent task/task group since we'll have the right
630
+ // synchronization then.
568
631
}
569
632
570
- // Adjust user-interactive priorities down to user-initiated.
571
- if (jobFlags. getPriority () == JobPriority::UserInteractive)
572
- jobFlags. setPriority (JobPriority::UserInitiated);
633
+ if ( isUnspecified (basePriority)) {
634
+ basePriority = JobPriority::Default;
635
+ }
573
636
574
- // If there is still no job priority, use the default priority.
575
- if (jobFlags.getPriority () == JobPriority::Unspecified)
576
- jobFlags.setPriority (JobPriority::Default);
637
+ SWIFT_TASK_DEBUG_LOG (" Task's base priority = %d" , basePriority);
577
638
578
- JobPriority basePriority = jobFlags.getPriority ();
639
+ // TODO (rokhinip): Figure out the semantics of the job priority and where
640
+ // it ought to be set conclusively - seems like it ought to be at enqueue
641
+ // time. For now, maintain current semantics of setting jobPriority as well.
642
+ jobFlags.setPriority (basePriority);
579
643
580
644
// Figure out the size of the header.
581
645
size_t headerSize = sizeof (AsyncTask);
@@ -669,7 +733,7 @@ static AsyncTaskAndContext swift_task_create_commonImpl(
669
733
// Initialize the task so that resuming it will run the given
670
734
// function on the initial context.
671
735
AsyncTask *task = nullptr ;
672
- bool captureCurrentVoucher = taskCreateFlags. copyTaskLocals () || jobFlags. task_isChildTask ( );
736
+ bool captureCurrentVoucher = ! taskIsDetached (taskCreateFlags, jobFlags);
673
737
if (asyncLet) {
674
738
// Initialize the refcount bits to "immortal", so that
675
739
// ARC operations don't have any effect on the task.
@@ -710,7 +774,7 @@ static AsyncTaskAndContext swift_task_create_commonImpl(
710
774
futureAsyncContextPrefix->indirectResult = futureFragment->getStoragePtr ();
711
775
}
712
776
713
- SWIFT_TASK_DEBUG_LOG (" creating task %p with parent %p" , task, parent);
777
+ SWIFT_TASK_DEBUG_LOG (" creating task %p with parent %p at base pri %zu " , task, parent, basePriority );
714
778
715
779
// Initialize the task-local allocator.
716
780
initialContext->ResumeParent = reinterpret_cast <TaskContinuationFunction *>(
0 commit comments