diff mbox series

vivid: fix (partially) timing issues

Message ID 2aa5b7ff-0ae6-8810-159f-29fb6122d288@xs4all.nl
State Accepted
Commit 6e8c09bb8d60a0b905295e9e2c999b39953c5bf3
Headers show
Series vivid: fix (partially) timing issues | expand

Commit Message

Hans Verkuil Oct. 2, 2020, 2:48 p.m. UTC
The vivid driver is a bit flaky w.r.t. the kthread timing, esp. when running
inside a virtual machine.

This is caused by calling schedule_timeout_uninterruptible(1) which can actually
take more than one jiffie. A while loop with schedule() turns out to be a lot
more precise. Also, if mutex_trylock() fails, then just call schedule() instead
of schedule_timeout_uninterruptible(1). There is no need to wait until the next
jiffer, just schedule(), then try to get the lock again.

This is still not precise enough, it is still relatively easy to get missed
frames. This really should be converted to use a proper timer, but for now
this solves the worst problems.

Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
---
diff mbox series

Patch

diff --git a/drivers/media/test-drivers/vivid/vivid-kthread-cap.c b/drivers/media/test-drivers/vivid/vivid-kthread-cap.c
index 01a9d671b947..67fb3c00f9ad 100644
--- a/drivers/media/test-drivers/vivid/vivid-kthread-cap.c
+++ b/drivers/media/test-drivers/vivid/vivid-kthread-cap.c
@@ -819,7 +819,7 @@  static int vivid_thread_vid_cap(void *data)
 			break;

 		if (!mutex_trylock(&dev->mutex)) {
-			schedule_timeout_uninterruptible(1);
+			schedule();
 			continue;
 		}

@@ -888,7 +888,9 @@  static int vivid_thread_vid_cap(void *data)
 			next_jiffies_since_start = jiffies_since_start;

 		wait_jiffies = next_jiffies_since_start - jiffies_since_start;
-		schedule_timeout_interruptible(wait_jiffies ? wait_jiffies : 1);
+		while (jiffies - cur_jiffies < wait_jiffies &&
+		       !kthread_should_stop())
+			schedule();
 	}
 	dprintk(dev, 1, "Video Capture Thread End\n");
 	return 0;
diff --git a/drivers/media/test-drivers/vivid/vivid-kthread-out.c b/drivers/media/test-drivers/vivid/vivid-kthread-out.c
index 6780687978f9..79c57d14ac4e 100644
--- a/drivers/media/test-drivers/vivid/vivid-kthread-out.c
+++ b/drivers/media/test-drivers/vivid/vivid-kthread-out.c
@@ -167,7 +167,7 @@  static int vivid_thread_vid_out(void *data)
 			break;

 		if (!mutex_trylock(&dev->mutex)) {
-			schedule_timeout_uninterruptible(1);
+			schedule();
 			continue;
 		}

@@ -233,7 +233,9 @@  static int vivid_thread_vid_out(void *data)
 			next_jiffies_since_start = jiffies_since_start;

 		wait_jiffies = next_jiffies_since_start - jiffies_since_start;
-		schedule_timeout_interruptible(wait_jiffies ? wait_jiffies : 1);
+		while (jiffies - cur_jiffies < wait_jiffies &&
+		       !kthread_should_stop())
+			schedule();
 	}
 	dprintk(dev, 1, "Video Output Thread End\n");
 	return 0;
diff --git a/drivers/media/test-drivers/vivid/vivid-kthread-touch.c b/drivers/media/test-drivers/vivid/vivid-kthread-touch.c
index 674507b5ccb5..38fdfee79498 100644
--- a/drivers/media/test-drivers/vivid/vivid-kthread-touch.c
+++ b/drivers/media/test-drivers/vivid/vivid-kthread-touch.c
@@ -69,7 +69,7 @@  static int vivid_thread_touch_cap(void *data)
 			break;

 		if (!mutex_trylock(&dev->mutex)) {
-			schedule_timeout_uninterruptible(1);
+			schedule();
 			continue;
 		}
 		cur_jiffies = jiffies;
@@ -128,7 +128,9 @@  static int vivid_thread_touch_cap(void *data)
 			next_jiffies_since_start = jiffies_since_start;

 		wait_jiffies = next_jiffies_since_start - jiffies_since_start;
-		schedule_timeout_interruptible(wait_jiffies ? wait_jiffies : 1);
+		while (jiffies - cur_jiffies < wait_jiffies &&
+		       !kthread_should_stop())
+			schedule();
 	}
 	dprintk(dev, 1, "Touch Capture Thread End\n");
 	return 0;
diff --git a/drivers/media/test-drivers/vivid/vivid-sdr-cap.c b/drivers/media/test-drivers/vivid/vivid-sdr-cap.c
index 2b7522e16efc..a1e52708b7ca 100644
--- a/drivers/media/test-drivers/vivid/vivid-sdr-cap.c
+++ b/drivers/media/test-drivers/vivid/vivid-sdr-cap.c
@@ -142,7 +142,7 @@  static int vivid_thread_sdr_cap(void *data)
 			break;

 		if (!mutex_trylock(&dev->mutex)) {
-			schedule_timeout_uninterruptible(1);
+			schedule();
 			continue;
 		}

@@ -201,7 +201,9 @@  static int vivid_thread_sdr_cap(void *data)
 			next_jiffies_since_start = jiffies_since_start;

 		wait_jiffies = next_jiffies_since_start - jiffies_since_start;
-		schedule_timeout_interruptible(wait_jiffies ? wait_jiffies : 1);
+		while (jiffies - cur_jiffies < wait_jiffies &&
+		       !kthread_should_stop())
+			schedule();
 	}
 	dprintk(dev, 1, "SDR Capture Thread End\n");
 	return 0;