version 1.28, 2000/06/10 01:41:05 |
version 1.29, 2000/06/17 14:38:15 |
|
|
static int maxLocal; /* The most local ones we can have */ |
static int maxLocal; /* The most local ones we can have */ |
STATIC int nJobs; /* The number of children currently running */ |
STATIC int nJobs; /* The number of children currently running */ |
STATIC int nLocal; /* The number of local children */ |
STATIC int nLocal; /* The number of local children */ |
STATIC Lst jobs; /* The structures that describe them */ |
STATIC LIST jobs; /* The structures that describe them */ |
STATIC Boolean jobFull; /* Flag to tell when the job table is full. It |
STATIC Boolean jobFull; /* Flag to tell when the job table is full. It |
* is set TRUE when (1) the total number of |
* is set TRUE when (1) the total number of |
* running jobs equals the maximum allowed or |
* running jobs equals the maximum allowed or |
|
|
* been migrated home, the job is placed on the stoppedJobs queue to be run |
* been migrated home, the job is placed on the stoppedJobs queue to be run |
* when the next job finishes. |
* when the next job finishes. |
*/ |
*/ |
STATIC Lst stoppedJobs; /* Lst of Job structures describing |
STATIC LIST stoppedJobs; /* Lst of Job structures describing |
* jobs that were stopped due to concurrency |
* jobs that were stopped due to concurrency |
* limits or migration home */ |
* limits or migration home */ |
|
|
|
|
(void) fprintf(stdout, "JobPassSig(%d) called.\n", signo); |
(void) fprintf(stdout, "JobPassSig(%d) called.\n", signo); |
(void) fflush(stdout); |
(void) fflush(stdout); |
} |
} |
Lst_ForEach(jobs, JobCondPassSig, &signo); |
Lst_ForEach(&jobs, JobCondPassSig, &signo); |
|
|
/* |
/* |
* Deal with proper cleanup based on the signal received. We only run |
* Deal with proper cleanup based on the signal received. We only run |
|
|
(void) KILL(getpid(), signo); |
(void) KILL(getpid(), signo); |
|
|
signo = SIGCONT; |
signo = SIGCONT; |
Lst_ForEach(jobs, JobCondPassSig, &signo); |
Lst_ForEach(&jobs, JobCondPassSig, &signo); |
|
|
(void) sigprocmask(SIG_SETMASK, &omask, NULL); |
(void) sigprocmask(SIG_SETMASK, &omask, NULL); |
sigprocmask(SIG_SETMASK, &omask, NULL); |
sigprocmask(SIG_SETMASK, &omask, NULL); |
|
|
if (strcmp(cmd, "...") == 0) { |
if (strcmp(cmd, "...") == 0) { |
job->node->type |= OP_SAVE_CMDS; |
job->node->type |= OP_SAVE_CMDS; |
if ((job->flags & JOB_IGNDOTS) == 0) { |
if ((job->flags & JOB_IGNDOTS) == 0) { |
job->tailCmds = Lst_Succ(Lst_Member(job->node->commands, |
job->tailCmds = Lst_Succ(Lst_Member(&job->node->commands, cmd)); |
cmd)); |
|
return 0; |
return 0; |
} |
} |
return 1; |
return 1; |
|
|
* For debugging, we replace each command with the result of expanding |
* For debugging, we replace each command with the result of expanding |
* the variables in the command. |
* the variables in the command. |
*/ |
*/ |
cmdNode = Lst_Member(job->node->commands, cmd); |
cmdNode = Lst_Member(&job->node->commands, cmd); |
cmdStart = cmd = Var_Subst(cmd, job->node, FALSE); |
cmdStart = cmd = Var_Subst(cmd, job->node, FALSE); |
Lst_Replace(cmdNode, cmdStart); |
Lst_Replace(cmdNode, cmdStart); |
|
|
|
|
char *result; |
char *result; |
|
|
result = Var_Subst((char *)cmd, (GNode *)gn, FALSE); |
result = Var_Subst((char *)cmd, (GNode *)gn, FALSE); |
Lst_AtEnd(postCommands->commands, result); |
Lst_AtEnd(&postCommands->commands, result); |
} |
} |
|
|
|
|
|
|
WSTOPSIG(*status)); |
WSTOPSIG(*status)); |
} |
} |
job->flags |= JOB_RESUME; |
job->flags |= JOB_RESUME; |
Lst_AtEnd(stoppedJobs, job); |
Lst_AtEnd(&stoppedJobs, job); |
#ifdef REMOTE |
#ifdef REMOTE |
if (job->flags & JOB_REMIGRATE) |
if (job->flags & JOB_REMIGRATE) |
JobRestart(job); |
JobRestart(job); |
|
|
#endif |
#endif |
} |
} |
job->flags &= ~JOB_CONTINUING; |
job->flags &= ~JOB_CONTINUING; |
Lst_AtEnd(jobs, job); |
Lst_AtEnd(&jobs, job); |
nJobs += 1; |
nJobs += 1; |
if (!(job->flags & JOB_REMOTE)) { |
if (!(job->flags & JOB_REMOTE)) { |
if (DEBUG(JOB)) { |
if (DEBUG(JOB)) { |
|
|
* ok, it's ok. If there's an error, this puppy is done. |
* ok, it's ok. If there's an error, this puppy is done. |
*/ |
*/ |
if (compatMake && (WIFEXITED(*status) && |
if (compatMake && (WIFEXITED(*status) && |
!Lst_IsAtEnd(job->node->commands))) { |
!Lst_IsAtEnd(&job->node->commands))) { |
switch (JobStart(job->node, job->flags & JOB_IGNDOTS, job)) { |
switch (JobStart(job->node, job->flags & JOB_IGNDOTS, job)) { |
case JOB_RUNNING: |
case JOB_RUNNING: |
done = FALSE; |
done = FALSE; |
|
|
void (*abortProc) __P((char *, ...)); |
void (*abortProc) __P((char *, ...)); |
/* Function to abort with message */ |
/* Function to abort with message */ |
{ |
{ |
if (OP_NOP(gn->type) && Lst_IsEmpty(gn->commands) && |
if (OP_NOP(gn->type) && Lst_IsEmpty(&gn->commands) && |
(gn->type & OP_LIB) == 0) { |
(gn->type & OP_LIB) == 0) { |
/* |
/* |
* No commands. Look for .DEFAULT rule from which we might infer |
* No commands. Look for .DEFAULT rule from which we might infer |
* commands |
* commands |
*/ |
*/ |
if ((DEFAULT != NULL) && !Lst_IsEmpty(DEFAULT->commands)) { |
if ((DEFAULT != NULL) && !Lst_IsEmpty(&DEFAULT->commands)) { |
/* |
/* |
* Make only looks for a .DEFAULT if the node was never the |
* Make only looks for a .DEFAULT if the node was never the |
* target of an operator, so that's what we do too. If |
* target of an operator, so that's what we do too. If |
|
|
* Now the job is actually running, add it to the table. |
* Now the job is actually running, add it to the table. |
*/ |
*/ |
nJobs += 1; |
nJobs += 1; |
Lst_AtEnd(jobs, job); |
Lst_AtEnd(&jobs, job); |
if (nJobs == maxJobs) { |
if (nJobs == maxJobs) { |
jobFull = TRUE; |
jobFull = TRUE; |
} |
} |
|
|
(void) fprintf(stdout, "*** holding\n"); |
(void) fprintf(stdout, "*** holding\n"); |
(void) fflush(stdout); |
(void) fflush(stdout); |
} |
} |
Lst_AtFront(stoppedJobs, job); |
Lst_AtFront(&stoppedJobs, job); |
jobFull = TRUE; |
jobFull = TRUE; |
if (DEBUG(JOB)) { |
if (DEBUG(JOB)) { |
(void) fprintf(stdout, "Job queue is full.\n"); |
(void) fprintf(stdout, "Job queue is full.\n"); |
|
|
} |
} |
#endif |
#endif |
|
|
Lst_AtEnd(jobs, job); |
Lst_AtEnd(&jobs, job); |
nJobs += 1; |
nJobs += 1; |
if (nJobs == maxJobs) { |
if (nJobs == maxJobs) { |
jobFull = TRUE; |
jobFull = TRUE; |
|
|
(void) fprintf(stdout, "holding\n"); |
(void) fprintf(stdout, "holding\n"); |
(void) fflush(stdout); |
(void) fflush(stdout); |
} |
} |
Lst_AtFront(stoppedJobs, job); |
Lst_AtFront(&stoppedJobs, job); |
jobFull = TRUE; |
jobFull = TRUE; |
if (DEBUG(JOB)) { |
if (DEBUG(JOB)) { |
(void) fprintf(stdout, "Job queue is full.\n"); |
(void) fprintf(stdout, "Job queue is full.\n"); |
|
|
(void) fprintf(stdout, "table full\n"); |
(void) fprintf(stdout, "table full\n"); |
(void) fflush(stdout); |
(void) fflush(stdout); |
} |
} |
Lst_AtFront(stoppedJobs, job); |
Lst_AtFront(&stoppedJobs, job); |
jobFull = TRUE; |
jobFull = TRUE; |
if (DEBUG(JOB)) { |
if (DEBUG(JOB)) { |
(void) fprintf(stdout, "Job queue is full.\n"); |
(void) fprintf(stdout, "Job queue is full.\n"); |
|
|
* and print it to the command file. If the command was an |
* and print it to the command file. If the command was an |
* ellipsis, note that there's nothing more to execute. |
* ellipsis, note that there's nothing more to execute. |
*/ |
*/ |
if ((job->flags&JOB_FIRST) && (Lst_Open(gn->commands) != SUCCESS)){ |
if ((job->flags&JOB_FIRST) && (Lst_Open(&gn->commands) != SUCCESS)){ |
cmdsOK = FALSE; |
cmdsOK = FALSE; |
} else { |
} else { |
LstNode ln = Lst_Next(gn->commands); |
LstNode ln = Lst_Next(&gn->commands); |
|
|
if ((ln == NULL) || !JobPrintCommand(Lst_Datum(ln), job)) { |
if ((ln == NULL) || !JobPrintCommand(Lst_Datum(ln), job)) { |
noExec = TRUE; |
noExec = TRUE; |
Lst_Close(gn->commands); |
Lst_Close(&gn->commands); |
} |
} |
if (noExec && !(job->flags & JOB_FIRST)) { |
if (noExec && !(job->flags & JOB_FIRST)) { |
/* |
/* |
|
|
* We can do all the commands at once. hooray for sanity |
* We can do all the commands at once. hooray for sanity |
*/ |
*/ |
numCommands = 0; |
numCommands = 0; |
Lst_Find(gn->commands, JobPrintCommand, job); |
Lst_Find(&gn->commands, JobPrintCommand, job); |
|
|
/* |
/* |
* If we didn't print out any commands to the shell script, |
* If we didn't print out any commands to the shell script, |
|
|
* doesn't do any harm in this case and may do some good. |
* doesn't do any harm in this case and may do some good. |
*/ |
*/ |
if (cmdsOK) |
if (cmdsOK) |
Lst_Find(gn->commands, JobPrintCommand, job); |
Lst_Find(&gn->commands, JobPrintCommand, job); |
/* |
/* |
* Don't execute the shell, thank you. |
* Don't execute the shell, thank you. |
*/ |
*/ |
|
|
(void) fflush(stdout); |
(void) fflush(stdout); |
} |
} |
job->flags |= JOB_RESTART; |
job->flags |= JOB_RESTART; |
Lst_AtEnd(stoppedJobs, job); |
Lst_AtEnd(&stoppedJobs, job); |
} else { |
} else { |
if ((nLocal >= maxLocal) && local) { |
if ((nLocal >= maxLocal) && local) { |
/* |
/* |
|
|
} |
} |
|
|
|
|
jnode = Lst_Find(jobs, JobCmpPid, &pid); |
jnode = Lst_Find(&jobs, JobCmpPid, &pid); |
|
|
if (jnode == NULL) { |
if (jnode == NULL) { |
if (WIFSIGNALED(status) && (WTERMSIG(status) == SIGCONT)) { |
if (WIFSIGNALED(status) && (WTERMSIG(status) == SIGCONT)) { |
jnode = Lst_Find(stoppedJobs, JobCmpPid, &pid); |
jnode = Lst_Find(&stoppedJobs, JobCmpPid, &pid); |
if (jnode == NULL) { |
if (jnode == NULL) { |
Error("Resumed child (%d) not in table", pid); |
Error("Resumed child (%d) not in table", pid); |
continue; |
continue; |
} |
} |
job = (Job *)Lst_Datum(jnode); |
job = (Job *)Lst_Datum(jnode); |
(void) Lst_Remove(stoppedJobs, jnode); |
Lst_Remove(&stoppedJobs, jnode); |
} else { |
} else { |
Error("Child (%d) not in table?", pid); |
Error("Child (%d) not in table?", pid); |
continue; |
continue; |
} |
} |
} else { |
} else { |
job = (Job *) Lst_Datum(jnode); |
job = (Job *) Lst_Datum(jnode); |
Lst_Remove(jobs, jnode); |
Lst_Remove(&jobs, jnode); |
nJobs -= 1; |
nJobs -= 1; |
if (jobFull && DEBUG(JOB)) { |
if (jobFull && DEBUG(JOB)) { |
(void) fprintf(stdout, "Job queue is no longer full.\n"); |
(void) fprintf(stdout, "Job queue is no longer full.\n"); |
|
|
free(readfdsp); |
free(readfdsp); |
return; |
return; |
} else { |
} else { |
if (Lst_Open(jobs) == FAILURE) { |
if (Lst_Open(&jobs) == FAILURE) { |
free(readfdsp); |
free(readfdsp); |
Punt("Cannot open job table"); |
Punt("Cannot open job table"); |
} |
} |
while (nfds && (ln = Lst_Next(jobs)) != NULL) { |
while (nfds && (ln = Lst_Next(&jobs)) != NULL) { |
job = (Job *) Lst_Datum(ln); |
job = (Job *) Lst_Datum(ln); |
if (FD_ISSET(job->inPipe, readfdsp)) { |
if (FD_ISSET(job->inPipe, readfdsp)) { |
JobDoOutput(job, FALSE); |
JobDoOutput(job, FALSE); |
nfds -= 1; |
nfds -= 1; |
} |
} |
} |
} |
Lst_Close(jobs); |
Lst_Close(&jobs); |
} |
} |
free(readfdsp); |
free(readfdsp); |
} |
} |
|
|
{ |
{ |
GNode *begin; /* node for commands to do at the very start */ |
GNode *begin; /* node for commands to do at the very start */ |
|
|
jobs = Lst_Init(); |
Lst_Init(&jobs); |
stoppedJobs = Lst_Init(); |
Lst_Init(&stoppedJobs); |
maxJobs = maxproc; |
maxJobs = maxproc; |
maxLocal = maxlocal; |
maxLocal = maxlocal; |
nJobs = 0; |
nJobs = 0; |
|
|
Job_Empty() |
Job_Empty() |
{ |
{ |
if (nJobs == 0) { |
if (nJobs == 0) { |
if (!Lst_IsEmpty(stoppedJobs) && !aborting) { |
if (!Lst_IsEmpty(&stoppedJobs) && !aborting) { |
/* |
/* |
* The job table is obviously not full if it has no jobs in |
* The job table is obviously not full if it has no jobs in |
* it...Try and restart the stopped jobs. |
* it...Try and restart the stopped jobs. |
|
|
|
|
aborting = ABORT_INTERRUPT; |
aborting = ABORT_INTERRUPT; |
|
|
(void) Lst_Open(jobs); |
(void) Lst_Open(&jobs); |
while ((ln = Lst_Next(jobs)) != NULL) { |
while ((ln = Lst_Next(&jobs)) != NULL) { |
job = (Job *) Lst_Datum(ln); |
job = (Job *) Lst_Datum(ln); |
|
|
if (!Targ_Precious(job->node)) { |
if (!Targ_Precious(job->node)) { |
|
|
} |
} |
|
|
#ifdef REMOTE |
#ifdef REMOTE |
(void)Lst_Open(stoppedJobs); |
(void)Lst_Open(&stoppedJobs); |
while ((ln = Lst_Next(stoppedJobs)) != NULL) { |
while ((ln = Lst_Next(&stoppedJobs)) != NULL) { |
job = (Job *) Lst_Datum(ln); |
job = (Job *) Lst_Datum(ln); |
|
|
if (job->flags & JOB_RESTART) { |
if (job->flags & JOB_RESTART) { |
|
|
#endif /* RMT_WANTS_SIGNALS */ |
#endif /* RMT_WANTS_SIGNALS */ |
} |
} |
#endif |
#endif |
Lst_Close(stoppedJobs); |
Lst_Close(&stoppedJobs); |
|
|
if (runINTERRUPT && !touchFlag) { |
if (runINTERRUPT && !touchFlag) { |
interrupt = Targ_FindNode(".INTERRUPT", TARG_NOCREATE); |
interrupt = Targ_FindNode(".INTERRUPT", TARG_NOCREATE); |
|
|
int |
int |
Job_Finish() |
Job_Finish() |
{ |
{ |
if (postCommands != NULL && !Lst_IsEmpty(postCommands->commands)) { |
if (postCommands != NULL && !Lst_IsEmpty(&postCommands->commands)) { |
if (errors) { |
if (errors) { |
Error("Errors reported so .END ignored"); |
Error("Errors reported so .END ignored"); |
} else { |
} else { |
|
|
|
|
if (nJobs) { |
if (nJobs) { |
|
|
(void) Lst_Open(jobs); |
(void) Lst_Open(&jobs); |
while ((ln = Lst_Next(jobs)) != NULL) { |
while ((ln = Lst_Next(&jobs)) != NULL) { |
job = (Job *) Lst_Datum(ln); |
job = (Job *) Lst_Datum(ln); |
|
|
/* |
/* |
|
|
(void) fprintf(stdout, "JobFlagForMigration(%d) called.\n", hostID); |
(void) fprintf(stdout, "JobFlagForMigration(%d) called.\n", hostID); |
(void) fflush(stdout); |
(void) fflush(stdout); |
} |
} |
jnode = Lst_Find(jobs, JobCmpRmtID, &hostID); |
jnode = Lst_Find(&jobs, JobCmpRmtID, &hostID); |
|
|
if (jnode == NULL) { |
if (jnode == NULL) { |
jnode = Lst_Find(stoppedJobs, JobCmpRmtID, &hostID); |
jnode = Lst_Find(&stoppedJobs, JobCmpRmtID, &hostID); |
if (jnode == NULL) { |
if (jnode == NULL) { |
if (DEBUG(JOB)) { |
if (DEBUG(JOB)) { |
Error("Evicting host(%d) not in table", hostID); |
Error("Evicting host(%d) not in table", hostID); |
|
|
{ |
{ |
Job *job; |
Job *job; |
|
|
while (!jobFull && (job = (Job *)Lst_DeQueue(stoppedJobs)) != NULL) { |
while (!jobFull && (job = (Job *)Lst_DeQueue(&stoppedJobs)) != NULL) { |
if (DEBUG(JOB)) { |
if (DEBUG(JOB)) { |
(void) fprintf(stdout, |
(void) fprintf(stdout, |
"Job queue is not full. Restarting a stopped job.\n"); |
"Job queue is not full. Restarting a stopped job.\n"); |