This is an automatic generated email to let you know that the following patch were queued at the http://git.linuxtv.org/cgit.cgi/v4l-utils.git tree:
Subject: v4l2-compliance: test stream locking Author: Hans Verkuil <hans.verk...@cisco.com> Date: Fri May 11 14:49:33 2018 +0200 When in a blocking wait for DQBUF it should be possible to call STREAMOFF from a forked process. Signed-off-by: Hans Verkuil <hans.verk...@cisco.com> utils/v4l2-compliance/v4l2-compliance.cpp | 2 + utils/v4l2-compliance/v4l2-compliance.h | 1 + utils/v4l2-compliance/v4l2-test-buffers.cpp | 92 +++++++++++++++++++++++++++++ 3 files changed, 95 insertions(+) --- http://git.linuxtv.org/cgit.cgi/v4l-utils.git/commit/?id=79d98edd1a27233667a6bc38d3d7f8958c2ec02c diff --git a/utils/v4l2-compliance/v4l2-compliance.cpp b/utils/v4l2-compliance/v4l2-compliance.cpp index 75146caf1866..36c4c0a626d7 100644 --- a/utils/v4l2-compliance/v4l2-compliance.cpp +++ b/utils/v4l2-compliance/v4l2-compliance.cpp @@ -1014,6 +1014,8 @@ void testNode(struct node &node, struct node &expbuf_node, media_type type, // Reopen after each streaming test to reset the streaming state // in case of any errors in the preceeding test. node.reopen(); + printf("\ttest blocking wait: %s\n", ok(testBlockingWait(&node))); + node.reopen(); printf("\ttest MMAP: %s\n", ok(testMmap(&node, frame_count))); node.reopen(); printf("\ttest USERPTR: %s\n", ok(testUserPtr(&node, frame_count))); diff --git a/utils/v4l2-compliance/v4l2-compliance.h b/utils/v4l2-compliance/v4l2-compliance.h index 00d341a2b46d..3c7911555563 100644 --- a/utils/v4l2-compliance/v4l2-compliance.h +++ b/utils/v4l2-compliance/v4l2-compliance.h @@ -252,6 +252,7 @@ int testSubDevFrameInterval(struct node *node, unsigned pad); int testReqBufs(struct node *node); int testReadWrite(struct node *node); int testExpBuf(struct node *node); +int testBlockingWait(struct node *node); int testMmap(struct node *node, unsigned frame_count); int testUserPtr(struct node *node, unsigned frame_count); int testDmaBuf(struct node *expbuf_node, struct node *node, unsigned frame_count); diff --git a/utils/v4l2-compliance/v4l2-test-buffers.cpp b/utils/v4l2-compliance/v4l2-test-buffers.cpp index 9b0933ef1fea..3986435bf7af 100644 --- a/utils/v4l2-compliance/v4l2-test-buffers.cpp +++ b/utils/v4l2-compliance/v4l2-test-buffers.cpp @@ -26,6 +26,7 @@ #include <sys/types.h> #include <sys/stat.h> #include <sys/mman.h> +#include <sys/wait.h> #include <fcntl.h> #include <ctype.h> #include <errno.h> @@ -1167,6 +1168,97 @@ int testDmaBuf(struct node *expbuf_node, struct node *node, unsigned frame_count return 0; } +static int testBlockingDQBuf(struct node *node, cv4l_queue &q) +{ + int pid_dqbuf; + int pid_streamoff; + int pid; + + fail_on_test(q.reqbufs(node, 2)); + fail_on_test(node->streamon(q.g_type())); + + /* + * This test checks if a blocking wait in VIDIOC_DQBUF doesn't block + * other ioctls. + */ + pid_dqbuf = fork(); + fail_on_test(pid_dqbuf == -1); + + if (pid_dqbuf == 0) { // Child + /* + * In the child process we call VIDIOC_DQBUF and wait + * indefinitely since no buffers are queued. + */ + cv4l_buffer buf(q.g_type(), V4L2_MEMORY_MMAP); + + node->dqbuf(buf); + exit(0); + } + + /* Wait for the child process to start and block */ + usleep(100000); + pid = waitpid(pid_dqbuf, NULL, WNOHANG); + /* Check that it is really blocking */ + fail_on_test(pid); + + pid_streamoff = fork(); + fail_on_test(pid_streamoff == -1); + + if (pid_streamoff == 0) { // Child + /* + * In the second child call STREAMOFF: this shouldn't + * be blocked by the DQBUF! + */ + node->streamoff(q.g_type()); + exit(0); + } + + int wstatus_streamoff = 0; + + /* Wait for the second child to start and exit */ + usleep(250000); + pid = waitpid(pid_streamoff, &wstatus_streamoff, WNOHANG); + kill(pid_dqbuf, SIGKILL); + fail_on_test(pid != pid_streamoff); + /* Test that the second child exited properly */ + if (!pid || !WIFEXITED(wstatus_streamoff)) { + kill(pid_streamoff, SIGKILL); + fail_on_test(!pid || !WIFEXITED(wstatus_streamoff)); + } + + fail_on_test(node->streamoff(q.g_type())); + fail_on_test(q.reqbufs(node, 0)); + return 0; +} + +int testBlockingWait(struct node *node) +{ + bool can_stream = node->g_caps() & V4L2_CAP_STREAMING; + int type; + + if (!can_stream || !node->valid_buftypes) + return ENOTTY; + + buffer_info.clear(); + for (type = 0; type <= V4L2_BUF_TYPE_LAST; type++) { + if (!(node->valid_buftypes & (1 << type))) + continue; + if (v4l_type_is_overlay(type)) + continue; + + cv4l_queue q(type, V4L2_MEMORY_MMAP); + cv4l_queue m2m_q(v4l_type_invert(type), V4L2_MEMORY_MMAP); + + if (testSetupVbi(node, type)) + continue; + + fail_on_test(testBlockingDQBuf(node, q)); + if (node->is_m2m) + fail_on_test(testBlockingDQBuf(node, m2m_q)); + } + return 0; +} + static void restoreCropCompose(struct node *node, __u32 field, v4l2_selection &crop, v4l2_selection &compose) { _______________________________________________ linuxtv-commits mailing list linuxtv-commits@linuxtv.org https://www.linuxtv.org/cgi-bin/mailman/listinfo/linuxtv-commits