Module Name: src Committed By: riastradh Date: Sun Dec 19 11:21:30 UTC 2021
Modified Files: src/sys/external/bsd/drm2/include/linux: rwsem.h src/sys/external/bsd/drm2/linux: files.drmkms_linux Added Files: src/sys/external/bsd/drm2/linux: linux_rwsem.c Log Message: linux: Draft rwsem with bodgy semantics. To generate a diff of this commit: cvs rdiff -u -r1.2 -r1.3 src/sys/external/bsd/drm2/include/linux/rwsem.h cvs rdiff -u -r1.29 -r1.30 src/sys/external/bsd/drm2/linux/files.drmkms_linux cvs rdiff -u -r0 -r1.1 src/sys/external/bsd/drm2/linux/linux_rwsem.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/include/linux/rwsem.h diff -u src/sys/external/bsd/drm2/include/linux/rwsem.h:1.2 src/sys/external/bsd/drm2/include/linux/rwsem.h:1.3 --- src/sys/external/bsd/drm2/include/linux/rwsem.h:1.2 Mon Aug 27 07:47:01 2018 +++ src/sys/external/bsd/drm2/include/linux/rwsem.h Sun Dec 19 11:21:30 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: rwsem.h,v 1.2 2018/08/27 07:47:01 riastradh Exp $ */ +/* $NetBSD: rwsem.h,v 1.3 2021/12/19 11:21:30 riastradh Exp $ */ /*- * Copyright (c) 2014 The NetBSD Foundation, Inc. @@ -45,64 +45,30 @@ #include <sys/mutex.h> +#define destroy_rwsem linux_destroy_rwsem +#define down_read linux_down_read +#define down_read_trylock linux_down_read_trylock +#define down_write linux_down_write +#define downgrade_write linux_downgrade_write +#define init_rwsem linux_init_rwsem +#define up_read linux_up_read +#define up_write linux_up_write + struct rw_semaphore { - krwlock_t rws_lock; + kmutex_t rws_lock; + kcondvar_t rws_cv; + struct lwp *rws_writer; + unsigned rws_readers; + bool rws_writewanted; }; -static inline void -init_rwsem(struct rw_semaphore *rwsem) -{ - - rw_init(&rwsem->rws_lock); -} - -static inline void -destroy_rwsem(struct rw_semaphore *rwsem) -{ - - rw_destroy(&rwsem->rws_lock); -} - -static inline void -down_read(struct rw_semaphore *rwsem) -{ - - rw_enter(&rwsem->rws_lock, RW_READER); -} - -static inline bool -down_read_trylock(struct rw_semaphore *rwsem) -{ - - return rw_tryenter(&rwsem->rws_lock, RW_READER); -} - -static inline void -down_write(struct rw_semaphore *rwsem) -{ - - rw_enter(&rwsem->rws_lock, RW_WRITER); -} - -static inline void -up_read(struct rw_semaphore *rwsem) -{ - - rw_exit(&rwsem->rws_lock); -} - -static inline void -up_write(struct rw_semaphore *rwsem) -{ - - rw_exit(&rwsem->rws_lock); -} - -static inline void -downgrade_write(struct rw_semaphore *rwsem) -{ - - rw_downgrade(&rwsem->rws_lock); -} +void init_rwsem(struct rw_semaphore *); +void destroy_rwsem(struct rw_semaphore *); +void down_read(struct rw_semaphore *); +bool down_read_trylock(struct rw_semaphore *); +void down_write(struct rw_semaphore *); +void up_read(struct rw_semaphore *); +void up_write(struct rw_semaphore *); +void downgrade_write(struct rw_semaphore *); #endif /* _LINUX_RWSEM_H_ */ Index: src/sys/external/bsd/drm2/linux/files.drmkms_linux diff -u src/sys/external/bsd/drm2/linux/files.drmkms_linux:1.29 src/sys/external/bsd/drm2/linux/files.drmkms_linux:1.30 --- src/sys/external/bsd/drm2/linux/files.drmkms_linux:1.29 Sun Dec 19 10:55:27 2021 +++ src/sys/external/bsd/drm2/linux/files.drmkms_linux Sun Dec 19 11:21:30 2021 @@ -1,4 +1,4 @@ -# $NetBSD: files.drmkms_linux,v 1.29 2021/12/19 10:55:27 riastradh Exp $ +# $NetBSD: files.drmkms_linux,v 1.30 2021/12/19 11:21:30 riastradh Exp $ define drmkms_linux: i2cexec, i2c_bitbang @@ -19,6 +19,7 @@ file external/bsd/drm2/linux/linux_kmap. file external/bsd/drm2/linux/linux_list_sort.c drmkms_linux file external/bsd/drm2/linux/linux_module.c drmkms_linux file external/bsd/drm2/linux/linux_pci.c drmkms_linux +file external/bsd/drm2/linux/linux_rwsem.c drmkms_linux file external/bsd/drm2/linux/linux_stop_machine.c drmkms_linux file external/bsd/drm2/linux/linux_sync_file.c drmkms_linux file external/bsd/drm2/linux/linux_wait_bit.c drmkms_linux Added files: Index: src/sys/external/bsd/drm2/linux/linux_rwsem.c diff -u /dev/null src/sys/external/bsd/drm2/linux/linux_rwsem.c:1.1 --- /dev/null Sun Dec 19 11:21:30 2021 +++ src/sys/external/bsd/drm2/linux/linux_rwsem.c Sun Dec 19 11:21:30 2021 @@ -0,0 +1,166 @@ +/* $NetBSD: linux_rwsem.c,v 1.1 2021/12/19 11:21:30 riastradh Exp $ */ + +/*- + * Copyright (c) 2021 The NetBSD Foundation, Inc. + * All rights reserved. + * + * 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. + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: linux_rwsem.c,v 1.1 2021/12/19 11:21:30 riastradh Exp $"); + +#include <sys/types.h> + +#include <sys/condvar.h> +#include <sys/lwp.h> +#include <sys/rwlock.h> + +#include <machine/limits.h> + +#include <lib/libkern/libkern.h> + +#include <linux/rwsem.h> + +void +init_rwsem(struct rw_semaphore *rwsem) +{ + + mutex_init(&rwsem->rws_lock, MUTEX_DEFAULT, IPL_NONE); + cv_init(&rwsem->rws_cv, "lnxrwsem"); + rwsem->rws_writer = NULL; + rwsem->rws_readers = 0; +} + +void +destroy_rwsem(struct rw_semaphore *rwsem) +{ + + KASSERT(rwsem->rws_readers == 0); + KASSERT(rwsem->rws_writer == NULL); + cv_destroy(&rwsem->rws_cv); + mutex_destroy(&rwsem->rws_lock); +} + +void +down_read(struct rw_semaphore *rwsem) +{ + + mutex_enter(&rwsem->rws_lock); + while (rwsem->rws_writer || rwsem->rws_writewanted) + cv_wait(&rwsem->rws_cv, &rwsem->rws_lock); + KASSERT(rwsem->rws_readers < UINT_MAX); + rwsem->rws_readers++; + mutex_exit(&rwsem->rws_lock); +} + +bool +down_read_trylock(struct rw_semaphore *rwsem) +{ + bool ret = false; + + /* + * Note: Linux apparently relies on down_read_trylock to + * quietly succeed when the caller already holds a reader lock. + * This is why we can't use rwlock(9), which absolutely + * prohibits recursive use and crashes immediately under + * LOCKDEBUG if you try it. + */ + + mutex_enter(&rwsem->rws_lock); + if (rwsem->rws_writer == NULL && !rwsem->rws_writewanted) { + KASSERT(rwsem->rws_readers < UINT_MAX); + rwsem->rws_readers++; + ret = true; + } + mutex_exit(&rwsem->rws_lock); + + return ret; +} + +void +up_read(struct rw_semaphore *rwsem) +{ + + mutex_enter(&rwsem->rws_lock); + KASSERT(rwsem->rws_readers); + KASSERT(rwsem->rws_writer == NULL); + if (--rwsem->rws_readers == 0) + cv_broadcast(&rwsem->rws_cv); + mutex_exit(&rwsem->rws_lock); +} + +void +down_write(struct rw_semaphore *rwsem) +{ + + mutex_enter(&rwsem->rws_lock); + + /* If another writer is waiting, get in the queue. */ + while (rwsem->rws_writewanted) + cv_wait(&rwsem->rws_cv, &rwsem->rws_lock); + + /* + * No other writers waiting. Our turn. Announce our intent to + * readers, and wait for the writer or readers to finish. + */ + rwsem->rws_writewanted = true; + while (rwsem->rws_writer || rwsem->rws_readers) { + KASSERTMSG(rwsem->rws_writer != curlwp, + "locking against myself: rwsem=%p lwp=%p", rwsem, curlwp); + cv_wait(&rwsem->rws_cv, &rwsem->rws_lock); + } + + /* At last, it is ours! */ + KASSERT(rwsem->rws_readers == 0); + KASSERT(rwsem->rws_writer == NULL); + KASSERT(rwsem->rws_writewanted); + rwsem->rws_writewanted = false; + rwsem->rws_writer = curlwp; + + mutex_exit(&rwsem->rws_lock); +} + +void +up_write(struct rw_semaphore *rwsem) +{ + + mutex_enter(&rwsem->rws_lock); + KASSERT(rwsem->rws_writer == curlwp); + KASSERT(rwsem->rws_readers == 0); + rwsem->rws_writer = NULL; + cv_broadcast(&rwsem->rws_cv); + mutex_exit(&rwsem->rws_lock); +} + +void +downgrade_write(struct rw_semaphore *rwsem) +{ + + mutex_enter(&rwsem->rws_lock); + KASSERT(rwsem->rws_writer == curlwp); + KASSERT(rwsem->rws_readers == 0); + rwsem->rws_writer = NULL; + rwsem->rws_readers = 1; + cv_broadcast(&rwsem->rws_cv); + mutex_exit(&rwsem->rws_lock); +}