1241675Suqs/*
2241675Suqs * CDDL HEADER START
3241675Suqs *
4241675Suqs * The contents of this file are subject to the terms of the
5241675Suqs * Common Development and Distribution License (the "License").
6241675Suqs * You may not use this file except in compliance with the License.
7241675Suqs *
8241675Suqs * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9241675Suqs * or http://www.opensolaris.org/os/licensing.
10241675Suqs * See the License for the specific language governing permissions
11241675Suqs * and limitations under the License.
12241675Suqs *
13241675Suqs * When distributing Covered Code, include this CDDL HEADER in each
14241675Suqs * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15241675Suqs * If applicable, add the following below this CDDL HEADER, with the
16241675Suqs * fields enclosed by brackets "[]" replaced with your own identifying
17241675Suqs * information: Portions Copyright [yyyy] [name of copyright owner]
18241675Suqs *
19241675Suqs * CDDL HEADER END
20241675Suqs */
21241675Suqs
22241675Suqs/*
23241675Suqs * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
24241675Suqs */
25241675Suqs
26241675Suqs#ifndef	_SYNCH_H
27241675Suqs#define	_SYNCH_H
28241675Suqs
29241675Suqs/*
30241675Suqs * synch.h:
31241675Suqs * definitions needed to use the thread synchronization interface
32241675Suqs */
33241675Suqs
34241675Suqs#ifndef _ASM
35241675Suqs#include <sys/machlock.h>
36241675Suqs#include <sys/time_impl.h>
37241675Suqs#include <sys/synch.h>
38241675Suqs#endif /* _ASM */
39241675Suqs
40241675Suqs#ifdef __cplusplus
41241675Suqsextern "C" {
42241675Suqs#endif
43241675Suqs
44241675Suqs#ifndef _ASM
45241675Suqs
46241675Suqs/*
47241675Suqs * Semaphores
48241675Suqs */
49241675Suqstypedef struct _sema {
50241675Suqs	/* this structure must be the same as sem_t in <semaphore.h> */
51241675Suqs	uint32_t	count;		/* semaphore count */
52241675Suqs	uint16_t	type;
53241675Suqs	uint16_t	magic;
54241675Suqs	upad64_t	pad1[3];	/* reserved for a mutex_t */
55241675Suqs	upad64_t 	pad2[2];	/* reserved for a cond_t */
56241675Suqs} sema_t;
57241675Suqs
58241675Suqs/*
59241675Suqs * POSIX.1c Note:
60241675Suqs * POSIX.1c requires that <pthread.h> define the structures pthread_mutex_t
61241675Suqs * and pthread_cond_t.  These structures are identical to mutex_t (lwp_mutex_t)
62241675Suqs * and cond_t (lwp_cond_t) which are defined in <synch.h>.  A nested included
63241675Suqs * of <synch.h> (to allow a "#typedef mutex_t  pthread_mutex_t") would pull in
64241675Suqs * non-posix symbols/constants violating the namespace restrictions.  Hence,
65241675Suqs * pthread_mutex_t/pthread_cond_t have been redefined in <pthread.h> (actually
66241675Suqs * in <sys/types.h>).  Any modifications done to mutex_t/lwp_mutex_t or
67241675Suqs * cond_t/lwp_cond_t should also be done to pthread_mutex_t/pthread_cond_t.
68241675Suqs */
69241675Suqstypedef lwp_mutex_t mutex_t;
70241675Suqstypedef lwp_cond_t cond_t;
71241675Suqs
72241675Suqs/*
73241675Suqs * Readers/writer locks
74241675Suqs *
75241675Suqs * NOTE: The layout of this structure should be kept in sync with the layout
76241675Suqs * of the correponding structure of pthread_rwlock_t in sys/types.h.
77241675Suqs * Also, there is an identical structure for lwp_rwlock_t in <sys/synch.h>.
78241675Suqs * Because we have to deal with C++, we cannot redefine this one as that one.
79241675Suqs */
80241675Suqstypedef struct _rwlock {
81241675Suqs	int32_t		readers;	/* rwstate word */
82241675Suqs	uint16_t	type;
83241675Suqs	uint16_t	magic;
84241675Suqs	mutex_t		mutex;		/* used with process-shared rwlocks */
85241675Suqs	cond_t		readercv;	/* used only to indicate ownership */
86241675Suqs	cond_t		writercv;	/* used only to indicate ownership */
87241675Suqs} rwlock_t;
88241675Suqs
89241675Suqs#ifdef	__STDC__
90241675Suqsint	_lwp_mutex_lock(lwp_mutex_t *);
91241675Suqsint	_lwp_mutex_unlock(lwp_mutex_t *);
92241675Suqsint	_lwp_mutex_trylock(lwp_mutex_t *);
93241675Suqsint	_lwp_cond_wait(lwp_cond_t *, lwp_mutex_t *);
94241675Suqsint	_lwp_cond_timedwait(lwp_cond_t *, lwp_mutex_t *, timespec_t *);
95241675Suqsint	_lwp_cond_reltimedwait(lwp_cond_t *, lwp_mutex_t *, timespec_t *);
96241675Suqsint	_lwp_cond_signal(lwp_cond_t *);
97241675Suqsint	_lwp_cond_broadcast(lwp_cond_t *);
98241675Suqsint	_lwp_sema_init(lwp_sema_t *, int);
99241675Suqsint	_lwp_sema_wait(lwp_sema_t *);
100241675Suqsint	_lwp_sema_trywait(lwp_sema_t *);
101241675Suqsint	_lwp_sema_post(lwp_sema_t *);
102241675Suqsint	cond_init(cond_t *, int, void *);
103241675Suqsint	cond_destroy(cond_t *);
104241675Suqsint	cond_wait(cond_t *, mutex_t *);
105241675Suqsint	cond_timedwait(cond_t *, mutex_t *, const timespec_t *);
106241675Suqsint	cond_reltimedwait(cond_t *, mutex_t *, const timespec_t *);
107241675Suqsint	cond_signal(cond_t *);
108241675Suqsint	cond_broadcast(cond_t *);
109241675Suqsint	mutex_init(mutex_t *, int, void *);
110241675Suqsint	mutex_destroy(mutex_t *);
111241675Suqsint	mutex_consistent(mutex_t *);
112241675Suqsint	mutex_lock(mutex_t *);
113241675Suqsint	mutex_trylock(mutex_t *);
114241675Suqsint	mutex_unlock(mutex_t *);
115241675Suqsint	rwlock_init(rwlock_t *, int, void *);
116241675Suqsint	rwlock_destroy(rwlock_t *);
117241675Suqsint	rw_rdlock(rwlock_t *);
118241675Suqsint	rw_wrlock(rwlock_t *);
119241675Suqsint	rw_unlock(rwlock_t *);
120241675Suqsint	rw_tryrdlock(rwlock_t *);
121241675Suqsint	rw_trywrlock(rwlock_t *);
122241675Suqsint	sema_init(sema_t *, unsigned int, int, void *);
123241675Suqsint	sema_destroy(sema_t *);
124241675Suqsint	sema_wait(sema_t *);
125241675Suqsint	sema_timedwait(sema_t *, const timespec_t *);
126241675Suqsint	sema_reltimedwait(sema_t *, const timespec_t *);
127241675Suqsint	sema_post(sema_t *);
128241675Suqsint	sema_trywait(sema_t *);
129241675Suqs
130241675Suqs#else	/* __STDC__ */
131241675Suqs
132241675Suqsint	_lwp_mutex_lock();
133241675Suqsint	_lwp_mutex_unlock();
134241675Suqsint	_lwp_mutex_trylock();
135241675Suqsint	_lwp_cond_wait();
136241675Suqsint	_lwp_cond_timedwait();
137241675Suqsint	_lwp_cond_reltimedwait();
138241675Suqsint	_lwp_cond_signal();
139241675Suqsint	_lwp_cond_broadcast();
140241675Suqsint	_lwp_sema_init();
141241675Suqsint	_lwp_sema_wait();
142241675Suqsint	_lwp_sema_trywait();
143241675Suqsint	_lwp_sema_post();
144241675Suqsint	cond_init();
145241675Suqsint	cond_destroy();
146241675Suqsint	cond_wait();
147241675Suqsint	cond_timedwait();
148241675Suqsint	cond_reltimedwait();
149241675Suqsint	cond_signal();
150241675Suqsint	cond_broadcast();
151241675Suqsint	mutex_init();
152241675Suqsint	mutex_destroy();
153241675Suqsint	mutex_consistent();
154241675Suqsint	mutex_lock();
155241675Suqsint	mutex_trylock();
156241675Suqsint	mutex_unlock();
157241675Suqsint	rwlock_init();
158241675Suqsint	rwlock_destroy();
159241675Suqsint	rw_rdlock();
160241675Suqsint	rw_wrlock();
161241675Suqsint	rw_unlock();
162241675Suqsint	rw_tryrdlock();
163241675Suqsint	rw_trywrlock();
164241675Suqsint	sema_init();
165241675Suqsint	sema_destroy();
166241675Suqsint	sema_wait();
167241675Suqsint	sema_timedwait();
168241675Suqsint	sema_reltimedwait();
169241675Suqsint	sema_post();
170241675Suqsint	sema_trywait();
171241675Suqs
172241675Suqs#endif	/* __STDC__ */
173241675Suqs
174241675Suqs#endif /* _ASM */
175241675Suqs
176241675Suqs/* "Magic numbers" tagging synchronization object types */
177241675Suqs#define	MUTEX_MAGIC	_MUTEX_MAGIC
178241675Suqs#define	SEMA_MAGIC	_SEMA_MAGIC
179241675Suqs#define	COND_MAGIC	_COND_MAGIC
180241675Suqs#define	RWL_MAGIC	_RWL_MAGIC
181241675Suqs
182241675Suqs/*
183241675Suqs * POSIX.1c Note:
184241675Suqs * DEFAULTMUTEX is defined same as PTHREAD_MUTEX_INITIALIZER in <pthread.h>.
185241675Suqs * DEFAULTCV is defined same as PTHREAD_COND_INITIALIZER in <pthread.h>.
186241675Suqs * DEFAULTRWLOCK is defined same as PTHREAD_RWLOCK_INITIALIZER in <pthread.h>.
187241675Suqs * Any changes to these macros should be reflected in <pthread.h>
188241675Suqs */
189241675Suqs#define	DEFAULTMUTEX	\
190241675Suqs	{{0, 0, 0, {USYNC_THREAD}, MUTEX_MAGIC}, \
191241675Suqs	{{{0, 0, 0, 0, 0, 0, 0, 0}}}, 0}
192241675Suqs#define	SHAREDMUTEX	\
193241675Suqs	{{0, 0, 0, {USYNC_PROCESS}, MUTEX_MAGIC}, \
194241675Suqs	{{{0, 0, 0, 0, 0, 0, 0, 0}}}, 0}
195241675Suqs#define	RECURSIVEMUTEX	\
196241675Suqs	{{0, 0, 0, {USYNC_THREAD|LOCK_RECURSIVE}, MUTEX_MAGIC}, \
197241675Suqs	{{{0, 0, 0, 0, 0, 0, 0, 0}}}, 0}
198241675Suqs#define	ERRORCHECKMUTEX	\
199241675Suqs	{{0, 0, 0, {USYNC_THREAD|LOCK_ERRORCHECK}, MUTEX_MAGIC}, \
200241675Suqs	{{{0, 0, 0, 0, 0, 0, 0, 0}}}, 0}
201241675Suqs#define	RECURSIVE_ERRORCHECKMUTEX	\
202241675Suqs	{{0, 0, 0, {USYNC_THREAD|LOCK_RECURSIVE|LOCK_ERRORCHECK}, \
203241675Suqs	MUTEX_MAGIC}, {{{0, 0, 0, 0, 0, 0, 0, 0}}}, 0}
204241675Suqs#define	DEFAULTCV	\
205241675Suqs	{{{0, 0, 0, 0}, USYNC_THREAD, COND_MAGIC}, 0}
206241675Suqs#define	SHAREDCV	\
207241675Suqs	{{{0, 0, 0, 0}, USYNC_PROCESS, COND_MAGIC}, 0}
208241675Suqs#define	DEFAULTSEMA	\
209241675Suqs	{0, USYNC_THREAD, SEMA_MAGIC, {0, 0, 0}, {0, 0}}
210241675Suqs#define	SHAREDSEMA	\
211241675Suqs	{0, USYNC_PROCESS, SEMA_MAGIC, {0, 0, 0}, {0, 0}}
212241675Suqs#define	DEFAULTRWLOCK	\
213241675Suqs	{0, USYNC_THREAD, RWL_MAGIC, DEFAULTMUTEX, DEFAULTCV, DEFAULTCV}
214241675Suqs#define	SHAREDRWLOCK	\
215241675Suqs	{0, USYNC_PROCESS, RWL_MAGIC, SHAREDMUTEX, SHAREDCV, SHAREDCV}
216241675Suqs
217241675Suqs/*
218241675Suqs * Tests on lock states.
219241675Suqs */
220241675Suqs#define	SEMA_HELD(x)		_sema_held(x)
221241675Suqs#define	RW_READ_HELD(x)		_rw_read_held(x)
222241675Suqs#define	RW_WRITE_HELD(x)	_rw_write_held(x)
223241675Suqs#define	RW_LOCK_HELD(x)		(RW_READ_HELD(x) || RW_WRITE_HELD(x))
224241675Suqs#define	MUTEX_HELD(x)		_mutex_held(x)
225241675Suqs
226241675Suqs/*
227241675Suqs * The following definitions are for assertions which can be checked
228241675Suqs * statically by tools like lock_lint.  You can also define your own
229241675Suqs * run-time test for each.  If you don't, we define them to 1 so that
230241675Suqs * such assertions simply pass.
231241675Suqs */
232241675Suqs#ifndef NO_LOCKS_HELD
233241675Suqs#define	NO_LOCKS_HELD	1
234241675Suqs#endif
235241675Suqs#ifndef NO_COMPETING_THREADS
236241675Suqs#define	NO_COMPETING_THREADS	1
237241675Suqs#endif
238241675Suqs
239241675Suqs#ifndef _ASM
240241675Suqs
241241675Suqs#ifdef	__STDC__
242241675Suqs
243241675Suqs/*
244241675Suqs * The *_held() functions apply equally well to Solaris threads
245241675Suqs * and to Posix threads synchronization objects, but the formal
246241675Suqs * type declarations are different, so we just declare the argument
247241675Suqs * to each *_held() function to be a void *, expecting that they will
248241675Suqs * be called with the proper type of argument in each case.
249241675Suqs */
250241675Suqsint _sema_held(void *);			/* sema_t or sem_t */
251241675Suqsint _rw_read_held(void *);		/* rwlock_t or pthread_rwlock_t */
252241675Suqsint _rw_write_held(void *);		/* rwlock_t or pthread_rwlock_t */
253241675Suqsint _mutex_held(void *);		/* mutex_t or pthread_mutex_t */
254241675Suqs
255241675Suqs#else	/* __STDC__ */
256241675Suqs
257241675Suqsint _sema_held();
258241675Suqsint _rw_read_held();
259241675Suqsint _rw_write_held();
260241675Suqsint _mutex_held();
261241675Suqs
262241675Suqs#endif	/* __STDC__ */
263241675Suqs
264241675Suqs/* Pause API */
265241675Suqs#ifdef	__STDC__
266241675Suqsvoid smt_pause(void);
267241675Suqs#else	/* __STDC__ */
268241675Suqsvoid smt_pause();
269241675Suqs#endif	/* __STDC__ */
270241675Suqs
271241675Suqs#endif /* _ASM */
272241675Suqs
273241675Suqs#ifdef	__cplusplus
274241675Suqs}
275241675Suqs#endif
276241675Suqs
277241675Suqs#endif	/* _SYNCH_H */
278241675Suqs