From: cheloha Date: Tue, 11 May 2021 13:29:25 +0000 (+0000) Subject: timeout_barrier(9), timeout_del_barrier(9): remove kernel lock X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=c34a0df36ba0cc1c1ddc1785bb2cf469469374a3;p=openbsd timeout_barrier(9), timeout_del_barrier(9): remove kernel lock In timeout_barrier(9) we take/release the kernel lock to ensure that the given timeout has finished running (if it had been running at all). This approach is inefficient. If we put a barrier timeout on the queue and wait for it to run in cond_wait(9) we can block instead of spinning for the kernel lock. We already do this for process-context timeouts in timeout_barrier(9) anyway. Discussed with dlg@, visa@, and mpi@. ok dlg@ --- diff --git a/share/man/man9/timeout.9 b/share/man/man9/timeout.9 index 6706bedbdec..b2836bd5e1f 100644 --- a/share/man/man9/timeout.9 +++ b/share/man/man9/timeout.9 @@ -1,4 +1,4 @@ -.\" $OpenBSD: timeout.9,v 1.52 2021/04/26 20:32:30 mvs Exp $ +.\" $OpenBSD: timeout.9,v 1.53 2021/05/11 13:29:25 cheloha Exp $ .\" .\" Copyright (c) 2000 Artur Grabowski .\" All rights reserved. @@ -23,7 +23,7 @@ .\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF .\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd $Mdocdate: April 26 2021 $ +.Dd $Mdocdate: May 11 2021 $ .Dt TIMEOUT_SET 9 .Os .Sh NAME @@ -194,11 +194,6 @@ but it will wait until any current execution of the timeout has completed. ensures that any current execution of the timeout in the argument .Fa to has completed before returning. -If the timeout -.Fa to -has been initialised with -.Fn timeout_set -it will take the kernel lock. .Pp The .Fn timeout_pending diff --git a/sys/kern/kern_timeout.c b/sys/kern/kern_timeout.c index acf752a8381..882560f6cda 100644 --- a/sys/kern/kern_timeout.c +++ b/sys/kern/kern_timeout.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_timeout.c,v 1.83 2021/02/08 08:18:45 mpi Exp $ */ +/* $OpenBSD: kern_timeout.c,v 1.84 2021/05/11 13:29:25 cheloha Exp $ */ /* * Copyright (c) 2001 Thomas Nordin * Copyright (c) 2000-2001 Artur Grabowski @@ -172,10 +172,10 @@ void softclock_create_thread(void *); void softclock_process_kclock_timeout(struct timeout *, int); void softclock_process_tick_timeout(struct timeout *, int); void softclock_thread(void *); +void timeout_barrier_timeout(void *); uint32_t timeout_bucket(const struct timeout *); uint32_t timeout_maskwheel(uint32_t, const struct timespec *); void timeout_run(struct timeout *); -void timeout_proc_barrier(void *); /* * The first thing in a struct timeout is its struct circq, so we @@ -490,34 +490,38 @@ timeout_del_barrier(struct timeout *to) void timeout_barrier(struct timeout *to) { - int needsproc = ISSET(to->to_flags, TIMEOUT_PROC); + struct timeout barrier; + struct cond c; + int procflag; - timeout_sync_order(needsproc); + procflag = (to->to_flags & TIMEOUT_PROC); + timeout_sync_order(procflag); - if (!needsproc) { - KERNEL_LOCK(); - splx(splsoftclock()); - KERNEL_UNLOCK(); - } else { - struct cond c = COND_INITIALIZER(); - struct timeout barrier; + timeout_set_flags(&barrier, timeout_barrier_timeout, &c, procflag); + barrier.to_process = curproc->p_p; + cond_init(&c); - timeout_set_proc(&barrier, timeout_proc_barrier, &c); - barrier.to_process = curproc->p_p; + mtx_enter(&timeout_mutex); - mtx_enter(&timeout_mutex); - SET(barrier.to_flags, TIMEOUT_ONQUEUE); + barrier.to_time = ticks; + SET(barrier.to_flags, TIMEOUT_ONQUEUE); + if (procflag) CIRCQ_INSERT_TAIL(&timeout_proc, &barrier.to_list); - mtx_leave(&timeout_mutex); + else + CIRCQ_INSERT_TAIL(&timeout_todo, &barrier.to_list); + mtx_leave(&timeout_mutex); + + if (procflag) wakeup_one(&timeout_proc); + else + softintr_schedule(softclock_si); - cond_wait(&c, "tmobar"); - } + cond_wait(&c, "tmobar"); } void -timeout_proc_barrier(void *arg) +timeout_barrier_timeout(void *arg) { struct cond *c = arg;