Module Name:    src
Committed By:   thorpej
Date:           Wed Nov 24 16:35:33 UTC 2021

Modified Files:
        src/sys/kern: sys_eventfd.c sys_timerfd.c

Log Message:
Fix "restart" semantics -- restart is terminal, so don't clear the
condition when previous waiters have drained.  ("restart" is a bad
name for that this function does, fwiw.)

This should address a kernel assertion failure reported by Chavdar Ivanov
on current-users.


To generate a diff of this commit:
cvs rdiff -u -r1.7 -r1.8 src/sys/kern/sys_eventfd.c
cvs rdiff -u -r1.6 -r1.7 src/sys/kern/sys_timerfd.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/kern/sys_eventfd.c
diff -u src/sys/kern/sys_eventfd.c:1.7 src/sys/kern/sys_eventfd.c:1.8
--- src/sys/kern/sys_eventfd.c:1.7	Mon Sep 27 00:40:49 2021
+++ src/sys/kern/sys_eventfd.c	Wed Nov 24 16:35:33 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: sys_eventfd.c,v 1.7 2021/09/27 00:40:49 thorpej Exp $	*/
+/*	$NetBSD: sys_eventfd.c,v 1.8 2021/11/24 16:35:33 thorpej Exp $	*/
 
 /*-
  * Copyright (c) 2020 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sys_eventfd.c,v 1.7 2021/09/27 00:40:49 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sys_eventfd.c,v 1.8 2021/11/24 16:35:33 thorpej Exp $");
 
 /*
  * eventfd
@@ -64,7 +64,6 @@ struct eventfd {
 	kmutex_t	efd_lock;
 	kcondvar_t	efd_read_wait;
 	kcondvar_t	efd_write_wait;
-	kcondvar_t	efd_restart_wait;
 	struct selinfo	efd_read_sel;
 	struct selinfo	efd_write_sel;
 	eventfd_t	efd_val;
@@ -97,7 +96,6 @@ eventfd_create(unsigned int const val, i
 	mutex_init(&efd->efd_lock, MUTEX_DEFAULT, IPL_NONE);
 	cv_init(&efd->efd_read_wait, "efdread");
 	cv_init(&efd->efd_write_wait, "efdwrite");
-	cv_init(&efd->efd_restart_wait, "efdrstrt");
 	selinit(&efd->efd_read_sel);
 	selinit(&efd->efd_write_sel);
 	efd->efd_val = val;
@@ -119,13 +117,11 @@ eventfd_destroy(struct eventfd * const e
 {
 
 	KASSERT(efd->efd_nwaiters == 0);
-	KASSERT(efd->efd_restarting == false);
 	KASSERT(efd->efd_has_read_waiters == false);
 	KASSERT(efd->efd_has_write_waiters == false);
 
 	cv_destroy(&efd->efd_read_wait);
 	cv_destroy(&efd->efd_write_wait);
-	cv_destroy(&efd->efd_restart_wait);
 
 	seldestroy(&efd->efd_read_sel);
 	seldestroy(&efd->efd_write_sel);
@@ -152,11 +148,10 @@ eventfd_wait(struct eventfd * const efd,
 	}
 
 	/*
-	 * We're going to block.  If there is a restart in-progress,
-	 * wait for that to complete first.
+	 * We're going to block.  Check if we need to return ERESTART.
 	 */
-	while (efd->efd_restarting) {
-		cv_wait(&efd->efd_restart_wait, &efd->efd_lock);
+	if (efd->efd_restarting) {
+		return ERESTART;
 	}
 
 	if (is_write) {
@@ -175,18 +170,12 @@ eventfd_wait(struct eventfd * const efd,
 
 	/*
 	 * If a restart was triggered while we were asleep, we need
-	 * to return ERESTART if no other error was returned.  If we
-	 * are the last waiter coming out of the restart drain, clear
-	 * the condition.
+	 * to return ERESTART if no other error was returned.
 	 */
 	if (efd->efd_restarting) {
 		if (error == 0) {
 			error = ERESTART;
 		}
-		if (efd->efd_nwaiters == 0) {
-			efd->efd_restarting = false;
-			cv_broadcast(&efd->efd_restart_wait);
-		}
 	}
 
 	return error;

Index: src/sys/kern/sys_timerfd.c
diff -u src/sys/kern/sys_timerfd.c:1.6 src/sys/kern/sys_timerfd.c:1.7
--- src/sys/kern/sys_timerfd.c:1.6	Mon Sep 27 00:40:49 2021
+++ src/sys/kern/sys_timerfd.c	Wed Nov 24 16:35:33 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: sys_timerfd.c,v 1.6 2021/09/27 00:40:49 thorpej Exp $	*/
+/*	$NetBSD: sys_timerfd.c,v 1.7 2021/11/24 16:35:33 thorpej Exp $	*/
 
 /*-
  * Copyright (c) 2020 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sys_timerfd.c,v 1.6 2021/09/27 00:40:49 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sys_timerfd.c,v 1.7 2021/11/24 16:35:33 thorpej Exp $");
 
 /*
  * timerfd
@@ -71,7 +71,6 @@ __KERNEL_RCSID(0, "$NetBSD: sys_timerfd.
 struct timerfd {
 	struct itimer	tfd_itimer;
 	kcondvar_t	tfd_read_wait;
-	kcondvar_t	tfd_restart_wait;
 	struct selinfo	tfd_read_sel;
 	int64_t		tfd_nwaiters;
 	bool		tfd_cancel_on_set;
@@ -162,7 +161,6 @@ timerfd_create(clockid_t const clock_id,
 	KASSERT(clock_id == CLOCK_REALTIME || clock_id == CLOCK_MONOTONIC);
 
 	cv_init(&tfd->tfd_read_wait, "tfdread");
-	cv_init(&tfd->tfd_restart_wait, "tfdrstrt");
 	selinit(&tfd->tfd_read_sel);
 	getnanotime(&tfd->tfd_btime);
 
@@ -188,14 +186,12 @@ timerfd_destroy(struct timerfd * const t
 {
 
 	KASSERT(tfd->tfd_nwaiters == 0);
-	KASSERT(tfd->tfd_restarting == false);
 
 	itimer_lock();
 	itimer_poison(&tfd->tfd_itimer);
 	itimer_fini(&tfd->tfd_itimer);	/* drops itimer lock */
 
 	cv_destroy(&tfd->tfd_read_wait);
-	cv_destroy(&tfd->tfd_restart_wait);
 
 	seldestroy(&tfd->tfd_read_sel);
 
@@ -219,11 +215,10 @@ timerfd_wait(struct timerfd * const tfd,
 	}
 
 	/*
-	 * We're going to block.  If there is a restart in-progress,
-	 * wait for that to complete first.
+	 * We're going to block.  Check if we need to return ERESTART.
 	 */
-	while (tfd->tfd_restarting) {
-		cv_wait(&tfd->tfd_restart_wait, &itimer_mutex);
+	if (tfd->tfd_restarting) {
+		return ERESTART;
 	}
 
 	tfd->tfd_nwaiters++;
@@ -234,18 +229,12 @@ timerfd_wait(struct timerfd * const tfd,
 
 	/*
 	 * If a restart was triggered while we were asleep, we need
-	 * to return ERESTART if no other error was returned.  If we
-	 * are the last waiter coming out of the restart drain, clear
-	 * the condition.
+	 * to return ERESTART if no other error was returned.
 	 */
 	if (tfd->tfd_restarting) {
 		if (error == 0) {
 			error = ERESTART;
 		}
-		if (tfd->tfd_nwaiters == 0) {
-			tfd->tfd_restarting = false;
-			cv_broadcast(&tfd->tfd_restart_wait);
-		}
 	}
 
 	return error;

Reply via email to