rwlock.h 3.57 KB
Newer Older
Bob Halley's avatar
Bob Halley committed
1
/*
2
 * Copyright (C) 1998-2001, 2003-2007, 2016, 2017  Internet Systems Consortium, Inc. ("ISC")
3
 *
4
5
6
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
Bob Halley's avatar
Bob Halley committed
7
 */
Bob Halley's avatar
add    
Bob Halley committed
8

Automatic Updater's avatar
Automatic Updater committed
9
/* $Id: rwlock.h,v 1.28 2007/06/19 23:47:18 tbox Exp $ */
David Lawrence's avatar
David Lawrence committed
10

Bob Halley's avatar
add    
Bob Halley committed
11
12
13
#ifndef ISC_RWLOCK_H
#define ISC_RWLOCK_H 1

14
/*! \file isc/rwlock.h */
15

Mark Andrews's avatar
Mark Andrews committed
16
#include <isc/condition.h>
Bob Halley's avatar
Bob Halley committed
17
#include <isc/lang.h>
Mark Andrews's avatar
Mark Andrews committed
18
#include <isc/platform.h>
19
#include <isc/types.h>
Bob Halley's avatar
add    
Bob Halley committed
20

21
#if defined(ISC_PLATFORM_HAVESTDATOMIC)
22
#include <stdint.h>
23
24
25
#include <stdatomic.h>
#endif

Bob Halley's avatar
Bob Halley committed
26
27
ISC_LANG_BEGINDECLS

Bob Halley's avatar
add    
Bob Halley committed
28
typedef enum {
29
30
	isc_rwlocktype_none = 0,
	isc_rwlocktype_read,
Bob Halley's avatar
add    
Bob Halley committed
31
32
33
	isc_rwlocktype_write
} isc_rwlocktype_t;

Brian Wellington's avatar
Brian Wellington committed
34
#ifdef ISC_PLATFORM_USETHREADS
35
#if (defined(ISC_PLATFORM_HAVESTDATOMIC) && defined(ATOMIC_INT_LOCK_FREE)) || (defined(ISC_PLATFORM_HAVEXADD) && defined(ISC_PLATFORM_HAVECMPXCHG))
36
#define ISC_RWLOCK_USEATOMIC 1
37
38
39
#if (defined(ISC_PLATFORM_HAVESTDATOMIC) && defined(ATOMIC_INT_LOCK_FREE))
#define ISC_RWLOCK_USESTDATOMIC 1
#endif
40
41
#endif

42
struct isc_rwlock {
Bob Halley's avatar
Bob Halley committed
43
	/* Unlocked. */
Bob Halley's avatar
Bob Halley committed
44
	unsigned int		magic;
Bob Halley's avatar
add    
Bob Halley committed
45
	isc_mutex_t		lock;
Evan Hunt's avatar
Evan Hunt committed
46
	isc_int32_t		spins;
47

48
#if defined(ISC_RWLOCK_USEATOMIC)
49
50
51
52
53
54
55
56
57
58
59
60
61
62
	/*
	 * When some atomic instructions with hardware assistance are
	 * available, rwlock will use those so that concurrent readers do not
	 * interfere with each other through mutex as long as no writers
	 * appear, massively reducing the lock overhead in the typical case.
	 *
	 * The basic algorithm of this approach is the "simple
	 * writer-preference lock" shown in the following URL:
	 * http://www.cs.rochester.edu/u/scott/synchronization/pseudocode/rw.html
	 * but our implementation does not rely on the spin lock unlike the
	 * original algorithm to be more portable as a user space application.
	 */

	/* Read or modified atomically. */
63
64
65
66
67
#if defined(ISC_RWLOCK_USESTDATOMIC)
	atomic_int_fast32_t	write_requests;
	atomic_int_fast32_t	write_completions;
	atomic_int_fast32_t	cnt_and_flag;
#else
68
69
70
	isc_int32_t		write_requests;
	isc_int32_t		write_completions;
	isc_int32_t		cnt_and_flag;
71
#endif
72
73
74
75
76
77
78
79
80
81
82
83

	/* Locked by lock. */
	isc_condition_t		readable;
	isc_condition_t		writeable;
	unsigned int		readers_waiting;

	/* Locked by rwlock itself. */
	unsigned int		write_granted;

	/* Unlocked. */
	unsigned int		write_quota;

84
#else  /* ISC_RWLOCK_USEATOMIC */
85

86
	/*%< Locked by lock. */
Bob Halley's avatar
add    
Bob Halley committed
87
88
89
	isc_condition_t		readable;
	isc_condition_t		writeable;
	isc_rwlocktype_t	type;
Andreas Gustafsson's avatar
Andreas Gustafsson committed
90

91
	/*% The number of threads that have the lock. */
Bob Halley's avatar
add    
Bob Halley committed
92
	unsigned int		active;
Andreas Gustafsson's avatar
Andreas Gustafsson committed
93

94
	/*%
Andreas Gustafsson's avatar
Andreas Gustafsson committed
95
96
97
98
	 * The number of lock grants made since the lock was last switched
	 * from reading to writing or vice versa; used in determining
	 * when the quota is reached and it is time to switch.
	 */
Bob Halley's avatar
add    
Bob Halley committed
99
	unsigned int		granted;
100

Bob Halley's avatar
add    
Bob Halley committed
101
102
103
	unsigned int		readers_waiting;
	unsigned int		writers_waiting;
	unsigned int		read_quota;
Bob Halley's avatar
Bob Halley committed
104
	unsigned int		write_quota;
105
	isc_rwlocktype_t	original;
106
#endif  /* ISC_RWLOCK_USEATOMIC */
107
};
Brian Wellington's avatar
Brian Wellington committed
108
109
110
111
112
113
114
115
#else /* ISC_PLATFORM_USETHREADS */
struct isc_rwlock {
	unsigned int		magic;
	isc_rwlocktype_t	type;
	unsigned int		active;
};
#endif /* ISC_PLATFORM_USETHREADS */

Bob Halley's avatar
add    
Bob Halley committed
116
117

isc_result_t
Bob Halley's avatar
Bob Halley committed
118
119
isc_rwlock_init(isc_rwlock_t *rwl, unsigned int read_quota,
		unsigned int write_quota);
Bob Halley's avatar
add    
Bob Halley committed
120
121
122
123

isc_result_t
isc_rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type);

124
125
126
isc_result_t
isc_rwlock_trylock(isc_rwlock_t *rwl, isc_rwlocktype_t type);

Bob Halley's avatar
add    
Bob Halley committed
127
128
129
isc_result_t
isc_rwlock_unlock(isc_rwlock_t *rwl, isc_rwlocktype_t type);

130
131
132
133
134
135
isc_result_t
isc_rwlock_tryupgrade(isc_rwlock_t *rwl);

void
isc_rwlock_downgrade(isc_rwlock_t *rwl);

Bob Halley's avatar
add    
Bob Halley committed
136
137
138
void
isc_rwlock_destroy(isc_rwlock_t *rwl);

Bob Halley's avatar
Bob Halley committed
139
140
ISC_LANG_ENDDECLS

Bob Halley's avatar
add    
Bob Halley committed
141
#endif /* ISC_RWLOCK_H */