summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/sys/condvar_impl.h
blob: a5b8038b3927ef623c1127945e514ea87370505a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef _SYS_CONDVAR_IMPL_H
#define	_SYS_CONDVAR_IMPL_H

/*
 * Implementation-private definitions for condition variables
 */

#ifndef	_ASM
#include <sys/types.h>
#include <sys/thread.h>
#endif	/* _ASM */

#ifdef	__cplusplus
extern "C" {
#endif

#ifndef	_ASM

/*
 * Condtion variables.
 */

typedef struct _condvar_impl {
	ushort_t	cv_waiters;
} condvar_impl_t;

#define	CV_HAS_WAITERS(cvp)	(((condvar_impl_t *)(cvp))->cv_waiters != 0)

#endif	/* _ASM */


/*
 * The cvwaitlock_t structure and associated macros provide an implementation
 * of a locking mechanism that allows recursion on the reader lock without
 * danger of a pending write lock elsewhere being able to cause a deadlock.
 * The provision for supporting recursion is necessary for use with the
 * netinfo (neti) kernel module when processing network data.
 *
 * Support for recursion (giving precedence to readers and allowing them
 * to enter even when a write is blocked) can result in write starvation.
 * There is no priority inheritence for this locking interface.
 */
typedef	struct	cvwaitlock_s	{
	kmutex_t	cvw_lock;
	kcondvar_t	cvw_waiter;
	int		cvw_refcnt;
} cvwaitlock_t;


#define	CVW_INIT(_c)		{				\
	mutex_init(&(_c)->cvw_lock, NULL, MUTEX_DRIVER, NULL);	\
	cv_init(&(_c)->cvw_waiter, NULL, CV_DRIVER, NULL);	\
	(_c)->cvw_refcnt = 0;					\
}

#define	CVW_ENTER_READ(_c)	{				\
	mutex_enter(&(_c)->cvw_lock);				\
	while ((_c)->cvw_refcnt < 0)				\
		cv_wait(&((_c)->cvw_waiter), &(_c)->cvw_lock);	\
	(_c)->cvw_refcnt++;					\
	mutex_exit(&(_c)->cvw_lock);				\
}

#define	CVW_ENTER_WRITE(_c)	{				\
	mutex_enter(&(_c)->cvw_lock);				\
	while ((_c)->cvw_refcnt != 0)				\
		cv_wait(&((_c)->cvw_waiter), &(_c)->cvw_lock);	\
	(_c)->cvw_refcnt = -1;					\
	mutex_exit(&(_c)->cvw_lock);				\
}

#define	CVW_EXIT_READ(_c)	{			\
	mutex_enter(&(_c)->cvw_lock);			\
	ASSERT((_c)->cvw_refcnt > 0);			\
	if ((--((_c)->cvw_refcnt)) == 0)		\
		cv_broadcast(&(_c)->cvw_waiter);	\
	mutex_exit(&(_c)->cvw_lock);			\
}

#define	CVW_EXIT_WRITE(_c)	{			\
	mutex_enter(&(_c)->cvw_lock);			\
	ASSERT((_c)->cvw_refcnt == -1);			\
	(_c)->cvw_refcnt = 0;				\
	cv_broadcast(&(_c)->cvw_waiter);		\
	mutex_exit(&(_c)->cvw_lock);			\
}

#define	CVW_WRITE_TO_READ(_c)	{			\
	mutex_enter(&(_c)->cvw_lock);			\
	ASSERT((_c)->cvw_refcnt == -1);			\
	(_c)->cvw_refcnt = 1;				\
	cv_broadcast(&(_c)->cvw_waiter);		\
	mutex_exit(&(_c)->cvw_lock);			\
}

#define	CVW_DESTROY(_c)	{				\
	mutex_destroy(&(_c)->cvw_lock);			\
	cv_destroy(&(_c)->cvw_waiter);			\
}

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_CONDVAR_IMPL_H */