Home | History | Annotate | Line # | Download | only in sys
      1 /*	$NetBSD: rwlock.h,v 1.19 2023/09/07 20:05:41 ad Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2002, 2006, 2007, 2008, 2019, 2020 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Jason R. Thorpe and Andrew Doran.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #ifndef _SYS_RWLOCK_H_
     33 #define	_SYS_RWLOCK_H_
     34 
     35 /*
     36  * The rwlock provides exclusive access when held as a "writer",
     37  * and shared access when held as a "reader".
     38  *
     39  * Architectures may optionally provide stubs for the following functions to
     40  * implement the easy (unlocked, no waiters) cases.  If these stubs are
     41  * provided, __HAVE_RW_STUBS should be defined.
     42  *
     43  *	rw_enter()
     44  *	rw_exit()
     45  *	rw_tryenter()
     46  */
     47 
     48 #if !defined(_KERNEL)
     49 #include <sys/types.h>
     50 #include <sys/inttypes.h>
     51 #endif
     52 
     53 typedef enum krw_t {
     54 	RW_READER = 0,
     55 	RW_WRITER = 1
     56 } krw_t;
     57 
     58 typedef struct krwlock krwlock_t;
     59 
     60 #ifdef __RWLOCK_PRIVATE
     61 #include <sys/stdbool.h>
     62 /*
     63  * Bits in the owner field of the lock that indicate lock state.  If the
     64  * WRITE_LOCKED bit is clear, then the owner field is actually a count of
     65  * the number of readers.  The rw_owner field is laid out like so:
     66  *
     67  *  N                     5        4        3        2        1        0
     68  *  +------------------------------------------------------------------+
     69  *  | owner or read count | nodbug | <free> | wrlock | wrwant |  wait  |
     70  *  +------------------------------------------------------------------+
     71  */
     72 #define	RW_HAS_WAITERS		0x01UL	/* lock has waiters */
     73 #define	RW_WRITE_WANTED		0x02UL	/* >= 1 waiter is a writer */
     74 #define	RW_WRITE_LOCKED		0x04UL	/* lock is currently write locked */
     75 #define	RW_NODEBUG		0x10UL	/* LOCKDEBUG disabled */
     76 
     77 #define	RW_READ_COUNT_SHIFT	5
     78 #define	RW_READ_INCR		(1UL << RW_READ_COUNT_SHIFT)
     79 #define	RW_THREAD		((uintptr_t)-RW_READ_INCR)
     80 #define	RW_OWNER(rw)		((rw)->rw_owner & RW_THREAD)
     81 #define	RW_COUNT(rw)		((rw)->rw_owner & RW_THREAD)
     82 #define	RW_FLAGS(rw)		((rw)->rw_owner & ~RW_THREAD)
     83 
     84 void	rw_vector_enter(krwlock_t *, const krw_t);
     85 void	rw_vector_exit(krwlock_t *);
     86 int	rw_vector_tryenter(krwlock_t *, const krw_t);
     87 #endif	/* __RWLOCK_PRIVATE */
     88 
     89 struct krwlock {
     90 	volatile uintptr_t	rw_owner;
     91 };
     92 
     93 #ifdef _KERNEL
     94 
     95 void	_rw_init(krwlock_t *, uintptr_t);
     96 void	rw_init(krwlock_t *);
     97 void	rw_destroy(krwlock_t *);
     98 
     99 int	rw_tryenter(krwlock_t *, const krw_t);
    100 int	rw_tryupgrade(krwlock_t *);
    101 void	rw_downgrade(krwlock_t *);
    102 
    103 int	rw_read_held(krwlock_t *);
    104 int	rw_write_held(krwlock_t *);
    105 int	rw_lock_held(krwlock_t *);
    106 krw_t	rw_lock_op(krwlock_t *);
    107 
    108 void	rw_enter(krwlock_t *, const krw_t);
    109 void	rw_exit(krwlock_t *);
    110 
    111 void	rw_obj_init(void);
    112 krwlock_t *rw_obj_alloc(void);
    113 void	rw_obj_hold(krwlock_t *);
    114 bool	rw_obj_free(krwlock_t *);
    115 u_int	rw_obj_refcnt(krwlock_t *);
    116 krwlock_t *rw_obj_tryalloc(void);
    117 
    118 #endif	/* _KERNEL */
    119 
    120 #endif /* _SYS_RWLOCK_H_ */
    121