• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/bin/sh
2##############################################################################
3#                                                                            #
4# Copyright (c) International Business Machines  Corp., 2007                 #
5#               Sivakumar Chinnaiah, Sivakumar.C@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
37TST_ID="numa01"
38TST_CNT=10
39TST_SETUP=setup
40TST_TESTFUNC=test
41TST_NEEDS_TMPDIR=1
42TST_NEEDS_ROOT=1
43TST_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#
53extract_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
61wait_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
82setup()
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
107test1()
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
131test2()
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
165test3()
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
200test4()
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
226test5()
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
253test6()
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
285test7()
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
309test8()
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#
348test9()
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
368test10()
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
402tst_run
403