Column: Embedded design
Uncovering performance issues of the interrupt request handler
Mohammed Billoo, founder of MAB Labs, charts his experiences with the new Linux support by Percepio’s Tracealyzer v4.4 tool through real-world projects
I
n last month’s Electronics World, we saw how Tracealyzer for Linux, developed by Percepio, can be a valuable utility to ensure that our Linux driver works properly. While that article
provided high-level overview of the relevant views Tracealyzer offers for our analysis, this article will dive into a key component of a Linux device driver, the interrupt request (IRQ) handler, and how Tracealyzer can give feedback on its performance. Essentially, we want to perform the
fewest operations possible in an IRQ handler, because the kernel (and the entire processor) is in a sensitive state. For example, all interrupts are masked (i.e. no other interrupt can fire) and the Linux scheduler is effectively paused for the duration of the IRQ handler’s task. Thus, we need to ensure that we are doing only the bare minimum to address the interrupt, such as register operations and moving data around in the processor memory, and defer managing the data transfer operation itself to other kernel mechanisms (such as a tasklet). In our specific example, we know from the device specification that an interrupt will fire every 80 milliseconds, so that will be the upper bound on how long the IRQ handler to execute. We can use Tracealyzer to ensure
that our IRQ handler is doing as little as possible, with the advantage that it eliminates the need for any extraneous printks (which, as we’ll see, can actually hide incorrect implementations) and
08 March 2021
www.electronicsworld.co.uk
comparison of timestamps in kernel logs. Tracealyzer for Linux also eliminates the need to pore over LTTng traces to evaluate performance. It provides a clear view of our IRQ handler.
The example Going back to the example of a Linux device driver for our data acquisition device, recall that a GPIO from the device will be the signal to the driver that data is ready to be collected. Our simple IRQ handler is shown
below, along with the relevant code to “register” it with the kernel:
static int __init mab_init(void) {
result = request_irq(irq_number,
(irq_handler_t) mab_irq_handler, IRQF_TRIGGER_RISING, “mab_
irq_handler”, NULL); return result;
}
static irq_handler_t mab_irq_ handler(unsigned int irq, void *device, struct pt_regs *regs) {
printk(KERN_INFO “MAB - got interrupt!\n”); return (irq_handler_t) IRQ_ HANDLED; }
We’re simply printing to the kernel log that we received an interrupt, and letting
After transferring the LTTng traces
to our host machine and firing up Tracealyzer, when we open the Trace View we see the following: Selection Details (Figure 1, top) and Actor Instances graph (Figure 1, bottom). Note that only the IRQ handler is selected in the Actor Instance graph in order to focus our attention. The View dropdown box in Actor
Instance Graph has been adjusted to select Periodicity – From Ready. It shows us how often the IRQ handler is firing, which is roughly every 80ms and in line with our expectation. The “Selection Details” window shows
that, in one instance, the IRQ handler took approximately 3.3ms to execute. If we change the View dropdown box of the
$> lttng create $> lttng enable-event -k irq_* $> lttng start
the kernel know by way of the return value IRQ_HANDLED that the interrupt was handled. Before we load our kernel module
and connect our device, we have to start LTTng on the target device slightly differently from what’s described in the “Getting Started With Tracealyzer for Linux” guide. We’ll need to run the following commands to tell LTTng to only capture IRQ handlers (we’re also going to ignore scheduler events in order to focus solely on the interrupt handler):
Page 1 |
Page 2 |
Page 3 |
Page 4 |
Page 5 |
Page 6 |
Page 7 |
Page 8 |
Page 9 |
Page 10 |
Page 11 |
Page 12 |
Page 13 |
Page 14 |
Page 15 |
Page 16 |
Page 17 |
Page 18 |
Page 19 |
Page 20 |
Page 21 |
Page 22 |
Page 23 |
Page 24 |
Page 25 |
Page 26 |
Page 27 |
Page 28 |
Page 29 |
Page 30 |
Page 31 |
Page 32 |
Page 33 |
Page 34 |
Page 35 |
Page 36 |
Page 37 |
Page 38 |
Page 39 |
Page 40 |
Page 41 |
Page 42 |
Page 43 |
Page 44