1/*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2018 John H. Baldwin <jhb@FreeBSD.org>
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28#include <atf-c.h>
29#include <ucontext.h>
30
31static char uc_stack[16 * 1024];
32
33static void
34check_1(int arg1)
35{
36
37	ATF_REQUIRE_EQ(arg1, 1);
38}
39
40ATF_TC_WITHOUT_HEAD(makecontext_arg1);
41ATF_TC_BODY(makecontext_arg1, tc)
42{
43	ucontext_t ctx[2];
44
45	ATF_REQUIRE_EQ(getcontext(&ctx[1]), 0);
46	ctx[1].uc_stack.ss_sp = uc_stack;
47	ctx[1].uc_stack.ss_size = sizeof(uc_stack);
48	ctx[1].uc_link = &ctx[0];
49	makecontext(&ctx[1], (void (*)(void))check_1, 1, 1);
50
51	ATF_REQUIRE_EQ(swapcontext(&ctx[0], &ctx[1]), 0);
52}
53
54static void
55check_2(int arg1, int arg2)
56{
57
58	ATF_REQUIRE_EQ(arg1, 1);
59	ATF_REQUIRE_EQ(arg2, 2);
60}
61
62ATF_TC_WITHOUT_HEAD(makecontext_arg2);
63ATF_TC_BODY(makecontext_arg2, tc)
64{
65	ucontext_t ctx[2];
66
67	ATF_REQUIRE_EQ(getcontext(&ctx[1]), 0);
68	ctx[1].uc_stack.ss_sp = uc_stack;
69	ctx[1].uc_stack.ss_size = sizeof(uc_stack);
70	ctx[1].uc_link = &ctx[0];
71	makecontext(&ctx[1], (void (*)(void))check_2, 2, 1, 2);
72
73	ATF_REQUIRE_EQ(swapcontext(&ctx[0], &ctx[1]), 0);
74}
75
76static void
77check_3(int arg1, int arg2, int arg3)
78{
79
80	ATF_REQUIRE_EQ(arg1, 1);
81	ATF_REQUIRE_EQ(arg2, 2);
82	ATF_REQUIRE_EQ(arg3, 3);
83}
84
85ATF_TC_WITHOUT_HEAD(makecontext_arg3);
86ATF_TC_BODY(makecontext_arg3, tc)
87{
88	ucontext_t ctx[2];
89
90	ATF_REQUIRE_EQ(getcontext(&ctx[1]), 0);
91	ctx[1].uc_stack.ss_sp = uc_stack;
92	ctx[1].uc_stack.ss_size = sizeof(uc_stack);
93	ctx[1].uc_link = &ctx[0];
94	makecontext(&ctx[1], (void (*)(void))check_3, 3, 1, 2, 3);
95
96	ATF_REQUIRE_EQ(swapcontext(&ctx[0], &ctx[1]), 0);
97}
98
99static void
100check_4(int arg1, int arg2, int arg3, int arg4)
101{
102
103	ATF_REQUIRE_EQ(arg1, 1);
104	ATF_REQUIRE_EQ(arg2, 2);
105	ATF_REQUIRE_EQ(arg3, 3);
106	ATF_REQUIRE_EQ(arg4, 4);
107}
108
109ATF_TC_WITHOUT_HEAD(makecontext_arg4);
110ATF_TC_BODY(makecontext_arg4, tc)
111{
112	ucontext_t ctx[2];
113
114	ATF_REQUIRE_EQ(getcontext(&ctx[1]), 0);
115	ctx[1].uc_stack.ss_sp = uc_stack;
116	ctx[1].uc_stack.ss_size = sizeof(uc_stack);
117	ctx[1].uc_link = &ctx[0];
118	makecontext(&ctx[1], (void (*)(void))check_4, 4, 1, 2, 3, 4);
119
120	ATF_REQUIRE_EQ(swapcontext(&ctx[0], &ctx[1]), 0);
121}
122
123static void
124check_5(int arg1, int arg2, int arg3, int arg4, int arg5)
125{
126
127	ATF_REQUIRE_EQ(arg1, 1);
128	ATF_REQUIRE_EQ(arg2, 2);
129	ATF_REQUIRE_EQ(arg3, 3);
130	ATF_REQUIRE_EQ(arg4, 4);
131	ATF_REQUIRE_EQ(arg5, 5);
132}
133
134ATF_TC_WITHOUT_HEAD(makecontext_arg5);
135ATF_TC_BODY(makecontext_arg5, tc)
136{
137	ucontext_t ctx[2];
138
139	ATF_REQUIRE_EQ(getcontext(&ctx[1]), 0);
140	ctx[1].uc_stack.ss_sp = uc_stack;
141	ctx[1].uc_stack.ss_size = sizeof(uc_stack);
142	ctx[1].uc_link = &ctx[0];
143	makecontext(&ctx[1], (void (*)(void))check_5, 5, 1, 2, 3, 4, 5);
144
145	ATF_REQUIRE_EQ(swapcontext(&ctx[0], &ctx[1]), 0);
146}
147
148static void
149check_6(int arg1, int arg2, int arg3, int arg4, int arg5, int arg6)
150{
151
152	ATF_REQUIRE_EQ(arg1, 1);
153	ATF_REQUIRE_EQ(arg2, 2);
154	ATF_REQUIRE_EQ(arg3, 3);
155	ATF_REQUIRE_EQ(arg4, 4);
156	ATF_REQUIRE_EQ(arg5, 5);
157	ATF_REQUIRE_EQ(arg6, 6);
158}
159
160ATF_TC_WITHOUT_HEAD(makecontext_arg6);
161ATF_TC_BODY(makecontext_arg6, tc)
162{
163	ucontext_t ctx[2];
164
165	ATF_REQUIRE_EQ(getcontext(&ctx[1]), 0);
166	ctx[1].uc_stack.ss_sp = uc_stack;
167	ctx[1].uc_stack.ss_size = sizeof(uc_stack);
168	ctx[1].uc_link = &ctx[0];
169	makecontext(&ctx[1], (void (*)(void))check_6, 6, 1, 2, 3, 4, 5, 6);
170
171	ATF_REQUIRE_EQ(swapcontext(&ctx[0], &ctx[1]), 0);
172}
173
174ATF_TP_ADD_TCS(tp)
175{
176
177	ATF_TP_ADD_TC(tp, makecontext_arg1);
178	ATF_TP_ADD_TC(tp, makecontext_arg2);
179	ATF_TP_ADD_TC(tp, makecontext_arg3);
180	ATF_TP_ADD_TC(tp, makecontext_arg4);
181	ATF_TP_ADD_TC(tp, makecontext_arg5);
182	ATF_TP_ADD_TC(tp, makecontext_arg6);
183
184	return (atf_no_error());
185}
186