Пример #1
0
void
test_signal(long iter, long nthreads)
{
	int i;
	int j;
	int k;
	pthread_t *pt;
	unsigned long max = 0;
	unsigned long min = 0;
	stats_container_t dat;
	stats_record_t rec;

	stats_container_init(&dat,iter * nthreads);

	pt = (pthread_t *)malloc(sizeof(*pt) * nthreads);
	if (pt == NULL) {
		fprintf(stderr, "Out of memory\n");
		exit(-1);
	}
	for (j = 0; j < nthreads; j++) {
		child_waiting[j] = 0;
		pt[j] = create_thread_(j);
	}
	for (i = 0; i < (iter - 1) * nthreads; i+=nthreads) {
		for (j = 0 , k = i; j < nthreads; j++ , k++) {
			wake_child(j, broadcast_flag);
			rec.x = k;
			rec.y = latency;
			stats_container_append(&dat, rec);
			pthread_mutex_lock(&child_mutex);
			child_waiting[j] = 0;
			pthread_mutex_unlock(&child_mutex);
		}
	}
	for (j = 0; j < nthreads; j++) {
		wake_child(j, broadcast_flag);
		pthread_mutex_lock(&child_mutex);
		child_waiting[j] = 3;
		pthread_mutex_unlock(&child_mutex);
		if (pthread_join(pt[j], NULL) != 0) {
			fprintf(stderr, "%d: ", j);
			perror("pthread_join");
			exit(-1);
		}
	}
	min = (unsigned long)-1;
	for (i = 0; i < iter * nthreads; i++){
		latency = dat.records[i].y;
		if (latency > PASS_US)
			fail = 1;
		min = MIN(min, latency);
		max = MAX(max, latency);
	}
	printf("Recording statistics...\n");
	printf("Minimum: %lu us\n", min);
	printf("Maximum: %lu us\n", max);
	printf("Average: %f us\n", stats_avg(&dat));
	printf("Standard Deviation: %f\n", stats_stddev(&dat));
}
Пример #2
0
static void record_time(int id, unsigned long long time, unsigned long l)
{
    unsigned long long ltime;
    stats_record_t rec;
    if (loop >= nr_runs)
        return;
    time -= now;
    ltime = rt_gettime() / NS_PER_US;
    ltime -= now;
    rec.x = loop;
    rec.y = time;
    stats_container_append(&intervals[id], rec);
    rec.x = loop;
    rec.y = ltime;
    stats_container_append(&intervals_length[id], rec);
    rec.x = loop;
    rec.y = l;
    stats_container_append(&intervals_loops[id], rec);
}
Пример #3
0
void * high_prio_thread(void *arg)
{
	nsec_t high_start, high_end, high_get_lock;
	unsigned int i;

	stats_container_init(&cpu_delay_dat, iterations);
	stats_container_init(&cpu_delay_hist, HIST_BUCKETS);
	stats_quantiles_init(&cpu_delay_quantiles, (int)log10(iterations));

	printf("High prio thread started\n");

	for (i = 0; i < iterations; i++) {
		/* Wait for all threads to reach barrier wait. When
		   woken up, low prio thread will own the mutex
		 */
		pthread_barrier_wait(&bar1);

		high_start = rt_gettime();
		pthread_mutex_lock(&lock);
		high_end = rt_gettime();
		high_get_lock = high_end - low_unlock;

		busy_work_ms(high_work_time);
		pthread_mutex_unlock(&lock);

		rec.x = i;
		rec.y = high_get_lock / NS_PER_US;
		stats_container_append(&cpu_delay_dat, rec);

		/* Wait for all threads to finish this iteration */
		pthread_barrier_wait(&bar2);
	}

	stats_hist(&cpu_delay_hist, &cpu_delay_dat);
	stats_container_save("samples", "pi_perf Latency Scatter Plot",
				"Iteration", "Latency (us)", &cpu_delay_dat, "points");
	stats_container_save("hist", "pi_perf Latency Histogram",
				"Latency (us)", "Samples", &cpu_delay_hist, "steps");

	printf("Time taken for high prio thread to get the lock once released by low prio thread\n");
	printf("Min delay = %ld us\n", stats_min(&cpu_delay_dat));
	printf("Max delay = %ld us\n", stats_max(&cpu_delay_dat));
	printf("Average delay = %4.2f us\n", stats_avg(&cpu_delay_dat));
	printf("Standard Deviation = %4.2f us\n", stats_stddev(&cpu_delay_dat));
	printf("Quantiles:\n");
	stats_quantiles_calc(&cpu_delay_dat, &cpu_delay_quantiles);
	stats_quantiles_print(&cpu_delay_quantiles);

	max_pi_delay = stats_max(&cpu_delay_dat);

	return NULL;
}
Пример #4
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;
}
Пример #5
0
void *thread_worker(void* arg)
{
	struct timespec start, stop;
	int i;
	unsigned long long delta;
	unsigned long long min=-1, max=0;

	stats_container_t dat;
	stats_record_t rec;

	stats_container_init(&dat, NUMRUNS);

        for (i=0; i < NUMRUNS; i++) {

		do_work(1); /* warm cache */

		/* do test */
		clock_gettime(CLOCK_MONOTONIC, &start);
		do_work(NUMLOOPS);
		clock_gettime(CLOCK_MONOTONIC, &stop);


		/* calc delta, min and max */
		delta = ts_sub(stop, start);
		if (delta < min)
			min = delta;
		if (delta> max)
			max = delta;
		rec.x = i;
		rec.y = delta;
		stats_container_append(&dat, rec);

		printf("delta: %llu ns\n", delta);
		usleep(1); /* let other things happen */
	}

	printf("max jitter: ");
	print_unit(max - min);
	stats_container_save("samples", "Scheduling Jitter Scatter Plot",\
				"Iteration", "Delay (ns)", &dat, "points");
	return NULL;
}
Пример #6
0
void * low_prio_thread(void *arg)
{
	nsec_t low_start, low_hold;
	unsigned int i;

	stats_container_init(&low_dat, iterations);

	printf("Low prio thread started\n");

	for (i = 0; i < iterations; i++) {
		pthread_mutex_lock(&lock);
		/* Wait for all threads to reach barrier wait.
		   Since we already own the mutex, high prio
		   thread will boost our priority.
		*/
		pthread_barrier_wait(&bar1);

		low_start = rt_gettime();
		busy_work_ms(low_work_time);
		low_unlock = rt_gettime();
		low_hold = low_unlock - low_start;

		pthread_mutex_unlock(&lock);

		rec.x = i;
		rec.y = low_hold / NS_PER_US;
		stats_container_append(&low_dat, rec);

		if (i == iterations-1)
			end = 1;

		/* Wait for all threads to finish this iteration */
		pthread_barrier_wait(&bar2);
	}

	return NULL;
}
Пример #7
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;
}
Пример #8
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;
}
Пример #9
0
int main(int argc, char *argv[])
{
	int i, j, k, err;
	unsigned long long delta;
	unsigned long long max, min;
	struct sched_param param;
	stats_container_t dat;
	stats_container_t hist;
	stats_quantiles_t quantiles;
	stats_record_t rec;
	struct timespec *start_data;
	struct timespec *stop_data;

	if (stats_cmdline(argc, argv) < 0) {
		printf("usage: %s help\n", argv[0]);
		exit(1);
	}

	if (iterations < MIN_ITERATION) {
		iterations = MIN_ITERATION;
		printf("user \"iterations\" value is too small (use: %d)\n",
		       iterations);
	}

	stats_container_init(&dat, iterations);
	stats_container_init(&hist, HIST_BUCKETS);
	stats_quantiles_init(&quantiles, (int)log10(iterations));
	setup();

	mlockall(MCL_CURRENT | MCL_FUTURE);

	start_data = calloc(iterations, sizeof(struct timespec));
	if (start_data == NULL) {
		printf("Memory allocation Failed (too many Iteration: %d)\n",
		       iterations);
		exit(1);
	}
	stop_data = calloc(iterations, sizeof(struct timespec));
	if (stop_data == NULL) {
		printf("Memory allocation Failed (too many Iteration: %d)\n",
		       iterations);
		free(start_data);
		exit(1);
	}

	/* switch to SCHED_FIFO 99 */
	param.sched_priority = sched_get_priority_max(SCHED_FIFO);
	err = sched_setscheduler(0, SCHED_FIFO, &param);

	/* Check that the user has the appropriate privileges */
	if (err) {
		if (errno == EPERM) {
			fprintf(stderr,
				"This program runs with a scheduling policy of SCHED_FIFO at priority %d\n",
				param.sched_priority);
			fprintf(stderr,
				"You don't have the necessary privileges to create such a real-time process.\n");
		} else {
			fprintf(stderr, "Failed to set scheduler, errno %d\n",
				errno);
		}
		exit(1);
	}

	printf("\n----------------------\n");
	printf("Gettimeofday() Latency\n");
	printf("----------------------\n");
	printf("Iterations: %d\n\n", iterations);

	/* collect iterations pairs of gtod calls */
	max = min = 0;
	if (latency_threshold) {
		latency_trace_enable();
		latency_trace_start();
	}
	/* This loop runs for a long time, hence can cause soft lockups.
	   Calling sleep periodically avoids this. */
	for (i = 0; i < (iterations / 10000); i++) {
		for (j = 0; j < 10000; j++) {
			k = (i * 10000) + j;
			clock_gettime(CLOCK_MONOTONIC, &start_data[k]);
			clock_gettime(CLOCK_MONOTONIC, &stop_data[k]);
		}
		usleep(1000);
	}
	for (i = 0; i < iterations; i++) {
		delta = timespec_subtract(&start_data[i], &stop_data[i]);
		rec.x = i;
		rec.y = delta;
		stats_container_append(&dat, rec);
		if (i == 0 || delta < min)
			min = delta;
		if (delta > max)
			max = delta;
		if (latency_threshold && delta > latency_threshold)
			break;
	}
	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);
		}
	}

	stats_hist(&hist, &dat);
	stats_container_save(filenames[SCATTER_FILENAME], titles[SCATTER_TITLE],
			     labels[SCATTER_LABELX], labels[SCATTER_LABELY],
			     &dat, "points");
	stats_container_save(filenames[HIST_FILENAME], titles[HIST_TITLE],
			     labels[HIST_LABELX], labels[HIST_LABELY], &hist,
			     "steps");

	/* report on deltas */
	printf("Min: %llu ns\n", min);
	printf("Max: %llu ns\n", max);
	printf("Avg: %.4f ns\n", stats_avg(&dat));
	printf("StdDev: %.4f ns\n", stats_stddev(&dat));
	printf("Quantiles:\n");
	stats_quantiles_calc(&dat, &quantiles);
	stats_quantiles_print(&quantiles);

	stats_container_free(&dat);
	stats_container_free(&hist);
	stats_quantiles_free(&quantiles);

	return 0;
}
Пример #10
0
void *signal_receiving_thread(void *arg)
{
	int i, ret, sig;
	long delta;
	long max, min;
	sigset_t set, oset;

	stats_container_t dat;
	stats_container_t hist;
	stats_quantiles_t quantiles;
	stats_record_t rec;

	stats_container_init(&dat, ITERATIONS);
	stats_container_init(&hist, HIST_BUCKETS);
	stats_quantiles_init(&quantiles, (int)log10(ITERATIONS));

	debug(DBG_DEBUG, "Signal receiving thread running\n");

	if ((sigaddset(&set, SIGNALNUMBER))) {
		perror("sigaddset:");
		exit(1);
	}
	if ((ret = pthread_sigmask(SIG_BLOCK, &set, &oset))) {
		printf("pthread_sigmask returned %d\n", ret);
		exit(1);
	}

	/* Let the sending thread know that receiver is ready */
	atomic_set(1, &flag);

	debug(DBG_DEBUG, "Signal receiving thread ready to receive\n");

	if (latency_threshold) {
		latency_trace_enable();
		latency_trace_start();
	}

	/* Warm up */
	for (i = 0; i < 5; i++) {
		sigwait(&set, &sig);
		atomic_set(1, &flag);
	}

	max = min = 0;
	fail = 0;
	debug(DBG_INFO, "\n\n");

	for (i = 0; i < ITERATIONS; i++) {
		sigwait(&set, &sig);
		end = rt_gettime();
		delta = (end - begin)/NS_PER_US;
		rec.x = i;
		rec.y = delta;
		stats_container_append(&dat, rec);

		if (i == 0 || delta < min)
			min = delta;

		if (delta > max)
			max = delta;

		if (delta > pass_criteria) fail++;

		debug(DBG_INFO, "Iteration %d: Took %ld us. Max = %ld us, "
		      "Min = %ld us\n", i, delta, max, min);

		fflush(stdout);
		buffer_print();

		if (latency_threshold && (delta > latency_threshold)) {
			atomic_set(2, &flag);
			break;
		}

		atomic_set(1, &flag);
	}

	if (latency_threshold) {
		latency_trace_stop();

		if (i != ITERATIONS) {
			printf("Latency threshold (%luus) exceeded at iteration %d\n",
			       latency_threshold, i);
			fflush(stdout);
			buffer_print();
			latency_trace_print();
			stats_container_resize(&dat, i + 1);
		}
	}

	stats_hist(&hist, &dat);
	stats_container_save("samples", "pthread_kill Latency Scatter Plot",
			     "Iteration", "Latency (us)", &dat, "points");
	stats_container_save("hist", "pthread_kill Latency Histogram",
			     "Latency (us)", "Samples", &hist, "steps");

	printf("\n");
	printf("Min: %lu us\n", stats_min(&dat));
	printf("Max: %lu 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("Failures: %d\n", fail);
	printf("Criteria: Time < %d us\n", (int)pass_criteria);
	printf("Result: %s", fail ? "FAIL" : "PASS");
	printf("\n\n");

	return NULL;
}