Skip to content

Instantly share code, notes, and snippets.

@sequix
Last active September 6, 2023 03:06
Show Gist options
  • Select an option

  • Save sequix/c5da2e76bcebd654003437a323cb114f to your computer and use it in GitHub Desktop.

Select an option

Save sequix/c5da2e76bcebd654003437a323cb114f to your computer and use it in GitHub Desktop.

Revisions

  1. sequix revised this gist Sep 6, 2023. 1 changed file with 41 additions and 15 deletions.
    56 changes: 41 additions & 15 deletions cpuset.sh
    Original file line number Diff line number Diff line change
    @@ -2,7 +2,7 @@
    set -euo pipefail

    help() {
    printf "cpuset.sh version: 3\n"
    printf "cpuset.sh version: 3.1\n"
    printf "usage:\n"
    printf "cpuset.sh union 0-1 2 3-4,5 => 0-5\n"
    printf "cpuset.sh intersect 0-9 4-6 4-5 => 4-5\n"
    @@ -20,6 +20,8 @@ expand() {
    local acc=""
    local lacc=""
    local src="$1"
    local rst
    declare -a rst
    for (( i=0; i<${#src}; i++ )); do
    c="${src:$i:1}"
    case "$c" in
    @@ -36,9 +38,9 @@ expand() {
    ;;
    ,)
    if [ -n "$lacc" ]; then
    seq "$lacc" "$acc"
    rst+=($(seq "$lacc" "$acc"))
    elif [ -n "$acc" ]; then
    echo "$acc"
    rst+=("$acc")
    fi
    acc=""
    lacc=""
    @@ -51,10 +53,11 @@ expand() {
    lc="$c"
    done
    if [ -n "$lacc" ]; then
    seq "$lacc" "$acc"
    rst+=($(seq "$lacc" "$acc"))
    elif [ -n "$acc" ]; then
    echo "$acc"
    rst+=("$acc")
    fi
    <<<"${rst[@]}" tr ' ' '\n' | sort -nu
    }

    expand_to_file() {
    @@ -65,7 +68,7 @@ expand_to_file() {
    echo "$filename"
    }

    shrink() {
    shrink_internal() {
    local cpus=("$@")
    local n=${#cpus[@]}

    @@ -110,7 +113,7 @@ union() {
    for cpus; do
    files+=($(expand_to_file "$cpus"))
    done
    shrink $(sort -n "${files[@]}" | uniq)
    shrink_internal $(sort -nu "${files[@]}")
    rm -f "${files[@]}"
    }

    @@ -120,7 +123,7 @@ intersect() {
    for cpus; do
    files+=($(expand_to_file "$cpus"))
    done
    shrink $(sort -n "${files[@]}" | uniq -c | awk "\$1==${#files[@]} {print \$2}")
    shrink_internal $(sort -n "${files[@]}" | uniq -c | awk "\$1==${#files[@]} {print \$2}")
    rm -f "${files[@]}"
    }

    @@ -131,17 +134,40 @@ minus() {
    local bf=""
    af=$(expand_to_file "$a")
    bf=$(expand_to_file "$b")
    shrink $(sort -n "$af" "$bf" "$bf" | uniq -u)
    shrink_internal $(sort -n "$af" "$bf" "$bf" | uniq -u)
    rm -f "$af" "$bf"
    }

    tomask() {
    local rst=0
    declare -i rst
    for cpu in $(expand "$1"); do
    rst=$((rst | 1<<cpu))
    local cpus
    cpus=($(expand "$1"))
    local n=${#cpus[@]}

    if [ $n -eq 0 ]; then
    echo 0
    return
    fi

    local c=0
    local ni=0
    local nc="${cpus[0]}"
    local max="${cpus[$((n-1))]}"
    local rst=""
    local rst_c=0

    for ((c=0; c<=max; c+=4)); do
    rst_c=0
    while [ "$((c+3))" -ge "$nc" ]; do
    rst_c=$(( rst_c | (1<<(nc-c)) ))
    ni=$((ni+1))
    if [ "$ni" -ge "$n" ]; then
    break
    fi
    nc=${cpus[$ni]}
    done
    rst="$(printf "%x" ${rst_c})${rst}"
    done
    printf "%x\n" $rst
    echo "$rst"
    }

    todigit() {
    @@ -227,7 +253,7 @@ todigit() {
    esac
    base=$((base+4))
    done
    shrink "${rst[@]}"
    shrink_internal "${rst[@]}"
    }

    main() {
  2. sequix created this gist Sep 5, 2023.
    298 changes: 298 additions & 0 deletions cpuset.sh
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,298 @@
    #!/bin/bash
    set -euo pipefail

    help() {
    printf "cpuset.sh version: 3\n"
    printf "usage:\n"
    printf "cpuset.sh union 0-1 2 3-4,5 => 0-5\n"
    printf "cpuset.sh intersect 0-9 4-6 4-5 => 4-5\n"
    printf "cpuset.sh minus 0-9 4-5 => 0-3,6-9\n"
    printf "cpuset.sh shrink 0,1,2,3 => 0-3\n"
    printf 'cpuset.sh expand 0-3 => 0\\n1\\n2\\n3\\n\n'
    printf "cpuset.sh tomask 0-15 => ffff\n"
    printf "cpuset.sh todigit ffff => 0-15\n"
    }

    expand() {
    local i=0
    local c=""
    local lc=""
    local acc=""
    local lacc=""
    local src="$1"
    for (( i=0; i<${#src}; i++ )); do
    c="${src:$i:1}"
    case "$c" in
    [0-9])
    acc=$((acc*10+$c))
    ;;
    -)
    if ! <<<"$lc" grep -q "[0-9]"; then
    echo "invalid hyphen in set $src"
    exit 1
    fi
    lacc="$acc"
    acc=""
    ;;
    ,)
    if [ -n "$lacc" ]; then
    seq "$lacc" "$acc"
    elif [ -n "$acc" ]; then
    echo "$acc"
    fi
    acc=""
    lacc=""
    ;;
    *)
    echo "invalid character '$c' in set $src"
    exit 1
    ;;
    esac
    lc="$c"
    done
    if [ -n "$lacc" ]; then
    seq "$lacc" "$acc"
    elif [ -n "$acc" ]; then
    echo "$acc"
    fi
    }

    expand_to_file() {
    local src="$1"
    local filename=""
    filename=$(mktemp)
    expand "$src" >"$filename"
    echo "$filename"
    }

    shrink() {
    local cpus=("$@")
    local n=${#cpus[@]}

    if [ $n -eq 0 ]; then
    return
    elif [ $n -eq 1 ]; then
    echo "${cpus[0]}"
    return
    fi

    local i=0
    local j=1
    local ci="${cpus[0]}"
    local cj=""
    local cj1=""
    local rst=""

    for ((j=1; j < $n; j++)); do
    cj="${cpus[$j]}"
    cj1="${cpus[$((j-1))]}"
    if [ "$cj" -ne "$((cj1+1))" ]; then
    if [ "$j" -eq "$((i+1))" ]; then
    rst="${rst}${ci},"
    else
    rst="${rst}${ci}-${cj1},"
    fi
    i="$j"
    ci="${cj}"
    fi
    done
    if [ "$j" -eq "$((i+1))" ]; then
    rst="${rst}${ci}"
    else
    rst="${rst}${ci}-${cpus[$((j-1))]}"
    fi
    echo $rst
    }

    union() {
    local files
    declare -a files
    for cpus; do
    files+=($(expand_to_file "$cpus"))
    done
    shrink $(sort -n "${files[@]}" | uniq)
    rm -f "${files[@]}"
    }

    intersect() {
    local files
    declare -a files
    for cpus; do
    files+=($(expand_to_file "$cpus"))
    done
    shrink $(sort -n "${files[@]}" | uniq -c | awk "\$1==${#files[@]} {print \$2}")
    rm -f "${files[@]}"
    }

    minus() {
    local a="$1"
    local b="$2"
    local af=""
    local bf=""
    af=$(expand_to_file "$a")
    bf=$(expand_to_file "$b")
    shrink $(sort -n "$af" "$bf" "$bf" | uniq -u)
    rm -f "$af" "$bf"
    }

    tomask() {
    local rst=0
    declare -i rst
    for cpu in $(expand "$1"); do
    rst=$((rst | 1<<cpu))
    done
    printf "%x\n" $rst
    }

    todigit() {
    local c=""
    local src="$1"
    local i=${#src}
    local base=0
    local rst
    declare -a rst

    for ((i=i-1; i>=0; i--)); do
    c=${src:$i:1}
    case "$c" in
    0)
    true
    ;;
    1)
    rst+=($((base+0)))
    ;;
    2)
    rst+=($((base+1)))
    ;;
    3)
    rst+=($((base+0)))
    rst+=($((base+1)))
    ;;
    4)
    rst+=($((base+2)))
    ;;
    5)
    rst+=($((base+0)))
    rst+=($((base+2)))
    ;;
    6)
    rst+=($((base+1)))
    rst+=($((base+2)))
    ;;
    7)
    rst+=($((base+0)))
    rst+=($((base+1)))
    rst+=($((base+2)))
    ;;
    8)
    rst+=($((base+3)))
    ;;
    9)
    rst+=($((base+0)))
    rst+=($((base+3)))
    ;;
    a|A)
    rst+=($((base+1)))
    rst+=($((base+3)))
    ;;
    b|B)
    rst+=($((base+0)))
    rst+=($((base+1)))
    rst+=($((base+3)))
    ;;
    c|C)
    rst+=($((base+2)))
    rst+=($((base+3)))
    ;;
    d|D)
    rst+=($((base+0)))
    rst+=($((base+2)))
    rst+=($((base+3)))
    ;;
    e|E)
    rst+=($((base+1)))
    rst+=($((base+2)))
    rst+=($((base+3)))
    ;;
    f|F)
    rst+=($((base+0)))
    rst+=($((base+1)))
    rst+=($((base+2)))
    rst+=($((base+3)))
    ;;
    *)
    echo "invalid mask '$src'"
    exit 1
    ;;
    esac
    base=$((base+4))
    done
    shrink "${rst[@]}"
    }

    main() {
    if [ $# -eq 0 ]; then
    help
    exit 0
    fi
    case "$1" in
    union)
    shift 1
    if [ $# -eq 0 ]; then
    echo "at least 1 argument for union action"
    exit 1
    fi
    union "$@"
    ;;
    intersect)
    shift 1
    if [ $# -eq 0 ]; then
    echo "at least 1 argument for intersect action"
    exit 1
    fi
    intersect "$@"
    ;;
    minus)
    if [ $# -ne 3 ]; then
    echo "expected exact 2 arguments for minus action"
    exit 1
    fi
    minus "$2" "$3"
    ;;
    shrink)
    if [ $# -ne 2 ]; then
    echo "expected exact 1 argument for shrink action"
    exit 1
    fi
    union "$2"
    ;;
    expand)
    if [ $# -ne 2 ]; then
    echo "expected exact 1 argument for expand action"
    exit 1
    fi
    expand "$2"
    ;;
    tomask)
    if [ $# -ne 2 ]; then
    echo "expected exact 1 argument for tomask action"
    exit 1
    fi
    tomask "$2"
    ;;
    todigit)
    if [ $# -ne 2 ]; then
    echo "expected exact 1 argument for todigit action"
    exit 1
    fi
    todigit "$2"
    ;;
    *)
    echo "invalid action '$1'"
    help
    exit 1
    ;;
    esac
    }

    main "$@"