From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by yocto-www.yoctoproject.org (Postfix, from userid 118) id 53818E0095F; Tue, 10 Feb 2015 06:17:12 -0800 (PST) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on yocto-www.yoctoproject.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 X-Spam-HAM-Report: * -2.3 RCVD_IN_DNSWL_MED RBL: Sender listed at http://www.dnswl.org/, * medium trust * [147.11.1.11 listed in list.dnswl.org] * -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% * [score: 0.0000] Received: from mail.windriver.com (mail.windriver.com [147.11.1.11]) by yocto-www.yoctoproject.org (Postfix) with ESMTP id 38DABE0094C for ; Tue, 10 Feb 2015 06:17:10 -0800 (PST) Received: from ALA-HCA.corp.ad.wrs.com (ala-hca.corp.ad.wrs.com [147.11.189.40]) by mail.windriver.com (8.14.9/8.14.5) with ESMTP id t1AEH7Fa017419 (version=TLSv1/SSLv3 cipher=AES128-SHA bits=128 verify=FAIL); Tue, 10 Feb 2015 06:17:07 -0800 (PST) Received: from [128.224.56.48] (128.224.56.48) by ALA-HCA.corp.ad.wrs.com (147.11.189.50) with Microsoft SMTP Server id 14.3.174.1; Tue, 10 Feb 2015 06:17:07 -0800 Message-ID: <54DA12C7.8000000@windriver.com> Date: Tue, 10 Feb 2015 09:16:39 -0500 From: Bruce Ashfield User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.3.0 MIME-Version: 1.0 To: Stephen Flowers , References: <54DA0258.9070108@gmail.com> In-Reply-To: <54DA0258.9070108@gmail.com> Subject: Re: Yocto Realtime tests on beaglebone black X-BeenThere: yocto@yoctoproject.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Discussion of all things Yocto Project List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 10 Feb 2015 14:17:12 -0000 Content-Type: text/plain; charset="windows-1252"; format=flowed Content-Transfer-Encoding: 7bit On 15-02-10 08:06 AM, Stephen Flowers wrote: > Hi All, > > I have built the realtime kernel using Yocto and deployed on the > beaglebone black (specifically core-image-rt-sdk). I have written a > program to test the timer latency and interrupt latency of userspace > applications. For this I'm using a simple timerfd to generate a > periodic 10ms gpio toggle which itself acts as a gpio interrupt on > another gpio pin. > I find the latency is much worse on the preempt_rt kernel than the > standard one. RT kernel gives around 220us average with the standard > kernel about 80us. Testing with Xenomai gives about 60us. The response > times are measured with an external logic analyser, and taken with no > other load on the system. Kernel version is 3.14. > > The difference between standard and RT kernel configs: > Preemption model: desktop vs. realtime kernel > Timer: 100Hz vs 1000Hz > High resolution timers disabled Can you share the full .config for both configurations ? That should shed a bit more light on what might be misconfigured. I haven't run tests on the beaglebone black myself, but on similar ARM boards, performance has been as expected. You are talking about average latency above, what about the max latency ? We expect that the preempt-rt kernel will have a higher minimum, and often average latency .. but will be significantly better in maximum latency. It would also be useful to grab cyclictest results for the standard and preempt-rt kernel as a baseline performance measure. Bruce > > I'm having a hard time figuring out why the RT kernel gives worse > latency. Anyone have any insight into this? > Included the source code below. > > Thanks & Regards, > Steve > > #include > #include > #include > #include > #include > #include > #include > #include > #include "poll.h" > #include "fcntl.h" > #include "string.h" > #include "errno.h" > #include > > #define TIMER_OUT_PATH "/sys/class/gpio/gpio47" > #define LED_OUT_PATH "/sys/class/gpio/gpio26" > #define IRQ_IN_PATH "/sys/class/gpio/gpio46" > > static int timer_toggle = 0; > static int output_toggle = 0; > > void stack_prefault(void) > { > unsigned char dummy[8192]; > memset(dummy, 0, 8192); > } > > > int main(int argc, char* argv[]) > { > struct itimerspec itv; > unsigned long long timer_increment = 0; > > clock_t prevClock; > int sigCnt = 0; > struct sigaction sa; > struct sched_param sp; > > struct pollfd fdset[2]; > int fd_in; > int action; > int fd_led; > int fd_timer_out; > int fd_timer_in; > > char buf[2]; > int len; > > // setup gpio > if(system("echo 46 > /sys/class/gpio/export") == -1) > perror("unable to export gpio 46"); > > if(system("echo 47 > /sys/class/gpio/export") == -1) > perror("unable to export gpio 47"); > > if(system("echo 26 > /sys/class/gpio/export") == -1) > perror("unable to export gpio 26"); > > // timer out > if(system("echo out > /sys/class/gpio/gpio47/direction") == -1) > perror("unable to set 47 to output"); > > // led out > if(system("echo out > /sys/class/gpio/gpio26/direction") == -1) > perror("unable to set 26 to output"); > > // irq in > if(system("echo in > /sys/class/gpio/gpio46/direction") == -1) > perror("unable to set 46 to input"); > > if(system("echo both > /sys/class/gpio/gpio46/edge") == -1) > perror("unable to set 46 edge"); > > // set scheduling parameters > sp.sched_priority = sched_get_priority_max(SCHED_FIFO); > if(sched_setscheduler(0, SCHED_FIFO, &sp) == -1) > { > perror("setscheduler"); > exit(-1); > } > > // lock memory > if(mlockall(MCL_CURRENT|MCL_FUTURE) == -1) > perror("mlockall"); > > stack_prefault(); > > // Set up timer > fd_timer_in = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK); > printf("fd_timer:%d\n",fd_timer_in); > > if(fd_timer_in < 0) > { > perror("timerfd_create()"); > } > > itv.it_value.tv_sec = 0; > itv.it_value.tv_nsec = 10000000; > itv.it_interval.tv_sec = 0; > itv.it_interval.tv_nsec = 10000000; > if(-1 == timerfd_settime(fd_timer_in, 0, &itv, NULL)) > { > perror("settime()"); > } > > // setup file descriptor for poll() > fd_in = open(IRQ_IN_PATH "/value", O_RDONLY | O_NONBLOCK); > printf("fd irq input:%d\n",fd_in); > > if(fd_in < 0) > { > perror("file open problem"); > exit(0); > } > > while(1) > { > memset((void*)fdset, 0, sizeof(fdset)); > fdset[0].fd = fd_in; > fdset[0].events = POLLPRI | POLLERR; > fdset[0].revents = 0; > > fdset[1].fd = fd_timer_in; > fdset[1].events = POLLIN | POLLERR; > fdset[1].revents = 0; > action = poll(fdset, 2, -1); > > if(action < 0) > { > if(errno == EINTR) > { > // when signal interrupts poll, we poll again > continue; > } > else > { > perror("poll failed"); > exit(0); > } > } > > if(fdset[1].revents & POLLIN) > { > //len = read(fdset[1].fd, 0, SEEK_SET); > len = read(fdset[1].fd, &timer_increment, > sizeof(timer_increment)); > > fd_timer_out = open( TIMER_OUT_PATH "/value", O_WRONLY); > > if(timer_toggle ^= 1) > { > write(fd_timer_out, "1", 2); > } > else > { > write(fd_timer_out, "0", 2); > } > > close(fd_timer_out); > } > > if(fdset[0].revents & POLLPRI) > { > lseek(fdset[0].fd, 0, SEEK_SET); // read from start of file > len = read(fdset[0].fd, buf, sizeof(buf)); > > fd_led = open( LED_OUT_PATH "/value", O_WRONLY | O_NONBLOCK); > > if(buf[0] == '1') > { > write(fd_led, "1", 2); > } > else > { > write(fd_led, "0", 2); > } > > close(fd_led); > } > } > > close(fd_in); > close(fd_timer_in); > close(fd_led); > printf("finished\n"); > return 0; > } > > > > >