@@ -998,9 +998,14 @@ struct Diagnostic {
998998
999999#[ derive( PartialEq , Clone , Copy , Debug ) ]
10001000enum MainThreadWorkerState {
1001+ /// Doing nothing.
10011002 Idle ,
1003+
1004+ /// Doing codegen, i.e. MIR-to-LLVM-IR conversion.
10021005 Codegenning ,
1003- LLVMing ,
1006+
1007+ /// Idle, but lending the compiler process's Token to an LLVM thread so it can do useful work.
1008+ Lending ,
10041009}
10051010
10061011fn start_executing_work < B : ExtraBackendMethods > (
@@ -1296,7 +1301,13 @@ fn start_executing_work<B: ExtraBackendMethods>(
12961301 let mut tokens = Vec :: new ( ) ;
12971302
12981303 let mut main_thread_worker_state = MainThreadWorkerState :: Idle ;
1299- let mut running = 0 ;
1304+
1305+ // How many LLVM worker threads are running while holding a Token. This
1306+ // *excludes* the LLVM worker thread that the main thread is lending a
1307+ // Token to (when the main thread is in the `Lending` state).
1308+ // In other words, the number of LLVM threads is actually equal to
1309+ // `running + if main_thread_worker_state == Lending { 1 } else { 0 }`.
1310+ let mut running_with_own_token = 0 ;
13001311
13011312 let prof = & cgcx. prof ;
13021313 let mut llvm_start_time: Option < VerboseTimingGuard < ' _ > > = None ;
@@ -1307,8 +1318,8 @@ fn start_executing_work<B: ExtraBackendMethods>(
13071318 // only apply if codegen hasn't been aborted as they represent pending
13081319 // work to be done.
13091320 while codegen_state == Ongoing
1310- || running > 0
1311- || main_thread_worker_state == MainThreadWorkerState :: LLVMing
1321+ || running_with_own_token > 0
1322+ || main_thread_worker_state == MainThreadWorkerState :: Lending
13121323 || ( codegen_state == Completed
13131324 && !( work_items. is_empty ( )
13141325 && needs_fat_lto. is_empty ( )
@@ -1323,13 +1334,14 @@ fn start_executing_work<B: ExtraBackendMethods>(
13231334 if main_thread_worker_state == MainThreadWorkerState :: Idle {
13241335 // Compute the number of workers that will be running once we've taken as many
13251336 // items from the work queue as we can, plus one for the main thread. It's not
1326- // critically important that we use this instead of just `running`, but it
1327- // prevents the `queue_full_enough` heuristic from fluctuating just because a
1328- // worker finished up and we decreased the `running` count, even though we're
1329- // just going to increase it right after this when we put a new worker to work.
1330- let extra_tokens = tokens. len ( ) . checked_sub ( running) . unwrap ( ) ;
1337+ // critically important that we use this instead of just
1338+ // `running_with_own_token`, but it prevents the `queue_full_enough` heuristic
1339+ // from fluctuating just because a worker finished up and we decreased the
1340+ // `running_with_own_token` count, even though we're just going to increase it
1341+ // right after this when we put a new worker to work.
1342+ let extra_tokens = tokens. len ( ) . checked_sub ( running_with_own_token) . unwrap ( ) ;
13311343 let additional_running = std:: cmp:: min ( extra_tokens, work_items. len ( ) ) ;
1332- let anticipated_running = running + additional_running + 1 ;
1344+ let anticipated_running = running_with_own_token + additional_running + 1 ;
13331345
13341346 if !queue_full_enough ( work_items. len ( ) , anticipated_running) {
13351347 // The queue is not full enough, process more codegen units:
@@ -1352,7 +1364,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
13521364 cgcx. config ( item. module_kind ( ) ) ,
13531365 & mut llvm_start_time,
13541366 ) ;
1355- main_thread_worker_state = MainThreadWorkerState :: LLVMing ;
1367+ main_thread_worker_state = MainThreadWorkerState :: Lending ;
13561368 spawn_work ( cgcx, item) ;
13571369 }
13581370 }
@@ -1363,7 +1375,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
13631375 // going to LTO and then push a bunch of work items onto our
13641376 // queue to do LTO
13651377 if work_items. is_empty ( )
1366- && running == 0
1378+ && running_with_own_token == 0
13671379 && main_thread_worker_state == MainThreadWorkerState :: Idle
13681380 {
13691381 assert ! ( !started_lto) ;
@@ -1401,7 +1413,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
14011413 cgcx. config ( item. module_kind ( ) ) ,
14021414 & mut llvm_start_time,
14031415 ) ;
1404- main_thread_worker_state = MainThreadWorkerState :: LLVMing ;
1416+ main_thread_worker_state = MainThreadWorkerState :: Lending ;
14051417 spawn_work ( cgcx, item) ;
14061418 } else {
14071419 // There is no unstarted work, so let the main thread
@@ -1410,16 +1422,16 @@ fn start_executing_work<B: ExtraBackendMethods>(
14101422 // We reduce the `running` counter by one. The
14111423 // `tokens.truncate()` below will take care of
14121424 // giving the Token back.
1413- debug_assert ! ( running > 0 ) ;
1414- running -= 1 ;
1415- main_thread_worker_state = MainThreadWorkerState :: LLVMing ;
1425+ debug_assert ! ( running_with_own_token > 0 ) ;
1426+ running_with_own_token -= 1 ;
1427+ main_thread_worker_state = MainThreadWorkerState :: Lending ;
14161428 }
14171429 }
14181430 MainThreadWorkerState :: Codegenning => bug ! (
14191431 "codegen worker should not be codegenning after \
14201432 codegen was already completed"
14211433 ) ,
1422- MainThreadWorkerState :: LLVMing => {
1434+ MainThreadWorkerState :: Lending => {
14231435 // Already making good use of that token
14241436 }
14251437 }
@@ -1431,7 +1443,10 @@ fn start_executing_work<B: ExtraBackendMethods>(
14311443
14321444 // Spin up what work we can, only doing this while we've got available
14331445 // parallelism slots and work left to spawn.
1434- while codegen_state != Aborted && !work_items. is_empty ( ) && running < tokens. len ( ) {
1446+ while codegen_state != Aborted
1447+ && !work_items. is_empty ( )
1448+ && running_with_own_token < tokens. len ( )
1449+ {
14351450 let ( item, _) = work_items. pop ( ) . unwrap ( ) ;
14361451
14371452 maybe_start_llvm_timer ( prof, cgcx. config ( item. module_kind ( ) ) , & mut llvm_start_time) ;
@@ -1440,22 +1455,22 @@ fn start_executing_work<B: ExtraBackendMethods>(
14401455 CodegenContext { worker : get_worker_id ( & mut free_worker_ids) , ..cgcx. clone ( ) } ;
14411456
14421457 spawn_work ( cgcx, item) ;
1443- running += 1 ;
1458+ running_with_own_token += 1 ;
14441459 }
14451460
1446- // Relinquish accidentally acquired extra tokens
1447- tokens. truncate ( running ) ;
1461+ // Relinquish accidentally acquired extra tokens.
1462+ tokens. truncate ( running_with_own_token ) ;
14481463
14491464 // If a thread exits successfully then we drop a token associated
1450- // with that worker and update our `running ` count. We may later
1451- // re-acquire a token to continue running more work. We may also not
1452- // actually drop a token here if the worker was running with an
1453- // "ephemeral token"
1465+ // with that worker and update our `running_with_own_token ` count.
1466+ // We may later re-acquire a token to continue running more work.
1467+ // We may also not actually drop a token here if the worker was
1468+ // running with an "ephemeral token".
14541469 let mut free_worker = |worker_id| {
1455- if main_thread_worker_state == MainThreadWorkerState :: LLVMing {
1470+ if main_thread_worker_state == MainThreadWorkerState :: Lending {
14561471 main_thread_worker_state = MainThreadWorkerState :: Idle ;
14571472 } else {
1458- running -= 1 ;
1473+ running_with_own_token -= 1 ;
14591474 }
14601475
14611476 free_worker_ids. push ( worker_id) ;
@@ -1471,13 +1486,13 @@ fn start_executing_work<B: ExtraBackendMethods>(
14711486 Ok ( token) => {
14721487 tokens. push ( token) ;
14731488
1474- if main_thread_worker_state == MainThreadWorkerState :: LLVMing {
1489+ if main_thread_worker_state == MainThreadWorkerState :: Lending {
14751490 // If the main thread token is used for LLVM work
14761491 // at the moment, we turn that thread into a regular
14771492 // LLVM worker thread, so the main thread is free
14781493 // to react to codegen demand.
14791494 main_thread_worker_state = MainThreadWorkerState :: Idle ;
1480- running += 1 ;
1495+ running_with_own_token += 1 ;
14811496 }
14821497 }
14831498 Err ( e) => {
@@ -1523,7 +1538,8 @@ fn start_executing_work<B: ExtraBackendMethods>(
15231538 // to exit as soon as possible, but we want to make sure all
15241539 // existing work has finished. Flag codegen as being done, and
15251540 // then conditions above will ensure no more work is spawned but
1526- // we'll keep executing this loop until `running` hits 0.
1541+ // we'll keep executing this loop until `running_with_own_token`
1542+ // hits 0.
15271543 Message :: CodegenAborted => {
15281544 codegen_state = Aborted ;
15291545 }
0 commit comments