Пример #1
0
void *low_prio_rt_thread(void *arg)
{
	struct thread *t = (struct thread *)arg;
	while (!thread_quit(t)) {
		while_not_flag(LOW_START_CYCLE, t)
		    rt_nanosleep(1 * NS_PER_MS);
		debug(DBG_INFO, "low try mutex\n");
		pthread_mutex_lock(&pi_mutex);
		debug(DBG_INFO, "low grab mutex\n");
		write_flag(MED_START_WORK);
		rt_nanosleep(1 * NS_PER_MS);
		while_not_flag(LOW_DROP_MUTEX, t) {
			//printf("!"); fflush(NULL);
			rt_nanosleep(1);
		}
		debug(DBG_INFO, "low drop mutex\n");
		low_drop_time = rt_gettime();
		pthread_mutex_unlock(&pi_mutex);
		while_not_flag(END_OF_CYCLE, t) {
			//printf("@"); fflush(NULL);
			rt_nanosleep(1 * NS_PER_MS);
		}
Пример #2
0
void *periodic_thread(void *thread)
{
	struct thread *t = (struct thread *)thread;
	struct periodic_arg *parg = (struct periodic_arg *)t->arg;
	nsec_t period = parg->period;
	void*(*func)(void*) = parg->func;

	int i = 0;
	nsec_t next, now;
	nsec_t exe_start, exe_end, exe_time;

	next = rt_gettime();
	while (i < parg->iterations) {
		next += period;
		if (rt_gettime() > next) {
			printf("TID %d missed period, aborting\n", t->id);
			fail[t->id] = 1;
			break;
		}
		exe_start = rt_gettime();
		func(parg->arg);
		exe_end = rt_gettime();
		exe_time = exe_end - exe_start;
		rec.x = i;
		rec.y = exe_time/NS_PER_US;
		stats_container_append(&dat[t->id], rec);

		i++;

		now = rt_gettime();
		if (now > next) {
			printf("Missed period, aborting (calc took too long)\n");
			fail[t->id] = 1;
			break;
		}
		rt_nanosleep(next - now);
	}

	printf("TID %d (%c - prio %d) complete\n", t->id, groupname[t->id>>2],
	       t->priority);

	return NULL;
}
Пример #3
0
int periodic_thread(nsec_t period, int iterations, int loops)
{
	stats_container_t dat;
	stats_container_t hist;
	stats_quantiles_t quantiles;
	stats_record_t rec;

	int i = 0;
	int fail = 0;
	nsec_t next, now;
	nsec_t exe_start, exe_end, exe_time;
	char *samples_filename;
	char *hist_filename;

	stats_container_init(&dat, iterations);
	stats_container_init(&hist, HIST_BUCKETS);
	stats_quantiles_init(&quantiles, (int)log10(iterations));
	if (asprintf(&samples_filename, "%s-samples", filename_prefix) == -1) {
		fprintf(stderr, "Failed to allocate string for samples filename\n");
		return -1;
	}

	if (asprintf(&hist_filename, "%s-hist", filename_prefix) == -1) {
		fprintf(stderr, "Failed to allocate string for samples filename\n");
		return -1;
	}
	next = rt_gettime();
	while (i < iterations) {
		next += period;
		now = rt_gettime();
		if (now > next) {
			printf("Missed period, aborting (didn't get scheduled in time)\n");
			fail = 1;
			break;
		}
		exe_start = rt_gettime();
		calc(loops);
		exe_end = rt_gettime();
		exe_time = exe_end - exe_start;
		rec.x = i;
		rec.y = exe_time/NS_PER_US;
		stats_container_append(&dat, rec);

		i++;

		now = rt_gettime();
		if (now > next) {
			printf("Missed period, aborting (calc took too long)\n");
			fail = 1;
			break;
		}
		rt_nanosleep(next - now);
	}

	stats_container_save(samples_filename, "Periodic CPU Load Scatter Plot",\
			     "Iteration", "Runtime (us)", &dat, "points");
	stats_container_save(hist_filename, "Periodic CPU Load Histogram",\
			     "Runtime (us)", "Samples", &hist, "steps");

	printf("  Execution Time Statistics:\n");
	printf("Min: %ld us\n", stats_min(&dat));
	printf("Max: %ld us\n", stats_max(&dat));
	printf("Avg: %.4f us\n", stats_avg(&dat));
	printf("StdDev: %.4f us\n", stats_stddev(&dat));
	printf("Quantiles:\n");
	stats_quantiles_calc(&dat, &quantiles);
	stats_quantiles_print(&quantiles);
	printf("Criteria: no missed periods\n");
	printf("Result: %s\n", fail ? "FAIL":"PASS");

	free(samples_filename);
	free(hist_filename);

	return fail;
}
Пример #4
0
void *periodic_thread(void *arg)
{
	int i;
	nsec_t delay, avg_delay = 0, start_delay, min_delay = -1ULL, max_delay = 0;
	int failures = 0;
	nsec_t next = 0, now = 0, sched_delta = 0, delta = 0, prev = 0, iter_start;

 	/* wait for the specified start time */
 	rt_nanosleep_until(start);

	now = rt_gettime();
	start_delay = (now - start)/NS_PER_US;
	iter_start = next = now;

	debug(DBG_INFO, "ITERATION DELAY(US) MAX_DELAY(US) FAILURES\n");
	debug(DBG_INFO, "--------- --------- ------------- --------\n");

	if (latency_threshold) {
		latency_trace_enable();
		latency_trace_start();
	}
	for (i = 0; i < iterations; i++) {
		/* wait for the period to start */
		next += period;
		prev = now;
		now = rt_gettime();

		if (next < now) {
			printf("\nPERIOD MISSED!\n");
			printf("     scheduled delta: %8llu us\n", sched_delta/1000);
			printf("	actual delta: %8llu us\n", delta/1000);
			printf("	     latency: %8llu us\n", (delta-sched_delta)/1000);
			printf("---------------------------------------\n");
			printf("      previous start: %8llu us\n", (prev-iter_start)/1000);
			printf("		 now: %8llu us\n", (now-iter_start)/1000);
			printf("     scheduled start: %8llu us\n", (next-iter_start)/1000);
			printf("next scheduled start is in the past!\n");
			ret = 1;
			break;
		}

		sched_delta = next - now; /* how long we should sleep */
		delta = 0;
		do {
			nsec_t new_now;

			rt_nanosleep(next - now);
			new_now = rt_gettime();
			delta += new_now - now; /* how long we did sleep */
			now = new_now;
		} while (now < next);

		/* start of period */
		delay = (now - iter_start - (nsec_t)(i+1)*period)/NS_PER_US;
		rec.x = i;
		rec.y = delay;
		stats_container_append(&dat, rec);

		if (delay < min_delay)
			min_delay = delay;
		if (delay > max_delay)
			max_delay = delay;
		if (delay > pass_criteria) {
			failures++;
			ret = 1;
		}
		avg_delay += delay;
		if (latency_threshold && delay > latency_threshold)
			break;

		/* continuous status ticker */
		debug(DBG_INFO, "%9i %9llu %13llu %8i\r", i, delay, max_delay, failures);
		fflush(stdout);

		busy_work_ms(load_ms);
	}
	if (latency_threshold) {
		latency_trace_stop();
		if (i != iterations) {
			printf("Latency threshold (%lluus) exceeded at iteration %d\n",
				latency_threshold, i);
			latency_trace_print();
			stats_container_resize(&dat, i+1);
		}
	}

	/* save samples before the quantile calculation messes things up! */
	stats_hist(&hist, &dat);
	stats_container_save("samples", "Periodic Scheduling Latency Scatter Plot",\
			     "Iteration", "Latency (us)", &dat, "points");
	stats_container_save("hist", "Periodic Scheduling Latency Histogram",\
 			     "Latency (us)", "Samples", &hist, "steps");

	avg_delay /= i;
	printf("\n\n");
	printf("Start: %4llu us: %s\n", start_delay,
		start_delay < pass_criteria ? "PASS" : "FAIL");
	printf("Min:   %4llu us: %s\n", min_delay,
		min_delay < pass_criteria ? "PASS" : "FAIL");
	printf("Max:   %4llu us: %s\n", max_delay,
		max_delay < pass_criteria ? "PASS" : "FAIL");
	printf("Avg:   %4llu us: %s\n", avg_delay,
		avg_delay < pass_criteria ? "PASS" : "FAIL");
	printf("StdDev: %.4f us\n", stats_stddev(&dat));
	printf("Quantiles:\n");
	stats_quantiles_calc(&dat, &quantiles);
	stats_quantiles_print(&quantiles);
	printf("Failed Iterations: %d\n", failures);

	return NULL;
}
Пример #5
0
int main(int argc, char **argv)
{
    pthread_t *threads;
    long i;
    int ret;
    struct timespec intv;
    struct sched_param param;

    rt_init("a:r:t:e:l:h:", parse_args, argc, argv);
    signal(SIGINT, stop_log);

    if (argc >= (optind + 1))
        nr_tasks = atoi(argv[optind]);
    else {
        numcpus = sysconf(_SC_NPROCESSORS_ONLN);
        nr_tasks = numcpus + 1;
    }

    intervals = malloc(sizeof(stats_container_t) * nr_tasks);
    if (!intervals)
        debug(DBG_ERR, "malloc failed\n");
    memset(intervals, 0, sizeof(stats_container_t) * nr_tasks);

    intervals_length = malloc(sizeof(stats_container_t) * nr_tasks);
    if (!intervals_length)
        debug(DBG_ERR, "malloc failed\n");
    memset(intervals_length, 0, sizeof(stats_container_t) * nr_tasks);

    if (!intervals_loops)
        debug(DBG_ERR, "malloc failed\n");
    intervals_loops = malloc(sizeof(stats_container_t) * nr_tasks);
    memset(intervals_loops, 0, sizeof(stats_container_t) * nr_tasks);

    threads = malloc(sizeof(*threads) * nr_tasks);
    if (!threads)
        debug(DBG_ERR, "malloc failed\n");
    memset(threads, 0, sizeof(*threads) * nr_tasks);

    ret = pthread_barrier_init(&start_barrier, NULL, nr_tasks + 1);
    ret = pthread_barrier_init(&end_barrier, NULL, nr_tasks + 1);
    if (ret < 0)
        debug(DBG_ERR, "pthread_barrier_init failed: %s\n",
              strerror(ret));


    for (i = 0; i < nr_tasks; i++) {
        stats_container_init(&intervals[i], nr_runs);
        stats_container_init(&intervals_length[i], nr_runs);
        stats_container_init(&intervals_loops[i], nr_runs);
    }

    thread_pids = malloc(sizeof(long) * nr_tasks);
    if (!thread_pids)
        debug(DBG_ERR, "malloc thread_pids failed\n");

    for (i = 0; i < nr_tasks; i++) {
        threads[i] = create_fifo_thread(start_task, (void *)i,
                                        prio_start + i);
    }

    /*
     * Progress bar uses stderr to let users see it when
     * redirecting output. So we convert stderr to use line
     * buffering so the progress bar doesn't flicker.
     */
    setlinebuf(stderr);

    /* up our prio above all tasks */
    memset(&param, 0, sizeof(param));
    param.sched_priority = nr_tasks + prio_start;
    if (sched_setscheduler(0, SCHED_FIFO, &param))
        debug(DBG_WARN, "Warning, can't set priority of"
              "main thread !\n");
    intv.tv_sec = INTERVAL / NS_PER_SEC;
    intv.tv_nsec = INTERVAL % (1 * NS_PER_SEC);

    print_progress_bar(0);

    setup_ftrace_marker();

    for (loop = 0; loop < nr_runs; loop++) {
        unsigned long long end;

        now = rt_gettime() / NS_PER_US;

        ftrace_write("Loop %d now=%lld\n", loop, now);

        pthread_barrier_wait(&start_barrier);

        ftrace_write("All running!!!\n");

        rt_nanosleep(intv.tv_nsec);
        print_progress_bar((loop * 100) / nr_runs);

        end = rt_gettime() / NS_PER_US;
        ftrace_write("Loop %d end now=%lld diff=%lld\n",
                     loop, end, end - now);
        ret = pthread_barrier_wait(&end_barrier);

        if (stop || (check && check_times(loop))) {
            loop++;
            nr_runs = loop;
            break;
        }
    }
    putc('\n', stderr);

    pthread_barrier_wait(&start_barrier);
    done = 1;
    pthread_barrier_wait(&end_barrier);

    join_threads();
    print_results();

    if (stop) {
        /*
         * We use this test in bash while loops
         * So if we hit Ctrl-C then let the while
         * loop know to break.
         */
        if (check < 0)
            exit(-1);
        else
            exit(1);
    }
    if (check < 0)
        exit(-1);
    else
        exit(0);

    return 0;
}