1f08c3bdfSopenharmony_ci#!/bin/bash
2f08c3bdfSopenharmony_ci# Copyright (c) International Business Machines  Corp., 2008
3f08c3bdfSopenharmony_ci# Author: Matt Helsley <matthltc@us.ibm.com>
4f08c3bdfSopenharmony_ci#
5f08c3bdfSopenharmony_ci# This library is free software; you can redistribute it and/or
6f08c3bdfSopenharmony_ci# modify it under the terms of the GNU Lesser General Public
7f08c3bdfSopenharmony_ci# License as published by the Free Software Foundation; either
8f08c3bdfSopenharmony_ci# version 2.1 of the License, or (at your option) any later version.
9f08c3bdfSopenharmony_ci#
10f08c3bdfSopenharmony_ci# This library is distributed in the hope that it will be useful,
11f08c3bdfSopenharmony_ci# but WITHOUT ANY WARRANTY; without even the implied warranty of
12f08c3bdfSopenharmony_ci# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13f08c3bdfSopenharmony_ci# Lesser General Public License for more details.
14f08c3bdfSopenharmony_ci#
15f08c3bdfSopenharmony_ci# You should have received a copy of the GNU Lesser General Public
16f08c3bdfSopenharmony_ci# License along with this library; if not, write to the Free Software
17f08c3bdfSopenharmony_ci# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18f08c3bdfSopenharmony_ci#
19f08c3bdfSopenharmony_ci#
20f08c3bdfSopenharmony_ci
21f08c3bdfSopenharmony_ci# A library of cgroup test functions for testing the cgroup freezer and,
22f08c3bdfSopenharmony_ci# if present, a cgroup signal subsystem.
23f08c3bdfSopenharmony_ci#
24f08c3bdfSopenharmony_ci# Most of these assume the current directory is the cgroup of interest.
25f08c3bdfSopenharmony_ci# mount_{freezer|signal} and make_sample_cgroup are the exceptions to this rule.
26f08c3bdfSopenharmony_ci#
27f08c3bdfSopenharmony_ci# On failure, a message indicating what failed is printed and the
28f08c3bdfSopenharmony_ci#    exit status of the failing command is returned. If "result" is unset
29f08c3bdfSopenharmony_ci#    then we assign the exit status of the failed command to it.
30f08c3bdfSopenharmony_ci#
31f08c3bdfSopenharmony_ci# The variable "result" holds the exit status of the first command that failed,
32f08c3bdfSopenharmony_ci#    $UNFINISHED if no command has failed yet, or $FINISHED if no command
33f08c3bdfSopenharmony_ci#    has failed and we've finished all significant parts of the test. Note:
34f08c3bdfSopenharmony_ci#    significant parts usually do not include the cleanup of the test.
35f08c3bdfSopenharmony_ci#
36f08c3bdfSopenharmony_ci
37f08c3bdfSopenharmony_ci
38f08c3bdfSopenharmony_ci# xargs 4.1.20 only accepts -i instead of -I
39f08c3bdfSopenharmony_ci# However -I is added and -i deprecated somewhere between (4.1.20, 4.2.32]
40f08c3bdfSopenharmony_ciXRGSV=$(xargs --version | sed -e 's/^[^[:digit:]]*//')
41f08c3bdfSopenharmony_ciexport XARGS_REPL_STR="%"
42f08c3bdfSopenharmony_cicase ${XRGSV} in
43f08c3bdfSopenharmony_ci[456789].[23456789][0-9]*.*|[1-9][0-9][0-9]*.*.*) # version > 4.1.*
44f08c3bdfSopenharmony_ci	export XARGS_REPL_OPT="-I${XARGS_REPL_STR}"
45f08c3bdfSopenharmony_ci	;;
46f08c3bdfSopenharmony_ci4.1.*|*)
47f08c3bdfSopenharmony_ci	export XARGS_REPL_OPT="-i${XARGS_REPL_STR}"
48f08c3bdfSopenharmony_ci	;;
49f08c3bdfSopenharmony_ciesac
50f08c3bdfSopenharmony_ciunset XRGSV
51f08c3bdfSopenharmony_ci
52f08c3bdfSopenharmony_ciexport UNFINISHED=""
53f08c3bdfSopenharmony_ciexport FINISHED=0
54f08c3bdfSopenharmony_ciexport TMP=${TMP:-/tmp}
55f08c3bdfSopenharmony_ci
56f08c3bdfSopenharmony_ci#
57f08c3bdfSopenharmony_ci# Tests are either running or cleaning up. Cleanup phases do not emit TFAIL.
58f08c3bdfSopenharmony_ci#
59f08c3bdfSopenharmony_ciexport LIB_TEST_STATE="running"
60f08c3bdfSopenharmony_ci
61f08c3bdfSopenharmony_ciexport max_state_samples=5 # number of times to sample
62f08c3bdfSopenharmony_ciexport sample_state_period=1  # number of seconds between samplings
63f08c3bdfSopenharmony_ciexport sample_sleep=5     # how long the sample program should sleep
64f08c3bdfSopenharmony_ciexport result="$UNFINISHED"
65f08c3bdfSopenharmony_ci
66f08c3bdfSopenharmony_ci# These are echo'd to freezer.state.
67f08c3bdfSopenharmony_ciexport FREEZE='FROZEN'
68f08c3bdfSopenharmony_ciexport THAW='THAWED'
69f08c3bdfSopenharmony_ci
70f08c3bdfSopenharmony_ci# We use /bin/echo to write to cgroup files because it's exit status will not
71f08c3bdfSopenharmony_ci# hide write errors (bash's echo does not indicate if the write succeeded).
72f08c3bdfSopenharmony_ciexport CG_FILE_WRITE=/bin/echo
73f08c3bdfSopenharmony_ci
74f08c3bdfSopenharmony_cideclare -r UNFINISHED FINISHED FREEZE THAW max_state_samples sample_state_period
75f08c3bdfSopenharmony_ci
76f08c3bdfSopenharmony_ci# When we're running we want to issue failure results when things go wrong.
77f08c3bdfSopenharmony_cifunction running_cgroup_test()
78f08c3bdfSopenharmony_ci{
79f08c3bdfSopenharmony_ci	export LIB_TEST_STATE="TFAIL"
80f08c3bdfSopenharmony_ci}
81f08c3bdfSopenharmony_ci
82f08c3bdfSopenharmony_ci# But when we're cleaning up we want to issue warnings (if not TINFO).
83f08c3bdfSopenharmony_cifunction cleanup_cgroup_test()
84f08c3bdfSopenharmony_ci{
85f08c3bdfSopenharmony_ci	export LIB_TEST_STATE="TWARN"
86f08c3bdfSopenharmony_ci}
87f08c3bdfSopenharmony_ci
88f08c3bdfSopenharmony_ci# Mounts the cgroup filesystem somewhere and pushes pwd onto the dir stack
89f08c3bdfSopenharmony_cifunction mount_cgroup_subsys()
90f08c3bdfSopenharmony_ci{
91f08c3bdfSopenharmony_ci	local rc=0
92f08c3bdfSopenharmony_ci
93f08c3bdfSopenharmony_ci	mkdir -p $TMP/${cgroup_subsys}_test > /dev/null 2>&1
94f08c3bdfSopenharmony_ci	rc=$?
95f08c3bdfSopenharmony_ci
96f08c3bdfSopenharmony_ci	# Don't test status because we don't care if the directory already
97f08c3bdfSopenharmony_ci	# exists.
98f08c3bdfSopenharmony_ci
99f08c3bdfSopenharmony_ci	if [ ! -d $TMP/${cgroup_subsys}_test ]; then
100f08c3bdfSopenharmony_ci		result=${result:-$rc}
101f08c3bdfSopenharmony_ci		tst_brkm TBROK "Failed to make mount point for cgroup filesystem"
102f08c3bdfSopenharmony_ci		return $result
103f08c3bdfSopenharmony_ci	fi
104f08c3bdfSopenharmony_ci
105f08c3bdfSopenharmony_ci	mount -t cgroup -o${cgroup_subsys} test_cgroup_${cgroup_subsys} $TMP/${cgroup_subsys}_test
106f08c3bdfSopenharmony_ci	rc=$?
107f08c3bdfSopenharmony_ci	if [ $rc -ne 0 ]; then
108f08c3bdfSopenharmony_ci		result=${result:-$rc}
109f08c3bdfSopenharmony_ci		tst_resm TINFO "Failed to mount cgroup filesystem with ${cgroup_subsys} subsystem."
110f08c3bdfSopenharmony_ci		rmdir $TMP/${cgroup_subsys}_test 2> /dev/null
111f08c3bdfSopenharmony_ci		return $rc
112f08c3bdfSopenharmony_ci	fi
113f08c3bdfSopenharmony_ci
114f08c3bdfSopenharmony_ci	export mount_cgroup_freezer_saved_dir="$(pwd)"
115f08c3bdfSopenharmony_ci	cd $TMP/${cgroup_subsys}_test > /dev/null 2>&1
116f08c3bdfSopenharmony_ci	rc=$?
117f08c3bdfSopenharmony_ci	if [ $rc -ne 0 ]; then
118f08c3bdfSopenharmony_ci		result=${result:-$rc}
119f08c3bdfSopenharmony_ci		tst_brkm TBROK "Failed to change working directory into cgroup filesystem (pwd: \"$(pwd)\")"
120f08c3bdfSopenharmony_ci		umount $TMP/${cgroup_subsys}_test || umount -l $TMP/${cgroup_subsys}_test || tst_brkm TBROK "Failed to unmount cgroup filesystem with ${cgroup_subsys} subsystem"
121f08c3bdfSopenharmony_ci		rmdir $TMP/${cgroup_subsys}_test 2> /dev/null
122f08c3bdfSopenharmony_ci		return $rc
123f08c3bdfSopenharmony_ci	fi
124f08c3bdfSopenharmony_ci
125f08c3bdfSopenharmony_ci	return 0
126f08c3bdfSopenharmony_ci}
127f08c3bdfSopenharmony_ci
128f08c3bdfSopenharmony_cifunction mount_freezer()
129f08c3bdfSopenharmony_ci{
130f08c3bdfSopenharmony_ci	export cgroup_subsys=freezer
131f08c3bdfSopenharmony_ci	mount_cgroup_subsys
132f08c3bdfSopenharmony_ci}
133f08c3bdfSopenharmony_ci
134f08c3bdfSopenharmony_cifunction mount_signal()
135f08c3bdfSopenharmony_ci{
136f08c3bdfSopenharmony_ci	export cgroup_subsys=signal
137f08c3bdfSopenharmony_ci	mount_cgroup_subsys
138f08c3bdfSopenharmony_ci}
139f08c3bdfSopenharmony_ci
140f08c3bdfSopenharmony_ci# umounts the cgroup filesystem and pops the dir stack
141f08c3bdfSopenharmony_cifunction umount_cgroup_subsys()
142f08c3bdfSopenharmony_ci{
143f08c3bdfSopenharmony_ci	cd "${mount_cgroup_freezer_saved_dir}"
144f08c3bdfSopenharmony_ci	local cwd_result=$?
145f08c3bdfSopenharmony_ci	umount $TMP/${cgroup_subsys}_test > /dev/null 2>&1 \
146f08c3bdfSopenharmony_ci	  || umount -l $TMP/${cgroup_subsys}_test || \
147f08c3bdfSopenharmony_ci	    tst_brkm TBROK "Failed to unmount cgroup filesystem (umount exit status: $?)"
148f08c3bdfSopenharmony_ci	local umnt_result=$?
149f08c3bdfSopenharmony_ci	local rc=0
150f08c3bdfSopenharmony_ci
151f08c3bdfSopenharmony_ci	if [ $cwd_result -ne 0 ]; then
152f08c3bdfSopenharmony_ci		result=${result:-$cwd_result}
153f08c3bdfSopenharmony_ci		rc=$cwd_result
154f08c3bdfSopenharmony_ci	elif [ $umnt_result -ne 0 ]; then
155f08c3bdfSopenharmony_ci		result=${result:-$umnt_result}
156f08c3bdfSopenharmony_ci		rc=$umnt_result
157f08c3bdfSopenharmony_ci	elif [ $umnt_result -eq 0 -a $cwd_result -eq 0 ]; then
158f08c3bdfSopenharmony_ci		rmdir $TMP/${cgroup_subsys}_test
159f08c3bdfSopenharmony_ci		return 0
160f08c3bdfSopenharmony_ci	fi
161f08c3bdfSopenharmony_ci
162f08c3bdfSopenharmony_ci	return $rc
163f08c3bdfSopenharmony_ci}
164f08c3bdfSopenharmony_ci
165f08c3bdfSopenharmony_cifunction umount_freezer()
166f08c3bdfSopenharmony_ci{
167f08c3bdfSopenharmony_ci	[ "${cgroup_subsys}" != "freezer" ] && {
168f08c3bdfSopenharmony_ci		result=${result:-5}
169f08c3bdfSopenharmony_ci		exit -1
170f08c3bdfSopenharmony_ci	}
171f08c3bdfSopenharmony_ci	umount_cgroup_subsys
172f08c3bdfSopenharmony_ci	unset cgroup_subsys
173f08c3bdfSopenharmony_ci}
174f08c3bdfSopenharmony_ci
175f08c3bdfSopenharmony_cifunction cleanup_freezer()
176f08c3bdfSopenharmony_ci{
177f08c3bdfSopenharmony_ci	local save_result="${result}"
178f08c3bdfSopenharmony_ci	local save_pwd="$(pwd)"
179f08c3bdfSopenharmony_ci
180f08c3bdfSopenharmony_ci	mount_freezer && {
181f08c3bdfSopenharmony_ci		# Run these commands in bash because we need $(cmd subst) and
182f08c3bdfSopenharmony_ci		# we need to redirect to different freezer.state files for each
183f08c3bdfSopenharmony_ci		# group
184f08c3bdfSopenharmony_ci		# Kill any leftover tasks
185f08c3bdfSopenharmony_ci		disown -a
186f08c3bdfSopenharmony_ci		find $TMP/${cgroup_subsys}_test -mindepth 1 -depth -type d -print0 | \
187f08c3bdfSopenharmony_ci		xargs -0r -n 1 ${XARGS_REPL_OPT} /bin/bash -c 'kill $(cat "'"${XARGS_REPL_STR}"'/tasks") 2> /dev/null'
188f08c3bdfSopenharmony_ci
189f08c3bdfSopenharmony_ci		# For each group in the freezer hierarch, that its tasks
190f08c3bdfSopenharmony_ci		find $TMP/${cgroup_subsys}_test -mindepth 1 -depth -type d -print0 | \
191f08c3bdfSopenharmony_ci		xargs -0r -n 1 ${XARGS_REPL_OPT} /bin/bash -c "\"${CG_FILE_WRITE}\" \"${THAW}\" > '${XARGS_REPL_STR}/freezer.state'"
192f08c3bdfSopenharmony_ci
193f08c3bdfSopenharmony_ci		# Kill any leftover tasks
194f08c3bdfSopenharmony_ci		find $TMP/${cgroup_subsys}_test -mindepth 1 -depth -type d -print0 | \
195f08c3bdfSopenharmony_ci		xargs -0r -n 1 ${XARGS_REPL_OPT} /bin/bash -c 'kill $(cat "'"${XARGS_REPL_STR}"'/tasks") 2> /dev/null'
196f08c3bdfSopenharmony_ci
197f08c3bdfSopenharmony_ci		sleep 2
198f08c3bdfSopenharmony_ci
199f08c3bdfSopenharmony_ci		# Really kill any leftover tasks
200f08c3bdfSopenharmony_ci		find $TMP/${cgroup_subsys}_test -mindepth 1 -depth -type d -print0 | \
201f08c3bdfSopenharmony_ci		xargs -0r -n 1 ${XARGS_REPL_OPT} /bin/bash -c 'kill -s SIGKILL $(cat "'"${XARGS_REPL_STR}"'/tasks") 2> /dev/null'
202f08c3bdfSopenharmony_ci
203f08c3bdfSopenharmony_ci		# Don't need to run these xargs commands in bash since we want
204f08c3bdfSopenharmony_ci		# to see what's left on stdout
205f08c3bdfSopenharmony_ci		LINES=$(find $TMP/${cgroup_subsys}_test -mindepth 1 -depth -type d -print0 | \
206f08c3bdfSopenharmony_ci			xargs -0r -n 1 ${XARGS_REPL_OPT} cat "${XARGS_REPL_STR}/tasks" | wc -l)
207f08c3bdfSopenharmony_ci		if (( LINES == 0 )); then
208f08c3bdfSopenharmony_ci			# Remove the empty groups
209f08c3bdfSopenharmony_ci			find $TMP/${cgroup_subsys}_test -mindepth 1 -depth -type d -print0 | xargs -r0 rmdir
210f08c3bdfSopenharmony_ci		else
211f08c3bdfSopenharmony_ci			tst_resm TWARN "Could not cleanup:"
212f08c3bdfSopenharmony_ci			find $TMP/${cgroup_subsys}_test -mindepth 1 -depth -type d -print0 | xargs -0r -n 1 ${XARGS_REPL_OPT} ls -ld "${XARGS_REPL_STR}/tasks"
213f08c3bdfSopenharmony_ci		fi
214f08c3bdfSopenharmony_ci
215f08c3bdfSopenharmony_ci		umount_freezer
216f08c3bdfSopenharmony_ci	}
217f08c3bdfSopenharmony_ci
218f08c3bdfSopenharmony_ci	if [ "$save_pwd" != `pwd` ]; then
219f08c3bdfSopenharmony_ci		tst_resm TWARN "libcgroup_subsys: cleanup_freezer() is broken"
220f08c3bdfSopenharmony_ci		cd "$save_pwd"
221f08c3bdfSopenharmony_ci	fi
222f08c3bdfSopenharmony_ci
223f08c3bdfSopenharmony_ci	result="${save_result}"
224f08c3bdfSopenharmony_ci}
225f08c3bdfSopenharmony_ci
226f08c3bdfSopenharmony_cifunction umount_signal()
227f08c3bdfSopenharmony_ci{
228f08c3bdfSopenharmony_ci	[ "${cgroup_subsys}" != "signal" ] && {
229f08c3bdfSopenharmony_ci		result=${result:-6}
230f08c3bdfSopenharmony_ci		exit -1
231f08c3bdfSopenharmony_ci	}
232f08c3bdfSopenharmony_ci	umount_cgroup_subsys
233f08c3bdfSopenharmony_ci	unset cgroup_subsys
234f08c3bdfSopenharmony_ci}
235f08c3bdfSopenharmony_ci
236f08c3bdfSopenharmony_cifunction cleanup_signal()
237f08c3bdfSopenharmony_ci{
238f08c3bdfSopenharmony_ci	local save_result="${result}"
239f08c3bdfSopenharmony_ci	local save_pwd="$(pwd)"
240f08c3bdfSopenharmony_ci
241f08c3bdfSopenharmony_ci	mount_signal && {
242f08c3bdfSopenharmony_ci		find $TMP/${cgroup_subsys}_test -mindepth 1 -depth -type d -print0 | xargs -r0 rmdir
243f08c3bdfSopenharmony_ci		umount_signal
244f08c3bdfSopenharmony_ci	}
245f08c3bdfSopenharmony_ci
246f08c3bdfSopenharmony_ci	if [ "$save_pwd" != `pwd` ]; then
247f08c3bdfSopenharmony_ci		tst_resm TWARN "libcgroup_subsys: cleanup_signal() is broken"
248f08c3bdfSopenharmony_ci		cd "$save_pwd"
249f08c3bdfSopenharmony_ci	fi
250f08c3bdfSopenharmony_ci	result="${save_result}"
251f08c3bdfSopenharmony_ci}
252f08c3bdfSopenharmony_ci
253f08c3bdfSopenharmony_cifunction assert_cgroup_rwfile()
254f08c3bdfSopenharmony_ci{
255f08c3bdfSopenharmony_ci	local file="$1"
256f08c3bdfSopenharmony_ci	local descr="$2"
257f08c3bdfSopenharmony_ci	local rc=0
258f08c3bdfSopenharmony_ci
259f08c3bdfSopenharmony_ci	if [ ! -e "${file}" ]; then
260f08c3bdfSopenharmony_ci		tst_resm ${LIB_TEST_STATE} "$descr missing"
261f08c3bdfSopenharmony_ci		rc=1
262f08c3bdfSopenharmony_ci	fi
263f08c3bdfSopenharmony_ci
264f08c3bdfSopenharmony_ci	if [ ! -f "${file}" ]; then
265f08c3bdfSopenharmony_ci		tst_resm ${LIB_TEST_STATE} "$descr is not a regular file"
266f08c3bdfSopenharmony_ci		rc=2
267f08c3bdfSopenharmony_ci	fi
268f08c3bdfSopenharmony_ci
269f08c3bdfSopenharmony_ci	if [ ! -r "${file}" ]; then
270f08c3bdfSopenharmony_ci		tst_resm ${LIB_TEST_STATE} "$descr is not readable"
271f08c3bdfSopenharmony_ci		rc=3
272f08c3bdfSopenharmony_ci	fi
273f08c3bdfSopenharmony_ci
274f08c3bdfSopenharmony_ci	if [ ! -w "${file}" ]; then
275f08c3bdfSopenharmony_ci		tst_resm ${LIB_TEST_STATE} "$descr is not writeable"
276f08c3bdfSopenharmony_ci		rc=4
277f08c3bdfSopenharmony_ci	fi
278f08c3bdfSopenharmony_ci
279f08c3bdfSopenharmony_ci	[ $rc -ne 0 ] && {
280f08c3bdfSopenharmony_ci		result=${result:-$rc}
281f08c3bdfSopenharmony_ci		local s="$(stat "${file}")"
282f08c3bdfSopenharmony_ci		tst_resm ${LIB_TEST_STATE} "${s}"
283f08c3bdfSopenharmony_ci	}
284f08c3bdfSopenharmony_ci
285f08c3bdfSopenharmony_ci	return $rc
286f08c3bdfSopenharmony_ci}
287f08c3bdfSopenharmony_ci
288f08c3bdfSopenharmony_cifunction assert_cgroup_tasks_rwfile()
289f08c3bdfSopenharmony_ci{
290f08c3bdfSopenharmony_ci	assert_cgroup_rwfile "tasks" "task list"
291f08c3bdfSopenharmony_ci	return $?
292f08c3bdfSopenharmony_ci}
293f08c3bdfSopenharmony_ci
294f08c3bdfSopenharmony_cifunction dump_named_cgroup_tasks()
295f08c3bdfSopenharmony_ci{
296f08c3bdfSopenharmony_ci	local cgroup_name="$1"
297f08c3bdfSopenharmony_ci	local tasks
298f08c3bdfSopenharmony_ci
299f08c3bdfSopenharmony_ci	tasks=( $(cat "${cgroup_name}/tasks") ) # don't assign directly (bash bug)
300f08c3bdfSopenharmony_ci	if [ -z "${tasks[*]}" ]; then
301f08c3bdfSopenharmony_ci		return 0
302f08c3bdfSopenharmony_ci	fi
303f08c3bdfSopenharmony_ci	ps -p "${tasks[*]}" -o 'pid,ppid,pgid,tid,tpgid,blocked,ignored,pending,stat,tty,args'
304f08c3bdfSopenharmony_ci}
305f08c3bdfSopenharmony_ci
306f08c3bdfSopenharmony_cifunction dump_cgroup_tasks()
307f08c3bdfSopenharmony_ci{
308f08c3bdfSopenharmony_ci	dump_named_cgroup_tasks "$(pwd)"
309f08c3bdfSopenharmony_ci}
310f08c3bdfSopenharmony_ci
311f08c3bdfSopenharmony_cifunction assert_cgroup_tasks_empty()
312f08c3bdfSopenharmony_ci{
313f08c3bdfSopenharmony_ci	local nlines=$(( `cat tasks | wc -l` + 0))
314f08c3bdfSopenharmony_ci	local rc=$?
315f08c3bdfSopenharmony_ci
316f08c3bdfSopenharmony_ci	[ $rc -eq 0 -a $nlines -eq 0 ] && return 0
317f08c3bdfSopenharmony_ci	rc=$?
318f08c3bdfSopenharmony_ci	result=${result:-$rc}
319f08c3bdfSopenharmony_ci	tst_resm ${LIB_TEST_STATE} "cgroup task list is not empty: "
320f08c3bdfSopenharmony_ci	dump_cgroup_tasks 1>&2
321f08c3bdfSopenharmony_ci	return $rc
322f08c3bdfSopenharmony_ci}
323f08c3bdfSopenharmony_ci
324f08c3bdfSopenharmony_cifunction assert_task_in_named_cgroup()
325f08c3bdfSopenharmony_ci{
326f08c3bdfSopenharmony_ci	local task_pid=$1
327f08c3bdfSopenharmony_ci	local cgroup_name="$2"
328f08c3bdfSopenharmony_ci
329f08c3bdfSopenharmony_ci	cat "${cgroup_name}/tasks" | grep -E "^${task_pid}\$" > /dev/null 2>&1 && return 0
330f08c3bdfSopenharmony_ci	local rc=$?
331f08c3bdfSopenharmony_ci	result=${result:-$rc}
332f08c3bdfSopenharmony_ci	tst_resm ${LIB_TEST_STATE} "Expected pid ${task_pid} is not in \"${cgroup_name}\" task list"
333f08c3bdfSopenharmony_ci	dump_named_cgroup_tasks "${cgroup_name}" 1>&2
334f08c3bdfSopenharmony_ci	return $rc
335f08c3bdfSopenharmony_ci}
336f08c3bdfSopenharmony_ci
337f08c3bdfSopenharmony_cifunction assert_task_not_in_named_cgroup()
338f08c3bdfSopenharmony_ci{
339f08c3bdfSopenharmony_ci	local task_pid=$1
340f08c3bdfSopenharmony_ci	local cgroup_name="$2"
341f08c3bdfSopenharmony_ci
342f08c3bdfSopenharmony_ci	cat "${cgroup_name}/tasks" | grep -E "^${task_pid}\$" > /dev/null 2>&1 || return 0
343f08c3bdfSopenharmony_ci	local rc=1 # $? == 0 is an error in this case
344f08c3bdfSopenharmony_ci	result=${result:-$rc}
345f08c3bdfSopenharmony_ci	tst_resm ${LIB_TEST_STATE} "Expected pid ${task_pid} is in \"${cgroup_name}\" task list"
346f08c3bdfSopenharmony_ci	dump_named_cgroup_tasks "${cgroup_name}" 1>&2
347f08c3bdfSopenharmony_ci	return $rc
348f08c3bdfSopenharmony_ci}
349f08c3bdfSopenharmony_ci
350f08c3bdfSopenharmony_cifunction assert_task_in_cgroup()
351f08c3bdfSopenharmony_ci{
352f08c3bdfSopenharmony_ci	assert_task_in_named_cgroup $1 "$(pwd)"
353f08c3bdfSopenharmony_ci	return $?
354f08c3bdfSopenharmony_ci}
355f08c3bdfSopenharmony_ci
356f08c3bdfSopenharmony_cifunction assert_task_not_in_cgroup()
357f08c3bdfSopenharmony_ci{
358f08c3bdfSopenharmony_ci	assert_task_not_in_named_cgroup $1 "$(pwd)"
359f08c3bdfSopenharmony_ci	return $?
360f08c3bdfSopenharmony_ci}
361f08c3bdfSopenharmony_ci
362f08c3bdfSopenharmony_cifunction assert_sample_proc_in_cgroup()
363f08c3bdfSopenharmony_ci{
364f08c3bdfSopenharmony_ci	assert_task_in_cgroup $sample_proc
365f08c3bdfSopenharmony_ci	return $?
366f08c3bdfSopenharmony_ci}
367f08c3bdfSopenharmony_ci
368f08c3bdfSopenharmony_cifunction assert_sample_proc_not_in_cgroup()
369f08c3bdfSopenharmony_ci{
370f08c3bdfSopenharmony_ci	assert_task_not_in_cgroup $sample_proc
371f08c3bdfSopenharmony_ci	return $?
372f08c3bdfSopenharmony_ci}
373f08c3bdfSopenharmony_ci
374f08c3bdfSopenharmony_cifunction assert_sample_proc_in_named_cgroup()
375f08c3bdfSopenharmony_ci{
376f08c3bdfSopenharmony_ci	assert_task_in_named_cgroup $sample_proc "$1"
377f08c3bdfSopenharmony_ci	return $?
378f08c3bdfSopenharmony_ci}
379f08c3bdfSopenharmony_ci
380f08c3bdfSopenharmony_cifunction assert_sample_proc_not_in_named_cgroup()
381f08c3bdfSopenharmony_ci{
382f08c3bdfSopenharmony_ci	assert_task_not_in_named_cgroup $sample_proc "$1"
383f08c3bdfSopenharmony_ci	return $?
384f08c3bdfSopenharmony_ci}
385f08c3bdfSopenharmony_ci
386f08c3bdfSopenharmony_cifunction get_task_state()
387f08c3bdfSopenharmony_ci{
388f08c3bdfSopenharmony_ci	ps -p $1 -o 'state=' 2>/dev/null
389f08c3bdfSopenharmony_ci}
390f08c3bdfSopenharmony_ci
391f08c3bdfSopenharmony_ci# TODO Check: Do these need to ignore case differences?
392f08c3bdfSopenharmony_cifunction assert_task_state()
393f08c3bdfSopenharmony_ci{
394f08c3bdfSopenharmony_ci	local task_pid=$1
395f08c3bdfSopenharmony_ci	local expected_state="$2"
396f08c3bdfSopenharmony_ci	local ps_state="$(get_task_state ${task_pid})"
397f08c3bdfSopenharmony_ci	local rc=$?
398f08c3bdfSopenharmony_ci
399f08c3bdfSopenharmony_ci	[ $rc -eq 0 -a "$ps_state" == "${expected_state}" ] && return 0
400f08c3bdfSopenharmony_ci	rc=$?
401f08c3bdfSopenharmony_ci	result=${result:-$rc}
402f08c3bdfSopenharmony_ci	tst_resm ${LIB_TEST_STATE} "Expected task ${task_pid} to be in state \"${expected_state}\""
403f08c3bdfSopenharmony_ci	return $rc
404f08c3bdfSopenharmony_ci}
405f08c3bdfSopenharmony_ci
406f08c3bdfSopenharmony_ci#
407f08c3bdfSopenharmony_ci# Check that the specified task is not in the specified state
408f08c3bdfSopenharmony_ci#
409f08c3bdfSopenharmony_cifunction assert_task_not_in_state()
410f08c3bdfSopenharmony_ci{
411f08c3bdfSopenharmony_ci	local task_pid=$1
412f08c3bdfSopenharmony_ci	local expected_state="$2"
413f08c3bdfSopenharmony_ci	local ps_state="$(get_task_state ${task_pid})"
414f08c3bdfSopenharmony_ci 	local rc=$?
415f08c3bdfSopenharmony_ci
416f08c3bdfSopenharmony_ci	[ $rc -eq 0 -a "$ps_state" != "${expected_state}" ] && return 0
417f08c3bdfSopenharmony_ci	rc=$?
418f08c3bdfSopenharmony_ci	result=${result:-$rc}
419f08c3bdfSopenharmony_ci	tst_resm ${LIB_TEST_STATE} "Expected task ${task_pid} to not be in state \"${expected_state}\""
420f08c3bdfSopenharmony_ci	return $rc
421f08c3bdfSopenharmony_ci}
422f08c3bdfSopenharmony_ci
423f08c3bdfSopenharmony_ci#
424f08c3bdfSopenharmony_ci# Frozen tasks are in the "D" state according to ps
425f08c3bdfSopenharmony_ci# tasks in "T" state may also be in a "frozen" state
426f08c3bdfSopenharmony_ci#
427f08c3bdfSopenharmony_cifunction assert_task_not_frozen()
428f08c3bdfSopenharmony_ci{
429f08c3bdfSopenharmony_ci	local task_pid=$1
430f08c3bdfSopenharmony_ci	local ps_state="$(ps -p $task_pid -o 'state=')"
431f08c3bdfSopenharmony_ci	local rc=$?
432f08c3bdfSopenharmony_ci
433f08c3bdfSopenharmony_ci	[ $rc -eq 0 -a "$ps_state" != "D" ] && return 0
434f08c3bdfSopenharmony_ci	rc=$?
435f08c3bdfSopenharmony_ci	result=${result:-$rc}
436f08c3bdfSopenharmony_ci	tst_resm ${LIB_TEST_STATE} "Expected task ${task_pid} is not frozen (unexpected task state: \"$ps_state\")"
437f08c3bdfSopenharmony_ci	return $rc
438f08c3bdfSopenharmony_ci}
439f08c3bdfSopenharmony_ci
440f08c3bdfSopenharmony_cifunction assert_task_is_frozen()
441f08c3bdfSopenharmony_ci{
442f08c3bdfSopenharmony_ci	local task_pid=$1
443f08c3bdfSopenharmony_ci	local ps_state="$(ps -p $task_pid -o 'state=')"
444f08c3bdfSopenharmony_ci	local rc=$?
445f08c3bdfSopenharmony_ci
446f08c3bdfSopenharmony_ci	[ $rc -eq 0 -a "$ps_state" == "D" -o "$ps_state" == "T" ] && return 0
447f08c3bdfSopenharmony_ci	rc=$?
448f08c3bdfSopenharmony_ci	result=${result:-$rc}
449f08c3bdfSopenharmony_ci	tst_resm ${LIB_TEST_STATE} "Expected task ${task_pid} to be frozen (unexpected task state: \"$ps_state\")"
450f08c3bdfSopenharmony_ci	return $rc
451f08c3bdfSopenharmony_ci}
452f08c3bdfSopenharmony_ci
453f08c3bdfSopenharmony_cifunction assert_sample_proc_not_frozen()
454f08c3bdfSopenharmony_ci{
455f08c3bdfSopenharmony_ci	assert_task_not_frozen $sample_proc
456f08c3bdfSopenharmony_ci	return $?
457f08c3bdfSopenharmony_ci}
458f08c3bdfSopenharmony_ci
459f08c3bdfSopenharmony_cifunction assert_sample_proc_is_frozen()
460f08c3bdfSopenharmony_ci{
461f08c3bdfSopenharmony_ci	assert_task_is_frozen $sample_proc
462f08c3bdfSopenharmony_ci	return $?
463f08c3bdfSopenharmony_ci}
464f08c3bdfSopenharmony_ci
465f08c3bdfSopenharmony_cifunction assert_sample_proc_stopped()
466f08c3bdfSopenharmony_ci{
467f08c3bdfSopenharmony_ci	assert_task_state $sample_proc 'T'
468f08c3bdfSopenharmony_ci	return $?
469f08c3bdfSopenharmony_ci}
470f08c3bdfSopenharmony_ci
471f08c3bdfSopenharmony_cifunction assert_sample_proc_not_stopped()
472f08c3bdfSopenharmony_ci{
473f08c3bdfSopenharmony_ci	assert_task_not_in_state $sample_proc 'T'
474f08c3bdfSopenharmony_ci	return $?
475f08c3bdfSopenharmony_ci}
476f08c3bdfSopenharmony_ci
477f08c3bdfSopenharmony_cifunction assert_sample_proc_sleeping()
478f08c3bdfSopenharmony_ci{
479f08c3bdfSopenharmony_ci	assert_task_state $sample_proc 'S'
480f08c3bdfSopenharmony_ci	return $?
481f08c3bdfSopenharmony_ci}
482f08c3bdfSopenharmony_ci
483f08c3bdfSopenharmony_cifunction assert_sample_proc_not_sleeping()
484f08c3bdfSopenharmony_ci{
485f08c3bdfSopenharmony_ci	assert_task_not_in_state $sample_proc 'S'
486f08c3bdfSopenharmony_ci	return $?
487f08c3bdfSopenharmony_ci}
488f08c3bdfSopenharmony_ci
489f08c3bdfSopenharmony_cifunction assert_cgroup_subsys_state_rwfile()
490f08c3bdfSopenharmony_ci{
491f08c3bdfSopenharmony_ci	if [ "${cgroup_subsys}" == "freezer" ]; then
492f08c3bdfSopenharmony_ci		assert_cgroup_rwfile "freezer.state" "freezer state"
493f08c3bdfSopenharmony_ci		return $?
494f08c3bdfSopenharmony_ci	elif [ "${cgroup_subsys}" == "freezer" ]; then
495f08c3bdfSopenharmony_ci		assert_cgroup_rwfile "signal.kill" "signal file"
496f08c3bdfSopenharmony_ci		return $?
497f08c3bdfSopenharmony_ci	else
498f08c3bdfSopenharmony_ci		return -1
499f08c3bdfSopenharmony_ci	fi
500f08c3bdfSopenharmony_ci}
501f08c3bdfSopenharmony_ci
502f08c3bdfSopenharmony_cifunction get_freezer_state()
503f08c3bdfSopenharmony_ci{
504f08c3bdfSopenharmony_ci	local state="$(cat freezer.state)"
505f08c3bdfSopenharmony_ci	local rc=$?
506f08c3bdfSopenharmony_ci
507f08c3bdfSopenharmony_ci	if [ $rc -ne 0 ]; then
508f08c3bdfSopenharmony_ci		result=${result:-$rc}
509f08c3bdfSopenharmony_ci		tst_resm ${LIB_TEST_STATE} "Failed to read freezer state."
510f08c3bdfSopenharmony_ci		return $rc
511f08c3bdfSopenharmony_ci	fi
512f08c3bdfSopenharmony_ci	echo "${state}"
513f08c3bdfSopenharmony_ci	return 0
514f08c3bdfSopenharmony_ci}
515f08c3bdfSopenharmony_ci
516f08c3bdfSopenharmony_cifunction assert_cgroup_freezer_state()
517f08c3bdfSopenharmony_ci{
518f08c3bdfSopenharmony_ci	local goal_state="$1"
519f08c3bdfSopenharmony_ci	local state="$(get_freezer_state)"
520f08c3bdfSopenharmony_ci	local rc=$?
521f08c3bdfSopenharmony_ci
522f08c3bdfSopenharmony_ci	[ $rc -eq 0 -a "${state}" == "${goal_state}" ] && return 0
523f08c3bdfSopenharmony_ci	rc=$?
524f08c3bdfSopenharmony_ci	result=${result:-$rc}
525f08c3bdfSopenharmony_ci	tst_resm ${LIB_TEST_STATE} "Expected freezer state \"$2\" but found freezer state: \"$state\""
526f08c3bdfSopenharmony_ci	return $rc
527f08c3bdfSopenharmony_ci}
528f08c3bdfSopenharmony_ci
529f08c3bdfSopenharmony_cifunction make_sample_cgroup_named()
530f08c3bdfSopenharmony_ci{
531f08c3bdfSopenharmony_ci	local name="$1"
532f08c3bdfSopenharmony_ci	local saved_dir="$(pwd)"
533f08c3bdfSopenharmony_ci	mkdir "${name}"
534f08c3bdfSopenharmony_ci	local rc=$?
535f08c3bdfSopenharmony_ci
536f08c3bdfSopenharmony_ci	# So long as we made the directory we don't care
537f08c3bdfSopenharmony_ci	if [ ! -d "${name}" -a $rc -ne 0 ]; then
538f08c3bdfSopenharmony_ci		# But if it doesn't exist report the exit status of mkdir
539f08c3bdfSopenharmony_ci		result=${result:-$rc}
540f08c3bdfSopenharmony_ci		return $rc
541f08c3bdfSopenharmony_ci	fi
542f08c3bdfSopenharmony_ci
543f08c3bdfSopenharmony_ci	cd "${name}" > /dev/null 2>&1
544f08c3bdfSopenharmony_ci
545f08c3bdfSopenharmony_ci	rc=$?
546f08c3bdfSopenharmony_ci	if [ $rc -ne 0 ]; then
547f08c3bdfSopenharmony_ci		result=${result:-$rc}
548f08c3bdfSopenharmony_ci		return $rc
549f08c3bdfSopenharmony_ci	fi
550f08c3bdfSopenharmony_ci
551f08c3bdfSopenharmony_ci	assert_cgroup_tasks_rwfile || {
552f08c3bdfSopenharmony_ci		cd "${saved_dir}"
553f08c3bdfSopenharmony_ci		return $?
554f08c3bdfSopenharmony_ci	}
555f08c3bdfSopenharmony_ci	assert_cgroup_tasks_empty || {
556f08c3bdfSopenharmony_ci		cd "${saved_dir}"
557f08c3bdfSopenharmony_ci		return $?
558f08c3bdfSopenharmony_ci	}
559f08c3bdfSopenharmony_ci	assert_cgroup_subsys_state_rwfile || {
560f08c3bdfSopenharmony_ci		cd "${saved_dir}"
561f08c3bdfSopenharmony_ci		return $?
562f08c3bdfSopenharmony_ci	}
563f08c3bdfSopenharmony_ci	cd "${saved_dir}"
564f08c3bdfSopenharmony_ci	return 0
565f08c3bdfSopenharmony_ci}
566f08c3bdfSopenharmony_ci
567f08c3bdfSopenharmony_cifunction make_sample_cgroup()
568f08c3bdfSopenharmony_ci{
569f08c3bdfSopenharmony_ci	make_sample_cgroup_named "child"
570f08c3bdfSopenharmony_ci	local rc=$?
571f08c3bdfSopenharmony_ci
572f08c3bdfSopenharmony_ci	# So long as we made the directory we don't care
573f08c3bdfSopenharmony_ci	if [ $rc -ne 0 ]; then
574f08c3bdfSopenharmony_ci		return $rc
575f08c3bdfSopenharmony_ci	fi
576f08c3bdfSopenharmony_ci
577f08c3bdfSopenharmony_ci	cd "child" # we know this will succeed since make_sample_cgroup_named
578f08c3bdfSopenharmony_ci		   # tested this
579f08c3bdfSopenharmony_ci	return 0
580f08c3bdfSopenharmony_ci}
581f08c3bdfSopenharmony_ci
582f08c3bdfSopenharmony_cifunction rm_sample_cgroup_named()
583f08c3bdfSopenharmony_ci{
584f08c3bdfSopenharmony_ci	local cgroup_name="$1"
585f08c3bdfSopenharmony_ci	local saved_dir="$(pwd)"
586f08c3bdfSopenharmony_ci	local rc=0
587f08c3bdfSopenharmony_ci
588f08c3bdfSopenharmony_ci	cd "${cgroup_name}" && {
589f08c3bdfSopenharmony_ci		assert_cgroup_tasks_rwfile || {
590f08c3bdfSopenharmony_ci			cd "${saved_dir}"
591f08c3bdfSopenharmony_ci			return $?
592f08c3bdfSopenharmony_ci		}
593f08c3bdfSopenharmony_ci		assert_cgroup_tasks_empty || {
594f08c3bdfSopenharmony_ci			cd "${saved_dir}"
595f08c3bdfSopenharmony_ci			return $?
596f08c3bdfSopenharmony_ci		}
597f08c3bdfSopenharmony_ci		assert_cgroup_subsys_state_rwfile || {
598f08c3bdfSopenharmony_ci			cd "${saved_dir}"
599f08c3bdfSopenharmony_ci			return $?
600f08c3bdfSopenharmony_ci		}
601f08c3bdfSopenharmony_ci		cd "${saved_dir}"
602f08c3bdfSopenharmony_ci	} || {
603f08c3bdfSopenharmony_ci		rc=$?
604f08c3bdfSopenharmony_ci		result=${result:-$rc}
605f08c3bdfSopenharmony_ci		return $rc
606f08c3bdfSopenharmony_ci	}
607f08c3bdfSopenharmony_ci
608f08c3bdfSopenharmony_ci	[ -d "${cgroup_name}" ] && rmdir "${cgroup_name}" && return 0
609f08c3bdfSopenharmony_ci	rc=$?
610f08c3bdfSopenharmony_ci	tst_resm TWARN "Failed to remove cgroup \"${cgroup_name}\""
611f08c3bdfSopenharmony_ci	result=${result:-$rc}
612f08c3bdfSopenharmony_ci	return $rc
613f08c3bdfSopenharmony_ci}
614f08c3bdfSopenharmony_ci
615f08c3bdfSopenharmony_cifunction rm_sample_cgroup()
616f08c3bdfSopenharmony_ci{
617f08c3bdfSopenharmony_ci	local cgroup_name="$(basename $(pwd))"
618f08c3bdfSopenharmony_ci	local rc=0
619f08c3bdfSopenharmony_ci
620f08c3bdfSopenharmony_ci	cd .. || {
621f08c3bdfSopenharmony_ci		rc=$?
622f08c3bdfSopenharmony_ci		result=${result:-$rc}
623f08c3bdfSopenharmony_ci		return $rc
624f08c3bdfSopenharmony_ci	}
625f08c3bdfSopenharmony_ci	rm_sample_cgroup_named "${cgroup_name}"
626f08c3bdfSopenharmony_ci	return $?
627f08c3bdfSopenharmony_ci}
628f08c3bdfSopenharmony_ci
629f08c3bdfSopenharmony_cifunction ls_pids()
630f08c3bdfSopenharmony_ci{
631f08c3bdfSopenharmony_ci	ps -e -o 'pid=' | sed -e 's/[[:space:]]\+//g'
632f08c3bdfSopenharmony_ci}
633f08c3bdfSopenharmony_ci
634f08c3bdfSopenharmony_cifunction assert_task_exists()
635f08c3bdfSopenharmony_ci{
636f08c3bdfSopenharmony_ci	local task_pid=$1
637f08c3bdfSopenharmony_ci
638f08c3bdfSopenharmony_ci	ls_pids | grep -E "^${task_pid}\$" > /dev/null 2>&1 && return 0
639f08c3bdfSopenharmony_ci	local rc=$?
640f08c3bdfSopenharmony_ci
641f08c3bdfSopenharmony_ci	result=${result:-$rc}
642f08c3bdfSopenharmony_ci	tst_resm ${LIB_TEST_STATE} "Expected pid ${task_pid} does not exist"
643f08c3bdfSopenharmony_ci	return $rc
644f08c3bdfSopenharmony_ci}
645f08c3bdfSopenharmony_ci
646f08c3bdfSopenharmony_cifunction assert_task_does_not_exist()
647f08c3bdfSopenharmony_ci{
648f08c3bdfSopenharmony_ci	local task_pid=$1
649f08c3bdfSopenharmony_ci
650f08c3bdfSopenharmony_ci	ls_pids | grep -E "^${task_pid}\$" > /dev/null 2>&1 || return 0
651f08c3bdfSopenharmony_ci	local rc=1 # $? == 0 is an error in this case
652f08c3bdfSopenharmony_ci
653f08c3bdfSopenharmony_ci	result=${result:-$rc}
654f08c3bdfSopenharmony_ci	tst_resm ${LIB_TEST_STATE} "Did not expect pid ${task_pid} to exist"
655f08c3bdfSopenharmony_ci	return $rc
656f08c3bdfSopenharmony_ci}
657f08c3bdfSopenharmony_ci
658f08c3bdfSopenharmony_cifunction assert_sample_proc_exists()
659f08c3bdfSopenharmony_ci{
660f08c3bdfSopenharmony_ci	assert_task_exists $sample_proc
661f08c3bdfSopenharmony_ci	return $?
662f08c3bdfSopenharmony_ci}
663f08c3bdfSopenharmony_ci
664f08c3bdfSopenharmony_cifunction assert_sample_proc_does_not_exist()
665f08c3bdfSopenharmony_ci{
666f08c3bdfSopenharmony_ci	assert_task_does_not_exist $sample_proc
667f08c3bdfSopenharmony_ci	return $rc
668f08c3bdfSopenharmony_ci}
669f08c3bdfSopenharmony_ci
670f08c3bdfSopenharmony_cifunction start_sample_proc()
671f08c3bdfSopenharmony_ci{
672f08c3bdfSopenharmony_ci	local sample_cmd="/bin/sleep"
673f08c3bdfSopenharmony_ci	local args
674f08c3bdfSopenharmony_ci
675f08c3bdfSopenharmony_ci	args=( $sample_sleep ) # can't assign directly because of bash v2/v3 inconsistency
676f08c3bdfSopenharmony_ci	if [ $# -gt 0 ]; then
677f08c3bdfSopenharmony_ci		sample_cmd="$1"
678f08c3bdfSopenharmony_ci		shift 1
679f08c3bdfSopenharmony_ci		args=( "$@" )
680f08c3bdfSopenharmony_ci	fi
681f08c3bdfSopenharmony_ci
682f08c3bdfSopenharmony_ci	[ -n "$sample_proc" ] && assert_sample_proc_does_not_exist
683f08c3bdfSopenharmony_ci
684f08c3bdfSopenharmony_ci	"$sample_cmd" "${args[@]}" &
685f08c3bdfSopenharmony_ci	local rc=$?
686f08c3bdfSopenharmony_ci	export sample_proc=$!
687f08c3bdfSopenharmony_ci	assert_sample_proc_exists
688f08c3bdfSopenharmony_ci
689f08c3bdfSopenharmony_ci	return $rc
690f08c3bdfSopenharmony_ci}
691f08c3bdfSopenharmony_ci
692f08c3bdfSopenharmony_cifunction add_sample_proc_to_named_cgroup()
693f08c3bdfSopenharmony_ci{
694f08c3bdfSopenharmony_ci	local cgroup_name="$1"
695f08c3bdfSopenharmony_ci
696f08c3bdfSopenharmony_ci	assert_sample_proc_exists
697f08c3bdfSopenharmony_ci	"${CG_FILE_WRITE}" $sample_proc > "${cgroup_name}/tasks"
698f08c3bdfSopenharmony_ci	local rc=$?
699f08c3bdfSopenharmony_ci	if [ $rc -ne 0 ]; then
700f08c3bdfSopenharmony_ci		result=${result:-$rc}
701f08c3bdfSopenharmony_ci		tst_resm ${LIB_TEST_STATE} "Failed to add sample process $sample_proc to cgroup \"${cgroup_name}\""
702f08c3bdfSopenharmony_ci		return $rc
703f08c3bdfSopenharmony_ci	fi
704f08c3bdfSopenharmony_ci	assert_task_in_named_cgroup $sample_proc "${cgroup_name}"
705f08c3bdfSopenharmony_ci	return $?
706f08c3bdfSopenharmony_ci}
707f08c3bdfSopenharmony_ci
708f08c3bdfSopenharmony_cifunction add_sample_proc_to_cgroup()
709f08c3bdfSopenharmony_ci{
710f08c3bdfSopenharmony_ci	add_sample_proc_to_named_cgroup "$(pwd)"
711f08c3bdfSopenharmony_ci	return $?
712f08c3bdfSopenharmony_ci}
713f08c3bdfSopenharmony_ci
714f08c3bdfSopenharmony_cifunction kill_sample_proc()
715f08c3bdfSopenharmony_ci{
716f08c3bdfSopenharmony_ci	if [ -z "$sample_proc" ]; then
717f08c3bdfSopenharmony_ci		# It's no longer running or never started.
718f08c3bdfSopenharmony_ci		# If it was supposed to have started but did not then that
719f08c3bdfSopenharmony_ci		# should be determined by checking start_sample_proc results.
720f08c3bdfSopenharmony_ci		return 0
721f08c3bdfSopenharmony_ci	fi
722f08c3bdfSopenharmony_ci
723f08c3bdfSopenharmony_ci	# Hey, bash, don't print out any of your messy job status notices
724f08c3bdfSopenharmony_ci	disown -a
725f08c3bdfSopenharmony_ci
726f08c3bdfSopenharmony_ci	if [ "$(get_task_state $sample_proc)" == "D" ]; then
727f08c3bdfSopenharmony_ci		tst_resm TWARN "sample process is frozen stiff"
728f08c3bdfSopenharmony_ci		kill $sample_proc
729f08c3bdfSopenharmony_ci		local rc=$?
730f08c3bdfSopenharmony_ci		result=${result:-$rc}
731f08c3bdfSopenharmony_ci		return $rc
732f08c3bdfSopenharmony_ci	fi
733f08c3bdfSopenharmony_ci
734f08c3bdfSopenharmony_ci	# kill child processes of the sample process
735f08c3bdfSopenharmony_ci	while pgrep -P $sample_proc ; do
736f08c3bdfSopenharmony_ci		pkill -SIGTERM -P $sample_proc
737f08c3bdfSopenharmony_ci		sleep 1
738f08c3bdfSopenharmony_ci		pkill -SIGKILL -P $sample_proc
739f08c3bdfSopenharmony_ci
740f08c3bdfSopenharmony_ci		ps -p $(pgrep -P $sample_proc) -o 'state=' | grep -v D && continue
741f08c3bdfSopenharmony_ci		# Give up if all the child processes are frozen in D state or
742f08c3bdfSopenharmony_ci		# if there aren't any more child processes
743f08c3bdfSopenharmony_ci		break
744f08c3bdfSopenharmony_ci	done
745f08c3bdfSopenharmony_ci	# DEBUG dump pstree under $sample_proc:
746f08c3bdfSopenharmony_ci	# pstree -A -p $sample_proc
747f08c3bdfSopenharmony_ci	kill $sample_proc > /dev/null 2>&1 || kill -s SIGKILL $sample_proc > /dev/null 2>&1 || {
748f08c3bdfSopenharmony_ci		local rc=$?
749f08c3bdfSopenharmony_ci
750f08c3bdfSopenharmony_ci		ps -p $sample_proc -o 'state=' > /dev/null 2>&1
751f08c3bdfSopenharmony_ci		if [ $? -eq 1 ]; then
752f08c3bdfSopenharmony_ci			# It's dead. We're OK.
753f08c3bdfSopenharmony_ci			return 0
754f08c3bdfSopenharmony_ci		fi
755f08c3bdfSopenharmony_ci		# It's still alive somehow! Give up.
756f08c3bdfSopenharmony_ci		result=${result:-$rc}
757f08c3bdfSopenharmony_ci		tst_resm TWARN "Failed to kill sample process $sample_proc (kill exit status: $rc)"
758f08c3bdfSopenharmony_ci	}
759f08c3bdfSopenharmony_ci	assert_sample_proc_not_in_cgroup
760f08c3bdfSopenharmony_ci	assert_sample_proc_does_not_exist
761f08c3bdfSopenharmony_ci	return $?
762f08c3bdfSopenharmony_ci}
763f08c3bdfSopenharmony_ci
764f08c3bdfSopenharmony_cifunction issue_freeze_cmd()
765f08c3bdfSopenharmony_ci{
766f08c3bdfSopenharmony_ci	local goal_state="FROZEN"
767f08c3bdfSopenharmony_ci	local sample_state_count=1
768f08c3bdfSopenharmony_ci	local state="$(get_freezer_state)"
769f08c3bdfSopenharmony_ci	local rc=$?
770f08c3bdfSopenharmony_ci
771f08c3bdfSopenharmony_ci	if [ $rc -ne 0 ]; then
772f08c3bdfSopenharmony_ci		return $rc
773f08c3bdfSopenharmony_ci	fi
774f08c3bdfSopenharmony_ci
775f08c3bdfSopenharmony_ci	while [ "${state}" != "${goal_state}" ]; do
776f08c3bdfSopenharmony_ci		"${CG_FILE_WRITE}" "${FREEZE}" > freezer.state
777f08c3bdfSopenharmony_ci		sleep $sample_state_period
778f08c3bdfSopenharmony_ci		state="$(get_freezer_state)"
779f08c3bdfSopenharmony_ci		rc=$?
780f08c3bdfSopenharmony_ci		if [ $rc -ne 0 ]; then
781f08c3bdfSopenharmony_ci			break
782f08c3bdfSopenharmony_ci		fi
783f08c3bdfSopenharmony_ci
784f08c3bdfSopenharmony_ci		((sample_state_count++))
785f08c3bdfSopenharmony_ci		if [ "$sample_state_count" -ge "$max_state_samples" ]; then
786f08c3bdfSopenharmony_ci			break
787f08c3bdfSopenharmony_ci		fi
788f08c3bdfSopenharmony_ci	done
789f08c3bdfSopenharmony_ci
790f08c3bdfSopenharmony_ci	if [ "${state}" == "${goal_state}" ]; then
791f08c3bdfSopenharmony_ci		return 0
792f08c3bdfSopenharmony_ci	fi
793f08c3bdfSopenharmony_ci
794f08c3bdfSopenharmony_ci	result=${result:-$rc}
795f08c3bdfSopenharmony_ci	tst_resm ${LIB_TEST_STATE} "Failed to issue freeze command (freezer state: \"`get_freezer_state`\")."
796f08c3bdfSopenharmony_ci	return $rc
797f08c3bdfSopenharmony_ci}
798f08c3bdfSopenharmony_ci
799f08c3bdfSopenharmony_ci# If we're trying to "freeze" tasks with SIGTOP
800f08c3bdfSopenharmony_cifunction issue_stop_as_freeze_cmd()
801f08c3bdfSopenharmony_ci{
802f08c3bdfSopenharmony_ci	local goal_state="T"
803f08c3bdfSopenharmony_ci	local sample_state_count=1
804f08c3bdfSopenharmony_ci	local ps_state="$(get_task_state ${task_pid})"
805f08c3bdfSopenharmony_ci	local rc=$?
806f08c3bdfSopenharmony_ci
807f08c3bdfSopenharmony_ci	if [ $rc -ne 0 ]; then
808f08c3bdfSopenharmony_ci		return $rc
809f08c3bdfSopenharmony_ci	fi
810f08c3bdfSopenharmony_ci
811f08c3bdfSopenharmony_ci	while [ "${ps_state}" != "${goal_state}" ]; do
812f08c3bdfSopenharmony_ci		kill -s SIGSTOP $sample_proc
813f08c3bdfSopenharmony_ci		sleep $sample_state_period
814f08c3bdfSopenharmony_ci		ps_state="$(get_task_state ${task_pid})"
815f08c3bdfSopenharmony_ci		rc=$?
816f08c3bdfSopenharmony_ci		if [ $rc -ne 0 ]; then
817f08c3bdfSopenharmony_ci			break
818f08c3bdfSopenharmony_ci		fi
819f08c3bdfSopenharmony_ci
820f08c3bdfSopenharmony_ci		((sample_state_count++))
821f08c3bdfSopenharmony_ci		if [ "$sample_state_count" -ge "$max_state_samples" ]; then
822f08c3bdfSopenharmony_ci			break
823f08c3bdfSopenharmony_ci		fi
824f08c3bdfSopenharmony_ci	done
825f08c3bdfSopenharmony_ci
826f08c3bdfSopenharmony_ci	if [ "${ps_state}" == "${goal_state}" ]; then
827f08c3bdfSopenharmony_ci		return 0
828f08c3bdfSopenharmony_ci	fi
829f08c3bdfSopenharmony_ci
830f08c3bdfSopenharmony_ci	result=${result:-$rc}
831f08c3bdfSopenharmony_ci	tst_resm ${LIB_TEST_STATE} "Failed to issue stop (freeze) command (task state: \"${ps_state}\")."
832f08c3bdfSopenharmony_ci	return $rc
833f08c3bdfSopenharmony_ci}
834f08c3bdfSopenharmony_ci
835f08c3bdfSopenharmony_cifunction send_signal()
836f08c3bdfSopenharmony_ci{
837f08c3bdfSopenharmony_ci	"${CG_FILE_WRITE}" $1 > 'signal.kill' && return 0
838f08c3bdfSopenharmony_ci	local rc=$?
839f08c3bdfSopenharmony_ci	result=${result:-$rc}
840f08c3bdfSopenharmony_ci	tst_resm ${LIB_TEST_STATE} "Failed to send signal: $1 to tasks in cgroup (rc: $rc)"
841f08c3bdfSopenharmony_ci 	return $rc
842f08c3bdfSopenharmony_ci}
843f08c3bdfSopenharmony_ci
844f08c3bdfSopenharmony_cifunction wait_until_goal_state_or_timeout()
845f08c3bdfSopenharmony_ci{
846f08c3bdfSopenharmony_ci	local goal_state="$1"
847f08c3bdfSopenharmony_ci	local sample_state_count=1
848f08c3bdfSopenharmony_ci	local state="$(get_freezer_state)"
849f08c3bdfSopenharmony_ci	local rc=$?
850f08c3bdfSopenharmony_ci
851f08c3bdfSopenharmony_ci	if [ $rc -ne 0 ]; then
852f08c3bdfSopenharmony_ci		return $rc
853f08c3bdfSopenharmony_ci	fi
854f08c3bdfSopenharmony_ci
855f08c3bdfSopenharmony_ci	while [ "${state}" != "${goal_state}" ]; do
856f08c3bdfSopenharmony_ci		sleep $sample_state_period
857f08c3bdfSopenharmony_ci		state="$(get_freezer_state)"
858f08c3bdfSopenharmony_ci		rc=$?
859f08c3bdfSopenharmony_ci		if [ $rc -ne 0 ]; then
860f08c3bdfSopenharmony_ci			break
861f08c3bdfSopenharmony_ci		fi
862f08c3bdfSopenharmony_ci
863f08c3bdfSopenharmony_ci		((sample_state_count++))
864f08c3bdfSopenharmony_ci		if [ "$sample_state_count" -ge "$max_state_samples" ]; then
865f08c3bdfSopenharmony_ci			break
866f08c3bdfSopenharmony_ci		fi
867f08c3bdfSopenharmony_ci	done
868f08c3bdfSopenharmony_ci	return $rc
869f08c3bdfSopenharmony_ci}
870f08c3bdfSopenharmony_ci
871f08c3bdfSopenharmony_ci# TODO convert signal scripts -- insert task between until and goal
872f08c3bdfSopenharmony_cifunction wait_until_sample_proc_goal_state_or_timeout()
873f08c3bdfSopenharmony_ci{
874f08c3bdfSopenharmony_ci	local goal_state="$1"
875f08c3bdfSopenharmony_ci	local sample_state_count=1
876f08c3bdfSopenharmony_ci	local ps_state="$(get_task_state ${sample_proc})"
877f08c3bdfSopenharmony_ci	local rc=$?
878f08c3bdfSopenharmony_ci
879f08c3bdfSopenharmony_ci	while [ $rc -eq 0 -a "${ps_state}" != "${goal_state}" -a \
880f08c3bdfSopenharmony_ci		"$sample_state_count" -lt "$max_state_samples" ]; do
881f08c3bdfSopenharmony_ci		sleep $sample_state_period
882f08c3bdfSopenharmony_ci		ps_state="$(get_task_state ${sample_proc})"
883f08c3bdfSopenharmony_ci		rc=$?
884f08c3bdfSopenharmony_ci		if [ $rc -ne 0 ]; then
885f08c3bdfSopenharmony_ci			result=${result:-$rc}
886f08c3bdfSopenharmony_ci			tst_resm ${LIB_TEST_STATE} "Failed to read process state."
887f08c3bdfSopenharmony_ci			break
888f08c3bdfSopenharmony_ci		fi
889f08c3bdfSopenharmony_ci
890f08c3bdfSopenharmony_ci		((sample_state_count++))
891f08c3bdfSopenharmony_ci	done
892f08c3bdfSopenharmony_ci	return $rc
893f08c3bdfSopenharmony_ci}
894f08c3bdfSopenharmony_ci
895f08c3bdfSopenharmony_ci# TODO convert signal scripts -- insert task between until and not
896f08c3bdfSopenharmony_cifunction wait_until_sample_proc_not_goal_state_or_timeout()
897f08c3bdfSopenharmony_ci{
898f08c3bdfSopenharmony_ci	local goal_state="$1"
899f08c3bdfSopenharmony_ci	local sample_state_count=1
900f08c3bdfSopenharmony_ci	local ps_state="$(get_task_state ${sample_proc})"
901f08c3bdfSopenharmony_ci	local rc=$?
902f08c3bdfSopenharmony_ci
903f08c3bdfSopenharmony_ci	while [ $rc -eq 0 -a "${ps_state}" == "${goal_state}" -a \
904f08c3bdfSopenharmony_ci		"$sample_state_count" -lt "$max_state_samples" ]; do
905f08c3bdfSopenharmony_ci		sleep $sample_state_period
906f08c3bdfSopenharmony_ci		ps_state="$(get_task_state ${sample_proc})"
907f08c3bdfSopenharmony_ci		rc=$?
908f08c3bdfSopenharmony_ci		if [ $rc -ne 0 ]; then
909f08c3bdfSopenharmony_ci			result=${result:-$rc}
910f08c3bdfSopenharmony_ci			tst_resm ${LIB_TEST_STATE} "Failed to read process state."
911f08c3bdfSopenharmony_ci			break
912f08c3bdfSopenharmony_ci		fi
913f08c3bdfSopenharmony_ci
914f08c3bdfSopenharmony_ci		((sample_state_count++))
915f08c3bdfSopenharmony_ci	done
916f08c3bdfSopenharmony_ci	return $rc
917f08c3bdfSopenharmony_ci}
918f08c3bdfSopenharmony_ci
919f08c3bdfSopenharmony_cifunction wait_until_frozen()
920f08c3bdfSopenharmony_ci{
921f08c3bdfSopenharmony_ci	wait_until_goal_state_or_timeout "FROZEN" || return $?
922f08c3bdfSopenharmony_ci	assert_cgroup_freezer_state "FROZEN" "ERROR: failed to freeze cgroup"
923f08c3bdfSopenharmony_ci	# TODO assert all tasks in cgroup are in 'D' or 'T' state
924f08c3bdfSopenharmony_ci	# TODO assert that trying to add a task to cgroup results in EBUSY
925f08c3bdfSopenharmony_ci	return $?
926f08c3bdfSopenharmony_ci}
927f08c3bdfSopenharmony_ci
928f08c3bdfSopenharmony_cifunction issue_thaw_cmd()
929f08c3bdfSopenharmony_ci{
930f08c3bdfSopenharmony_ci	"${CG_FILE_WRITE}" "${THAW}" > freezer.state && return 0
931f08c3bdfSopenharmony_ci	local rc=$?
932f08c3bdfSopenharmony_ci	result=${result:-$rc}
933f08c3bdfSopenharmony_ci	tst_resm ${LIB_TEST_STATE} "Failed to issue thaw command."
934f08c3bdfSopenharmony_ci	return $rc
935f08c3bdfSopenharmony_ci}
936f08c3bdfSopenharmony_ci
937f08c3bdfSopenharmony_cifunction issue_cont_as_thaw_cmd()
938f08c3bdfSopenharmony_ci{
939f08c3bdfSopenharmony_ci	local goal_state="T"
940f08c3bdfSopenharmony_ci	local sample_state_count=1
941f08c3bdfSopenharmony_ci	local ps_state="$(get_task_state ${task_pid})"
942f08c3bdfSopenharmony_ci	local rc=$?
943f08c3bdfSopenharmony_ci
944f08c3bdfSopenharmony_ci	if [ $rc -ne 0 ]; then
945f08c3bdfSopenharmony_ci		return $rc
946f08c3bdfSopenharmony_ci	fi
947f08c3bdfSopenharmony_ci
948f08c3bdfSopenharmony_ci	while [ "${ps_state}" == "${goal_state}" ]; do
949f08c3bdfSopenharmony_ci		kill -s SIGCONT $sample_proc
950f08c3bdfSopenharmony_ci		sleep $sample_state_period
951f08c3bdfSopenharmony_ci		ps_state="$(get_task_state ${task_pid})"
952f08c3bdfSopenharmony_ci		rc=$?
953f08c3bdfSopenharmony_ci		if [ $rc -ne 0 ]; then
954f08c3bdfSopenharmony_ci			break
955f08c3bdfSopenharmony_ci		fi
956f08c3bdfSopenharmony_ci
957f08c3bdfSopenharmony_ci		((sample_state_count++))
958f08c3bdfSopenharmony_ci		if [ "$sample_state_count" -ge "$max_state_samples" ]; then
959f08c3bdfSopenharmony_ci			break
960f08c3bdfSopenharmony_ci		fi
961f08c3bdfSopenharmony_ci	done
962f08c3bdfSopenharmony_ci
963f08c3bdfSopenharmony_ci	if [ "${ps_state}" != "${goal_state}" ]; then
964f08c3bdfSopenharmony_ci		return 0
965f08c3bdfSopenharmony_ci	fi
966f08c3bdfSopenharmony_ci
967f08c3bdfSopenharmony_ci	result=${result:-$rc}
968f08c3bdfSopenharmony_ci	tst_resm ${LIB_TEST_STATE} "Failed to issue continue (thaw) command (task state: \"${ps_state}\")."
969f08c3bdfSopenharmony_ci	return $rc
970f08c3bdfSopenharmony_ci}
971f08c3bdfSopenharmony_ci
972f08c3bdfSopenharmony_cifunction wait_until_thawed()
973f08c3bdfSopenharmony_ci{
974f08c3bdfSopenharmony_ci	wait_until_goal_state_or_timeout "THAWED" || return $?
975f08c3bdfSopenharmony_ci	assert_cgroup_freezer_state "THAWED" "ERROR: Failed to thaw cgroup."
976f08c3bdfSopenharmony_ci	return $?
977f08c3bdfSopenharmony_ci}
978f08c3bdfSopenharmony_ci
979f08c3bdfSopenharmony_cifunction wait_until_freezing()
980f08c3bdfSopenharmony_ci{
981f08c3bdfSopenharmony_ci	wait_until_goal_state_or_timeout "FREEZING"
982f08c3bdfSopenharmony_ci	# Time critical -- we race with the kernel as it freezes tasks in the
983f08c3bdfSopenharmony_ci	# cgroup. So rather than assert "FREEZING" we just return
984f08c3bdfSopenharmony_ci	return $?
985f08c3bdfSopenharmony_ci}
986f08c3bdfSopenharmony_ci
987f08c3bdfSopenharmony_cifunction wait_until_sample_proc_stopped()
988f08c3bdfSopenharmony_ci{
989f08c3bdfSopenharmony_ci	wait_until_sample_proc_state_or_timeout 'T' || return $?
990f08c3bdfSopenharmony_ci	assert_sample_proc_stopped
991f08c3bdfSopenharmony_ci	return $?
992f08c3bdfSopenharmony_ci}
993f08c3bdfSopenharmony_ci
994f08c3bdfSopenharmony_cifunction wait_until_sample_proc_not_stopped()
995f08c3bdfSopenharmony_ci{
996f08c3bdfSopenharmony_ci	wait_until_sample_proc_not_goal_state_or_timeout 'T' || return $?
997f08c3bdfSopenharmony_ci	assert_sample_proc_not_stopped
998f08c3bdfSopenharmony_ci	return $?
999f08c3bdfSopenharmony_ci}
1000