1766dfaacSMichal Berger#!/usr/bin/env bash 2*eb53c232Spaul luse# SPDX-License-Identifier: BSD-3-Clause 3*eb53c232Spaul luse# Copyright (C) 2021 Intel Corporation 4*eb53c232Spaul luse# All rights reserved. 5*eb53c232Spaul luse# 6766dfaacSMichal Bergertestdir=$(readlink -f "$(dirname "$0")") 7766dfaacSMichal Bergerrootdir=$(readlink -f "$testdir/../../") 8766dfaacSMichal Berger 9766dfaacSMichal Bergersource "$rootdir/test/common/autotest_common.sh" 10766dfaacSMichal Bergersource "$testdir/common.sh" 11766dfaacSMichal Berger 12766dfaacSMichal Bergertrap 'killprocess "$spdk_pid"' EXIT 13766dfaacSMichal Berger 14766dfaacSMichal Bergerfold_list_onto_array cpus $(parse_cpu_list <(echo "$spdk_cpus_csv")) 15766dfaacSMichal Berger# Normalize the indexes 16766dfaacSMichal Bergercpus=("${cpus[@]}") 17766dfaacSMichal Berger 18766dfaacSMichal Bergerbusy() { 19766dfaacSMichal Berger local selected_cpus cpu 20766dfaacSMichal Berger local reactor_framework 21766dfaacSMichal Berger local threads thread 2284fa73ebSTomasz Zawadzki local sched_period=1 # default, 1s 23766dfaacSMichal Berger 24766dfaacSMichal Berger # Create two busy threads with two cpus (not including main cpu) and check if either of 25766dfaacSMichal Berger # them is moved to either of the selected cpus. Expected load is ~100% on each thread and 26766dfaacSMichal Berger # each thread should remain on its designated cpu. 27766dfaacSMichal Berger 28766dfaacSMichal Berger fold_list_onto_array selected_cpus "${cpus[@]:1:2}" 29766dfaacSMichal Berger 30d47b0d2dSTomasz Zawadzki thread0=$(create_thread -n "thread0" -m "$(mask_cpus "${selected_cpus[@]}")" -a 100) 31d47b0d2dSTomasz Zawadzki thread1=$(create_thread -n "thread1" -m "$(mask_cpus "${selected_cpus[@]}")" -a 100) 32766dfaacSMichal Berger 3384fa73ebSTomasz Zawadzki sleep $((10 * sched_period)) 3484fa73ebSTomasz Zawadzki 35766dfaacSMichal Berger local samples=0 36766dfaacSMichal Berger 37766dfaacSMichal Berger xtrace_disable 38766dfaacSMichal Berger while ((samples++ < 5)); do 3984fa73ebSTomasz Zawadzki sleep $sched_period 40766dfaacSMichal Berger 41766dfaacSMichal Berger all_set=0 42766dfaacSMichal Berger reactor_framework=$(rpc_cmd framework_get_reactors | jq -r '.reactors[]') 43766dfaacSMichal Berger 44766dfaacSMichal Berger printf '*Sample %u\n' "$samples" 45766dfaacSMichal Berger for cpu in "${selected_cpus[@]}"; do 46766dfaacSMichal Berger threads=($(jq -r "select(.lcore == $cpu) | .lw_threads[].id" <<< "$reactor_framework")) 47766dfaacSMichal Berger 48766dfaacSMichal Berger if ((${#threads[@]} == 0)); then 49766dfaacSMichal Berger printf ' No threads found on cpu%u\n' "$cpu" 50766dfaacSMichal Berger continue 51766dfaacSMichal Berger fi 52766dfaacSMichal Berger 53766dfaacSMichal Berger get_thread_stats 54766dfaacSMichal Berger 55766dfaacSMichal Berger for thread in "${threads[@]}"; do 56766dfaacSMichal Berger if ((thread != thread0 && thread != thread1)); then 57766dfaacSMichal Berger printf ' Unexpected thread %u (%s) on cpu%u\n' \ 58766dfaacSMichal Berger "$thread" "${thread_map[thread]}" "$cpu" 59766dfaacSMichal Berger continue 3 60766dfaacSMichal Berger fi 61766dfaacSMichal Berger load=$((busy[thread] * 100 / (busy[thread] + idle[thread]))) 62766dfaacSMichal Berger if ((load < 95)); then 63766dfaacSMichal Berger printf ' Unexpected load on thread %u (%s): %u%% (< 95%%)\n' \ 64766dfaacSMichal Berger "$thread" "${thread_map[thread]}" "$load" 65766dfaacSMichal Berger continue 3 66766dfaacSMichal Berger fi 67766dfaacSMichal Berger printf ' Thread %u (%s) on cpu%u; load: %u%%\n' \ 68766dfaacSMichal Berger "$thread" "${thread_map[thread]}" "$cpu" "$load" 69766dfaacSMichal Berger eval "${thread_map[thread]}_cpus[$cpu]=$cpu" 70766dfaacSMichal Berger done 71766dfaacSMichal Berger done 72766dfaacSMichal Berger 73766dfaacSMichal Berger all_set=1 74766dfaacSMichal Berger done 75766dfaacSMichal Berger 76766dfaacSMichal Berger destroy_thread "$thread0" 77766dfaacSMichal Berger destroy_thread "$thread1" 78766dfaacSMichal Berger 79766dfaacSMichal Berger # The final expectation is that when target threads are ~100% busy, they will stay on their 80766dfaacSMichal Berger # designated cpus. FIXME: Does it make sense? if given cpu is not getting a break due to a 81766dfaacSMichal Berger # thread not becoming idle even for a tick, scheduler should not put any other threads on 82766dfaacSMichal Berger # that cpu nor move its assigned thread to any other cpu. 83766dfaacSMichal Berger printf 'Thread %u (%s) cpus: %s\n' "$thread0" "${thread_map[thread0]}" "${thread0_cpus[*]:-none}" 84766dfaacSMichal Berger printf 'Thread %u (%s) cpus: %s\n' "$thread1" "${thread_map[thread1]}" "${thread1_cpus[*]:-none}" 85766dfaacSMichal Berger [[ ${thread0_cpus[*]} != "${thread1_cpus[*]}" ]] 86766dfaacSMichal Berger ((${#thread0_cpus[@]} == 1 && ${#thread1_cpus[@]} == 1 && all_set == 1)) 87766dfaacSMichal Berger 88766dfaacSMichal Berger xtrace_restore 89766dfaacSMichal Berger} 90766dfaacSMichal Berger 91766dfaacSMichal Bergerbalanced() { 92766dfaacSMichal Berger 93766dfaacSMichal Berger local thread cpu 94766dfaacSMichal Berger local extra_threads 955c61089cSMichal Berger local sched_period=1 # default, 1s 965c61089cSMichal Berger local active_cpu 97766dfaacSMichal Berger 98766dfaacSMichal Berger # Exclude main cpu 99766dfaacSMichal Berger fold_list_onto_array selected_cpus "${cpus[@]:1}" 100766dfaacSMichal Berger 101d47b0d2dSTomasz Zawadzki thread0=$(create_thread -n "thread0" -m "$(mask_cpus "${selected_cpus[@]}")" -a 0) 102127fc0d0STomasz Zawadzki for cpu in "${selected_cpus[@]::${#selected_cpus[@]}-1}"; do 103766dfaacSMichal Berger extra_threads+=("$(create_thread -n "thread_cpu_$cpu" -m "$(mask_cpus "$cpu")" -a 100)") 104766dfaacSMichal Berger done 105766dfaacSMichal Berger 1065c61089cSMichal Berger # thread0 is idle, wait for scheduler to run (2x scheduling period) and check if it is on main core 1075c61089cSMichal Berger sleep $((2 * sched_period)) 108766dfaacSMichal Berger reactor_framework=$(rpc_cmd framework_get_reactors | jq -r '.reactors[]') 1095c61089cSMichal Berger [[ -n $(jq -r "select(.lcore == $spdk_main_core) | .lw_threads[] | select(.id == $thread0)") ]] <<< "$reactor_framework" 110766dfaacSMichal Berger 1115c61089cSMichal Berger # thread0 is active, wait for scheduler to run (2x) and check if it is not on main core 1125c61089cSMichal Berger active_thread "$thread0" 100 1135c61089cSMichal Berger sleep $((2 * sched_period)) 1145c61089cSMichal Berger reactor_framework=$(rpc_cmd framework_get_reactors | jq -r '.reactors[]') 115766dfaacSMichal Berger 1165c61089cSMichal Berger [[ -z $(jq -r "select(.lcore == $spdk_main_core) | .lw_threads[] | select(.id == $thread0)") ]] <<< "$reactor_framework" 1175c61089cSMichal Berger # Get the cpu thread was scheduled onto 1185c61089cSMichal Berger for cpu in "${selected_cpus[@]}"; do 1195c61089cSMichal Berger [[ -n $(jq -r "select(.lcore == $cpu) | .lw_threads[] | select(.id == $thread0)") ]] <<< "$reactor_framework" && active_cpu=$cpu 1205c61089cSMichal Berger done 1215c61089cSMichal Berger [[ -n ${selected_cpus[active_cpu]} ]] 122766dfaacSMichal Berger 1235c61089cSMichal Berger # thread0 is idle, wait for scheduler to run (2x) and check if it is on main core 1245c61089cSMichal Berger active_thread "$thread0" 0 1255c61089cSMichal Berger sleep $((2 * sched_period)) 1265c61089cSMichal Berger reactor_framework=$(rpc_cmd framework_get_reactors | jq -r '.reactors[]') 1275c61089cSMichal Berger 1285c61089cSMichal Berger [[ -n $(jq -r "select(.lcore == $spdk_main_core) | .lw_threads[] | select(.id == $thread0)") ]] <<< "$reactor_framework" 1295c61089cSMichal Berger 130127fc0d0STomasz Zawadzki # thread0 is active, wait for scheduler to run (2x) and check if it is not on main core 1315c61089cSMichal Berger active_thread "$thread0" 100 1325c61089cSMichal Berger sleep $((2 * sched_period)) 1335c61089cSMichal Berger reactor_framework=$(rpc_cmd framework_get_reactors | jq -r '.reactors[]') 1345c61089cSMichal Berger 135127fc0d0STomasz Zawadzki [[ -z $(jq -r "select(.lcore == $spdk_main_core) | .lw_threads[] | select(.id == $thread0)") ]] <<< "$reactor_framework" 136766dfaacSMichal Berger 137766dfaacSMichal Berger destroy_thread "$thread0" 138766dfaacSMichal Berger for thread in "${extra_threads[@]}"; do 139766dfaacSMichal Berger destroy_thread "$thread" 140766dfaacSMichal Berger done 141766dfaacSMichal Berger} 142766dfaacSMichal Berger 143d841e24bSMichal Bergercore_load() { 144d841e24bSMichal Berger local sched_period=1 # default, 1s 145d841e24bSMichal Berger local thread 146d841e24bSMichal Berger local on_main_core=0 on_next_core=0 147d841e24bSMichal Berger 148d841e24bSMichal Berger # Re-exec the scheduler app to make sure rr balancer won't affect threads without 149d841e24bSMichal Berger # configured cpumask from the previous test suites. 150d841e24bSMichal Berger 151c9c7c281SJosh Soref exec_under_dynamic_scheduler "$scheduler" -m "$spdk_cpumask" --main-core "$spdk_main_core" 152d841e24bSMichal Berger 153d841e24bSMichal Berger # Create thread0 with 90% activity no cpumask, expecting it to remain on main cpu 154d841e24bSMichal Berger thread0=$(create_thread -n "thread0" -a 90) 155d841e24bSMichal Berger 156d841e24bSMichal Berger sleep $((2 * sched_period)) 157d841e24bSMichal Berger update_thread_cpus_map 158d841e24bSMichal Berger 159d841e24bSMichal Berger ((thread_cpus[thread0] == spdk_main_core)) 160d841e24bSMichal Berger 161d841e24bSMichal Berger # Create thread1 with 90% activity. Expecting one of the threads to be moved to next 162d841e24bSMichal Berger # cpu and the other remain on main cpu. Verifying that threads are spread out when core 163d841e24bSMichal Berger # load is over 95% limit. 164d841e24bSMichal Berger thread1=$(create_thread -n "thread1" -a 90) 165d841e24bSMichal Berger 166d841e24bSMichal Berger # Three iterations are needed, as both active threads first are moved out of main core. 167d841e24bSMichal Berger # During next scheduling period one of them is moved back to the main core. 168d841e24bSMichal Berger sleep $((3 * sched_period)) 169d841e24bSMichal Berger update_thread_cpus_map 170d841e24bSMichal Berger 171d841e24bSMichal Berger ((thread_cpus[thread0] == spdk_main_core || thread_cpus[thread1] == spdk_main_core)) 172d841e24bSMichal Berger ((thread_cpus[thread0] != thread_cpus[thread1])) 173d841e24bSMichal Berger 174d841e24bSMichal Berger # Create thread2 with 10% activity. Expecting the idle thread2 to be placed on main cpu and two 175d841e24bSMichal Berger # other active threads on next cpus. Verifying the condition where core load over 95% moves threads 176d841e24bSMichal Berger # away from main cpu. 177d841e24bSMichal Berger thread2=$(create_thread -n "thread2" -a 10) 178d841e24bSMichal Berger 179d841e24bSMichal Berger sleep $((2 * sched_period)) 180d841e24bSMichal Berger update_thread_cpus_map 181d841e24bSMichal Berger 182d841e24bSMichal Berger ((thread_cpus[thread2] == spdk_main_core)) 183d841e24bSMichal Berger ((thread_cpus[thread1] != spdk_main_core)) 184d841e24bSMichal Berger ((thread_cpus[thread0] != spdk_main_core)) 185d841e24bSMichal Berger ((thread_cpus[thread0] != thread_cpus[thread1])) 186d841e24bSMichal Berger 187d841e24bSMichal Berger # Change all threads activity to 10%. Expecting all threads to be placed on main cpu. 188d841e24bSMichal Berger # Verifying the condition where core load less than 95% is grouping multiple threads. 189d841e24bSMichal Berger active_thread "$thread0" 10 190d841e24bSMichal Berger active_thread "$thread1" 10 191d841e24bSMichal Berger active_thread "$thread2" 10 192d841e24bSMichal Berger 193d841e24bSMichal Berger sleep $((2 * sched_period)) 194d841e24bSMichal Berger update_thread_cpus_map 195d841e24bSMichal Berger 196d841e24bSMichal Berger for thread in \ 197d841e24bSMichal Berger "$thread0" \ 198d841e24bSMichal Berger "$thread1" \ 199d841e24bSMichal Berger "$thread2"; do 200d841e24bSMichal Berger ((thread_cpus[thread] == spdk_main_core)) 201d841e24bSMichal Berger done 202d841e24bSMichal Berger 203d841e24bSMichal Berger # Create thread3, thread4 and thread 5 with 25% activity. Expecting one of the threads on next cpu 204d841e24bSMichal Berger # and rest on main cpu. Total load on main cpu will be (10*3+25*2) 80%, and next cpu 25%. 205d841e24bSMichal Berger thread3=$(create_thread -n "thread3" -a 25) 206d841e24bSMichal Berger thread4=$(create_thread -n "thread4" -a 25) 207d841e24bSMichal Berger thread5=$(create_thread -n "thread5" -a 25) 208d841e24bSMichal Berger 209d841e24bSMichal Berger # Three iterations are needed, as all threads look active on first iteration since they are on the main core. 210c9c7c281SJosh Soref # Second iteration will have them spread out over cores and only third will collapse to the expected scenario. 211d841e24bSMichal Berger sleep $((3 * sched_period)) 212d841e24bSMichal Berger update_thread_cpus_map 213d841e24bSMichal Berger 214e52df268SMichal Berger # Verify that load is not exceeding 80% on each of the cpus except the main and next cpu 215e52df268SMichal Berger get_cpu_time 5 user "${cpus[@]:2}" 216e52df268SMichal Berger 217e52df268SMichal Berger for cpu in "${!avg_cpu_time[@]}"; do 218e52df268SMichal Berger printf '* cpu%u avg load: %u%% (%s)\n' \ 219e52df268SMichal Berger "$cpu" "${avg_cpu_time[cpu]}" "${cpu_times[cpu]}" 220e52df268SMichal Berger ((avg_cpu_time[cpu] <= 80)) 221e52df268SMichal Berger done 222e52df268SMichal Berger 223d841e24bSMichal Berger for thread in \ 224d841e24bSMichal Berger "$thread0" \ 225d841e24bSMichal Berger "$thread1" \ 226d841e24bSMichal Berger "$thread2" \ 227d841e24bSMichal Berger "$thread3" \ 228d841e24bSMichal Berger "$thread4" \ 229d841e24bSMichal Berger "$thread5"; do 230d841e24bSMichal Berger if ((thread_cpus[thread] == spdk_main_core)); then 231d841e24bSMichal Berger ((++on_main_core)) 232d841e24bSMichal Berger else 233d841e24bSMichal Berger ((++on_next_core)) 234d841e24bSMichal Berger fi 235d841e24bSMichal Berger 236d841e24bSMichal Berger destroy_thread "$thread" 237d841e24bSMichal Berger done 238d841e24bSMichal Berger 239d841e24bSMichal Berger ((on_main_core == 5 && on_next_core == 1)) 240d841e24bSMichal Berger} 241d841e24bSMichal Berger 242c9c7c281SJosh Sorefexec_under_dynamic_scheduler "$scheduler" -m "$spdk_cpumask" --main-core "$spdk_main_core" 243766dfaacSMichal Berger 244766dfaacSMichal Bergerrun_test "busy" busy 245766dfaacSMichal Bergerrun_test "balanced" balanced 246d841e24bSMichal Bergerrun_test "core_load" core_load 247