Module Name: src Committed By: riastradh Date: Sun Dec 19 12:35:46 UTC 2021
Modified Files: src/sys/external/bsd/drm2/dist/drm: drm_syncobj.c Log Message: drm: Timeout audit -- drm_syncobj.c. To generate a diff of this commit: cvs rdiff -u -r1.6 -r1.7 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.6 src/sys/external/bsd/drm2/dist/drm/drm_syncobj.c:1.7 --- src/sys/external/bsd/drm2/dist/drm/drm_syncobj.c:1.6 Sun Dec 19 12:35:28 2021 +++ src/sys/external/bsd/drm2/dist/drm/drm_syncobj.c Sun Dec 19 12:35:45 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: drm_syncobj.c,v 1.6 2021/12/19 12:35:28 riastradh Exp $ */ +/* $NetBSD: drm_syncobj.c,v 1.7 2021/12/19 12:35:45 riastradh Exp $ */ /* * Copyright 2017 Red Hat @@ -125,7 +125,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: drm_syncobj.c,v 1.6 2021/12/19 12:35:28 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: drm_syncobj.c,v 1.7 2021/12/19 12:35:45 riastradh Exp $"); #include <linux/anon_inodes.h> #include <linux/file.h> @@ -169,32 +169,6 @@ 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); @@ -404,11 +378,45 @@ int drm_syncobj_find_fence(struct drm_fi #ifdef __NetBSD__ spin_lock(&syncobj->lock); -#endif + ret = 0; + while (wait.fence == NULL) { + unsigned start, end; + + if (timeout == 0) { + ret = -ETIME; + break; + } + mutex_spin_enter(&lock); + spin_unlock(&syncobj->lock); + start = getticks(); + /* XXX errno NetBSD->Linux */ + ret = -cv_timedwait_sig(&cv, &lock, MIN(timeout, INT_MAX/2)); + end = getticks(); + timeout -= MIN(timeout, end - start); + mutex_spin_exit(&lock); + spin_lock(&syncobj->lock); + KASSERTMSG((ret == 0 || ret == -EINTR || ret == -ERESTART || + ret == -EWOULDBLOCK), "ret=%d", ret); + if (ret == -EINTR || ret == -ERESTART) { + ret = -ERESTARTSYS; + break; + } else if (ret == -EWOULDBLOCK) { + /* Check once more, then give up. */ + ret = 0; + timeout = 0; + } else { + KASSERT(ret == 0); + } + } + *fence = wait.fence; + if (wait.node.next) + list_del_init(&wait.node); + spin_unlock(&syncobj->lock); + cv_destroy(&cv); + mutex_destroy(&lock); +#else do { -#ifndef __NetBSD__ set_current_state(TASK_INTERRUPTIBLE); -#endif if (wait.fence) { ret = 0; break; @@ -418,36 +426,20 @@ 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) drm_syncobj_remove_wait(syncobj, &wait); +#endif return ret; } @@ -1184,15 +1176,30 @@ static signed long drm_syncobj_array_wai } #ifdef __NetBSD__ - mutex_enter(&lock); - if (signalled) + mutex_spin_enter(&lock); + if (signalled) { ret = 0; - else - ret = -cv_wait_timeout_sig(&cv, &lock, &timeout); - mutex_exit(&lock); - if (ret) { + } else { + unsigned start, end; + + start = getticks(); + /* XXX errno NetBSD->Linux */ + ret = -cv_timedwait_sig(&cv, &lock, + MIN(timeout, INT_MAX/2)); + end = getticks(); + timeout -= MIN(timeout, end - start); + } + mutex_spin_exit(&lock); + KASSERTMSG((ret == 0 || ret == -EINTR || ret == -ERESTART || + ret == -EWOULDBLOCK), "ret=%d", ret); + if (ret == -EINTR || ret == -ERESTART) { timeout = -ERESTARTSYS; goto done_waiting; + } else if (ret == -EWOULDBLOCK) { + /* Poll fences once more, then exit. */ + timeout = 0; + } else { + KASSERT(ret == 0); } #else if (signal_pending(current)) {