Polling on GPIO (interrupt) use 10% CPU

Hi Folks,

I have a 1Khz signal (from an external FPGA) connected to the GPIO3.
The problem is the CPU usage of this poll(2) on GPIO3 IRQ signal is ~10% Total CPU
The code is from the example:
source code 3

this is my code:

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <poll.h>

int main(int argc, char *argv[]){
    int fd;
    char value;
    struct pollfd poll_gpio;

    poll_gpio.events = POLLPRI;

    // export GPIO
    fd = open ("/sys/class/gpio/export", O_WRONLY);
    write (fd, "3", 1);
    close (fd);

    // configure as input
    fd = open ("/sys/class/gpio/gpio3/direction", O_WRONLY);
    write (fd, "in", 2);
    close (fd);

    // configure interrupt
    fd = open ("/sys/class/gpio/gpio3/edge", O_WRONLY);
    write (fd, "rising", 6); // configure as rising edge
    close (fd);

    // open value file
    fd = open("/sys/class/gpio/gpio3/value", O_RDONLY);
    poll_gpio.fd = fd;

    poll (&poll_gpio, 1, -1); // discard first IRQ
    read (fd, &value, 1);

    // wait for interrupt
    while (1){
        poll (&poll_gpio, 1, -1);
        if ((poll_gpio.revents & POLLPRI) == POLLPRI){
            lseek(fd, 0, SEEK_SET);
            read (fd, &value, 1);
            usleep  (50);
//            printf("Interrupt GPIO val: %c\n", value);
//            break;
        }
    }

    close(fd); //close value file
    return EXIT_SUCCESS;
}

my uname -a is:

*Linux colibri-imx6 4.9.84-rt62+gb2a7f2f #1 SMP PREEMPT RT Mon Jun 25 15:44:22 CEST 2018 armv7l GNU/Linux*

the program is called “tdxgpio”
and the htop output is:

*1  [||                        1.5%]     Tasks: 40, 32 thr; 1 running
2  [||                        2.3%]     Load average: 0.25 0.10 0.05 
Mem[|||||||||||||||      135/495MB]     Uptime: 00:19:48
Swp[                         0/0MB]  

PID  USER   PRI  NI  VIRT   RES      SHR  S CPU%   MEM%   TIME+  Command          
766   root     20    0   1560   784       736   S  11.2        0.2       0:09.22 ./tdxgpio
773   root     20    0   3596  2364      1872 R   1.1         0.5       0:00.28 htop -d 50
627   root     20    0   70000 20484 16164 S   0.9         4.0       0:10.29 lxpanel --profi            
579   root     20    0  92076 12852    8684 S   0.5         2.5       0:04.42 /usr/bin/X -s0
364   avahi   20    0    3804  2668     2368 S   0.0         0.5       0:00.32 avahi-daemon:ru
628   root     20    0  84196 19316  15452 S    0.0        3.8       0:01.08 pcmanfm --deskto 
[....]

Why the cpu time is so high ?
Some suggestions/ideas ?
TIA

hi @Mane

You are using a Preempt RT Kernel and you are running the application tdxxgpio at high priority. Usually with RT Kernel the delay between two events is deterministic to a certain level but the Cpu usage is higher.

You should find the actual frequency of the CPU which should vary with load, then you will know more about what 10% of cpu load really means.

For reducing the cpu load, you could also increase the sleep time.

Moreoever, what is your application? What are your trying to do with this polling.

Hi Jaski,
I have the same result in a Real time thread running with SCHED_FIFO and priority= -95

The sleeping time of 50usec is for example. The result is the same also with sleeping time of 400usec.
In the thread I make a reading/writing to an FPGA via SPI.

And, setting up another GPIO when poll return, doing some things and setting down before return to the poll, I see with the oscilloscope a delay of 200usec between my reference clock and the other GPIO. But dhis dalay have a jitter of +/- 50 usec.

ret = write (pthrd_data->fd_sig, "1", 1);
TransferDataToFPGA (pthrd_data->fd_spi);
ret = write (pthrd_data->fd_sig, "0", 1);

Hi Jaski, I have the same result in a Real time thread running with SCHED_FIFO and priority= -95
The sleeping time of 50usec is for example. The result is the same also with sleeping time of 400usec. In the thread I make a reading/writing to an FPGA via SPI.
And, setting up another GPIO when poll return, doing some things and setting down before return to the poll, I see with the oscilloscope a delay of 200usec between my reference clock and the other GPIO. But dhis dalay have a jitter of +/- 50 usec

So this means, the CPU needs 10% of his time to do the tasks in while loop. Is there any issue with that? Could you find out the cpu frequncy, when the application tdxgpio is running?

Jaski, after setting the cpus scaling governor to “performance”, I have a better response from the system, reduced delay (~30uSec vs. 200) and less jitter.

The 10% of CPU time (read from htop) remain.
But I need to better understand what cpu time column really means because single core percentuals on top of the HTOP windows sometimes are smaller or higher than 10%.

Could you post the output of htop -n 1 when the tdxgpio is running? This will help us to better understand the cpu usage.

Jaski, -n isn’t a valid option for htop:

mane@akira:~/Toradex$ htop -n 1
htop: invalid option -- 'n'

Do you mean top instead?

root@colibri-imx6:~# top -n 1                                                                                                           

top - 08:08:37 up  1:19,  1 user,  load average: 0.08, 0.04, 0.05
Tasks: 165 total,   1 running, 164 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.4 us,  3.9 sy,  0.0 ni, 95.7 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :   508648 total,   246172 free,   143468 used,   119008 buff/cache
KiB Swap:        0 total,        0 free,        0 used.   355916 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                                                            
 1136 root      20   0    4820   2440   1948 R  20.0  0.5   0:00.10 top                                                                
  794 root     -51   0       0      0      0 S   5.0  0.0   1:35.92 irq/81-gpiolib                                                     
  976 root      20   0       0      0      0 S   5.0  0.0   0:06.72 kworker/1:3                                                        
 1130 root      20   0    1560    784    736 S   7.0  0.2   0:00.46 tdxgpio                                                            
    1 root      20   0   23224   4748   3804 S   0.0  0.9   0:03.69 systemd                                                            
    2 root      20   0       0      0      0 S   0.0  0.0   0:00.03 kthreadd                                                           
    3 root      20   0       0      0      0 S   0.0  0.0   0:01.27 ksoftirqd/0                                                        
    4 root      -2   0       0      0      0 S   0.0  0.0   0:01.43 ktimersoftd/0                                                      
    6 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 kworker/0:0H                                                       
    7 root      20   0       0      0      0 S   0.0  0.0   0:00.02 kworker/u4:0                                                       
    8 root      20   0       0      0      0 S   0.0  0.0   0:00.90 rcu_preempt                                                        
    9 root      20   0       0      0      0 S   0.0  0.0   0:00.00 rcu_sched                                                          
   10 root      20   0       0      0      0 S   0.0  0.0   0:00.70 rcuc/0                                                             
   11 root      20   0       0      0      0 S   0.0  0.0   0:00.00 kswork                                                             
   12 root      rt   0       0      0      0 S   0.0  0.0   0:00.00 posixcputmr/0                                                      
   13 root      rt   0       0      0      0 S   0.0  0.0   0:00.00 migration/0                                                        
   14 root      rt   0       0      0      0 S   0.0  0.0   0:00.01 watchdog/0                                                          
root@colibri-imx6:~# 

The %CPU for tdxgpio is 7% , too much (IMHO)

You are right, I meant top. Sorry for that.

7% is not that much. You are switching the GPIO every 1ms. So if we take 10% for the sake of simplicity, this means during 100us, the CPU is doing the task of while loop. This whole task time depends also from the GPIO Bus, which is not working at the same frequency as the CPU.
Anyway, 7% is not much. CPU usage about 70% or more would be much.

Ok, thank you!

You are welcome.