@@ -568,7 +568,8 @@ impl RuntimeGlue {
568568 let me = Local :: unsafe_borrow :: < Task > ( ) ;
569569 blk ( match ( * me) . taskgroup {
570570 None => {
571- // Main task, doing first spawn ever. Lazily initialize.
571+ // First task in its (unlinked/unsupervised) taskgroup.
572+ // Lazily initialize.
572573 let mut members = TaskSet :: new ( ) ;
573574 let my_handle = ( * me) . death . kill_handle . get_ref ( ) . clone ( ) ;
574575 members. insert ( NewTask ( my_handle) ) ;
@@ -591,37 +592,46 @@ impl RuntimeGlue {
591592 }
592593}
593594
595+ // Returns 'None' in the case where the child's TG should be lazily initialized.
594596fn 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 ) )
619610 } 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+ }
624632 }
633+ } else {
634+ None
625635 }
626636}
627637
@@ -670,20 +680,24 @@ fn spawn_raw_newsched(mut opts: TaskOpts, f: ~fn()) {
670680
671681 let child_wrapper: ~fn ( ) = || {
672682 // 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+ }
687701 }
688702 } ;
689703 // Should be run after the local-borrowed task is returned.
@@ -749,7 +763,7 @@ fn spawn_raw_newsched(mut opts: TaskOpts, f: ~fn()) {
749763 let join_task = join_task_cell. take ( ) ;
750764
751765 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" ) ;
753767 } ;
754768 new_sched. bootstrap ( bootstrap_task) ;
755769
@@ -793,7 +807,7 @@ fn spawn_raw_newsched(mut opts: TaskOpts, f: ~fn()) {
793807fn spawn_raw_oldsched ( mut opts : TaskOpts , f : ~fn ( ) ) {
794808
795809 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" ) ;
797811
798812 unsafe {
799813 let child_data = Cell :: new ( ( child_tg, ancestors, f) ) ;
0 commit comments