Module Name:    src
Committed By:   riastradh
Date:           Sun Dec 19 10:39:14 UTC 2021

Modified Files:
        src/sys/external/bsd/drm2/dist/drm: drm_syncobj.c

Log Message:
Touch up drm_syncobj.c.


To generate a diff of this commit:
cvs rdiff -u -r1.3 -r1.4 src/sys/external/bsd/drm2/dist/drm/drm_syncobj.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/external/bsd/drm2/dist/drm/drm_syncobj.c
diff -u src/sys/external/bsd/drm2/dist/drm/drm_syncobj.c:1.3 src/sys/external/bsd/drm2/dist/drm/drm_syncobj.c:1.4
--- src/sys/external/bsd/drm2/dist/drm/drm_syncobj.c:1.3	Sun Dec 19 01:16:13 2021
+++ src/sys/external/bsd/drm2/dist/drm/drm_syncobj.c	Sun Dec 19 10:39:14 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: drm_syncobj.c,v 1.3 2021/12/19 01:16:13 riastradh Exp $	*/
+/*	$NetBSD: drm_syncobj.c,v 1.4 2021/12/19 10:39:14 riastradh Exp $	*/
 
 /*
  * Copyright 2017 Red Hat
@@ -125,7 +125,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: drm_syncobj.c,v 1.3 2021/12/19 01:16:13 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: drm_syncobj.c,v 1.4 2021/12/19 10:39:14 riastradh Exp $");
 
 #include <linux/anon_inodes.h>
 #include <linux/file.h>
@@ -147,8 +147,20 @@ __KERNEL_RCSID(0, "$NetBSD: drm_syncobj.
 struct syncobj_wait_entry {
 	struct list_head node;
 #ifdef __NetBSD__
+	/*
+	 * Lock order:
+	 *	syncobj->lock	????	fence lock
+	 *	syncobj->lock	then	wait->lock
+	 *	fence lock	then	wait->lock
+	 *
+	 * syncobj->lock serializes wait->node and wait->fence.
+	 * wait->lock serializes wait->signalledp, and, by
+	 * interlocking with syncobj->lock, coordinates wakeups on
+	 * wait->cv for wait->fence.
+	 */
 	kmutex_t	*lock;
 	kcondvar_t	*cv;
+	bool		*signalledp;
 #else
 	struct task_struct *task;
 #endif
@@ -157,6 +169,32 @@ struct syncobj_wait_entry {
 	u64    point;
 };
 
+#ifdef __NetBSD__
+static int
+cv_wait_timeout_sig(kcondvar_t *cv, kmutex_t *lock, long *timeoutp)
+{
+	unsigned long ticks = *timeoutp;
+	unsigned starttime, endtime;
+	int error;
+
+	starttime = hardclock_ticks;
+	error = cv_timedwait_sig(cv, lock, MIN(ticks, INT_MAX));
+	endtime = hardclock_ticks;
+
+	if (error == EINTR || error == ERESTART) {
+		return ERESTARTSYS;
+	} else {
+		KASSERTMSG(error == 0 || error == EWOULDBLOCK,
+		    "error=%d", error);
+		if (endtime - starttime < ticks)
+			*timeoutp = ticks - (endtime - starttime);
+		else
+			*timeoutp = 0;
+		return 0;
+	}
+}
+#endif
+
 static void syncobj_wait_syncobj_func(struct drm_syncobj *syncobj,
 				      struct syncobj_wait_entry *wait);
 
@@ -352,12 +390,25 @@ int drm_syncobj_find_fence(struct drm_fi
 		return ret;
 
 	memset(&wait, 0, sizeof(wait));
+#ifdef __NetBSD__
+	kmutex_t lock;
+	kcondvar_t cv;
+	mutex_init(&lock, MUTEX_DEFAULT, IPL_VM);
+	cv_init(&cv, "drmfnfnc");
+	wait.cv = &cv;
+#else
 	wait.task = current;
 	wait.point = point;
+#endif
 	drm_syncobj_fence_add_wait(syncobj, &wait);
 
+#ifdef __NetBSD__
+	spin_lock(&syncobj->lock);
+#endif
 	do {
+#ifndef __NetBSD__
 		set_current_state(TASK_INTERRUPTIBLE);
+#endif
 		if (wait.fence) {
 			ret = 0;
 			break;
@@ -367,15 +418,32 @@ int drm_syncobj_find_fence(struct drm_fi
                         break;
                 }
 
+#ifdef __NetBSD__
+		mutex_enter(&lock);
+		spin_unlock(&syncobj->lock);
+		/* XXX errno NetBSD->Linux */
+		ret = -cv_wait_timeout_sig(&cv, &lock, &timeout);
+		mutex_exit(&lock);
+		spin_lock(&syncobj->lock);
+		if (ret)
+			break;
+#else
 		if (signal_pending(current)) {
 			ret = -ERESTARTSYS;
 			break;
 		}
 
                 timeout = schedule_timeout(timeout);
+#endif
 	} while (1);
 
+#ifdef __NetBSD__
+	spin_unlock(&syncobj->lock);
+	cv_destroy(&cv);
+	mutex_destroy(&lock);
+#else
 	__set_current_state(TASK_RUNNING);
+#endif
 	*fence = wait.fence;
 
 	if (wait.node.next)
@@ -611,16 +679,14 @@ static int drm_syncobj_fd_to_handle(stru
 		return -EINVAL;
 
 #ifdef __NetBSD__
-	if (file->f_ops != &drm_syncobj_file_ops) {
-		fd_putfile(fd);
-		return -EINVAL;
-	}
+	if (f.file->f_ops != &drm_syncobj_file_ops)
 #else
-	if (f.file->f_op != &drm_syncobj_file_fops) {
+	if (f.file->f_op != &drm_syncobj_file_fops)
+#endif
+	{
 		fdput(f);
 		return -EINVAL;
 	}
-#endif
 
 	/* take a reference to put in the idr */
 #ifdef __NetBSD__
@@ -642,11 +708,7 @@ static int drm_syncobj_fd_to_handle(stru
 	} else
 		drm_syncobj_put(syncobj);
 
-#ifdef __NetBSD__
-	fd_putfile(fd);
-#else
 	fdput(f);
-#endif
 	return ret;
 }
 
@@ -688,7 +750,7 @@ static int drm_syncobj_export_sync_file(
 		goto out;
 
 	/* Find the fence.  */
-	ret = drm_syncobj_find_fence(file_private, handle, &fence);
+	ret = drm_syncobj_find_fence(file_private, handle, 0, 0, &fence);
 	if (ret)
 		goto out;
 
@@ -951,6 +1013,7 @@ static void syncobj_wait_fence_func(stru
 
 #ifdef __NetBSD__
 	mutex_enter(wait->lock);
+	*wait->signalledp = true;
 	cv_broadcast(wait->cv);
 	mutex_exit(wait->lock);
 #else
@@ -970,7 +1033,9 @@ static void syncobj_wait_syncobj_func(st
 	if (!fence || dma_fence_chain_find_seqno(&fence, wait->point)) {
 		dma_fence_put(fence);
 		return;
-	} else if (!fence) {
+	}
+
+	if (!fence) {
 		wait->fence = dma_fence_get_stub();
 	} else {
 		wait->fence = fence;
@@ -1001,6 +1066,8 @@ static signed long drm_syncobj_array_wai
 #ifdef __NetBSD__
 	kmutex_t lock;
 	kcondvar_t cv;
+	bool signalled = false;
+	int ret;
 	mutex_init(&lock, MUTEX_DEFAULT, IPL_VM);
 	cv_init(&cv, "drmsynco");
 #endif
@@ -1030,11 +1097,10 @@ static signed long drm_syncobj_array_wai
 	 */
 	signaled_count = 0;
 	for (i = 0; i < count; ++i) {
-		struct dma_fence *fence;
-
 #ifdef __NetBSD__
 		entries[i].lock = &lock;
 		entries[i].cv = &cv;
+		entries[i].signalledp = &signalled;
 #else
 		entries[i].task = current;
 #endif
@@ -1117,21 +1183,15 @@ static signed long drm_syncobj_array_wai
 		}
 
 #ifdef __NetBSD__
-		unsigned long ticks = ret;
-		unsigned starttime = hardclock_ticks;
 		mutex_enter(&lock);
-		ret = -cv_timedwait_sig(&cv, &lock, MIN(ticks, INT_MAX));
+		if (signalled)
+			ret = 0;
+		else
+			ret = -cv_wait_timeout_sig(&cv, &lock, &timeout);
 		mutex_exit(&lock);
-		unsigned endtime = hardclock_ticks;
-		if (ret == -EINTR || ret == -ERESTART) {
-			ret = -ERESTARTSYS;
-		} else if (ret == -EWOULDBLOCK) {
-			if (endtime - starttime < ticks)
-				ret = ticks - (endtime - starttime);
-			else
-				ret = 0;
-		} else {
-			KASSERTMSG(ret == 0, "%ld", ret);
+		if (ret) {
+			timeout = -ERESTARTSYS;
+			goto done_waiting;
 		}
 #else
 		if (signal_pending(current)) {
@@ -1160,8 +1220,10 @@ cleanup_entries:
 
 err_free_points:
 	kfree(points);
+#ifdef __NetBSD__
 	cv_destroy(&cv);
 	mutex_destroy(&lock);
+#endif
 
 	return timeout;
 }

Reply via email to