@@ -568,7 +568,8 @@ impl RuntimeGlue {
568
568
let me = Local :: unsafe_borrow :: < Task > ( ) ;
569
569
blk ( match ( * me) . taskgroup {
570
570
None => {
571
- // Main task, doing first spawn ever. Lazily initialize.
571
+ // First task in its (unlinked/unsupervised) taskgroup.
572
+ // Lazily initialize.
572
573
let mut members = TaskSet :: new ( ) ;
573
574
let my_handle = ( * me) . death . kill_handle . get_ref ( ) . clone ( ) ;
574
575
members. insert ( NewTask ( my_handle) ) ;
@@ -591,37 +592,46 @@ impl RuntimeGlue {
591
592
}
592
593
}
593
594
595
+ // Returns 'None' in the case where the child's TG should be lazily initialized.
594
596
fn gen_child_taskgroup ( linked : bool , supervised : bool )
595
- -> ( TaskGroupArc , AncestorList , bool ) {
596
- do RuntimeGlue :: with_my_taskgroup |spawner_group| {
597
- let ancestors = AncestorList ( spawner_group. ancestors . map ( |x| x. clone ( ) ) ) ;
598
- if linked {
599
- // Child is in the same group as spawner.
600
- // Child's ancestors are spawner's ancestors.
601
- // Propagate main-ness.
602
- ( spawner_group. tasks . clone ( ) , ancestors, spawner_group. is_main )
603
- } else {
604
- // Child is in a separate group from spawner.
605
- let g = Exclusive :: new ( Some ( TaskGroupData {
606
- members : TaskSet :: new ( ) ,
607
- descendants : TaskSet :: new ( ) ,
608
- } ) ) ;
609
- let a = if supervised {
610
- let new_generation = incr_generation ( & ancestors) ;
611
- assert ! ( new_generation < uint:: max_value) ;
612
- // Child's ancestors start with the spawner.
613
- // Build a new node in the ancestor list.
614
- AncestorList ( Some ( Exclusive :: new ( AncestorNode {
615
- generation : new_generation,
616
- parent_group : spawner_group. tasks . clone ( ) ,
617
- ancestors : ancestors,
618
- } ) ) )
597
+ -> Option < ( TaskGroupArc , AncestorList , bool ) > {
598
+ // FIXME(#7544): Not safe to lazily initialize in the old runtime. Remove
599
+ // this context check once 'spawn_raw_oldsched' is gone.
600
+ if context ( ) == OldTaskContext || linked || supervised {
601
+ // with_my_taskgroup will lazily initialize the parent's taskgroup if
602
+ // it doesn't yet exist. We don't want to call it in the unlinked case.
603
+ do RuntimeGlue :: with_my_taskgroup |spawner_group| {
604
+ let ancestors = AncestorList ( spawner_group. ancestors . map ( |x| x. clone ( ) ) ) ;
605
+ if linked {
606
+ // Child is in the same group as spawner.
607
+ // Child's ancestors are spawner's ancestors.
608
+ // Propagate main-ness.
609
+ Some ( ( spawner_group. tasks . clone ( ) , ancestors, spawner_group. is_main ) )
619
610
} else {
620
- // Child has no ancestors.
621
- AncestorList ( None )
622
- } ;
623
- ( g, a, false )
611
+ // Child is in a separate group from spawner.
612
+ let g = Exclusive :: new ( Some ( TaskGroupData {
613
+ members : TaskSet :: new ( ) ,
614
+ descendants : TaskSet :: new ( ) ,
615
+ } ) ) ;
616
+ let a = if supervised {
617
+ let new_generation = incr_generation ( & ancestors) ;
618
+ assert ! ( new_generation < uint:: max_value) ;
619
+ // Child's ancestors start with the spawner.
620
+ // Build a new node in the ancestor list.
621
+ AncestorList ( Some ( Exclusive :: new ( AncestorNode {
622
+ generation : new_generation,
623
+ parent_group : spawner_group. tasks . clone ( ) ,
624
+ ancestors : ancestors,
625
+ } ) ) )
626
+ } else {
627
+ // Child has no ancestors.
628
+ AncestorList ( None )
629
+ } ;
630
+ Some ( ( g, a, false ) )
631
+ }
624
632
}
633
+ } else {
634
+ None
625
635
}
626
636
}
627
637
@@ -670,20 +680,24 @@ fn spawn_raw_newsched(mut opts: TaskOpts, f: ~fn()) {
670
680
671
681
let child_wrapper: ~fn ( ) = || {
672
682
// Child task runs this code.
673
- let child_data = Cell :: new ( child_data. take ( ) ) ; // :(
674
- let enlist_success = do Local :: borrow :: < Task , bool > |me| {
675
- let ( child_tg, ancestors, is_main) = child_data. take ( ) ;
676
- let mut ancestors = ancestors;
677
- // FIXME(#7544): Optimize out the xadd in this clone, somehow.
678
- let handle = me. death . kill_handle . get_ref ( ) . clone ( ) ;
679
- // Atomically try to get into all of our taskgroups.
680
- if enlist_many ( NewTask ( handle) , & child_tg, & mut ancestors) {
681
- // Got in. We can run the provided child body, and can also run
682
- // the taskgroup's exit-time-destructor afterward.
683
- me. taskgroup = Some ( Taskgroup ( child_tg, ancestors, is_main, None ) ) ;
684
- true
685
- } else {
686
- false
683
+
684
+ // If child data is 'None', the enlist is vacuously successful.
685
+ let enlist_success = do child_data. take ( ) . map_consume_default ( true ) |child_data| {
686
+ let child_data = Cell :: new ( child_data) ; // :(
687
+ do Local :: borrow :: < Task , bool > |me| {
688
+ let ( child_tg, ancestors, is_main) = child_data. take ( ) ;
689
+ let mut ancestors = ancestors;
690
+ // FIXME(#7544): Optimize out the xadd in this clone, somehow.
691
+ let handle = me. death . kill_handle . get_ref ( ) . clone ( ) ;
692
+ // Atomically try to get into all of our taskgroups.
693
+ if enlist_many ( NewTask ( handle) , & child_tg, & mut ancestors) {
694
+ // Got in. We can run the provided child body, and can also run
695
+ // the taskgroup's exit-time-destructor afterward.
696
+ me. taskgroup = Some ( Taskgroup ( child_tg, ancestors, is_main, None ) ) ;
697
+ true
698
+ } else {
699
+ false
700
+ }
687
701
}
688
702
} ;
689
703
// Should be run after the local-borrowed task is returned.
@@ -749,7 +763,7 @@ fn spawn_raw_newsched(mut opts: TaskOpts, f: ~fn()) {
749
763
let join_task = join_task_cell. take ( ) ;
750
764
751
765
let bootstrap_task = ~do Task :: new_root ( & mut new_sched. stack_pool ) || {
752
- rtdebug ! ( "boostraping a 1:1 scheduler" ) ;
766
+ rtdebug ! ( "bootstrapping a 1:1 scheduler" ) ;
753
767
} ;
754
768
new_sched. bootstrap ( bootstrap_task) ;
755
769
@@ -793,7 +807,7 @@ fn spawn_raw_newsched(mut opts: TaskOpts, f: ~fn()) {
793
807
fn spawn_raw_oldsched ( mut opts : TaskOpts , f : ~fn ( ) ) {
794
808
795
809
let ( child_tg, ancestors, is_main) =
796
- gen_child_taskgroup ( opts. linked , opts. supervised ) ;
810
+ gen_child_taskgroup ( opts. linked , opts. supervised ) . expect ( "old runtime needs TG" ) ;
797
811
798
812
unsafe {
799
813
let child_data = Cell :: new ( ( child_tg, ancestors, f) ) ;
0 commit comments