1 #!/bin/sh 2 ############################################################################## 3 # # 4 # Copyright (c) International Business Machines Corp., 2007 # 5 # Sivakumar Chinnaiah, Sivakumar.C (at] in.ibm.com # 6 # Copyright (c) Linux Test Project, 2016 # 7 # # 8 # This program is free software: you can redistribute it and/or modify # 9 # it under the terms of the GNU General Public License as published by # 10 # the Free Software Foundation, either version 3 of the License, or # 11 # (at your option) any later version. # 12 # # 13 # This program is distributed in the hope that it will be useful, # 14 # but WITHOUT ANY WARRANTY; without even the implied warranty of # 15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # 16 # GNU General Public License for more details. # 17 # # 18 # You should have received a copy of the GNU General Public License # 19 # along with this program. If not, see <http://www.gnu.org/licenses/>. # 20 # # 21 ############################################################################## 22 # # 23 # Description: Test Basic functionality of numactl command. # 24 # Test #1: Verifies cpunodebind and membind # 25 # Test #2: Verifies preferred node bind for memory allocation # 26 # Test #3: Verifies share memory allocation on preferred node # 27 # Test #4: Verifies memory interleave on all nodes # 28 # Test #5: Verifies share memory interleave on all nodes # 29 # Test #6: Verifies physcpubind # 30 # Test #7: Verifies localalloc # 31 # Test #8: Verifies memhog # 32 # Test #9: Verifies numa_node_size api # 33 # Test #10:Verifies Migratepages # 34 # # 35 ############################################################################## 36 37 TST_ID="numa01" 38 TST_CNT=10 39 TST_SETUP=setup 40 TST_TESTFUNC=test 41 TST_NEEDS_TMPDIR=1 42 TST_NEEDS_ROOT=1 43 TST_NEEDS_CMDS="numactl numastat awk" 44 45 . tst_test.sh 46 47 # 48 # Extracts the value of given numa node from the `numastat -p` output. 49 # 50 # $1 - Pid number. 51 # $2 - Node number. 52 # 53 extract_numastat_p() 54 { 55 local pid=$1 56 local node=$(($2 + 2)) 57 58 echo $(numastat -p $pid |grep '^Total' |awk '{print $'$node'}') 59 } 60 61 wait_for_support_numa() 62 { 63 local pid=$1 64 local retries=20 65 66 while [ $retries -gt 0 ]; do 67 local state=$(awk '{print $3}' /proc/$pid/stat) 68 69 if [ $state = 'T' ]; then 70 break 71 fi 72 73 retries=$((retries-1)) 74 tst_sleep 50ms 75 done 76 77 if [ $retries -le 0 ]; then 78 tst_brk TBROK "Timeouted while waiting for support_numa ($pid)" 79 fi 80 } 81 82 setup() 83 { 84 export MB=$((1024*1024)) 85 export PAGE_SIZE=$(getconf PAGE_SIZE) 86 87 # arguments to memory exercise program support_numa.c 88 ALLOC_1MB=1 89 SHARE_1MB=2 90 PAUSE=3 91 92 total_nodes=0 93 94 nodes_list=$(numactl --show | grep nodebind | cut -d ':' -f 2) 95 for node in $nodes_list; do 96 total_nodes=$((total_nodes+1)) 97 done 98 99 tst_res TINFO "The system contains $total_nodes nodes: $nodes_list" 100 if [ $total_nodes -le 1 ]; then 101 tst_brk TCONF "your machine does not support numa policy 102 or your machine is not a NUMA machine" 103 fi 104 } 105 106 # Verification of memory allocated on a node 107 test1() 108 { 109 Mem_curr=0 110 111 for node in $nodes_list; do 112 numactl --cpunodebind=$node --membind=$node support_numa $ALLOC_1MB & 113 pid=$! 114 115 wait_for_support_numa $pid 116 117 Mem_curr=$(echo "$(extract_numastat_p $pid $node) * $MB" |bc) 118 if [ $(echo "$Mem_curr < $MB" | bc) -eq 1 ]; then 119 tst_res TFAIL \ 120 "NUMA memory allocated in node$node is less than expected" 121 return 122 fi 123 124 kill -CONT $pid >/dev/null 2>&1 125 done 126 127 tst_res TPASS "NUMA local node and memory affinity" 128 } 129 130 # Verification of memory allocated on preferred node 131 test2() 132 { 133 Mem_curr=0 134 135 COUNTER=1 136 for node in $nodes_list; do 137 138 if [ $COUNTER -eq $total_nodes ]; then #wrap up for last node 139 Preferred_node=$(echo $nodes_list | cut -d ' ' -f 1) 140 else 141 # always next node is preferred node 142 Preferred_node=$(echo $nodes_list | cut -d ' ' -f $((COUNTER+1))) 143 fi 144 145 numactl --cpunodebind=$node --preferred=$Preferred_node support_numa $ALLOC_1MB & 146 pid=$! 147 148 wait_for_support_numa $pid 149 150 Mem_curr=$(echo "$(extract_numastat_p $pid $Preferred_node) * $MB" |bc) 151 if [ $(echo "$Mem_curr < $MB" |bc ) -eq 1 ]; then 152 tst_res TFAIL \ 153 "NUMA memory allocated in node$Preferred_node is less than expected" 154 return 155 fi 156 157 COUNTER=$((COUNTER+1)) 158 kill -CONT $pid >/dev/null 2>&1 159 done 160 161 tst_res TPASS "NUMA preferred node policy" 162 } 163 164 # Verification of share memory allocated on preferred node 165 test3() 166 { 167 Mem_curr=0 168 COUNTER=1 169 170 for node in $nodes_list; do 171 172 if [ $COUNTER -eq $total_nodes ] #wrap up for last node 173 then 174 Preferred_node=$(echo $nodes_list | cut -d ' ' -f 1) 175 else 176 # always next node is preferred node 177 Preferred_node=$(echo $nodes_list | cut -d ' ' -f $((COUNTER+1))) 178 fi 179 180 numactl --cpunodebind=$node --preferred=$Preferred_node support_numa $SHARE_1MB & 181 pid=$! 182 183 wait_for_support_numa $pid 184 185 Mem_curr=$(echo "$(extract_numastat_p $pid $Preferred_node) * $MB" |bc) 186 if [ $(echo "$Mem_curr < $MB" |bc ) -eq 1 ]; then 187 tst_res TFAIL \ 188 "NUMA share memory allocated in node$Preferred_node is less than expected" 189 return 190 fi 191 192 COUNTER=$((COUNTER+1)) 193 kill -CONT $pid >/dev/null 2>&1 194 done 195 196 tst_res TPASS "NUMA share memory allocated in preferred node" 197 } 198 199 # Verification of memory interleaved on all nodes 200 test4() 201 { 202 Mem_curr=0 203 # Memory will be allocated using round robin on nodes. 204 Exp_incr=$(echo "$MB / $total_nodes" |bc) 205 206 numactl --interleave=all support_numa $ALLOC_1MB & 207 pid=$! 208 209 wait_for_support_numa $pid 210 211 for node in $nodes_list; do 212 Mem_curr=$(echo "$(extract_numastat_p $pid $node) * $MB" |bc) 213 214 if [ $(echo "$Mem_curr < $Exp_incr" |bc ) -eq 1 ]; then 215 tst_res TFAIL \ 216 "NUMA interleave memory allocated in node$node is less than expected" 217 return 218 fi 219 done 220 221 kill -CONT $pid >/dev/null 2>&1 222 tst_res TPASS "NUMA interleave policy" 223 } 224 225 # Verification of shared memory interleaved on all nodes 226 test5() 227 { 228 Mem_curr=0 229 # Memory will be allocated using round robin on nodes. 230 Exp_incr=$(echo "$MB / $total_nodes" |bc) 231 232 numactl --interleave=all support_numa $SHARE_1MB & 233 pid=$! 234 235 wait_for_support_numa $pid 236 237 for node in $nodes_list; do 238 Mem_curr=$(echo "$(extract_numastat_p $pid $node) * $MB" |bc) 239 240 if [ $(echo "$Mem_curr < $Exp_incr" |bc ) -eq 1 ]; then 241 tst_res TFAIL \ 242 "NUMA interleave share memory allocated in node$node is less than expected" 243 return 244 fi 245 done 246 247 kill -CONT $pid >/dev/null 2>&1 248 249 tst_res TPASS "NUMA interleave policy on shared memory" 250 } 251 252 # Verification of physical cpu bind 253 test6() 254 { 255 no_of_cpus=0 #no. of cpu's exist 256 run_on_cpu=0 257 running_on_cpu=0 258 259 no_of_cpus=$(tst_ncpus) 260 # not sure whether cpu's can't be in odd number 261 run_on_cpu=$(($((no_of_cpus+1))/2)) 262 numactl --physcpubind=$run_on_cpu support_numa $PAUSE & #just waits for sigint 263 pid=$! 264 var=`awk '{ print $2 }' /proc/$pid/stat` 265 while [ $var = '(numactl)' ]; do 266 var=`awk '{ print $2 }' /proc/$pid/stat` 267 tst_sleep 100ms 268 done 269 # Warning !! 39 represents cpu number, on which process pid is currently running and 270 # this may change if Some more fields are added in the middle, may be in future 271 running_on_cpu=$(awk '{ print $39; }' /proc/$pid/stat) 272 if [ $running_on_cpu -ne $run_on_cpu ]; then 273 tst_res TFAIL \ 274 "Process running on cpu$running_on_cpu but expected to run on cpu$run_on_cpu" 275 ROD kill -INT $pid 276 return 277 fi 278 279 ROD kill -INT $pid 280 281 tst_res TPASS "NUMA phycpubind policy" 282 } 283 284 # Verification of local node allocation 285 test7() 286 { 287 Mem_curr=0 288 289 for node in $nodes_list; do 290 numactl --cpunodebind=$node --localalloc support_numa $ALLOC_1MB & 291 pid=$! 292 293 wait_for_support_numa $pid 294 295 Mem_curr=$(echo "$(extract_numastat_p $pid $node) * $MB" |bc) 296 if [ $(echo "$Mem_curr < $MB" |bc ) -eq 1 ]; then 297 tst_res TFAIL \ 298 "NUMA localnode memory allocated in node$node is less than expected" 299 return 300 fi 301 302 kill -CONT $pid >/dev/null 2>&1 303 done 304 305 tst_res TPASS "NUMA local node allocation" 306 } 307 308 # Verification of memhog with interleave policy 309 test8() 310 { 311 Mem_curr=0 312 # Memory will be allocated using round robin on nodes. 313 Exp_incr=$(echo "$MB / $total_nodes" |bc) 314 315 numactl --interleave=all memhog -r1000000 1MB 2>&1 >/dev/null & 316 pid=$! 317 318 for node in $nodes_list; do 319 Mem_curr=$(echo "$(extract_numastat_p $pid $node) * $MB" |bc) 320 321 if [ $(echo "$Mem_curr < $Exp_incr" |bc ) -eq 1 ]; then 322 tst_res TFAIL \ 323 "NUMA interleave memhog in node$node is less than expected" 324 return 325 fi 326 done 327 328 kill -9 $pid >/dev/null 2>&1 329 tst_res TPASS "NUMA MEMHOG policy" 330 } 331 332 # Function: hardware cheking with numa_node_size api 333 # 334 # Description: - Returns the size of available nodes if success. 335 # 336 # Input: - o/p of numactl --hardware command which is expected in the format 337 # shown below 338 # available: 2 nodes (0-1) 339 # node 0 size: 7808 MB 340 # node 0 free: 7457 MB 341 # node 1 size: 5807 MB 342 # node 1 free: 5731 MB 343 # node distances: 344 # node 0 1 345 # 0: 10 20 346 # 1: 20 10 347 # 348 test9() 349 { 350 RC=0 351 352 numactl --hardware > gavail_nodes 353 RC=$(awk '{ if ( NR == 1 ) {print $1;} }' gavail_nodes) 354 if [ $RC = "available:" ]; then 355 RC=$(awk '{ if ( NR == 1 ) {print $3;} }' gavail_nodes) 356 if [ $RC = "nodes" ]; then 357 RC=$(awk '{ if ( NR == 1 ) {print $2;} }' gavail_nodes) 358 tst_res TPASS "NUMA policy on lib NUMA_NODE_SIZE API" 359 else 360 tst_res TFAIL "Failed with numa policy" 361 fi 362 else 363 tst_res TFAIL "Failed with numa policy" 364 fi 365 } 366 367 # Verification of migratepages 368 test10() 369 { 370 Mem_curr=0 371 COUNTER=1 372 373 for node in $nodes_list; do 374 375 if [ $COUNTER -eq $total_nodes ]; then 376 Preferred_node=$(echo $nodes_list | cut -d ' ' -f 1) 377 else 378 Preferred_node=$(echo $nodes_list | cut -d ' ' -f $((COUNTER+1))) 379 fi 380 381 numactl --preferred=$node support_numa $ALLOC_1MB & 382 pid=$! 383 384 wait_for_support_numa $pid 385 386 migratepages $pid $node $Preferred_node 387 388 Mem_curr=$(echo "$(extract_numastat_p $pid $Preferred_node) * $MB" |bc) 389 if [ $(echo "$Mem_curr < $MB" |bc ) -eq 1 ]; then 390 tst_res TFAIL \ 391 "NUMA migratepages is not working fine" 392 return 393 fi 394 395 COUNTER=$((COUNTER+1)) 396 kill -CONT $pid >/dev/null 2>&1 397 done 398 399 tst_res TPASS "NUMA MIGRATEPAGES policy" 400 } 401 402 tst_run 403