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