float get_energy()
{
	static unsigned long int count = 0;
	int prev = !curr;

	/* Don't buffer data if redirected to a pipe */
	//setbuf(stdout, NULL);

	memset(&sys_stats[curr], 0, SYS_INFO_SIZE);
	read_process_stats(curr);
	read_cpufreq_stats(&sys_stats[curr]);

	u32 delta_runtime = subcount(sys_stats[curr].runtime, sys_stats[prev].runtime);
	float delta_cpu = (u64_subcount(sys_stats[curr].stats.utime, sys_stats[prev].stats.utime) + u64_subcount(sys_stats[curr].stats.stime, sys_stats[prev].stats.stime)) * (100.0f / delta_runtime);

	u32 delta_itv = u64_subcount(sys_stats[curr].itv, sys_stats[prev].itv);
	stm_time_t delta_timestamp = u64_subcount(sys_stats[curr].timestamp, sys_stats[prev].timestamp);

	/* (avg cpu time) * (cpu power) * (run percent) / 100 */
	double power = delta_cpu * sys_stats[curr].cpupower * (delta_runtime * 1.0f / delta_itv) / 100.0f;
	if (power != power) // check not NaN
	{
#ifdef POWER_DEBUG
		DEBUG(stdout, "NaN result\n");
#endif
		power = 0;
	}

	power_history[power_index].power = power;
	power_history[power_index].delta = delta_timestamp;
	/* timestamp set as last element to avoid critical raise in CPUEnergy */
	power_history[power_index].timestamp = sys_stats[curr].timestamp;
#ifdef POWER_DEBUG
	DEBUG(stdout, "[%lu - %d/%d] Power %f @ %llu for %f\n", count, power_index, RETENTION_SIZE, power_history[power_index].power, power_history[power_index].timestamp, power_history[power_index].delta / 1000000.0f);
#endif
	if(count > 0 && !power) {
#ifdef POWER_ALERT
		WARNING(stdout, "Power consumption read 0 W, the acquiring interval '%f msec' is too small. Start: %llu, End: %llu, delta: %f\n", (float)ACQUIRING_INTERVAL, sys_stats[prev].timestamp, sys_stats[curr].timestamp, delta_timestamp / 1000000.0);
#endif
	} else {
		power_index = NEXT_RETENTION_SIZE(power_index);
		curr ^= 1;
	}
	count++;

	return power;
}
int main(int argc, char *argv[]) {
    struct latency_entry *e;
    int delay, iterations;
    int pid, tid;
    int count, erase;
    int i;

    delay = 1;
    iterations = 0;
    pid = tid = 0;
    
    for (i = 1; i < argc; i++) {
        if (!strcmp(argv[i], "-d")) {
            if (i >= argc - 1) {
                fprintf(stderr, "Option -d expects an argument.\n");
                exit(EXIT_FAILURE);
            }
            delay = atoi(argv[++i]);
            continue;
        }
        if (!strcmp(argv[i], "-n")) {
            if (i >= argc - 1) {
                fprintf(stderr, "Option -n expects an argument.\n");
                exit(EXIT_FAILURE);
            }
            iterations = atoi(argv[++i]);
            continue;
        }
        if (!strcmp(argv[i], "-h")) {
            usage(argv[0]);
            exit(EXIT_SUCCESS);
        }
        if (!strcmp(argv[i], "-p")) {
            if (i >= argc - 1) {
                fprintf(stderr, "Option -p expects an argument.\n");
                exit(EXIT_FAILURE);
            }
            pid = atoi(argv[++i]);
            continue;
        }
        if (!strcmp(argv[i], "-t")) {
            if (i >= argc - 1) {
                fprintf(stderr, "Option -t expects an argument.\n");
                exit(EXIT_FAILURE);
            }
            tid = atoi(argv[++i]);
            continue;
        }
        fprintf(stderr, "Invalid argument \"%s\".\n", argv[i]);
        usage(argv[0]);
        exit(EXIT_FAILURE);
    }

    if (tid && !pid) {
        fprintf(stderr, "If you provide a thread ID with -t, you must provide a process ID with -p.\n");
        exit(EXIT_FAILURE);
    }

    check_latencytop();

    free_entries = NULL;

    signal(SIGINT, &signal_handler);
    signal(SIGTERM, &signal_handler);

    atexit(&disable_latencytop);

    set_latencytop(1);

    count = 0;
    erase = 1;

    while ((iterations == 0) || (count++ < iterations)) {

        sleep(delay);

        e = NULL;
        if (pid) {
            if (tid) {
                e = read_thread_stats(e, erase, pid, tid, 1);
            } else {
                e = read_process_stats(e, erase, pid);
            }
        } else {
            e = read_global_stats(e, erase);
        }
        erase = 0;

        clear_screen();
        if (pid) {
            if (tid) {
                printf("Latencies for thread %d in process %d:\n", tid, pid);
            } else {
                printf("Latencies for process %d:\n", pid);
            }
        } else {
            printf("Latencies across all processes:\n");
        }
        print_latency_entries(e);
    }

    set_latencytop(0);

    return 0;
}