1272343Sngie/*	$NetBSD: t_nice.c,v 1.8 2012/03/18 07:00:51 jruoho Exp $ */
2272343Sngie
3272343Sngie/*-
4272343Sngie * Copyright (c) 2011 The NetBSD Foundation, Inc.
5272343Sngie * All rights reserved.
6272343Sngie *
7272343Sngie * This code is derived from software contributed to The NetBSD Foundation
8272343Sngie * by Jukka Ruohonen.
9272343Sngie *
10272343Sngie * Redistribution and use in source and binary forms, with or without
11272343Sngie * modification, are permitted provided that the following conditions
12272343Sngie * are met:
13272343Sngie * 1. Redistributions of source code must retain the above copyright
14272343Sngie *    notice, this list of conditions and the following disclaimer.
15272343Sngie * 2. Redistributions in binary form must reproduce the above copyright
16272343Sngie *    notice, this list of conditions and the following disclaimer in the
17272343Sngie *    documentation and/or other materials provided with the distribution.
18272343Sngie *
19272343Sngie * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20272343Sngie * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21272343Sngie * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22272343Sngie * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23272343Sngie * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24272343Sngie * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25272343Sngie * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26272343Sngie * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27272343Sngie * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28272343Sngie * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29272343Sngie * POSSIBILITY OF SUCH DAMAGE.
30272343Sngie */
31272343Sngie#include <sys/cdefs.h>
32272343Sngie__RCSID("$NetBSD: t_nice.c,v 1.8 2012/03/18 07:00:51 jruoho Exp $");
33272343Sngie
34272343Sngie#include <sys/resource.h>
35272343Sngie#include <sys/wait.h>
36272343Sngie
37272343Sngie#include <atf-c.h>
38272343Sngie#include <errno.h>
39272343Sngie#include <limits.h>
40272343Sngie#include <pthread.h>
41272343Sngie#include <stdlib.h>
42272343Sngie#include <unistd.h>
43272343Sngie
44272343Sngiestatic void	*threadfunc(void *);
45272343Sngie
46272343Sngiestatic void *
47272343Sngiethreadfunc(void *arg)
48272343Sngie{
49272343Sngie	int pri, val;
50272343Sngie
51272343Sngie	val = *(int *)arg;
52272343Sngie
53272343Sngie	errno = 0;
54272343Sngie	pri = getpriority(PRIO_PROCESS, 0);
55272343Sngie	ATF_REQUIRE(errno == 0);
56272343Sngie
57272343Sngie	if (pri != val)
58272343Sngie		atf_tc_fail("nice(3) value was not propagated to threads");
59272343Sngie
60272343Sngie	return NULL;
61272343Sngie}
62272343Sngie
63272343SngieATF_TC(nice_err);
64272343SngieATF_TC_HEAD(nice_err, tc)
65272343Sngie{
66272343Sngie	atf_tc_set_md_var(tc, "descr",
67272343Sngie	    "Test nice(3) for invalid parameters (PR lib/42587)");
68272343Sngie	atf_tc_set_md_var(tc, "require.user", "unprivileged");
69272343Sngie}
70272343Sngie
71272343SngieATF_TC_BODY(nice_err, tc)
72272343Sngie{
73272343Sngie	int i;
74272343Sngie
75272343Sngie	/*
76272343Sngie	 * The call should fail with EPERM if the
77272343Sngie	 * supplied parameter is negative and the
78272343Sngie	 * caller does not have privileges.
79272343Sngie	 */
80272343Sngie	for (i = -20; i < 0; i++) {
81272343Sngie
82272343Sngie		errno = 0;
83272343Sngie
84272343Sngie		ATF_REQUIRE_ERRNO(EPERM, nice(i) == -1);
85272343Sngie	}
86272343Sngie}
87272343Sngie
88272343SngieATF_TC(nice_priority);
89272343SngieATF_TC_HEAD(nice_priority, tc)
90272343Sngie{
91272343Sngie	atf_tc_set_md_var(tc, "descr", "Test nice(3) vs. getpriority(2)");
92272343Sngie}
93272343Sngie
94272343SngieATF_TC_BODY(nice_priority, tc)
95272343Sngie{
96279397Sjilles#ifdef __FreeBSD__
97279397Sjilles	int i, pri, pri2, nic;
98279397Sjilles#else
99272343Sngie	int i, pri, nic;
100279397Sjilles#endif
101272343Sngie	pid_t pid;
102272343Sngie	int sta;
103272343Sngie
104272343Sngie	for (i = 0; i <= 20; i++) {
105272343Sngie
106272343Sngie		nic = nice(i);
107272343Sngie		ATF_REQUIRE(nic != -1);
108272343Sngie
109272343Sngie		errno = 0;
110272343Sngie		pri = getpriority(PRIO_PROCESS, 0);
111272343Sngie		ATF_REQUIRE(errno == 0);
112272343Sngie
113279397Sjilles#ifdef __NetBSD__
114272343Sngie		if (nic != pri)
115272343Sngie			atf_tc_fail("nice(3) and getpriority(2) conflict");
116279397Sjilles#endif
117272343Sngie
118272343Sngie		/*
119272343Sngie		 * Also verify that the nice(3) values
120272343Sngie		 * are inherited by child processes.
121272343Sngie		 */
122272343Sngie		pid = fork();
123272343Sngie		ATF_REQUIRE(pid >= 0);
124272343Sngie
125272343Sngie		if (pid == 0) {
126272343Sngie
127272343Sngie			errno = 0;
128279397Sjilles#ifdef __FreeBSD__
129272343Sngie			pri = getpriority(PRIO_PROCESS, 0);
130279397Sjilles#else
131279397Sjilles			pri2 = getpriority(PRIO_PROCESS, 0);
132279397Sjilles#endif
133272343Sngie			ATF_REQUIRE(errno == 0);
134272343Sngie
135279397Sjilles#ifdef __FreeBSD__
136279397Sjilles			if (pri != pri2)
137279397Sjilles#else
138272343Sngie			if (nic != pri)
139279397Sjilles#endif
140272343Sngie				_exit(EXIT_FAILURE);
141272343Sngie
142272343Sngie			_exit(EXIT_SUCCESS);
143272343Sngie		}
144272343Sngie
145272343Sngie		(void)wait(&sta);
146272343Sngie
147272343Sngie		if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
148272343Sngie			atf_tc_fail("nice(3) value was not inherited");
149272343Sngie	}
150272343Sngie}
151272343Sngie
152272343SngieATF_TC(nice_root);
153272343SngieATF_TC_HEAD(nice_root, tc)
154272343Sngie{
155272343Sngie	atf_tc_set_md_var(tc, "descr", "Test that nice(3) works");
156272343Sngie	atf_tc_set_md_var(tc, "require.user", "root");
157272343Sngie}
158272343Sngie
159272343SngieATF_TC_BODY(nice_root, tc)
160272343Sngie{
161272343Sngie	int i;
162272343Sngie
163272343Sngie	for (i = -20; i <= 20; i++) {
164272343Sngie
165272343Sngie		ATF_REQUIRE(nice(i) != -1);
166272343Sngie	}
167272343Sngie}
168272343Sngie
169272343SngieATF_TC(nice_thread);
170272343SngieATF_TC_HEAD(nice_thread, tc)
171272343Sngie{
172272343Sngie	atf_tc_set_md_var(tc, "descr", "Test nice(3) with threads");
173272343Sngie}
174272343Sngie
175272343SngieATF_TC_BODY(nice_thread, tc)
176272343Sngie{
177272343Sngie	pthread_t tid[5];
178279397Sjilles#ifdef __FreeBSD__
179279397Sjilles	int pri, rv, val;
180279397Sjilles#else
181272343Sngie	int rv, val;
182279397Sjilles#endif
183272343Sngie	size_t i;
184272343Sngie
185272343Sngie	/*
186272343Sngie	 * Test that the scheduling priority is
187272343Sngie	 * propagated to all system scope threads.
188272343Sngie	 */
189272343Sngie	for (i = 0; i < __arraycount(tid); i++) {
190272343Sngie
191272343Sngie		val = nice(i);
192272343Sngie		ATF_REQUIRE(val != -1);
193272343Sngie
194279397Sjilles#ifdef __FreeBSD__
195279397Sjilles		pri = getpriority(PRIO_PROCESS, 0);
196279397Sjilles		rv = pthread_create(&tid[i], NULL, threadfunc, &pri);
197279397Sjilles#else
198272343Sngie		rv = pthread_create(&tid[i], NULL, threadfunc, &val);
199279397Sjilles#endif
200272343Sngie		ATF_REQUIRE(rv == 0);
201272343Sngie
202272343Sngie		rv = pthread_join(tid[i], NULL);
203272343Sngie		ATF_REQUIRE(rv == 0);
204272343Sngie	}
205272343Sngie}
206272343Sngie
207272343SngieATF_TP_ADD_TCS(tp)
208272343Sngie{
209272343Sngie
210272343Sngie	ATF_TP_ADD_TC(tp, nice_err);
211272343Sngie	ATF_TP_ADD_TC(tp, nice_priority);
212272343Sngie	ATF_TP_ADD_TC(tp, nice_root);
213272343Sngie	ATF_TP_ADD_TC(tp, nice_thread);
214272343Sngie
215272343Sngie	return atf_no_error();
216272343Sngie}
217