From owner-svn-src-head@FreeBSD.ORG Thu May 28 02:39:07 2009 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id C7835106564A; Thu, 28 May 2009 02:39:07 +0000 (UTC) (envelope-from zml@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id B52F98FC13; Thu, 28 May 2009 02:39:07 +0000 (UTC) (envelope-from zml@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n4S2d7K7019906; Thu, 28 May 2009 02:39:07 GMT (envelope-from zml@svn.freebsd.org) Received: (from zml@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n4S2d748019904; Thu, 28 May 2009 02:39:07 GMT (envelope-from zml@svn.freebsd.org) Message-Id: <200905280239.n4S2d748019904@svn.freebsd.org> From: Zachary Loafman Date: Thu, 28 May 2009 02:39:07 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r192949 - head/tools/regression/file/flock X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 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: Thu, 28 May 2009 02:39:08 -0000 Author: zml Date: Thu May 28 02:39:07 2009 New Revision: 192949 URL: http://svn.freebsd.org/changeset/base/192949 Log: Add a regression test for multiple threads of the same process acquiring the same fcntl lock. Approved by: dfr (mentor) Modified: head/tools/regression/file/flock/Makefile head/tools/regression/file/flock/flock.c Modified: head/tools/regression/file/flock/Makefile ============================================================================== --- head/tools/regression/file/flock/Makefile Thu May 28 02:17:58 2009 (r192948) +++ head/tools/regression/file/flock/Makefile Thu May 28 02:39:07 2009 (r192949) @@ -4,4 +4,6 @@ PROG= flock NO_MAN= WARNS?= 6 +LDADD+= -lpthread + .include Modified: head/tools/regression/file/flock/flock.c ============================================================================== --- head/tools/regression/file/flock/flock.c Thu May 28 02:17:58 2009 (r192948) +++ head/tools/regression/file/flock/flock.c Thu May 28 02:39:07 2009 (r192949) @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -1401,6 +1402,112 @@ test15(int fd, __unused int argc, const #endif } +struct test_ctx { + struct flock tc_fl; + int tc_fd; +}; + +static void * +test16_func(void *tc_in) +{ + uintptr_t error; + struct test_ctx *tc = tc_in; + + error = fcntl(tc->tc_fd, F_SETLKW, &tc->tc_fl); + + pthread_exit((void *)error); +} + +#define THREADS 10 + +/* + * Test 16 - F_SETLKW from two threads + * + * If two threads within a process are blocked on a lock and the lock + * is granted, make sure things are sane. + */ +static int +test16(int fd, __unused int argc, const __unused char **argv) +{ + /* + * We create a child process to hold the lock which we will + * test. We use a pipe to communicate with the child. + */ + int pid; + int pfd[2]; + struct test_ctx tc = { .tc_fd = fd }; + char ch; + int i; + int error; + pthread_t thr[THREADS]; + + if (pipe(pfd) < 0) + err(1, "pipe"); + + tc.tc_fl.l_start = 0; + tc.tc_fl.l_len = 0; + tc.tc_fl.l_type = F_WRLCK; + tc.tc_fl.l_whence = SEEK_SET; + + pid = fork(); + if (pid < 0) + err(1, "fork"); + + if (pid == 0) { + /* + * We are the child. We set a write lock and then + * write one byte back to the parent to tell it. The + * parent will kill us when its done. + */ + if (fcntl(fd, F_SETLK, &tc.tc_fl) < 0) + err(1, "F_SETLK (child)"); + if (write(pfd[1], "a", 1) < 0) + err(1, "writing to pipe (child)"); + pause(); + exit(0); + } + + /* + * Wait until the child has set its lock and then perform the + * test. + */ + if (read(pfd[0], &ch, 1) != 1) + err(1, "reading from pipe (child)"); + + /* + * fcntl should wait until the alarm and then return -1 with + * errno set to EINTR. + */ + printf("16 - F_SETLKW on locked region by two threads: "); + + for (i = 0; i < THREADS; i++) { + error = pthread_create(&thr[i], NULL, test16_func, &tc); + if (error) + err(1, "pthread_create"); + } + + /* + * Sleep, then kill the child. This makes me a little sad, but it's + * tricky to tell whether the threads are all really blocked by this + * point. + */ + sleep(1); + kill(pid, SIGTERM); + safe_waitpid(pid); + close(pfd[0]); + close(pfd[1]); + + for (i = 0; i < THREADS; i++) { + void *res; + error = pthread_join(thr[i], &res); + if (error) + err(1, "pthread_join"); + FAIL((uintptr_t)res != 0); + } + + SUCCEED; +} + struct test { int (*testfn)(int, int, const char **); /* function to perform the test */ int num; /* test number */ @@ -1423,6 +1530,7 @@ struct test tests[] = { { test13, 13, 1 }, { test14, 14, 0 }, { test15, 15, 1 }, + { test16, 16, 1 }, }; int test_count = sizeof(tests) / sizeof(tests[0]);