version 1.147, 2020/01/13 14:14:24 |
version 1.148, 2020/01/13 14:51:50 |
|
|
#define ABORT_INTERRUPT 2 /* Because it was interrupted */ |
#define ABORT_INTERRUPT 2 /* Because it was interrupted */ |
#define ABORT_WAIT 3 /* Waiting for jobs to finish */ |
#define ABORT_WAIT 3 /* Waiting for jobs to finish */ |
|
|
static int maxJobs; /* The most children we can run at once */ |
|
static int nJobs; /* Number of jobs already allocated */ |
|
static bool no_new_jobs; /* Mark recursive shit so we shouldn't start |
static bool no_new_jobs; /* Mark recursive shit so we shouldn't start |
* something else at the same time |
* something else at the same time |
*/ |
*/ |
|
bool sequential; |
Job *runningJobs; /* Jobs currently running a process */ |
Job *runningJobs; /* Jobs currently running a process */ |
Job *errorJobs; /* Jobs in error at end */ |
Job *errorJobs; /* Jobs in error at end */ |
|
Job *availableJobs; /* Pool of available jobs */ |
static Job *heldJobs; /* Jobs not running yet because of expensive */ |
static Job *heldJobs; /* Jobs not running yet because of expensive */ |
static pid_t mypid; /* Used for printing debugging messages */ |
static pid_t mypid; /* Used for printing debugging messages */ |
|
static Job *extra_job; /* Needed for .INTERRUPT */ |
|
|
static volatile sig_atomic_t got_fatal; |
static volatile sig_atomic_t got_fatal; |
|
|
|
|
if (job->exit_type == JOB_EXIT_OKAY && |
if (job->exit_type == JOB_EXIT_OKAY && |
aborting != ABORT_ERROR && |
aborting != ABORT_ERROR && |
aborting != ABORT_INTERRUPT) { |
aborting != ABORT_INTERRUPT) { |
|
job->next = availableJobs; |
|
availableJobs = job; |
/* As long as we aren't aborting and the job didn't return a |
/* As long as we aren't aborting and the job didn't return a |
* non-zero status that we shouldn't ignore, we call |
* non-zero status that we shouldn't ignore, we call |
* Make_Update to update the parents. */ |
* Make_Update to update the parents. */ |
job->node->built_status = REBUILT; |
job->node->built_status = REBUILT; |
Make_Update(job->node); |
Make_Update(job->node); |
free(job); |
job->next = availableJobs; |
} else if (job->exit_type != JOB_EXIT_OKAY && keepgoing) |
availableJobs = job; |
free(job); |
} else if (job->exit_type != JOB_EXIT_OKAY && keepgoing) { |
|
job->next = availableJobs; |
|
availableJobs = job; |
|
} |
|
|
if (errorJobs != NULL && aborting != ABORT_INTERRUPT) |
if (errorJobs != NULL && aborting != ABORT_INTERRUPT) |
aborting = ABORT_ERROR; |
aborting = ABORT_ERROR; |
|
|
Job_Touch(gn); |
Job_Touch(gn); |
return NULL; |
return NULL; |
} else { |
} else { |
Job *job; |
Job *job = availableJobs; |
|
|
job = emalloc(sizeof(Job)); |
assert(job != NULL); |
if (job == NULL) |
availableJobs = availableJobs->next; |
Punt("can't create job: out of memory"); |
|
|
|
job_attach_node(job, gn); |
job_attach_node(job, gn); |
return job; |
return job; |
} |
} |
|
|
bool finished = job_run_next(job); |
bool finished = job_run_next(job); |
if (finished) |
if (finished) |
remove_job(job); |
remove_job(job); |
else |
else if (!sequential) |
determine_expensive_job(job); |
determine_expensive_job(job); |
} |
} |
|
|
|
|
job = prepare_job(gn); |
job = prepare_job(gn); |
if (!job) |
if (!job) |
return; |
return; |
nJobs++; |
|
may_continue_job(job); |
may_continue_job(job); |
} |
} |
|
|
|
|
static void |
static void |
remove_job(Job *job) |
remove_job(Job *job) |
{ |
{ |
nJobs--; |
|
postprocess_job(job); |
postprocess_job(job); |
} |
} |
|
|
|
|
} |
} |
|
|
void |
void |
Job_Init(int maxproc) |
Job_Init(int maxJobs) |
{ |
{ |
|
Job *j; |
|
int i; |
|
|
runningJobs = NULL; |
runningJobs = NULL; |
heldJobs = NULL; |
heldJobs = NULL; |
errorJobs = NULL; |
errorJobs = NULL; |
maxJobs = maxproc; |
availableJobs = NULL; |
|
sequential = maxJobs == 1; |
|
|
|
/* we allocate n+1 jobs, since we may need an extra job for |
|
* running .INTERRUPT. */ |
|
j = ereallocarray(NULL, sizeof(Job), maxJobs+1); |
|
for (i = 0; i != maxJobs; i++) { |
|
j[i].next = availableJobs; |
|
availableJobs = &j[i]; |
|
} |
|
extra_job = &j[maxJobs]; |
mypid = getpid(); |
mypid = getpid(); |
|
|
nJobs = 0; |
|
|
|
aborting = 0; |
aborting = 0; |
setup_all_signals(); |
setup_all_signals(); |
} |
} |
|
|
bool |
bool |
can_start_job(void) |
can_start_job(void) |
{ |
{ |
if (aborting || nJobs >= maxJobs) |
if (aborting || availableJobs == NULL) |
return false; |
return false; |
else |
else |
return true; |
return true; |
|
|
if (signo == SIGINT && !touchFlag) { |
if (signo == SIGINT && !touchFlag) { |
if ((interrupt_node->type & OP_DUMMY) == 0) { |
if ((interrupt_node->type & OP_DUMMY) == 0) { |
ignoreErrors = false; |
ignoreErrors = false; |
|
extra_job->next = availableJobs; |
|
availableJobs = extra_job; |
Job_Make(interrupt_node); |
Job_Make(interrupt_node); |
} |
} |
} |
} |