/* elevate to maximum realtime priority :) */ static void elevate_prio(void) { struct sched_param sp; FILE *cgroup_fp; pid_t us; int rc; us = getpid(); /* if cgroups are present add us otherwise we don't have permission to enable RT */ cgroup_fp = fopen("/sys/fs/cgroup/cpu/tasks", "w"); if (!cgroup_fp) goto nop; rc = fprintf(cgroup_fp, "%d", us); if (rc < 0) DIE_PERROR("fprintf failed"); fclose(cgroup_fp); nop: sp.sched_priority = sched_get_priority_max(SCHED_RR); if (sp.sched_priority < 0) DIE_PERROR("sched_get_priority_max failed"); rc = sched_setscheduler(0, SCHED_RR, &sp); if (rc < 0) DIE_PERROR("sched_setscheduler failed"); }
void data_init_cpu(void) { int i, values = 0; char *ptr; cpu_fp = fopen("/proc/stat", "r"); if (!cpu_fp) DIE_PERROR("open procfs failed"); /* detect number of columns in cpu line */ i = getline(&cpu_buf_ptr, &cpu_line_size, cpu_fp); if (i < 0) DIE_PERROR("getline failed"); /* skiped cpu summary line */ i = getline(&cpu_buf_ptr, &cpu_line_size, cpu_fp); if (i < 0) DIE_PERROR("getline failed"); fclose(cpu_fp); ptr = cpu_buf_ptr; while (*ptr != '\n') { if (*ptr == ' ') values++; ptr++; } cpu_line_entries = values; DEBUG("%d numerical values in cpu lines\n", cpu_line_entries); cpu_hist = calloc(nr_cpus, sizeof(struct cpu_usage)); if (!cpu_hist) DIE_PERROR("malloc failed"); cpu_delta = calloc(nr_cpus, sizeof(struct cpu_usage)); if (!cpu_delta) DIE_PERROR("malloc failed"); }
static int setup_netlink(void) { int rc, id, rcvbufsz = 0; struct sockaddr_nl nla; socklen_t len; nl_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC); if (nl_fd < 0) DIE_PERROR("netlink socket failed"); memset(&nla, 0, sizeof(nla)); nla.nl_family = AF_NETLINK; rc = bind(nl_fd, (struct sockaddr *) &nla, sizeof(struct sockaddr_nl)); if (rc < 0) DIE_PERROR("netlink bind failed"); len = sizeof(int); if (getsockopt(nl_fd, SOL_SOCKET, SO_RCVBUF, &rcvbufsz, &len) < 0) fprintf(stderr, "Unable to get socket rcv buf size\n"); else DEBUG("receive buffer size: %d\n", rcvbufsz); id = get_family_id(nl_fd); if (!id) DIE_PERROR("Error getting family id"); nl_id = id; DEBUG("family id %d\n", nl_id); return 0; }
/* get CPU summary values out of proc */ void query_cpu_summary(void) { struct cpu_usage now; ssize_t len; int cpu = 0; cpu_fp = fopen("/proc/stat", "r"); if (!cpu_fp) DIE_PERROR("open procfs failed"); len = getline(&cpu_buf_ptr, &cpu_line_size, cpu_fp); if (len < 0) DIE_PERROR("getline failed"); parse_cpu_sum_info(cpu_buf_ptr, cpu, &now); // XXX calc deltas and store in cpu_delta cpu_delta[cpu].user = (now.user - cpu_hist[cpu].user) * 10; cpu_delta[cpu].system = (now.system - cpu_hist[cpu].system) * 10; cpu_delta[cpu].irq = (now.irq - cpu_hist[cpu].irq) * 10; cpu_delta[cpu].softirq = (now.softirq - cpu_hist[cpu].softirq) * 10; cpu_delta[cpu].iowait = (now.iowait - cpu_hist[cpu].iowait) * 10; cpu_delta[cpu].idle = (now.idle - cpu_hist[cpu].idle) * 10; /* update cpu values */ memcpy(&cpu_hist[cpu], &now, sizeof(now)); fclose(cpu_fp); }
/* get system memory usage out of proc */ void query_memory(void) { size_t mem_line_size = 256; char mem_buf[256]; char *mem_buf_ptr = mem_buf; FILE *mem_fp; ssize_t len; int i = 0; mem_fp = fopen("/proc/meminfo", "r"); if (!mem_fp) DIE_PERROR("open procfs failed"); do { /* only intrested in first two lines: * MemTotal: 4980832 kB * MemFree: 1376304 kB */ if (i++ > 1) break; len = getline(&mem_buf_ptr, &mem_line_size, mem_fp); if (len < 0) DIE_PERROR("getline failed"); if (i == 1) sscanf(mem_buf_ptr, "MemTotal: %u kB\n", &mem_total); if (i == 2) sscanf(mem_buf_ptr, "MemFree: %u kB\n", &mem_free); } while (!feof(mem_fp)); fclose(mem_fp); }
static void measure_one_cycle(void) { struct timespec ts1, ts2, delta, sleep; int rc; current_sum_utime = 0; current_sum_stime = 0; current_sum_cpu_utime = 0; current_sum_cpu_stime = 0; if (nr_cycles) output->print_cycle_start(); else output->print_sync(); new_cycle = 1; rc = clock_gettime(CLOCK_MONOTONIC, &ts1); if (rc < 0) DIE_PERROR("clock_gettime failed"); query_tasks(); query_memory(); query_cpus(opt_all_cpus); print_tasks(); print_memory(); print_cpus(opt_all_cpus); rc = clock_gettime(CLOCK_MONOTONIC, &ts2); if (rc < 0) DIE_PERROR("clock_gettime failed"); timespec_delta(&ts1, &ts2, &delta); if (nr_cycles) output->print_cycle_end(&delta); /* check if we can meet the target measurement interval */ if (delta.tv_sec > target.tv_sec || (delta.tv_sec == target.tv_sec && delta.tv_nsec > target.tv_nsec)) { output->exit_output(); DIE("Target measurement intervall too small. Current overhead: %u seconds %lu ms\n", (int) delta.tv_sec, delta.tv_nsec / NSECS_PER_MSEC); } /* now go sleeping for the rest of the measurement interval */ if (nr_cycles) timespec_delta(&delta, &target, &sleep); else timespec_delta(&delta, &ts_sync, &sleep); wait_for_cycle_end(&sleep); nr_cycles++; }
static int open_conf_file(FILE **fh) { const char *home_env; conf_file = malloc(4096); if (conf_file == NULL) DIE_PERROR("malloc failed"); home_env = getenv("HOME"); if (home_env == NULL) goto no_home; sprintf(conf_file, "%s/.cmsfs-fuse/filetypes.conf", home_env); *fh = fopen(conf_file, "r"); if (*fh != NULL) goto out; no_home: sprintf(conf_file, "%s/%s", TOOLS_SYSCONFDIR, "/cmsfs-fuse/filetypes.conf"); *fh = fopen(conf_file, "r"); if (*fh == NULL) { free(conf_file); return -ENOENT; } out: DEBUG("using config file: %s\n", conf_file); return 0; }
/* get the number of configured CPUs, some may be offline */ int get_nr_cpus(void) { unsigned long cpus = sysconf(_SC_NPROCESSORS_CONF); if (cpus < 0) DIE_PERROR("sysconf failed"); return cpus; }
static void setup_cpumask(void) { nl_cpumask = malloc(20); /* enough for "0-4096" :) */ if (nl_cpumask < 0) DIE_PERROR("malloc failed"); memset(nl_cpumask, 0, 20); snprintf(nl_cpumask, 20, "0-%d", nr_cpus - 1); }
static void add_filetype(char *name, struct util_list *list) { struct filetype *entry; entry = malloc(sizeof(*entry)); if (entry == NULL) DIE_PERROR("malloc failed"); strncpy(entry->name, name, MAX_TYPE_LEN); util_list_add_head(list, entry); }
/* get per CPU values out of proc */ void query_all_cpus(void) { struct cpu_usage now; ssize_t len; int cpu, line; cpu_fp = fopen("/proc/stat", "r"); if (!cpu_fp) DIE_PERROR("open procfs failed"); /* this is a bit ugly (nr_cpus + 1) because of the summary line... */ for (line = 0; line < nr_cpus + 1; line++) { len = getline(&cpu_buf_ptr, &cpu_line_size, cpu_fp); if (len < 0) DIE_PERROR("getline failed"); /* skip summary line */ if (line == 0) continue; cpu = line - 1; parse_cpu_info(cpu_buf_ptr, cpu, &now); //if (nr_cycles) // output->print_cpu_info(i - 1, &now); // XXX calc deltas and store in cpu_delta cpu_delta[cpu].user = (now.user - cpu_hist[cpu].user) * 10; cpu_delta[cpu].system = (now.system - cpu_hist[cpu].system) * 10; cpu_delta[cpu].irq = (now.irq - cpu_hist[cpu].irq) * 10; cpu_delta[cpu].softirq = (now.softirq - cpu_hist[cpu].softirq) * 10; cpu_delta[cpu].iowait = (now.iowait - cpu_hist[cpu].iowait) * 10; cpu_delta[cpu].idle = (now.idle - cpu_hist[cpu].idle) * 10; /* update cpu values */ memcpy(&cpu_hist[cpu], &now, sizeof(now)); } fclose(cpu_fp); }
int main(int ac, char **av) { state_t state; int rc, c, repetitions = -1, warmup = 0; char buf[256]; char *usage = "-s\n OR [-S] [-W <warmup>] [-N <repetitions>] server\n"; while (( c = getopt(ac, av, "sSP:W:N:")) != EOF) { switch(c) { case 's': /* Server */ if (fork() == 0) { server_main(); } exit(0); case 'S': /* shutdown serverhost */ { int sock = tcp_connect(av[optind], TCP_CONNECT, SOCKOPT_NONE); rc = write(sock, "0", 1); if (rc < 0) DIE_PERROR("write failed"); close(sock); exit(0); } case 'W': warmup = atoi(optarg); break; case 'N': repetitions = atoi(optarg); break; default: lmbench_usage(ac, av, usage); break; } } if (optind + 1 != ac) { lmbench_usage(ac, av, usage); } handle_scheduler(benchmp_childid(), 0, 0); state.server = av[optind]; benchmp(NULL, doclient, NULL, 0, 1, warmup, repetitions, &state); sprintf(buf, "TCP/IP connection cost to %s", state.server); micro(buf, get_n()); exit(0); }
void server(void* cookie) { int pid, rc; state_t* state = (state_t*)cookie; pid = getpid(); state->pid = 0; if (state->fid_f == open_file) { /* Create a temporary file for clients to open */ sprintf(state->fname, "lat_selectXXXXXX"); state->fid = mkstemp(state->fname); if (state->fid <= 0) { char buf[L_tmpnam+128]; sprintf(buf, "lat_select: Could not create temp file %s", state->fname); perror(buf); exit(1); } close(state->fid); return; } /* Create a socket for clients to connect to */ state->sock = tcp_server(TCP_SELECT, SOCKOPT_REUSE); if (state->sock <= 0) { perror("lat_select: Could not open tcp server socket"); exit(1); } /* Start a server process to accept client connections */ switch(state->pid = fork()) { case 0: /* child server process */ while (pid == getppid()) { int newsock = tcp_accept(state->sock, SOCKOPT_NONE); rc = read(newsock, &state->fid, 1); if (rc < 0) DIE_PERROR("read failed"); close(newsock); } exit(0); case -1: /* error */ perror("lat_select::server(): fork() failed"); exit(1); default: break; } }
/* * TODO: check alignment */ void bm_alloc(int bits) { int bytes = bits / 8; if (!bits || bits < 0 || bits % 8) DIE("invalid bit count: %d", bits); map = malloc(bytes); if (!map) DIE_PERROR("allocating bitmap failed"); memset(map, 0, bytes); nr_bits = bits; DEBUG("alloc map @ %p for %d bits\n", map, nr_bits); }
void wait_for_cycle_end(struct timespec *sleep) { struct timespec remain; int rc; resume: rc = nanosleep(sleep, &remain); if (rc < 0 && errno == EINTR) { fprintf(stderr, "resuming interrupted sleep\n"); *sleep = remain; goto resume; } if (rc < 0) DIE_PERROR("nanosleep failed"); }
iter_t benchmp_interval(void* _state) { char c; iter_t iterations; double result; fd_set fds; struct timeval timeout; int rc; benchmp_child_state* state = (benchmp_child_state*)_state; iterations = (state->state == timing_interval ? state->iterations : state->iterations_batch); if (state->need_warmup) { /* remove spurious compilation warning */ result = state->enough; } else { result = stop(0,0); if (state->cleanup) { if (benchmp_sigchld_handler == SIG_DFL) signal(SIGCHLD, SIG_DFL); (*state->cleanup)(iterations, state->cookie); } save_n(state->iterations); result -= t_overhead() + get_n() * l_overhead(); settime(result >= 0. ? (uint64)result : 0.); } /* if the parent died, then give up */ if (getppid() == 1 && state->cleanup) { if (benchmp_sigchld_handler == SIG_DFL) signal(SIGCHLD, SIG_DFL); (*state->cleanup)(0, state->cookie); exit(0); } timeout.tv_sec = 0; timeout.tv_usec = 0; FD_ZERO(&fds); switch (state->state) { case warmup: iterations = state->iterations_batch; FD_SET(state->start_signal, &fds); select(state->start_signal+1, &fds, NULL, NULL, &timeout); if (FD_ISSET(state->start_signal, &fds)) { state->state = timing_interval; rc = read(state->start_signal, &c, sizeof(char)); if (rc < 0) DIE_PERROR("read failed"); iterations = state->iterations; } if (state->need_warmup) { state->need_warmup = 0; /* send 'ready' */ rc = write(state->response, &c, sizeof(char)); if (rc < 0) DIE_PERROR("write failed"); } break; case timing_interval: iterations = state->iterations; if (state->parallel > 1 || result > 0.95 * state->enough) { insertsort(gettime(), get_n(), get_results()); state->i++; /* we completed all the experiments, return results */ if (state->i >= state->repetitions) { state->state = cooldown; } } if (state->parallel == 1 && (result < 0.99 * state->enough || result > 1.2 * state->enough)) { if (result > 150.) { double tmp = iterations / result; tmp *= 1.1 * state->enough; iterations = (iter_t)(tmp + 1); } else { iterations <<= 3; if (iterations > 1<<27 || (result < 0. && iterations > 1<<20)) { state->state = cooldown; } } } state->iterations = iterations; if (state->state == cooldown) { /* send 'done' */ rc = write(state->response, (void*)&c, sizeof(char)); if (rc < 0) DIE_PERROR("write failed"); iterations = state->iterations_batch; } break; case cooldown: iterations = state->iterations_batch; FD_SET(state->result_signal, &fds); select(state->result_signal+1, &fds, NULL, NULL, &timeout); if (FD_ISSET(state->result_signal, &fds)) { /* * At this point all children have stopped their * measurement loops, so we can block waiting for * the parent to tell us to send our results back. * From this point on, we will do no more "work". */ rc = read(state->result_signal, (void*)&c, sizeof(char)); if (rc < 0) DIE_PERROR("read failed"); rc = write(state->response, (void*)get_results(), state->r_size); if (rc < 0) DIE_PERROR("write failed"); if (state->cleanup) { if (benchmp_sigchld_handler == SIG_DFL) signal(SIGCHLD, SIG_DFL); (*state->cleanup)(0, state->cookie); } /* Now wait for signal to exit */ rc = read(state->exit_signal, (void*)&c, sizeof(char)); if (rc < 0) DIE_PERROR("read failed"); exit(0); } }; if (state->initialize) { (*state->initialize)(iterations, state->cookie); } start(0); return (iterations); }
void benchmp_parent( int response, int start_signal, int result_signal, int exit_signal, pid_t* pids, int parallel, iter_t iterations, int warmup, int repetitions, int enough ) { int i, j, rc, bytes_read; result_t* results = NULL; result_t* merged_results = NULL; char* signals = NULL; unsigned char* buf; fd_set fds_read, fds_error; struct timeval timeout; if (benchmp_sigchld_received || benchmp_sigterm_received) { #ifdef _DEBUG fprintf(stderr, "benchmp_parent: entering, benchmp_sigchld_received=%d\n", benchmp_sigchld_received); #endif goto error_exit; } results = (result_t*)malloc(sizeof_result(repetitions)); merged_results = (result_t*)malloc(sizeof_result(parallel * repetitions)); signals = (char*)malloc(parallel * sizeof(char)); if (!results || !merged_results || !signals) return; /* Collect 'ready' signals */ for (i = 0; i < parallel * sizeof(char); i += bytes_read) { bytes_read = 0; FD_ZERO(&fds_read); FD_ZERO(&fds_error); FD_SET(response, &fds_read); FD_SET(response, &fds_error); timeout.tv_sec = 1; timeout.tv_usec = 0; select(response+1, &fds_read, NULL, &fds_error, &timeout); if (benchmp_sigchld_received || benchmp_sigterm_received || FD_ISSET(response, &fds_error)) { #ifdef _DEBUG fprintf(stderr, "benchmp_parent: ready, benchmp_sigchld_received=%d\n", benchmp_sigchld_received); #endif goto error_exit; } if (!FD_ISSET(response, &fds_read)) { continue; } bytes_read = read(response, signals, parallel * sizeof(char) - i); if (bytes_read < 0) { #ifdef _DEBUG fprintf(stderr, "benchmp_parent: ready, bytes_read=%d, %s\n", bytes_read, strerror(errno)); #endif goto error_exit; } } /* let the children run for warmup microseconds */ if (warmup > 0) { struct timeval delay; delay.tv_sec = warmup / 1000000; delay.tv_usec = warmup % 1000000; select(0, NULL, NULL, NULL, &delay); } /* send 'start' signal */ rc = write(start_signal, signals, parallel * sizeof(char)); if (rc < 0) DIE_PERROR("write failed"); /* Collect 'done' signals */ for (i = 0; i < parallel * sizeof(char); i += bytes_read) { bytes_read = 0; FD_ZERO(&fds_read); FD_ZERO(&fds_error); FD_SET(response, &fds_read); FD_SET(response, &fds_error); timeout.tv_sec = 1; timeout.tv_usec = 0; select(response+1, &fds_read, NULL, &fds_error, &timeout); if (benchmp_sigchld_received || benchmp_sigterm_received || FD_ISSET(response, &fds_error)) { #ifdef _DEBUG fprintf(stderr, "benchmp_parent: done, benchmp_child_died=%d\n", benchmp_sigchld_received); #endif goto error_exit; } if (!FD_ISSET(response, &fds_read)) { continue; } bytes_read = read(response, signals, parallel * sizeof(char) - i); if (bytes_read < 0) { #ifdef _DEBUG fprintf(stderr, "benchmp_parent: done, bytes_read=%d, %s\n", bytes_read, strerror(errno)); #endif goto error_exit; } } /* collect results */ insertinit(merged_results); for (i = 0; i < parallel; ++i) { int n = sizeof_result(repetitions); buf = (unsigned char*)results; FD_ZERO(&fds_read); FD_ZERO(&fds_error); /* tell one child to report its results */ rc = write(result_signal, buf, sizeof(char)); for (; n > 0; n -= bytes_read, buf += bytes_read) { bytes_read = 0; FD_SET(response, &fds_read); FD_SET(response, &fds_error); timeout.tv_sec = 1; timeout.tv_usec = 0; select(response+1, &fds_read, NULL, &fds_error, &timeout); if (benchmp_sigchld_received || benchmp_sigterm_received || FD_ISSET(response, &fds_error)) { #ifdef _DEBUG fprintf(stderr, "benchmp_parent: results, benchmp_sigchld_received=%d\n", benchmp_sigchld_received); #endif goto error_exit; } if (!FD_ISSET(response, &fds_read)) { continue; } bytes_read = read(response, buf, n); if (bytes_read < 0) { #ifdef _DEBUG fprintf(stderr, "benchmp_parent: results, bytes_read=%d, %s\n", bytes_read, strerror(errno)); #endif goto error_exit; } } for (j = 0; j < results->N; ++j) { insertsort(results->v[j].u, results->v[j].n, merged_results); } } /* we allow children to die now, without it causing an error */ signal(SIGCHLD, SIG_DFL); /* send 'exit' signals */ rc = write(exit_signal, results, parallel * sizeof(char)); if (rc < 0) DIE_PERROR("write failed"); /* Compute median time; iterations is constant! */ set_results(merged_results); goto cleanup_exit; error_exit: #ifdef _DEBUG fprintf(stderr, "benchmp_parent: error_exit!\n"); #endif signal(SIGCHLD, SIG_DFL); for (i = 0; i < parallel; ++i) { kill(pids[i], SIGTERM); waitpid(pids[i], NULL, 0); } free(merged_results); cleanup_exit: close(response); close(start_signal); close(result_signal); close(exit_signal); if (results) free(results); if (signals) free(signals); }
int main(int argc, char* argv[]) { pthread_t proc_events_thread; void *status; int rc, opt, cycles = INT_MAX; #ifdef DEBUG_ENABLED logfile = fopen(DEBUG_LOGFILE, "w"); if (logfile == NULL) DIE_PERROR("Cannot open file " DEBUG_LOGFILE " for writing"); #endif #ifdef CONFIG_NCURSES /* default is ncurses output */ output = &oops_ncurses; #else output = &oops_stdout; #endif while (1) { int option_index = 0; static struct option long_options[] = { { "realtime", no_argument, &opt_realtime, 1}, { "all_cpus", no_argument, &opt_all_cpus, 1}, { "sort", required_argument, 0, 's'}, { "output", required_argument, 0, 'o'}, { "seconds", required_argument, 0, 't' }, { "milliseconds",required_argument, 0, 'm' }, { "cycles", required_argument, 0, 'c' }, { "help", no_argument, 0, 'h' }, { 0, 0, 0, 0 }, }; opt = getopt_long(argc, argv, "s:o:c:h?", long_options, &option_index); if (opt == -1) break; switch (opt) { case 'o': if (strcmp(optarg, "csv") == 0) output = &oops_csv; else if (strcmp(optarg, "stdout") == 0) output = &oops_stdout; #ifdef CONFIG_NCURSES else if (strcmp(optarg, "ncurses") == 0) output = &oops_ncurses; #endif else if (strcmp(optarg, "nop") == 0) output = &oops_nop; else { /* unknown */ fprintf(stderr, "Unknown output method %s\n", optarg); print_help(argc, argv); } break; case 's': if (strcmp(optarg, "name") == 0) opt_sort = OPT_SORT_NAME; else if (strcmp(optarg, "id") == 0) opt_sort = OPT_SORT_TID; else if (strcmp(optarg, "time") == 0) opt_sort = OPT_SORT_TIME; else if (strcmp(optarg, "io") == 0) opt_sort = OPT_SORT_IO; else if (strcmp(optarg, "mem") == 0) opt_sort = OPT_SORT_MEM; else { /* unknown */ fprintf(stderr, "Unknown sort method %s\n", optarg); print_help(argc, argv); } break; case 't': target.tv_sec = atoi(optarg); break; case 'm': target.tv_nsec = atol(optarg) * NSECS_PER_MSEC; break; case 'c': cycles = atoi(optarg); break; case 0: break; case '?': case 'h': default: print_help(argc, argv); } } nr_cpus = get_nr_cpus(); bm_alloc(PID_MAX); rc = pthread_create(&proc_events_thread, NULL, proc_events_main, NULL); if (rc) DIE_PERROR("pthread_create failed"); pthread_setname_np(proc_events_thread, "nlmon-pevent"); setup_netlink(); start_task_monitor(); while (!procfs_thread) { DEBUG("...\n"); pthread_yield(); __sync_synchronize(); } rc = pthread_join(procfs_thread, &status); if (rc) DIE_PERROR("pthread_join failed"); else DEBUG("procfs scan thread exited\n"); data_init_cpu(); if (opt_realtime) elevate_prio(); cache_init(); output->init_output(); while (cycles--) measure_one_cycle(); output->exit_output(); stop_task_monitor(); exit(EXIT_SUCCESS); }
static void gather_data(struct taskstats *t) { struct taskstat_delta *delta; struct hash_entry *h; if (!nr_cycles && !once) { ts_version = t->version; ts_size = sizeof(*t); output->print_banner(t); once = 1; } h = get_hash_entry(t->ac_pid); if (!h) DIE("hash entry missing for process %d!", t->ac_pid); if (t->ac_pid != h->tid) DIE("pid mismatch in hash!"); // XXX this sucks, optimize later delta = malloc(sizeof(struct taskstat_delta)); if (!delta) DIE_PERROR("malloc failed"); memset(delta, 0, sizeof(struct taskstat_delta)); delta->pid = h->tgid; delta->tid = t->ac_pid; __gather_data_sanity(h, t); delta->utime = t->ac_utime - h->utime; delta->stime = t->ac_stime - h->stime; delta->cpu_delay = t->cpu_delay_total - h->cpu_delay; delta->rss = t->coremem - h->rss; delta->io_rd_bytes = t->read_char - h->io_rd_bytes; delta->io_wr_bytes = t->write_char - h->io_wr_bytes; delta->blkio_delay = t->blkio_delay_total - h->blkio_delay; /* store new values */ h->utime = t->ac_utime; h->stime = t->ac_stime; h->cpu_delay = t->cpu_delay_total; h->rss = t->coremem; h->io_rd_bytes = t->read_char; h->io_wr_bytes = t->write_char; h->blkio_delay = t->blkio_delay_total; put_hash_entry(t->ac_pid); if (t->ac_exitcode) DEBUG("exiting task: %d [%s]\n", t->ac_pid, t->ac_comm); current_sum_utime += delta->utime / 1000; current_sum_stime += delta->stime / 1000; if (!nr_cycles) return; /* only output if one value changed! */ if (output_wanted(delta)) { // XXX optimize later, maybe pointer to task string in hash entry? memcpy(&delta->comm, t->ac_comm, TS_COMM_LEN); cache_add(delta); } }