From 7617705101c9d799fc7b080e515a1161d1d05578 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Wed, 20 Aug 2014 18:50:30 +0200 Subject: functions: make use of taskset when available to set the CPU mask taskset is one of the ugliest tools ever invented. We had to go through a number of hacks to work around its limitations, including forcing the mask to hexadecimal representation using printf. We also had to first build a mask of currently online CPUs to filter the mask based on this so that taskset never fails with a sched_setaffinity() error. When the utility is found, _CPUMASK is defined to point to a local wrapper which does the conversion from cpumask to taskset format. When it's not available, cpumask is still used. --- sbin/init.d/functions | 80 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 75 insertions(+), 5 deletions(-) diff --git a/sbin/init.d/functions b/sbin/init.d/functions index 0be4e76..9a7619f 100755 --- a/sbin/init.d/functions +++ b/sbin/init.d/functions @@ -85,11 +85,13 @@ unset ${!svc_num_*} ${!res_kwd_*} # this is set to $? for the first do_xxx which doesn't return 0 STATUS_RET=0 -# cpumask executable for CPU affinity -_CPUMASK=/sbin/cpumask - -# Test cpumask is executable else unset -[ -x "$_CPUMASK" ] || unset _CPUMASK +if [ -x /usr/bin/taskset ]; then + _CPUMASK=cpumask_wrapper +elif [ -x /sbin/cpumask ]; then + _CPUMASK=/sbin/cpumask +else + unset _CPUMASK +fi # abort the process after displaying an error message. die() { @@ -396,6 +398,74 @@ best_effort_rmmod() { /sbin/modprobe -r "${modules[@]}" } +# returns a mask of online cpus, or 1 if the mask could not be determined +cpu_online_mask() { + local mask + local online + local range + local min + local max + + if [ ! -r /sys/devices/system/cpu/online ]; then + echo 1 + return 0 + fi + + mask=0 + online=$( ] { -p | [...] } +cpumask_wrapper() { + local online + local mask + local pid + + # parse -m, -p, --, and silently ignore other args + while [ -n "$1" ]; do + if [ -n "${1##-*}" ]; then + break; + elif [ "$1" = "--" ]; then shift; break; + elif [ "$1" = "-m" ]; then mask="$2"; shift; + elif [ "$1" = "-p" ]; then pid="$2"; shift; + fi + shift + done + + [ -n "$mask" ] || mask=0xffffffff + online=$(cpu_online_mask) + mask=$((mask & online)) + if [ $mask -eq 0 ]; then + # keep only the first online CPU if none is available + mask=$((online & ~(online - 1))) + fi + + # taskset only supports hexadecimal masks! + mask=$(printf "0x%x" $((mask))) + + if [ -n "$pid" ]; then + taskset -p "$mask" "$pid" + else + taskset "$mask" "$@" + fi +} + ######################################## # CONFIGURATION FILE LOADING FUNCTIONS # ######################################## -- 1.7.12.1