xref: /freebsd/sys/contrib/openzfs/lib/libspl/rwlock.c (revision 22649d4dba730d46244fd2dff4fd174903c8379f)
1 // SPDX-License-Identifier: CDDL-1.0
2 /*
3  * This file and its contents are supplied under the terms of the
4  * Common Development and Distribution License ("CDDL"), version 1.0.
5  * You may only use this file in accordance with the terms of version
6  * 1.0 of the CDDL.
7  *
8  * A full copy of the text of the CDDL should have accompanied this
9  * source.  A copy of the CDDL is also available via the Internet at
10  * https://opensource.org/license/CDDL-1.0.
11  */
12 /*
13  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
14  * Copyright (c) 2012, 2018 by Delphix. All rights reserved.
15  * Copyright (c) 2016 Actifio, Inc. All rights reserved.
16  * Copyright (c) 2025, Klara, Inc.
17  */
18 
19 #include <assert.h>
20 #include <pthread.h>
21 #include <errno.h>
22 #include <atomic.h>
23 #include <sys/rwlock.h>
24 
25 /*
26  * =========================================================================
27  * rwlocks
28  * =========================================================================
29  */
30 
31 void
rw_init(krwlock_t * rwlp,char * name,int type,void * arg)32 rw_init(krwlock_t *rwlp, char *name, int type, void *arg)
33 {
34 	(void) name, (void) type, (void) arg;
35 	VERIFY0(pthread_rwlock_init(&rwlp->rw_lock, NULL));
36 	rwlp->rw_readers = 0;
37 	rwlp->rw_owner = 0;
38 }
39 
40 void
rw_destroy(krwlock_t * rwlp)41 rw_destroy(krwlock_t *rwlp)
42 {
43 	VERIFY0(pthread_rwlock_destroy(&rwlp->rw_lock));
44 }
45 
46 void
rw_enter(krwlock_t * rwlp,krw_t rw)47 rw_enter(krwlock_t *rwlp, krw_t rw)
48 {
49 	if (rw == RW_READER) {
50 		VERIFY0(pthread_rwlock_rdlock(&rwlp->rw_lock));
51 		atomic_inc_uint(&rwlp->rw_readers);
52 	} else {
53 		VERIFY0(pthread_rwlock_wrlock(&rwlp->rw_lock));
54 		rwlp->rw_owner = pthread_self();
55 	}
56 }
57 
58 void
rw_exit(krwlock_t * rwlp)59 rw_exit(krwlock_t *rwlp)
60 {
61 	if (RW_READ_HELD(rwlp))
62 		atomic_dec_uint(&rwlp->rw_readers);
63 	else
64 		rwlp->rw_owner = 0;
65 
66 	VERIFY0(pthread_rwlock_unlock(&rwlp->rw_lock));
67 }
68 
69 int
rw_tryenter(krwlock_t * rwlp,krw_t rw)70 rw_tryenter(krwlock_t *rwlp, krw_t rw)
71 {
72 	int error;
73 
74 	if (rw == RW_READER)
75 		error = pthread_rwlock_tryrdlock(&rwlp->rw_lock);
76 	else
77 		error = pthread_rwlock_trywrlock(&rwlp->rw_lock);
78 
79 	if (error == 0) {
80 		if (rw == RW_READER)
81 			atomic_inc_uint(&rwlp->rw_readers);
82 		else
83 			rwlp->rw_owner = pthread_self();
84 
85 		return (1);
86 	}
87 
88 	VERIFY3S(error, ==, EBUSY);
89 
90 	return (0);
91 }
92 
93 int
rw_tryupgrade(krwlock_t * rwlp)94 rw_tryupgrade(krwlock_t *rwlp)
95 {
96 	(void) rwlp;
97 	return (0);
98 }
99