diff options
author | 2021-01-11 18:49:38 +0000 | |
---|---|---|
committer | 2021-01-11 18:49:38 +0000 | |
commit | 868335c7a7e1386e7268543f493441a6399c72a6 (patch) | |
tree | eff3398b964667b0196d68f054838093b1d649cd | |
parent | Print error if SSL_{connect,accept,shutdown}(3) don't run to completion. (diff) | |
download | wireguard-openbsd-868335c7a7e1386e7268543f493441a6399c72a6.tar.xz wireguard-openbsd-868335c7a7e1386e7268543f493441a6399c72a6.zip |
New rw_obj_init() API providing reference-counted rwlock.
Original port from NetBSD by guenther@, required for upcoming amap & anon
locking.
ok kettenis@
-rw-r--r-- | sys/kern/init_main.c | 3 | ||||
-rw-r--r-- | sys/kern/kern_rwlock.c | 123 | ||||
-rw-r--r-- | sys/sys/rwlock.h | 24 |
3 files changed, 147 insertions, 3 deletions
diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c index 5825a1471cb..dd78c085828 100644 --- a/sys/kern/init_main.c +++ b/sys/kern/init_main.c @@ -1,4 +1,4 @@ -/* $OpenBSD: init_main.c,v 1.304 2021/01/01 07:00:33 jsg Exp $ */ +/* $OpenBSD: init_main.c,v 1.305 2021/01/11 18:49:38 mpi Exp $ */ /* $NetBSD: init_main.c,v 1.84.4.1 1996/06/02 09:08:06 mrg Exp $ */ /* @@ -232,6 +232,7 @@ main(void *framep) KERNEL_LOCK_INIT(); SCHED_LOCK_INIT(); + rw_obj_init(); uvm_init(); disk_init(); /* must come before autoconfiguration */ tty_init(); /* initialise tty's */ diff --git a/sys/kern/kern_rwlock.c b/sys/kern/kern_rwlock.c index 406df8f6007..c73b1b17fa1 100644 --- a/sys/kern/kern_rwlock.c +++ b/sys/kern/kern_rwlock.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_rwlock.c,v 1.45 2020/03/02 17:07:49 visa Exp $ */ +/* $OpenBSD: kern_rwlock.c,v 1.46 2021/01/11 18:49:38 mpi Exp $ */ /* * Copyright (c) 2002, 2003 Artur Grabowski <art@openbsd.org> @@ -19,6 +19,7 @@ #include <sys/param.h> #include <sys/systm.h> +#include <sys/pool.h> #include <sys/proc.h> #include <sys/rwlock.h> #include <sys/limits.h> @@ -488,3 +489,123 @@ rrw_status(struct rrwlock *rrwl) { return (rw_status(&rrwl->rrwl_lock)); } + +/*- + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Andrew Doran. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#define RWLOCK_OBJ_MAGIC 0x5aa3c85d +struct rwlock_obj { + struct rwlock ro_lock; + u_int ro_magic; + u_int ro_refcnt; +}; + + +struct pool rwlock_obj_pool; + +/* + * rw_obj_init: + * + * Initialize the mutex object store. + */ +void +rw_obj_init(void) +{ + pool_init(&rwlock_obj_pool, sizeof(struct rwlock_obj), 0, IPL_MPFLOOR, + PR_WAITOK, "rwobjpl", NULL); +} + +/* + * rw_obj_alloc: + * + * Allocate a single lock object. + */ +void +_rw_obj_alloc_flags(struct rwlock **lock, const char *name, int flags, + struct lock_type *type) +{ + struct rwlock_obj *mo; + + mo = pool_get(&rwlock_obj_pool, PR_WAITOK); + mo->ro_magic = RWLOCK_OBJ_MAGIC; + _rw_init_flags(&mo->ro_lock, name, flags, type); + mo->ro_refcnt = 1; + + *lock = &mo->ro_lock; +} + +/* + * rw_obj_hold: + * + * Add a single reference to a lock object. A reference to the object + * must already be held, and must be held across this call. + */ + +void +rw_obj_hold(struct rwlock *lock) +{ + struct rwlock_obj *mo = (struct rwlock_obj *)lock; + + KASSERTMSG(mo->ro_magic == RWLOCK_OBJ_MAGIC, + "%s: lock %p: mo->ro_magic (%#x) != RWLOCK_OBJ_MAGIC (%#x)", + __func__, mo, mo->ro_magic, RWLOCK_OBJ_MAGIC); + KASSERTMSG(mo->ro_refcnt > 0, + "%s: lock %p: mo->ro_refcnt (%#x) == 0", + __func__, mo, mo->ro_refcnt); + + atomic_inc_int(&mo->ro_refcnt); +} + +/* + * rw_obj_free: + * + * Drop a reference from a lock object. If the last reference is being + * dropped, free the object and return true. Otherwise, return false. + */ +int +rw_obj_free(struct rwlock *lock) +{ + struct rwlock_obj *mo = (struct rwlock_obj *)lock; + + KASSERTMSG(mo->ro_magic == RWLOCK_OBJ_MAGIC, + "%s: lock %p: mo->ro_magic (%#x) != RWLOCK_OBJ_MAGIC (%#x)", + __func__, mo, mo->ro_magic, RWLOCK_OBJ_MAGIC); + KASSERTMSG(mo->ro_refcnt > 0, + "%s: lock %p: mo->ro_refcnt (%#x) == 0", + __func__, mo, mo->ro_refcnt); + + if (atomic_dec_int_nv(&mo->ro_refcnt) > 0) { + return false; + } +#if notyet + WITNESS_DESTROY(&mo->ro_lock); +#endif + pool_put(&rwlock_obj_pool, mo); + return true; +} diff --git a/sys/sys/rwlock.h b/sys/sys/rwlock.h index 9e6a7a26895..f5a2504f4e8 100644 --- a/sys/sys/rwlock.h +++ b/sys/sys/rwlock.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rwlock.h,v 1.27 2020/12/15 10:23:01 mpi Exp $ */ +/* $OpenBSD: rwlock.h,v 1.28 2021/01/11 18:49:38 mpi Exp $ */ /* * Copyright (c) 2002 Artur Grabowski <art@openbsd.org> * @@ -209,6 +209,28 @@ int rrw_status(struct rrwlock *); #define rrw_init(rrwl, name) _rrw_init_flags(rrwl, name, 0, NULL) #endif /* WITNESS */ + +/* + * Allocated, reference-counted rwlocks + */ + +#ifdef WITNESS +#define rw_obj_alloc_flags(rwl, name, flags) do { \ + static struct lock_type __lock_type = { .lt_name = #rwl }; \ + _rw_obj_alloc_flags(rwl, name, flags, &__lock_type); \ +} while (0) +#else +#define rw_obj_alloc_flags(rwl, name, flags) \ + _rw_obj_alloc_flags(rwl, name, flags, NULL) +#endif +#define rw_obj_alloc(rwl, name) rw_obj_alloc_flags(rwl, name, 0) + +void rw_obj_init(void); +void _rw_obj_alloc_flags(struct rwlock **, const char *, int, + struct lock_type *); +void rw_obj_hold(struct rwlock *); +int rw_obj_free(struct rwlock *); + #endif /* _KERNEL */ #endif /* _SYS_RWLOCK_H */ |