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;