From owner-svn-src-head@freebsd.org Sat Mar 18 15:25:53 2017 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 0AF4AD12A52; Sat, 18 Mar 2017 15:25:53 +0000 (UTC) (envelope-from badger@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id D96981F39; Sat, 18 Mar 2017 15:25:52 +0000 (UTC) (envelope-from badger@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v2IFPpk5094755; Sat, 18 Mar 2017 15:25:51 GMT (envelope-from badger@FreeBSD.org) Received: (from badger@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v2IFPpF0094754; Sat, 18 Mar 2017 15:25:51 GMT (envelope-from badger@FreeBSD.org) Message-Id: <201703181525.v2IFPpF0094754@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: badger set sender to badger@FreeBSD.org using -f From: Eric Badger Date: Sat, 18 Mar 2017 15:25:51 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r315484 - head/tests/sys/kern X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 18 Mar 2017 15:25:53 -0000 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 #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_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. */