2023-01-30 - 21:41

Scripts to set the SMP affinity mask of kernel threads

IRQ threads - Non-IRQ kernel threads

#!/bin/bash
 
defaultmask=7
defaultisolirq=27
defaultisolmask=8
 
cpucores=`grep ^processor /proc/cpuinfo | wc -l`
if test $cpucores -gt 16
then
  coremask=4294967295
elif test $cpucores -gt 8
then
  coremask=65535
elif test $cpucores -gt 4
then
  coremask=255
else  
  coremask=15  
fi
 
eval `cat /proc/cmdline | tr ' ' '\n' | grep isolcpus`
if test "$isolcpus"
then
  OLDIFS="$IFS"
  IFS=,
  isolmask=0
  for i in $isolcpus
  do
    thismask=$((2 ** $i))
    isolmask=$(($isolmask + $thismask))
  done
  IFS="$OLDIFS"
fi
if test "$isolmask"
then
  decidefaultmask=$(($coremask ^ $isolmask))
  defaultmask=`printf %x $decidefaultmask`
  decidefaultisolmask=$isolmask
  defaultisolmask=`printf %x $decidefaultisolmask`
fi
 
if test "$1" -a "$1" = --help
then
  echo "Usage: `basename $0` <mask> <isolirq> <isolmask>"
  echo "Function: Set SMP affinity mask of all IRQ threads to <mask>, except IRQs <isolirq> to <isolmask>"
  echo "          <mask> defaults to $defaultmask"
  echo "          <isolirq> defaults to $defaultisolirq"
  echo "          <isolmask> defaults to $defaultisolmask"
  echo "Options: none"
  exit 1
fi
 
strcmp() {
  if test -z "$1" -o -z "$2"
  then
    echo false
  else
    str1="$1"
    str2="$2"
    strlen1=`echo -n "$str1" | wc -c`
    strlen2=`echo -n "$str2" | wc -c`
    if test $strlen1 -gt $strlen2
    then
      str1="`echo $str1 | cut -c1-$strlen2`"
    elif test $strlen2 -gt $strlen1
    then
      str2="`echo $str2 | cut -c1-$strlen1`"
    fi
    test "$str1" = "$str2"
  fi
}
 
pidof()
{
  irqname="$1"
  if test -z "$irqname"
  then
    echo
    return
  fi
 
  cd /proc
  for pid in [0-9]*
  do
    taskname="`cat $pid/comm 2>/dev/null`"
    if test "$taskname"
    then
      if strcmp "$taskname" "$irqname"
      then
        echo $pid
        break
      fi
    fi
  done
  cd - >/dev/null
}
 
if test "$1"
then
  if echo $1 | grep -iq [^0-9a-f] 
  then
    echo "First argument for default mask is expected to be a lower-case hexadecimal number, not $1"
    exit 1
  fi
  mask=$1
else
  mask=$defaultmask
fi
 
if test "$2"
then
  if echo $2 | grep -q '[^0-9 ]'
  then
    echo "Second argument for isolated IRQs is expected to be a list of decimal numbers, not $2"
    exit 1
  fi
  isolirq="$2"
else
  isolirq="$defaultisolirq"
fi
 
if test "$3"
then
  if echo $1 | grep -iq [^0-9a-f] 
  then
    echo "Third argument for mask of isolated IRQs is expected to be a lower-case hexadecimal number, not $1"
    exit 1
  fi
  isolmask=$3
else
  isolmask=$defaultisolmask
fi
 
redcolor='\033[0;31m'
yellowcolor='\033[0;33m'
greencolor='\033[0;32m'
nocolor='\033[0m'
 
red() {
  printf $redcolor$@$nocolor
}
 
yellow() {
  printf $yellowcolor$@$nocolor
}
 
green() {
  printf $greencolor$@$nocolor
}
 
NOT() {
  echo `red NOT`
}
 
is() {
  echo `green is`
}
 
can() {
  echo `yellow can`
}
 
could() {
  echo `yellow could`
}
 
cd /proc/irq
 
 
for irq in `ls -1d [0-9]* | sort -n`
do
  irqshare=1
  while true
  do
    namedir="`find $irq/* -type d -print0 | xargs -0 printf %s@ | cut -d@ -f$irqshare`"
    if test "$namedir"
    then
      irqname=`basename "$namedir"`
      taskname=`echo irq/$irq-$irqname`
      pid=`pidof $taskname`
      if test -z "$pid"
      then
        taskname=`echo $irq-$irqname`
        pid=`pidof $taskname`
      fi  
      if test "$pid"
      then
        realcore10=`ps -o psr $pid | sed 's/^ *//' | grep ^[0-9]`
        realcoremask10=$((2 ** $realcore10))
        affinity=`grep Cpus_allowed: ../$pid/status | cut -f2 | sed s/^0*//`
        flags=`cat ../$pid/stat | sed 's/(.*)/comm/' | cut -d" " -f 9`
      else
        irqname=
      fi
    else
      if test $irqshare -gt 1
      then
        break
      fi
      irqname=
    fi
    if echo $isolirq | tr " " "\n" | grep -q ^$irq$
    then
      thismask=$isolmask
    else
      thismask=$mask
    fi
    if test "$irqname"
    then
      if test $(($flags & 0x04000000)) != 0
      then
        echo -n Affinity mask of interrupt $irq $irqname can `NOT` be modified, since it has the PF_NO_SETAFFINITY flag set
        if test $((0x$affinity - 0x$thismask)) = 0
        then
          if test $(($realcoremask10 & 0x$thismask)) != 0
          then
            echo ", but the affinity mask 0x$affinity of thread $irqname (PID $pid) fortunately `is` correct, and the thread is currently running on core $realcore10 which `is` ok"
          else
            echo ", but the affinity mask 0x$affinity of thread $irqname (PID $pid) fortunately `is` correct; however, the thread is currently running on core $realcore10 which is `NOT` ok"
          fi
        else
          if test $(($realcoremask10 & 0x$thismask)) != 0
          then
            echo ", but although the affinity mask of thread $irqname (PID $pid) is 0x$affinity which is `NOT` ok, the thread is currently running on core $realcore10 which `is` ok"
          else
            echo ", and because the affinity mask of thread $irqname (PID $pid) unfortunately is 0x$affinity which is `NOT` ok, the thread is running on core $realcore10 which is `NOT` ok"
          fi
        fi
      fi
    fi
    current_smp_affinity="`cat $irq/smp_affinity`"
    if test $((0x$current_smp_affinity - 0x$thismask)) != 0
    then
      if ! echo $thismask >$irq/smp_affinity 2>/dev/null
      then
        echo -n Default SMP affinity mask of interrupt $irq $irqname is 0x$current_smp_affinity and could `NOT` be set to 0x$thismask
        andorbut=but
      else
        echo -n Default SMP affinity mask of interrupt $irq $irqname was 0x$current_smp_affinity and `is` now corrected to 0x$thismask
        andorbut=and
      fi
    else
      echo -n Default SMP affinity mask of interrupt $irq $irqname `is` 0x$thismask and already correct
      andorbut=and
    fi
    if test "$irqname"
    then
      if test $((0x$affinity - 0x$thismask)) = 0
      then
        if test $(($realcoremask10 & 0x$thismask)) != 0
        then
          echo ", $andorbut the affinity mask 0x$affinity of thread $irqname (PID $pid) fortunately `is` correct, and the thread is currently running on core $realcore10 which `is` ok"
        else
          echo ", $andorbut the affinity mask 0x$affinity of thread $irqname (PID $pid) fortunately `is` correct; however, the thread is currently running on core $realcore10 which is `NOT` ok"
        fi
      else
        if taskset -p $thismask $pid >/dev/null 2>&1
        then
          echo -n ", $andorbut the affinity mask of thread $irqname (PID $pid) is 0x$affinity which is `NOT` ok, but successfully attempted to be modified to 0x$thismask"
          realcore10=`ps -o psr $pid | sed 's/^ *//' | grep ^[0-9]`
          realcoremask10=$((2 ** $realcore10))
          affinity=`grep Cpus_allowed: ../$pid/status | cut -f2 | sed s/^0*//`
          if test $((0x$affinity - 0x$thismask)) = 0
          then
            if test $(($realcoremask10 & 0x$thismask)) != 0
            then
              echo " and `is` now 0x$thismask, and the thread is currently running on core $realcore10 which `is` ok"
            else
              echo " and `is` now 0x$thismask, but the thread is currently running on core $realcore10 which is `NOT` ok"
            fi
          else
            echo -n , but still is 0x$affinity which `is`
            if test $((0x$affinity & 0x$thismask)) != 0
            then
              if test $(($realcoremask10 & 0x$thismask)) != 0
              then
                echo " potentially ok, and the thread is currently running on core $realcore10 which also `is` ok"
              else 
                echo " potentially ok, but the thread is currently running on core $realcore10 which is `NOT` ok"
              fi
            else
              if test $(($realcoremask10 & 0x$thismask)) != 0
              then
                echo " `NOT` ok, but the thread is currently running on core $realcore10 which `is` ok"
              else
                echo " `NOT` ok, and the thread is in fact currently running on core $realcore10 which is `NOT` ok"
              fi
            fi 
          fi
        else
          echo ", but the affinity mask of thread $irqname (PID $pid) is 0x$affinity which is `NOT` ok and could `NOT` be corrected"
        fi
      fi
    else
      echo
    fi
  irqshare=`expr $irqshare + 1`
  done
done
 

Output of the above script when running it on the 4-core system at rack #5, slot #4 at shadow position

Default SMP affinity mask of interrupt 0 is 0x01 and could NOT be set to 0x7
Default SMP affinity mask of interrupt 1 is 0x7 and already correct
Default SMP affinity mask of interrupt 2 is 0x01 and could NOT be set to 0x7
Default SMP affinity mask of interrupt 3 is 0x7 and already correct
Default SMP affinity mask of interrupt 4 is 0x7 and already correct
Default SMP affinity mask of interrupt 5 is 0x7 and already correct
Default SMP affinity mask of interrupt 6 is 0x7 and already correct
Default SMP affinity mask of interrupt 7 is 0x7 and already correct
Default SMP affinity mask of interrupt 8 rtc0 is 0x7 and already correct, and the affinity mask 0x7 of thread rtc0 (PID 139) fortunately is correct, and the thread is currently running on core 0 which is ok
Default SMP affinity mask of interrupt 9 acpi is 0x7 and already correct, and the affinity mask 0x7 of thread acpi (PID 107) fortunately is correct, and the thread is currently running on core 0 which is ok
Default SMP affinity mask of interrupt 10 is 0x7 and already correct
Default SMP affinity mask of interrupt 11 is 0x7 and already correct
Default SMP affinity mask of interrupt 12 is 0x7 and already correct
Default SMP affinity mask of interrupt 13 is 0x7 and already correct
Default SMP affinity mask of interrupt 14 is 0x7 and already correct
Default SMP affinity mask of interrupt 15 is 0x7 and already correct
Default SMP affinity mask of interrupt 16 ehci_hcd:usb1 is 0x7 and already correct, and the affinity mask 0x7 of thread ehci_hcd:usb1 (PID 137) fortunately is correct, and the thread is currently running on core 0 which is ok
Default SMP affinity mask of interrupt 19 i801_smbus is 0x7 and already correct, and the affinity mask 0x7 of thread i801_smbus (PID 255) fortunately is correct, and the thread is currently running on core 0 which is ok
Default SMP affinity mask of interrupt 23 ehci_hcd:usb2 is 0x7 and already correct, and the affinity mask 0x7 of thread ehci_hcd:usb2 (PID 138) fortunately is correct, and the thread is currently running on core 0 which is ok
Default SMP affinity mask of interrupt 26 ahci[0000:00:1f.2] is 0x7 and already correct, and the affinity mask 0x7 of thread ahci[0000:00:1f.2] (PID 119) fortunately is correct, and the thread is currently running on core 1 which is ok
Default SMP affinity mask of interrupt 27 enp0s25 is 0x8 and already correct, and the affinity mask 0x8 of thread enp0s25 (PID 609) fortunately is correct, and the thread is currently running on core 3 which is ok
Default SMP affinity mask of interrupt 28 i915 is 0x7 and already correct, and the affinity mask 0x7 of thread i915 (PID 263) fortunately is correct, and the thread is currently running on core 0 which is ok
Default SMP affinity mask of interrupt 29 enp2s0-rx-0 is 0x7 and already correct, and the affinity mask 0x7 of thread enp2s0-rx-0 (PID 544) fortunately is correct, and the thread is currently running on core 1 which is ok
Default SMP affinity mask of interrupt 30 enp2s0-tx-0 is 0x7 and already correct, and the affinity mask 0x7 of thread enp2s0-tx-0 (PID 545) fortunately is correct, and the thread is currently running on core 0 which is ok
Default SMP affinity mask of interrupt 31 enp2s0 is 0x7 and already correct, and the affinity mask 0x7 of thread enp2s0 (PID 546) fortunately is correct, and the thread is currently running on core 0 which is ok