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

Reply via email to