xref: /linux/tools/testing/selftests/net/lib/sh/defer.sh (revision fcc79e1714e8c2b8e216dc3149812edd37884eef)
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4# map[(scope_id,track,cleanup_id) -> cleanup_command]
5# track={d=default | p=priority}
6declare -A __DEFER__JOBS
7
8# map[(scope_id,track) -> # cleanup_commands]
9declare -A __DEFER__NJOBS
10
11# scope_id of the topmost scope.
12__DEFER__SCOPE_ID=0
13
14__defer__ndefer_key()
15{
16	local track=$1; shift
17
18	echo $__DEFER__SCOPE_ID,$track
19}
20
21__defer__defer_key()
22{
23	local track=$1; shift
24	local defer_ix=$1; shift
25
26	echo $__DEFER__SCOPE_ID,$track,$defer_ix
27}
28
29__defer__ndefers()
30{
31	local track=$1; shift
32
33	echo ${__DEFER__NJOBS[$(__defer__ndefer_key $track)]}
34}
35
36__defer__run()
37{
38	local track=$1; shift
39	local defer_ix=$1; shift
40	local defer_key=$(__defer__defer_key $track $defer_ix)
41
42	${__DEFER__JOBS[$defer_key]}
43	unset __DEFER__JOBS[$defer_key]
44}
45
46__defer__schedule()
47{
48	local track=$1; shift
49	local ndefers=$(__defer__ndefers $track)
50	local ndefers_key=$(__defer__ndefer_key $track)
51	local defer_key=$(__defer__defer_key $track $ndefers)
52	local defer="$@"
53
54	__DEFER__JOBS[$defer_key]="$defer"
55	__DEFER__NJOBS[$ndefers_key]=$((ndefers + 1))
56}
57
58__defer__scope_wipe()
59{
60	__DEFER__NJOBS[$(__defer__ndefer_key d)]=0
61	__DEFER__NJOBS[$(__defer__ndefer_key p)]=0
62}
63
64defer_scope_push()
65{
66	((__DEFER__SCOPE_ID++))
67	__defer__scope_wipe
68}
69
70defer_scope_pop()
71{
72	local defer_ix
73
74	for ((defer_ix=$(__defer__ndefers p); defer_ix-->0; )); do
75		__defer__run p $defer_ix
76	done
77
78	for ((defer_ix=$(__defer__ndefers d); defer_ix-->0; )); do
79		__defer__run d $defer_ix
80	done
81
82	__defer__scope_wipe
83	((__DEFER__SCOPE_ID--))
84}
85
86defer()
87{
88	__defer__schedule d "$@"
89}
90
91defer_prio()
92{
93	__defer__schedule p "$@"
94}
95
96defer_scopes_cleanup()
97{
98	while ((__DEFER__SCOPE_ID >= 0)); do
99		defer_scope_pop
100	done
101}
102
103in_defer_scope()
104{
105	local ret
106
107	defer_scope_push
108	"$@"
109	ret=$?
110	defer_scope_pop
111
112	return $ret
113}
114
115__defer__scope_wipe
116