/* * time pipeline (really a statement, not a built-in command) */ int timex(struct op *t, int f, volatile int *xerrok) { #define TF_NOARGS BIT(0) #define TF_NOREAL BIT(1) /* don't report real time */ #define TF_POSIX BIT(2) /* report in posix format */ int rv = 0; struct tms t0, t1, tms; clock_t t0t, t1t = 0; int tf = 0; extern clock_t j_usrtime, j_systime; /* computed by j_wait */ t0t = ksh_times(&t0); if (t->left) { /* * Two ways of getting cpu usage of a command: just use t0 * and t1 (which will get cpu usage from other jobs that * finish while we are executing t->left), or get the * cpu usage of t->left. at&t ksh does the former, while * pdksh tries to do the later (the j_usrtime hack doesn't * really work as it only counts the last job). */ j_usrtime = j_systime = 0; rv = execute(t->left, f | XTIME, xerrok); if (t->left->type == TCOM) tf |= t->left->str[0]; t1t = ksh_times(&t1); } else tf = TF_NOARGS; if (tf & TF_NOARGS) { /* ksh93 - report shell times (shell+kids) */ tf |= TF_NOREAL; tms.tms_utime = t0.tms_utime + t0.tms_cutime; tms.tms_stime = t0.tms_stime + t0.tms_cstime; } else { tms.tms_utime = t1.tms_utime - t0.tms_utime + j_usrtime; tms.tms_stime = t1.tms_stime - t0.tms_stime + j_systime; } if (!(tf & TF_NOREAL)) shf_fprintf(shl_out, tf & TF_POSIX ? "real %8s\n" : "%8ss real ", clocktos(t1t - t0t)); shf_fprintf(shl_out, tf & TF_POSIX ? "user %8s\n" : "%8ss user ", clocktos(tms.tms_utime)); shf_fprintf(shl_out, tf & TF_POSIX ? "sys %8s\n" : "%8ss system\n", clocktos(tms.tms_stime)); shf_flush(shl_out); return rv; }
int c_times(char **wp) { struct tms all; (void) ksh_times(&all); shprintf("Shell: %8ss user ", clocktos(all.tms_utime)); shprintf("%8ss system\n", clocktos(all.tms_stime)); shprintf("Kids: %8ss user ", clocktos(all.tms_cutime)); shprintf("%8ss system\n", clocktos(all.tms_cstime)); return 0; }
/* SIGCHLD handler to reap children and update job states * * If jobs are compiled in then this routine expects sigchld to be blocked. */ static void j_sigchld(int sig) { int errno_ = errno; Job *j; Proc *p = 0; int pid; WAIT_T status; struct tms t0, t1; /* Don't wait for any processes if a job is partially started. * This is so we don't do away with the process group leader * before all the processes in a pipe line are started (so the * setpgid() won't fail) */ for (j = job_list; j; j = j->next) if (j->ppid == procpid && !(j->flags & JF_STARTED)) { held_sigchld = 1; return; } ksh_times(&t0); do { pid = wait(&status); if (pid <= 0) /* return if would block (0) ... */ break; /* ... or no children or interrupted (-1) */ ksh_times(&t1); /* find job and process structures for this pid */ for (j = job_list; j != (Job *) 0; j = j->next) for (p = j->proc_list; p != (Proc *) 0; p = p->next) if (p->pid == pid) goto found; found: if (j == (Job *) 0) { /* Can occur if process has kids, then execs shell warningf(true, "bad process waited for (pid = %d)", pid); */ t0 = t1; continue; } j->usrtime += t1.tms_cutime - t0.tms_cutime; j->systime += t1.tms_cstime - t0.tms_cstime; t0 = t1; p->status = status; if (WIFSIGNALED(status)) p->state = PSIGNALLED; else p->state = PEXITED; check_job(j); /* check to see if entire job is done */ } while (0); errno = errno_; }