I am trying to optimise getting GPIO interrupts into userspace. On the single core rpi 1 I couldn't get rid of quite some timing jitter, which makes sense as there's a lot of stuff going on on the cpu.

Now with the dual core rpi2, I wanted to try this again.

The idea would be:

  • have 2 cores handle the OS including as many interrupt sources as possible.
  • have 1 core handling the BCM2708 GPIO catchall handler and my kernel modules IRQ
  • have 1 core running the userspace program

isolcpus worked nicely to get 2 cpus not being scheduled by regular tasks, but I am struggling with the irqs.

root@ucnraspberrypi2-1:~# echo 3 > /proc/irq/52/smp_affinity
bash: echo: write error: Input/output error

I get the same for any irq when I want to change cpu affinity.

Is that not implemented in the IRQ driver? If not, is there a hardware reason?

Any ideas? Thanks ...


Here's my /proc/interrupts:

root@ucnraspberrypi2-1:~# cat /proc/interrupts
           CPU0       CPU1       CPU2       CPU3       
 16:          0          0          0          0   ARMCTRL  bcm2708_fb dma
 24:        466          0          0          0   ARMCTRL  DMA IRQ
 25:       2370          0          0          0   ARMCTRL  DMA IRQ
 32:   17257562          0          0          0   ARMCTRL  dwc_otg, dwc_otg_pcd, dwc_otg_hcd:usb1
 52:          1          0          0          0   ARMCTRL  BCM2708 GPIO catchall handler
 65:         63          0          0          0   ARMCTRL  ARM Mailbox IRQ
 66:          2          0          0          0   ARMCTRL  VCHIQ doorbell
 75:          1          0          0          0   ARMCTRL
 79:          4          0          0          0   ARMCTRL  bcm2708_i2c.1
 80:          0          0          0          0   ARMCTRL  bcm2708_spi.0
 83:         33          0          0          0   ARMCTRL  uart-pl011
 84:      70207          0          0          0   ARMCTRL  mmc0
 99:     340237     325956     304090     304089   ARMCTRL  arch_timer
273:          1          0          0          0      GPIO  Some gpio pin description
FIQ:              usb_fiq
IPI0:          0          0          0          0  CPU wakeup interrupts
IPI1:          0          0          0          0  Timer broadcast interrupts
IPI2:     238100      75472     303997     303996  Rescheduling interrupts
IPI3:          2          2          4          4  Function call interrupts
IPI4:        126         10          0          0  Single function call interrupts
IPI5:          0          0          0          0  CPU stop interrupts
IPI6:          0          0          0          0  IRQ work interrupts
IPI7:          0          0          0          0  completion interrupts
Err:          0
  • Did smp_affinity work with the pi1? If so, then it's a driver problem. The kernel has been upgraded to 3.18 recently, and now uses a mechanism known as Device Tree, which means there is quite a bunch of work to convert various drivers. – M Noit Feb 19 '15 at 9:22
  • 1
    /proc/irq/<PID>/smp_affinity etc don't exist on the pi1, at least in some rather old raspbian version I have access to. But as it's a single core machine, that might be natural. – BeerSerc Feb 19 '15 at 13:45
  • Does this happens for all IRQs or only for the 52? – Dmitry Grigoryev Jan 22 at 13:33

Below is a script I wrote to configure CPU Affinity that can be adapted (to some more or less degree) to achieve your objective- ring-fencing a core for dedicated processing. What the below code does is restricts the OS to working on Cores 0-2 leaving Core 3 of our 4-core processor to exclusively perform video encoding which is indeed a CPU intensive operation. Since the application "Motion" I'm using is single threaded, it could only ever use a single core at any one time.

"taskset" is used to pin motion to the specified core. So since the OS can only work on cores 0-2, no timeslicing happens on core 3 where the video encoding occurs.

I've tested the following provided code and proven it does separate the CPU processing in the described way.

Cut-n-paste the code below into a file. Change the target of "taskset" from "motion" to your application. Then chmod 700 the file and execute it once you've made whatever other tweaks you care to make:


# Backup /etc/systemd/system.conf before we tweak it:
cp -p /etc/systemd/system.conf /etc/systemd/system.conf.ORIGINAL

# Limit OS to using only first 3 cores:
sed -i "s/#CPUAffinity=1 2/CPUAffinity=0 1 2/" /etc/systemd/system.conf

echo "Automate setting CPU Affinity for Motion on boot"

cat <<'EOF'> /home/pi/scripts/set-cpu-affinity.sh

# Note: the number following cp is the CPU/core number in this case three
taskset -cp 3 $(pgrep motion|cut -d ' ' -f2)


chmod 700 /home/pi/scripts/set-cpu-affinity.sh
chown pi:pi /home/pi/scripts/set-cpu-affinity.sh

# Note use of * Wants * directive to create a dependent relationship on Motion already being started:
cat <<EOF> /etc/systemd/system/set-cpu-affinity.service
Description=Set CPU Affinity for the Motion process after it starts on boot




systemctl enable set-cpu-affinity.service

# Change ownership of all files created by this script FROM user "root" TO user "pi":
chown -R pi:pi /home/pi
  • At least after second boot up /etc/systemd/system.conf.ORIGINAL is overwritten by a modified one so the backup line in the bash script doesn't make sense. I don't believe the motion.service is a static one (without [Install] section) so Wants=motion.service can be omitted. Instead you mean to start After=motion.service? User=root and Group=root can also be omitted because that's default. Is it right that you do not want to RemainAfterExit=yes after oneshot? – Ingo Jan 22 at 19:36
  • Script I gave only meant to be run once, so the "cp" backup will not be overwritten. The script creates a script file named "set-cpu-affinity.sh" and in order for the "pgrep" to succeed, the service "motion" must be up or the "motion" process won't be found and "taskset" will crap-out. So the "WANTS=" dependency will fire-up "motion" if not already started. So no, the "WANTS=" isn't optional- it's there to ensure the "taskset" doesn't happen before "motion" process is up. Since many things will be user "pi" I specify "root" to avoid confusion – F1Linux Jan 22 at 20:02
  • Better prepend backup line with [ -e /etc/systemd/system.conf.ORIGINAL ] || cp -p ... systemd is working asynchronous so Wants= doesn't ensure a unit is started before the "calling" unit. Execution order is undefined. It only ensures that it is started sometime. You must use After= to be sure. Look at man systemd.unit. You will find "Note that requirement dependencies do not influence the order in which services are started or stopped. This has to be configured independently with the After= or Before= options.". Please address me with @Ingo otherwise I won't see your reply. – Ingo Jan 22 at 20:36
  • "cp -p" just for comparative purposes: to see what file looked like before file changed. As for the "WANTS= dependency: "A weaker version of Requires=. Units listed in this option will be started if the configuring unit is. However, if the listed units fail to start or cannot be added to the transaction, this has no impact on the validity of the transaction as a whole. This is the recommended way to hook start-up of one unit to the start-up of another unit." (freedesktop.org/software/systemd/man/systemd.unit.html). Allows app to start if dep- which is performance-only- fails. – F1Linux Jan 22 at 20:50
  • @Ingo - ran out of characters on my above comment to ping you of the update bud- T – F1Linux Jan 22 at 20:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.