Tuesday, May 25, 2010

How to Measure the Duration of a RTAI Semaphore Operation

Today I was asked the question "How long does it take to signal a semaphore?".

This is important as I had to do it in an ISR [which serviced a quasi-timer IRQ] to signal an RT task to start doing a job (this is akin to Linux tasklets).

Here is how I measured it (interrupts are disable to keep the measurement accurate):

#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/types.h>

#include <rtai_sem.h>
#include <rtai_sched.h>

SEM pollSem;

static int __init testsem_init_module(void)
rt_typed_sem_init(&pollSem, 0, BIN_SEM | FIFO_Q);


volatile unsigned long long ticks_start;
"mov %%edx, %%ecx\n\t"
:"=A" (ticks_start));


volatile unsigned long long ticks_end;
"mov %%edx, %%ecx\n\t"
:"=A" (ticks_end));


long long dT = ticks_end - ticks_start;


printk(KERN_DEBUG "rt_sem_signal took %lld ticks\n", dT);

return -EBUSY;

The answer was (on a PIII/1.2GHz) about 300 cpu ticks which is ~0.25 uS.


Porting the Linux e100 Driver to RTnet

My client has been using the E100 Intel card that came with his embedded mobo. When using the RTnet driver (eepro100, an antique version of the Becker driver which did not do firmware download to the card) they were experience strange TX lockups which could only be cured by a power cycle.

It was either trying to fix the eepro100 driver (and maybe download firmware borrowed from the newer E100 driver) or port the stock Linux e100 driver which had no lockup issued, quod fecit.

Here are the steps (in e100.c):
- alter Makefile, Makefile.in from RTnet;
- junk Ethtool code, disable IPv6;
- junk eeprom write code;
- junk loopback test code;
- rip out the Linux stack calls and replace with RTDM if applicable;
- ditto for skb->rtskb;
- replace schedule_work with a semaphore and rtdm_nrtsig_pend()
- kmalloc / kcalloc / kzalloc wrapped for RTDM;
- pre-allocate a pool of 256 rtskbs for RX and initialise it;
- connect to STACK_manager in e100_open;
- added I/O RT task which is the RTnet bottom half -- waits on a semaphore, calls e100_poll() and if packets received signals RTnet to process the packets;
- changed the ISR (legacy) to signal the semaphore above is IRQ belongs to the driver;
- disabled set MAC code -- RTnet does not support it;
- disabled change MTU code -- RTnet does not support it;
- modify RTnet's configure to have "--enable-e100".

I spent most of the time trying to compile the hacked code. After I got an IRQ kicking I spent a lot of time making sure the driver is stable.

The ported driver (base kernel version is 2.6.29) is here.