static void launch_output_program (void) { char *program; /* name of the pager */ char *basename; /* basename of the pager */ /* Check if a output program should be called, and which one. Avoid all paging if only statistics are needed. */ if (autopager && isatty (fileno (stdout)) && !(inhibit_left && inhibit_right && inhibit_common)) { program = getenv ("PAGER"); #ifdef PAGER_PROGRAM if (program == NULL) program = PAGER_PROGRAM; #endif } else program = NULL; /* Use stdout as default output. */ output_file = stdout; /* Ensure the termcap initialization string is sent to stdout right away, never to the pager. */ #if HAVE_TPUTS if (termcap_init_string) { tputs (termcap_init_string, 0, putc_for_tputs); fflush (stdout); } #endif /* If we should use a pager, launch it. */ if (program && *program) { int is_less; if (basename = strrchr (program, '/'), basename) basename++; else basename = program; is_less = strstr (basename, "less") != NULL; if (is_less && no_init_term) { output_file = writepipe (program, "-X", NULL); } else { output_file = writepipe (program, NULL); } if (!output_file) { errexit (EXIT_FAILURE, errno, "%s", program); } /* If we are paging to less, use printer mode, not display mode. */ if (is_less) { find_termcap = 0; overstrike = 1; overstrike_for_less = 1; } } }
void etrace_if::scope_trigger(void) { if(m_scope->nb_periphs == 0) return; // init display display_init(); uint64_t stamp = 0; uint64_t sum, samp_per; sample_t *samp; periph_t *pperiph; uint8_t *vals; vals = new uint8_t[m_scope->nb_periphs + 2]; samp_per = m_scope->sample_period; while(1){ // sample rate ... and be sure to be last evaluated wait(m_scope->sample_period, SC_NS); wait(0, SC_NS); // get current sample stamp = sc_time_stamp().value()/1000; samp = get_sample(m_scope, stamp); // process sample (according to rules given by user -- or not sum = 0; for(pperiph = m_scope->head_periphs; pperiph != NULL; pperiph = pperiph->next){ sum += samp->per_costs[pperiph->idx].energy; vals[pperiph->idx] = (uint8_t)((samp->per_costs[pperiph->idx].energy * 100) / (samp_per * pperiph->pclass->max_energy_ms)); } vals[m_scope->nb_periphs] = (uint8_t) ((sum * 100) / (samp_per * m_scope->max_energy_ms)); vals[m_scope->nb_periphs + 1] = (uint8_t) ((roll_average (sum) * 100) / (samp_per * m_scope->max_energy_ms)); if(m_measure_started){ m_measure_accum += sum; m_measure_nbsamp++; } // display the values writepipe(m_disp_pipe, vals, m_scope->nb_periphs + 2); // clean things up if(samp != NULL) sample_free (samp); } }
void etrace_if::display_init(void) { int i; int disp_pipe[2]; unsigned int val; long long long_val; const char *pbuf; if(pipe(disp_pipe) < 0){ perror("etrace_if: pipe error"); exit(EXIT_FAILURE); } if((s_pid_graph[s_nb_graph++] = fork()) == 0){ setpgrp(); // son int null_fd; dup2(disp_pipe[0], STDIN_FILENO); close(disp_pipe[0]); close(disp_pipe[1]); null_fd = open("/dev/null", O_WRONLY); // make it silent dup2(null_fd, STDOUT_FILENO); //dup2 (null_fd, STDERR_FILENO); close(null_fd); if(execlp("chronograph", "chronograph", NULL) < 0){ perror("etrace_if: execlp failure"); _exit(EXIT_FAILURE); } } // father signal(SIGPIPE, SIG_IGN); close(disp_pipe[0]); m_disp_pipe = disp_pipe[1]; // setting the graph parameters pbuf = "Power consumption"; val = strlen (pbuf) + 1; writepipe(m_disp_pipe, &val, 4); writepipe(m_disp_pipe, pbuf, val); // number of graphs val = m_scope->nb_groups + 1; writepipe(m_disp_pipe, &val, 4); // sample period (20 ms) val = 20; writepipe(m_disp_pipe, &val, 4); // for each graph: number of curves, min value, max value int j, group_id; periph_t *tp, *pperiph = m_scope->head_periphs; i = 0; while(pperiph) { group_id = pperiph->group_id; tp = pperiph; j = i; while(tp && (tp->group_id == group_id)){ tp->idx = j++; tp = tp->next; } // number of curves in the graph val = j - i; writepipe(m_disp_pipe, &val, 4); // min value long_val = 0; writepipe(m_disp_pipe, &long_val, 8); // max value long_val = pperiph->pclass->max_energy_ms; m_scope->max_energy_ms += (j - i) * long_val; writepipe(m_disp_pipe, &long_val, 8); i = j; pperiph = tp; } // for total graph // number of curves in the graph (2) val = 2; writepipe(m_disp_pipe, &val, 4); // min value long_val = 0; writepipe(m_disp_pipe, &long_val, 8); // max value long_val =m_scope->max_energy_ms; writepipe(m_disp_pipe, &long_val, 8); // for each graph: graphs names pperiph = m_scope->head_periphs; while(pperiph){ pbuf = pperiph->group_name; val = strlen (pbuf) + 1; writepipe(m_disp_pipe, &val, 4); writepipe(m_disp_pipe, pbuf, val); group_id = pperiph->group_id; while(pperiph && (pperiph->group_id == group_id)) pperiph = pperiph->next; } // for total graph pbuf = "Total "; val = strlen(pbuf) + 1; writepipe(m_disp_pipe, &val, 4); writepipe(m_disp_pipe, pbuf, val); }
/** * @param tr_out Handler function for data read from stdin. Its parameters are: byte buffer, size of byte buffer, pid of child process. */ int playbatch(int *ret_code, FILE *fp_in, int (*tr_in)(), FILE *fp_out, int (*tr_out)(), FILE *fp_err, int (*tr_err)(), long vtimer, char *prog, char *argv[]) { int pid; int pipe_out[2], pipe_err[2], pipe_in[2]; pid = pipe_fork(pipe_in, pipe_out, pipe_err); if (pid < 0) { return ERRO; } if (pid == 0) { /* child */ struct rlimit resource_limit; struct itimerval interval_time; // Disable core dump resource_limit.rlim_cur = 0; resource_limit.rlim_max = 0; setrlimit(RLIMIT_CORE, &resource_limit); // Set max time a process can run before signaling with SIGVTALRM if (vtimer != 0) { interval_time.it_interval.tv_sec = vtimer; interval_time.it_interval.tv_usec = vtimer * 1000000L; interval_time.it_value.tv_sec = vtimer; interval_time.it_value.tv_usec = vtimer * 1000000L; signal(SIGVTALRM, SIG_DFL); // SIG_DFL is the default action for this signal, which is to terminate the process setitimer(ITIMER_VIRTUAL, &interval_time, NULL); } execv(prog, argv); exit(ERRO); } else { /* parent */ int child_retcode, bytes, result; int fim_le = FALSE; while (waitpid(pid, &child_retcode, WNOHANG) != pid) { // Read data from child's output pipe bytes = -1; if (ioctl(pipe_out[0], FIONREAD, &bytes) != -1) { if (bytes > 0) { bytes = read(pipe_out[0], buff, BUFFSIZE); } } if (bytes == -1) { result = ERRO; goto fim; } // Handle data if (tr_out != NULL) { result = tr_out(fp_out, buff, bytes, pid); if (result == ERRO || result != bytes) { result = ERRO; goto fim; } } // Read data from child's err pipe bytes = -1; if (ioctl(pipe_err[0], FIONREAD, &bytes) != -1) { if (bytes > 0) { bytes = read(pipe_err[0], buff, BUFFSIZE); } } if (bytes == -1) { result = ERRO; goto fim; } // Handle data if (tr_err != NULL) { result = tr_err(fp_err, buff, bytes, pid); if (result == ERRO || result != bytes) { result == ERRO; goto fim; } } if ( ! fim_le) { bytes = tr_in(fp_in, buff, BUFFSIZE); if (bytes < 0) { result = ERRO; goto fim; } else if (bytes == 0) { fim_le = TRUE; close(pipe_in[1]); } else { bytes = writepipe(pipe_in[1], buff, bytes); if (bytes < 0) { msg("Error writing to the pipe"); result = ERRO; goto fim; } else { if (bytes == 0) { continue; /* broken pipe! */ } } } } } // Handle any remaining output data do { bytes = -1; if (ioctl(pipe_out[0], FIONREAD, &bytes) != -1) { if (bytes > 0) { bytes = read(pipe_out[0], buff, BUFFSIZE); } } if (bytes == -1) { result = ERRO; goto fim; } // Handle data if (tr_out != NULL) { result = tr_out(fp_out, buff, bytes, pid); if (result == ERRO || result != bytes) { result = ERRO; goto fim; } } } while (bytes > 0); // Handle any remaining err data do { // Read data from child's err pipe bytes = -1; if (ioctl(pipe_err[0], FIONREAD, &bytes) != -1) { if (bytes > 0) { bytes = read(pipe_err[0], buff, BUFFSIZE); } } if (bytes == -1) { result = ERRO; goto fim; } // Handle data if (tr_err != NULL) { result = tr_err(fp_err, buff, bytes, pid); if (result == ERRO || result != bytes) { result == ERRO; goto fim; } } } while (bytes > 0); fim: waitpid(pid, &child_retcode, 0); close(pipe_in[1]); close(pipe_out[0]); close(pipe_err[0]); if (ret_code != NULL) { *ret_code = child_retcode; } return result; } }