Date: Sat, 18 Mar 2017 15:25:51 +0000 (UTC) From: Eric Badger <badger@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r315484 - head/tests/sys/kern Message-ID: <201703181525.v2IFPpF0094754@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: badger Date: Sat Mar 18 15:25:51 2017 New Revision: 315484 URL: https://svnweb.freebsd.org/changeset/base/315484 Log: ptrace_test: eliminate assumption about thread scheduling A couple of the ptrace tests make assumptions about which thread in a multithreaded process will run after a halt. This makes the tests less portable across branches, and susceptible to future breakage. Instead, twiddle thread scheduling and priorities to match the tests' expectation. X-MFC with: r313992 Sponsored by: Dell EMC Modified: head/tests/sys/kern/ptrace_test.c Modified: head/tests/sys/kern/ptrace_test.c ============================================================================== --- head/tests/sys/kern/ptrace_test.c Sat Mar 18 13:58:25 2017 (r315483) +++ head/tests/sys/kern/ptrace_test.c Sat Mar 18 15:25:51 2017 (r315484) @@ -33,6 +33,8 @@ __FBSDID("$FreeBSD$"); #include <sys/time.h> #include <sys/procctl.h> #include <sys/ptrace.h> +#include <sys/queue.h> +#include <sys/runq.h> #include <sys/syscall.h> #include <sys/sysctl.h> #include <sys/user.h> @@ -40,6 +42,7 @@ __FBSDID("$FreeBSD$"); #include <errno.h> #include <machine/cpufunc.h> #include <pthread.h> +#include <sched.h> #include <semaphore.h> #include <signal.h> #include <stdio.h> @@ -1872,15 +1875,11 @@ ATF_TC_BODY(ptrace__PT_KILL_competing_si 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_si 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_comp 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_st 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_st 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_st /* * 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. */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201703181525.v2IFPpF0094754>