Re: Linux RT patch for Pandaboard Omap 4 kernel 3.0.0-1205 error when compiling

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Nov 2, 2011 at 5:15 PM, HUNG BUI <buihung@xxxxxxxxx> wrote:
> Thank you Jiri and Sankara.
>
> With your help I have successful compiled rt patch for Ubuntu on Pandaboard.

Glad to have been of help.

> After reboot, i have the realtime 3.0.1 omap4 running. The cyclictest
> shows an acceptable result, with no load the maximum latency is around
> 30usec, with load it is ~150usec.

Could you tell me what kind of load did you apply? How long did you
run the tests?

Have you tried running the tests for long time (8+ hours) and observed
weird latencies (way too high) due to the fact that the time jumping
backwards? Also, you could run the test program (attached in
testTimerRes.c file) (Use the following options to compile :
COMPILER_or_CROSS-COMPILER -D_GNU_SOURCE -Wall -Wno-nonnull -std=c99
-O2 -lrt -lpthread -o testTimerRes testTimerRes.c ). If you run
without any arguments, it will display 10 time-stamps and that will
tell you whether you have enabled high-resolution timer or not. If
they are less than a usec apart, you have got high-res timer to work.
If you run it as "./testTimerRes -x <num>", it tries to get the
time-stamps in a loop and if the time-stamp goes backwards by more
than "num" naonsec's, it prints an error and exits the program and
prints by how many nanosec's the time-stamps went backwards and how
many iterations it took before this error happened. You can ignore the
argument <num> and simply run "./testTimerRes -x" and it will exit, if
the time-stamp goes backwards at all. I am really curious whether this
issue happens with the OMAP kernel that you have tried.

> I have a question about the minimal systems, it may be ridiculous but
> i don;t know how to get and run cyclictest, since I don;t have apt-get
> package, also no git. As I understand, I will have to compile it on
> pandaboard, but I found it hard to do it on the minimal fs.

You could cross-compile cyclictest on a different Linux system also
(x86 Linux or Linux VM on a x86 Windows, something like that).

> And second question, when you cross compile with make ARCH=arm
> CROSS_COMPILE=arm-angstrom-linux-gnueabi- uImage and get the uImage,
> your pandaboard is running Ubuntu or minimal fs ?
> Hung Bui

I am using a angstrom-based root file system (with quite a few tools
that we need) on panda board that my co-worker has put together for
our development.
Thanks, Sankara
/*
 * Copyright (C) 2011 Sankara Muthukrishnan <sankara.m@xxxxxx>
 *
 * based on functions/code-snippets from cyclictest (in rt_tests suite) that has
 * the following copyright notices:
 *
 * Check the resolution of timer 
 *
 * (C) 2008-2011 Clark Williams <williams@xxxxxxxxxx>
 * (C) 2005-2007 Thomas Gleixner <tglx@xxxxxxxxxxxxx>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License Version
 * 2 as published by the Free Software Foundation.
 * 
 */

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdarg.h>
#include <stdbool.h>
#include <unistd.h>
#include <fcntl.h>
#include <getopt.h>
#include <pthread.h>
#include <signal.h>
#include <sched.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#include <limits.h>
#include <linux/unistd.h>

#include <sys/prctl.h>
#include <sys/stat.h>
#include <sys/sysinfo.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/utsname.h>
#include <sys/mman.h>

#define USEC_PER_SEC		1000000
#define NSEC_PER_SEC		1000000000

#define gettid() syscall(__NR_gettid)

#define PRINTFL printf("%s:%d\n", __FILE__, __LINE__);
#define PRINTL printf("%d\n", __LINE__);

// typedef unsigned int bool;	
//
struct thread_param {
	int prio;
	int policy;
	int mode;
	int timermode;
	int signal;
	int clock;
	unsigned long max_cycles;
	struct thread_stat *stats;
	int bufmsk;
	unsigned long interval;
	int cpu;
	int node;
};

enum {
	AFFINITY_UNSPECIFIED,
	AFFINITY_SPECIFIED,
	AFFINITY_USEALL
};
static int setaffinity = AFFINITY_UNSPECIFIED;

static int affinity = 0;

static bool testCS = false;
static uint32_t testCSlat = 0;

void warn(char *fmt, ...)
{
	va_list ap;

	va_start(ap, fmt);
	fputs("WARNING: ", stderr);
	vfprintf(stderr, fmt, ap);
	va_end(ap);
}

void fatal(char *fmt, ...)
{
	va_list ap;

	va_start(ap, fmt);
	fputs("FATAL: ", stderr);
	vfprintf(stderr, fmt, ap);
	va_end(ap);
	exit(EXIT_FAILURE);
}

static int check_highres_timer(void)
{
	struct timespec ts;

	if (clock_getres(CLOCK_MONOTONIC, &ts))
		return 1;

	return (ts.tv_sec != 0 || ts.tv_nsec != 1);
}

static inline int64_t calcdiff_ns(struct timespec *t1, struct timespec *t2)
{
	int64_t diff;
	diff = NSEC_PER_SEC * (int64_t)((int) t1->tv_sec - (int) t2->tv_sec);
	diff += ((int) t1->tv_nsec - (int) t2->tv_nsec);
	return diff;
}

static inline void my_gettime(struct timespec *t, int *ret_api, int *errno_api, bool quit_on_err)
{
	*ret_api = clock_gettime(CLOCK_MONOTONIC, t); 
	if (*ret_api != 0) {
		if (quit_on_err)
			fatal("clock_gettime failed\n");
		else
			*errno_api = errno;
	}
}

static void *check_clock_source(void *param)
{
	#define NUM_LOOPS 11

	struct timespec prev, cur;
	int ret_gettime = 0, errno_gettime = 0;
	int64_t diff_ns = 0;
	bool quit_on_err = true;
	struct sched_param schedp;
	struct thread_param *par = param;
	cpu_set_t mask;
	int64_t time_stamp_diff[NUM_LOOPS] = {0};
	unsigned int same_val_iters[NUM_LOOPS] = {0};
	int i = 0;
	int64_t testCSiters = 0;

#if 0	
	memset(&prev, 0, sizeof(prev));
	memset(&cur, 0, sizeof(cur));
#endif	
	memset(&schedp, 0, sizeof(schedp));

	schedp.sched_priority = sched_get_priority_max(SCHED_FIFO);
	if (0 != sched_setscheduler(0, SCHED_FIFO, &schedp))
		warn("sched_setscheduler failed\n");

	if (par->cpu != -1) {
		CPU_ZERO(&mask);
		CPU_SET(par->cpu, &mask);
		if(sched_setaffinity(0, sizeof(mask), &mask) == -1)
			warn("Could not set CPU affinity to CPU #%d\n", par->cpu);
	}

	CPU_ZERO(&mask);
	if (sched_getaffinity(0, sizeof(mask), &mask) == -1)
		warn("Could not get CPU affinity to CPU #%d\n", par->cpu);
	else {
#if DEBUG
		 	printf("CPU=%d, tid=%d, pid=%d, ppid=%d, mask=0x%08X\n", 
			par->cpu, gettid(), getpid(), getppid(), (unsigned int) *(int *)&mask); 
			/* @sanTODO hack: typecasting mask is evil. fix it */
#endif
	}

#if DEBUG	
	printf("testClockSource=%d, testClockSourceMinimumLatency=%u\n", testCS, testCSlat);
#endif

	i = 0;
	my_gettime(&prev, &ret_gettime, &errno_gettime, quit_on_err);
	while (true) {
		my_gettime(&cur, &ret_gettime, &errno_gettime, quit_on_err);
		if (ret_gettime != 0) {
			errno_gettime = errno;
			printf("Fatal error: clock_gettime failed\n");
			break;
		}
		diff_ns = calcdiff_ns(&cur, &prev);
		if (diff_ns < 0 && abs(diff_ns) > testCSlat) { 
			printf("Fatal error: time-stamps going backwards\n");
			break;
		}
		if (!testCS) {
			if (diff_ns == 0) 
				same_val_iters[i]++;
			else {
				time_stamp_diff[i] = diff_ns;
				i++;
			}
		}
		else 
			testCSiters++;
		prev = cur;
		if (!testCS && i == NUM_LOOPS)
			break;
	}
	if (diff_ns < 0) 
		printf("diff_timestamp_nsec=%lld, current_time_stamp=%u:%u, prev_time_stamp=%u:%u\n", 
			diff_ns, (uint32_t)cur.tv_sec, (uint32_t)cur.tv_nsec, 
			(uint32_t)prev.tv_sec, (uint32_t)prev.tv_nsec);
	if (testCS)
		printf("testCSiters=%llu\n", testCSiters);
	if (!quit_on_err)
		printf("ret_gettime=%d, errno_gettime=%d\n", ret_gettime, errno_gettime);

	if (!testCS && i == NUM_LOOPS) {
		printf("No of iterations with same time-stamp, difference in time-stamps in nanosec when time-stamp changes\n");
		for (i = 1; i < NUM_LOOPS; i++) {
		// i = 0 is ignored, since it would vary for each run
			printf("iterations = %u, time-stamp difference = %lld nanosec\n",
				same_val_iters[i], time_stamp_diff[i]);
		}
	}
	return NULL;
}

static void display_help(int error)
{

	printf("Usage:\n"
	       "testClockSrc <options>\n\n"
	       "-a [NUM] --affinity        run the test thread on processor #NUM\n"
	       "                           default for NUM is 0\n"
	       "-x [NS]  --testCS=NS       test the clock source used by clock_gettime function\n"
	       "                           to see if the time-stamps jump backwards by more than\n"
	       "                           NS nanoseconds.\n"
	       "                           default for NS is 0.\n\n"
			 );

	exit(error);
}

/* Process commandline options */
static void process_options (int argc, char *argv[])
{
	int error = 0;
	int max_cpus = sysconf(_SC_NPROCESSORS_CONF);

	for (;;) {
		int option_index = 0;
		/** Options for getopt */
		static struct option long_options[] = {
			{"affinity", required_argument, NULL, 'a'},
			{"testCS", optional_argument, NULL, 'x'},
			{"help", no_argument, NULL, 'h'},
			{NULL, 0, NULL, 0}
		}; 
		int c = getopt_long(argc, argv, "a::hx::",
				    long_options, &option_index);
		if (c == -1)
			break;
		switch (c) {
		case 'a':
			if (optarg != NULL) {
				affinity = atoi(optarg);
				setaffinity = AFFINITY_SPECIFIED;
			} else if (optind<argc && atoi(argv[optind])) {
				affinity = atoi(argv[optind]);
				setaffinity = AFFINITY_SPECIFIED;
			} else {
				setaffinity = AFFINITY_USEALL;
			}
			break;
		case 'x':
			testCS = true;
			if (optarg != NULL) 
				testCSlat = atoi(optarg);	
			break;

		case 'h': display_help(0); break;
		case '?': display_help(0); break;
		}
	}

	if (setaffinity == AFFINITY_SPECIFIED) {
		if (affinity < 0)
			error = 1;
		if (affinity >= max_cpus) {
			warn("CPU #%d not found, only %d CPUs available\n",
			    affinity, max_cpus);
			error = 1;
		}
	} 	
}

int main(int argc, char *argv[])
{
	pthread_t thread;
	int status, i = 0;
	struct thread_param *par = NULL;
	int max_cpus = sysconf(_SC_NPROCESSORS_CONF);

	process_options(argc, argv);

	if (check_highres_timer())
		warn("High resolution timers not available\n");

	par = (struct thread_param *) malloc(sizeof(struct thread_param));
	if (par == NULL)
		fatal("error allocating thread_param struct for thread %d\n", i);
	memset(par, 0, sizeof(struct thread_param));

	switch (setaffinity) {
	case AFFINITY_UNSPECIFIED: par->cpu = -1; break;
	case AFFINITY_SPECIFIED: par->cpu = affinity; break;
	case AFFINITY_USEALL: par->cpu = i % max_cpus; break;
	}

	status = pthread_create(&thread, NULL, check_clock_source, par); 
	if (status)
		fatal("failed to create thread %d: %s\n", i, strerror(status));
	pthread_join(thread, NULL); 
	return 0;
}

[Index of Archives]     [RT Stable]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Video 4 Linux]     [Device Mapper]

  Powered by Linux