/*- *----------------------------------------------------------------------- * Make_Run -- * Initialize the nodes to remake and the list of nodes which are * ready to be made by doing a breadth-first traversal of the graph * starting from the nodes in the given list. Once this traversal * is finished, all the 'leaves' of the graph are in the toBeMade * queue. * Using this queue and the Job module, work back up the graph, * calling on MakeStartJobs to keep the job table as full as * possible. * * Results: * true if work was done. false otherwise. * * Side Effects: * The must_make field of all nodes involved in the creation of the given * targets is set to 1. The toBeMade list is set to contain all the * 'leaves' of these subgraphs. *----------------------------------------------------------------------- */ bool Make_Run(Lst targs) /* the initial list of targets */ { int errors; /* Number of errors the Job module reports */ GNode *gn; unsigned int i; bool cycle; /* wild guess at initial sizes */ Array_Init(&toBeMade, 500); Array_Init(&examine, 150); ohash_init(&targets, 10, &gnode_info); if (DEBUG(PARALLEL)) random_setup(); add_targets_to_make(targs); if (queryFlag) { /* * We wouldn't do any work unless we could start some jobs in * the next loop... (we won't actually start any, of course, * this is just to see if any of the targets was out of date) */ return MakeStartJobs(); } else { /* * Initialization. At the moment, no jobs are running and until * some get started, nothing will happen since the remaining * upward traversal of the graph is performed by the routines * in job.c upon the finishing of a job. So we fill the Job * table as much as we can before going into our loop. */ (void)MakeStartJobs(); } /* * Main Loop: The idea here is that the ending of jobs will take * care of the maintenance of data structures and the waiting for output * will cause us to be idle most of the time while our children run as * much as possible. Because the job table is kept as full as possible, * the only time when it will be empty is when all the jobs which need * running have been run, so that is the end condition of this loop. * Note that the Job module will exit if there were any errors unless * the keepgoing flag was given. */ while (!Job_Empty()) { handle_running_jobs(); (void)MakeStartJobs(); } errors = Job_Finish(); cycle = false; for (gn = ohash_first(&targets, &i); gn != NULL; gn = ohash_next(&targets, &i)) { if (has_been_built(gn)) continue; cycle = true; errors++; printf("Error: target %s unaccounted for (%s)\n", gn->name, status_to_string(gn)); } /* * Print the final status of each target. E.g. if it wasn't made * because some inferior reported an error. */ Lst_ForEach(targs, MakePrintStatus, &cycle); if (errors) Fatal("Errors while building"); return true; }
static void loop_handle_running_jobs() { while (nJobs) handle_running_jobs(); }