diff --git a/tests/sys/kern/ptrace_test.c b/tests/sys/kern/ptrace_test.c index abbb5e7815b..06ca3a7af10 100644 --- a/tests/sys/kern/ptrace_test.c +++ b/tests/sys/kern/ptrace_test.c @@ -33,6 +33,8 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include +#include #include #include #include @@ -40,6 +42,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -1872,15 +1875,11 @@ ATF_TC_BODY(ptrace__PT_KILL_competing_signal, tc) cpuset_t setmask; pthread_t t; pthread_barrier_t barrier; + struct sched_param sched_param; ATF_REQUIRE((fpid = fork()) != -1); if (fpid == 0) { - /* - * Bind to one CPU so only one thread at a time will run. This - * test expects that the first thread created (the main thread) - * will be unsuspended first and will block the second thread - * from running. - */ + /* Bind to one CPU so only one thread at a time will run. */ CPU_ZERO(&setmask); CPU_SET(0, &setmask); cpusetid_t setid; @@ -1893,6 +1892,20 @@ ATF_TC_BODY(ptrace__PT_KILL_competing_signal, tc) CHILD_REQUIRE(pthread_create(&t, NULL, mask_usr1_thread, (void*)&barrier) == 0); + /* + * Give the main thread higher priority. The test always + * assumes that, if both threads are able to run, the main + * thread runs first. + */ + sched_param.sched_priority = + (sched_get_priority_max(SCHED_FIFO) + + sched_get_priority_min(SCHED_FIFO)) / 2; + CHILD_REQUIRE(pthread_setschedparam(pthread_self(), + SCHED_FIFO, &sched_param) == 0); + sched_param.sched_priority -= RQ_PPQ; + CHILD_REQUIRE(pthread_setschedparam(t, SCHED_FIFO, + &sched_param) == 0); + sigset_t sigmask; sigemptyset(&sigmask); sigaddset(&sigmask, SIGUSR2); @@ -1952,23 +1965,19 @@ ATF_TC_WITHOUT_HEAD(ptrace__PT_KILL_competing_stop); ATF_TC_BODY(ptrace__PT_KILL_competing_stop, tc) { pid_t fpid, wpid; - int status, i; + int status; cpuset_t setmask; pthread_t t; pthread_barrier_t barrier; lwpid_t main_lwp; struct ptrace_lwpinfo pl; + struct sched_param sched_param; ATF_REQUIRE((fpid = fork()) != -1); if (fpid == 0) { trace_me(); - /* - * Bind to one CPU so only one thread at a time will run. This - * test expects that the first thread created (the main thread) - * will be unsuspended first and will block the second thread - * from running. - */ + /* Bind to one CPU so only one thread at a time will run. */ CPU_ZERO(&setmask); CPU_SET(0, &setmask); cpusetid_t setid; @@ -1981,6 +1990,20 @@ ATF_TC_BODY(ptrace__PT_KILL_competing_stop, tc) CHILD_REQUIRE(pthread_create(&t, NULL, mask_usr1_thread, (void*)&barrier) == 0); + /* + * Give the main thread higher priority. The test always + * assumes that, if both threads are able to run, the main + * thread runs first. + */ + sched_param.sched_priority = + (sched_get_priority_max(SCHED_FIFO) + + sched_get_priority_min(SCHED_FIFO)) / 2; + CHILD_REQUIRE(pthread_setschedparam(pthread_self(), + SCHED_FIFO, &sched_param) == 0); + sched_param.sched_priority -= RQ_PPQ; + CHILD_REQUIRE(pthread_setschedparam(t, SCHED_FIFO, + &sched_param) == 0); + sigset_t sigmask; sigemptyset(&sigmask); sigaddset(&sigmask, SIGUSR2); @@ -2027,34 +2050,43 @@ ATF_TC_BODY(ptrace__PT_KILL_competing_stop, tc) ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0); } - /* Let both threads hit their syscall entries. */ - for (i = 0; i < 2; ++i) { - ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0); + /* Proceed, allowing main thread to hit syscall entry for getpid(). */ + ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0); - wpid = waitpid(fpid, &status, 0); - ATF_REQUIRE(wpid == fpid); - ATF_REQUIRE(WIFSTOPPED(status)); - ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP); + wpid = waitpid(fpid, &status, 0); + ATF_REQUIRE(wpid == fpid); + ATF_REQUIRE(WIFSTOPPED(status)); + ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP); - ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, - sizeof(pl)) != -1); - ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE); + ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, + sizeof(pl)) != -1); + ATF_REQUIRE(pl.pl_lwpid == main_lwp); + ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE); + /* Prevent the main thread from hitting its syscall exit for now. */ + ATF_REQUIRE(ptrace(PT_SUSPEND, main_lwp, 0, 0) == 0); - /* - * Prevent the main thread from hitting its syscall exit for - * now. - */ - if (pl.pl_lwpid == main_lwp) - ATF_REQUIRE(ptrace(PT_SUSPEND, main_lwp, 0, 0) == 0); + /* + * Proceed, allowing second thread to hit syscall exit for + * pthread_barrier_wait(). + */ + ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0); - } + wpid = waitpid(fpid, &status, 0); + ATF_REQUIRE(wpid == fpid); + ATF_REQUIRE(WIFSTOPPED(status)); + ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP); + + ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, + sizeof(pl)) != -1); + ATF_REQUIRE(pl.pl_lwpid != main_lwp); + ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCX); /* Send a signal that only the second thread can handle. */ ATF_REQUIRE(kill(fpid, SIGUSR2) == 0); ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0); - /* The second wait() should report the SIGUSR2. */ + /* The next wait() should report the SIGUSR2. */ wpid = waitpid(fpid, &status, 0); ATF_REQUIRE(wpid == fpid); ATF_REQUIRE(WIFSTOPPED(status)); @@ -2065,10 +2097,11 @@ ATF_TC_BODY(ptrace__PT_KILL_competing_stop, tc) /* * At this point, the main thread is in the middle of a system call and - * has been resumed. The second thread has taken a signal which will be - * replaced with a SIGKILL. We expect the main thread will get to run - * first. It should notice the kill request and exit accordingly and - * not stop for the system call exit event. + * has been resumed. The second thread has taken a SIGUSR2 which will + * be replaced with a SIGKILL below. The main thread will get to run + * first. It should notice the kill request (even though the signal + * replacement occurred in the other thread) and exit accordingly. It + * should not stop for the system call exit event. */ /* Replace the SIGUSR2 with a kill. */