157718be8SEnji Cooper /* $NetBSD: t_spawnattr.c,v 1.1 2012/02/13 21:03:08 martin Exp $ */
257718be8SEnji Cooper
357718be8SEnji Cooper /*-
457718be8SEnji Cooper * Copyright (c) 2012 The NetBSD Foundation, Inc.
557718be8SEnji Cooper * All rights reserved.
657718be8SEnji Cooper *
757718be8SEnji Cooper * This code is derived from software contributed to The NetBSD Foundation
857718be8SEnji Cooper * by Charles Zhang <charles@NetBSD.org> and
957718be8SEnji Cooper * Martin Husemann <martin@NetBSD.org>.
1057718be8SEnji Cooper *
1157718be8SEnji Cooper * Redistribution and use in source and binary forms, with or without
1257718be8SEnji Cooper * modification, are permitted provided that the following conditions
1357718be8SEnji Cooper * are met:
1457718be8SEnji Cooper * 1. Redistributions of source code must retain the above copyright
1557718be8SEnji Cooper * notice, this list of conditions and the following disclaimer.
1657718be8SEnji Cooper * 2. Redistributions in binary form must reproduce the above copyright
1757718be8SEnji Cooper * notice, this list of conditions and the following disclaimer in the
1857718be8SEnji Cooper * documentation and/or other materials provided with the distribution.
1957718be8SEnji Cooper *
2057718be8SEnji Cooper * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2157718be8SEnji Cooper * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2257718be8SEnji Cooper * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2357718be8SEnji Cooper * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2457718be8SEnji Cooper * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2557718be8SEnji Cooper * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2657718be8SEnji Cooper * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2757718be8SEnji Cooper * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2857718be8SEnji Cooper * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2957718be8SEnji Cooper * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3057718be8SEnji Cooper * POSSIBILITY OF SUCH DAMAGE.
3157718be8SEnji Cooper */
3257718be8SEnji Cooper
3357718be8SEnji Cooper #include <atf-c.h>
3457718be8SEnji Cooper #include <stdio.h>
3557718be8SEnji Cooper #include <stdlib.h>
3657718be8SEnji Cooper #include <string.h>
3757718be8SEnji Cooper #include <errno.h>
3857718be8SEnji Cooper #include <fcntl.h>
3957718be8SEnji Cooper #include <sched.h>
4057718be8SEnji Cooper #include <signal.h>
4157718be8SEnji Cooper #include <spawn.h>
4257718be8SEnji Cooper #include <unistd.h>
4357718be8SEnji Cooper #include <sys/wait.h>
4457718be8SEnji Cooper
4557718be8SEnji Cooper static int get_different_scheduler(void);
463cc31a04SKonstantin Belousov static int get_different_priority(int scheduler);
473cc31a04SKonstantin Belousov
483cc31a04SKonstantin Belousov static const int schedulers[] = {
493cc31a04SKonstantin Belousov SCHED_OTHER,
503cc31a04SKonstantin Belousov SCHED_FIFO,
513cc31a04SKonstantin Belousov SCHED_RR
523cc31a04SKonstantin Belousov };
5357718be8SEnji Cooper
5457718be8SEnji Cooper static int
get_different_scheduler(void)553cc31a04SKonstantin Belousov get_different_scheduler(void)
5657718be8SEnji Cooper {
573cc31a04SKonstantin Belousov u_int i;
583cc31a04SKonstantin Belousov int scheduler;
5957718be8SEnji Cooper
6057718be8SEnji Cooper /* get current schedule policy */
6157718be8SEnji Cooper scheduler = sched_getscheduler(0);
62*36b9e15cSEnji Cooper for (i = 0; i < __arraycount(schedulers); i++) {
633cc31a04SKonstantin Belousov if (schedulers[i] == scheduler)
643cc31a04SKonstantin Belousov break;
653cc31a04SKonstantin Belousov }
66*36b9e15cSEnji Cooper ATF_REQUIRE_MSG(i < __arraycount(schedulers),
673cc31a04SKonstantin Belousov "Unknown current scheduler %d", scheduler);
6857718be8SEnji Cooper
6957718be8SEnji Cooper /* new scheduler */
703cc31a04SKonstantin Belousov i++;
71*36b9e15cSEnji Cooper if (i >= __arraycount(schedulers))
723cc31a04SKonstantin Belousov i = 0;
733cc31a04SKonstantin Belousov return schedulers[i];
7457718be8SEnji Cooper }
7557718be8SEnji Cooper
7657718be8SEnji Cooper static int
get_different_priority(int scheduler)773cc31a04SKonstantin Belousov get_different_priority(int scheduler)
7857718be8SEnji Cooper {
793cc31a04SKonstantin Belousov int max, min, new, priority;
8057718be8SEnji Cooper struct sched_param param;
8157718be8SEnji Cooper
8257718be8SEnji Cooper max = sched_get_priority_max(scheduler);
8357718be8SEnji Cooper min = sched_get_priority_min(scheduler);
8457718be8SEnji Cooper
8557718be8SEnji Cooper sched_getparam(0, ¶m);
8657718be8SEnji Cooper priority = param.sched_priority;
8757718be8SEnji Cooper
883cc31a04SKonstantin Belousov /*
893cc31a04SKonstantin Belousov * Change numerical value of the priority, to ensure that it
903cc31a04SKonstantin Belousov * was set for the spawned child.
913cc31a04SKonstantin Belousov */
923cc31a04SKonstantin Belousov new = priority + 1;
9357718be8SEnji Cooper if (new > max)
9457718be8SEnji Cooper new = min;
9557718be8SEnji Cooper return new;
9657718be8SEnji Cooper }
9757718be8SEnji Cooper
9857718be8SEnji Cooper ATF_TC(t_spawnattr);
9957718be8SEnji Cooper
ATF_TC_HEAD(t_spawnattr,tc)10057718be8SEnji Cooper ATF_TC_HEAD(t_spawnattr, tc)
10157718be8SEnji Cooper {
10257718be8SEnji Cooper atf_tc_set_md_var(tc, "require.user", "root");
10357718be8SEnji Cooper atf_tc_set_md_var(tc, "descr",
10457718be8SEnji Cooper "Tests posix_spawn with scheduler attributes");
10557718be8SEnji Cooper }
10657718be8SEnji Cooper
ATF_TC_BODY(t_spawnattr,tc)10757718be8SEnji Cooper ATF_TC_BODY(t_spawnattr, tc)
10857718be8SEnji Cooper {
10957718be8SEnji Cooper int pid, scheduler, child_scheduler, priority, status, err, pfd[2];
11057718be8SEnji Cooper char helper_arg[128];
11157718be8SEnji Cooper char * const args[] = { __UNCONST("h_spawnattr"), helper_arg, NULL };
11257718be8SEnji Cooper struct sched_param sp, child_sp;
11357718be8SEnji Cooper sigset_t sig;
11457718be8SEnji Cooper posix_spawnattr_t attr;
11557718be8SEnji Cooper char helper[FILENAME_MAX];
11657718be8SEnji Cooper
11757718be8SEnji Cooper /*
11857718be8SEnji Cooper * create a pipe to controll the child
11957718be8SEnji Cooper */
12057718be8SEnji Cooper err = pipe(pfd);
12157718be8SEnji Cooper ATF_REQUIRE_MSG(err == 0, "could not create pipe, errno %d", errno);
12257718be8SEnji Cooper sprintf(helper_arg, "%d", pfd[0]);
12357718be8SEnji Cooper
12457718be8SEnji Cooper posix_spawnattr_init(&attr);
12557718be8SEnji Cooper
12657718be8SEnji Cooper scheduler = get_different_scheduler();
1273cc31a04SKonstantin Belousov priority = get_different_priority(scheduler);
12857718be8SEnji Cooper sp.sched_priority = priority;
12957718be8SEnji Cooper
13057718be8SEnji Cooper sigemptyset(&sig);
13157718be8SEnji Cooper sigaddset(&sig, SIGUSR1);
13257718be8SEnji Cooper
13357718be8SEnji Cooper posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETSCHEDULER |
13457718be8SEnji Cooper POSIX_SPAWN_SETSCHEDPARAM | POSIX_SPAWN_SETPGROUP |
1353cc31a04SKonstantin Belousov POSIX_SPAWN_SETSIGMASK | POSIX_SPAWN_SETSIGDEF);
13657718be8SEnji Cooper posix_spawnattr_setpgroup(&attr, 0);
13757718be8SEnji Cooper posix_spawnattr_setschedparam(&attr, &sp);
13857718be8SEnji Cooper posix_spawnattr_setschedpolicy(&attr, scheduler);
13957718be8SEnji Cooper posix_spawnattr_setsigmask(&attr, &sig);
14057718be8SEnji Cooper posix_spawnattr_setsigdefault(&attr, &sig);
14157718be8SEnji Cooper
14257718be8SEnji Cooper sprintf(helper, "%s/h_spawnattr",
14357718be8SEnji Cooper atf_tc_get_config_var(tc, "srcdir"));
14457718be8SEnji Cooper err = posix_spawn(&pid, helper, NULL, &attr, args, NULL);
14557718be8SEnji Cooper ATF_REQUIRE_MSG(err == 0, "error %d", err);
14657718be8SEnji Cooper
14757718be8SEnji Cooper child_scheduler = sched_getscheduler(pid);
14857718be8SEnji Cooper ATF_REQUIRE_MSG(scheduler == child_scheduler,
14957718be8SEnji Cooper "scheduler = %d, child_scheduler = %d, pid %d, errno %d",
15057718be8SEnji Cooper scheduler, child_scheduler, pid, errno);
15157718be8SEnji Cooper
15257718be8SEnji Cooper sched_getparam(pid, &child_sp);
15357718be8SEnji Cooper ATF_REQUIRE_MSG(child_sp.sched_priority == sp.sched_priority,
15457718be8SEnji Cooper "priority is: %d, but we requested: %d",
15557718be8SEnji Cooper child_sp.sched_priority, sp.sched_priority);
15657718be8SEnji Cooper
15757718be8SEnji Cooper ATF_REQUIRE_MSG(pid == getpgid(pid), "child pid: %d, child pgid: %d",
15857718be8SEnji Cooper pid, getpgid(pid));
15957718be8SEnji Cooper
16057718be8SEnji Cooper /* ready, let child go */
16157718be8SEnji Cooper write(pfd[1], "q", 1);
16257718be8SEnji Cooper close(pfd[0]);
16357718be8SEnji Cooper close(pfd[1]);
16457718be8SEnji Cooper
16557718be8SEnji Cooper /* wait and check result from child */
16657718be8SEnji Cooper waitpid(pid, &status, 0);
16757718be8SEnji Cooper ATF_REQUIRE(WIFEXITED(status) && WEXITSTATUS(status) == EXIT_SUCCESS);
16857718be8SEnji Cooper
16957718be8SEnji Cooper posix_spawnattr_destroy(&attr);
17057718be8SEnji Cooper }
17157718be8SEnji Cooper
ATF_TP_ADD_TCS(tp)17257718be8SEnji Cooper ATF_TP_ADD_TCS(tp)
17357718be8SEnji Cooper {
17457718be8SEnji Cooper ATF_TP_ADD_TC(tp, t_spawnattr);
17557718be8SEnji Cooper
17657718be8SEnji Cooper return atf_no_error();
17757718be8SEnji Cooper }
178