umtx.h revision 216641
1124350Sschweikh/*-
299026Sjulian * Copyright (c) 2002, Jeffrey Roberson <jeff@freebsd.org>
399026Sjulian * All rights reserved.
499026Sjulian *
599026Sjulian * Redistribution and use in source and binary forms, with or without
699026Sjulian * modification, are permitted provided that the following conditions
799026Sjulian * are met:
899026Sjulian * 1. Redistributions of source code must retain the above copyright
999026Sjulian *    notice unmodified, this list of conditions, and the following
10124350Sschweikh *    disclaimer.
1199026Sjulian * 2. Redistributions in binary form must reproduce the above copyright
1299026Sjulian *    notice, this list of conditions and the following disclaimer in the
1399026Sjulian *    documentation and/or other materials provided with the distribution.
1499026Sjulian *
1599026Sjulian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1699026Sjulian * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1799026Sjulian * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1899026Sjulian * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1999026Sjulian * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2099026Sjulian * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2199026Sjulian * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2299026Sjulian * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2399026Sjulian * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2499026Sjulian * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2599026Sjulian *
2699026Sjulian * $FreeBSD: head/sys/sys/umtx.h 216641 2010-12-22 05:01:52Z davidxu $
2799026Sjulian *
2899026Sjulian */
29116182Sobrien
30116182Sobrien#ifndef _SYS_UMTX_H_
31116182Sobrien#define	_SYS_UMTX_H_
3299026Sjulian
3399026Sjulian#include <sys/_umtx.h>
3499026Sjulian#include <sys/limits.h>
3599026Sjulian
3699026Sjulian#define	UMTX_UNOWNED		0x0
3799026Sjulian#define	UMTX_CONTESTED		LONG_MIN
38130355Sjulian
3999026Sjulian#define USYNC_PROCESS_SHARED	0x0001	/* Process shared sync objs */
40107126Sjeff
41126326Sjhb#define	UMUTEX_UNOWNED		0x0
42122514Sjhb#define	UMUTEX_CONTESTED	0x80000000U
4399026Sjulian
4499026Sjulian#define	UMUTEX_ERROR_CHECK	0x0002	/* Error-checking mutex */
4599026Sjulian#define	UMUTEX_PRIO_INHERIT	0x0004	/* Priority inherited mutex */
46116355Salc#define	UMUTEX_PRIO_PROTECT	0x0008	/* Priority protect mutex */
4799026Sjulian
4899026Sjulian/* urwlock flags */
4999026Sjulian#define URWLOCK_PREFER_READER	0x0002
50103367Sjulian
5199026Sjulian#define URWLOCK_WRITE_OWNER	0x80000000U
52103367Sjulian#define URWLOCK_WRITE_WAITERS	0x40000000U
53103367Sjulian#define URWLOCK_READ_WAITERS	0x20000000U
5499026Sjulian#define URWLOCK_MAX_READERS	0x1fffffffU
5599026Sjulian#define URWLOCK_READER_COUNT(c)	((c) & URWLOCK_MAX_READERS)
56103367Sjulian
5799026Sjulian/* _usem flags */
58107719Sjulian#define SEM_NAMED	0x0002
59107719Sjulian
60107719Sjulian/* op code for _umtx_op */
6199026Sjulian#define	UMTX_OP_LOCK		0
62130199Sjulian#define	UMTX_OP_UNLOCK		1
63107006Sdavidxu#define	UMTX_OP_WAIT		2
64103367Sjulian#define	UMTX_OP_WAKE		3
65103367Sjulian#define	UMTX_OP_MUTEX_TRYLOCK	4
66130199Sjulian#define	UMTX_OP_MUTEX_LOCK	5
67107006Sdavidxu#define	UMTX_OP_MUTEX_UNLOCK	6
68107006Sdavidxu#define	UMTX_OP_SET_CEILING	7
69107006Sdavidxu#define	UMTX_OP_CV_WAIT		8
70130199Sjulian#define	UMTX_OP_CV_SIGNAL	9
71111115Sdavidxu#define	UMTX_OP_CV_BROADCAST	10
72111115Sdavidxu#define	UMTX_OP_WAIT_UINT	11
73111115Sdavidxu#define	UMTX_OP_RW_RDLOCK	12
74130355Sjulian#define	UMTX_OP_RW_WRLOCK	13
75111028Sjeff#define	UMTX_OP_RW_UNLOCK	14
76130355Sjulian#define	UMTX_OP_WAIT_UINT_PRIVATE	15
77130355Sjulian#define	UMTX_OP_WAKE_PRIVATE	16
78111028Sjeff#define	UMTX_OP_MUTEX_WAIT	17
79105854Sjulian#define	UMTX_OP_MUTEX_WAKE	18
80105854Sjulian#define	UMTX_OP_SEM_WAIT	19
81111028Sjeff#define	UMTX_OP_SEM_WAKE	20
82111028Sjeff#define	UMTX_OP_NWAKE_PRIVATE   21
8399026Sjulian#define	UMTX_OP_MAX		22
84130199Sjulian
85130199Sjulian/* Flags for UMTX_OP_CV_WAIT */
86105854Sjulian#define	CVWAIT_CHECK_UNPARKING	0x01
87130199Sjulian#define	CVWAIT_ABSTIME		0x02
88130199Sjulian#define	CVWAIT_CLOCKID		0x04
89130199Sjulian
90111028Sjeff#define	UMTX_CHECK_UNPARKING	CVWAIT_CHECK_UNPARKING
91111028Sjeff
92130355Sjulian#ifndef _KERNEL
93130355Sjulian
94130355Sjulianint _umtx_op(void *obj, int op, u_long val, void *uaddr, void *uaddr2);
95130355Sjulian
96130355Sjulian/*
97111028Sjeff * Old (deprecated) userland mutex system calls.
98130355Sjulian */
99130355Sjulianint _umtx_lock(struct umtx *mtx);
100130355Sjulianint _umtx_unlock(struct umtx *mtx);
101130355Sjulian
102130355Sjulian/*
103130355Sjulian * Standard api.  Try uncontested acquire/release and asks the
104133713Sjulian * kernel to resolve failures.
105130355Sjulian */
106130355Sjulianstatic __inline void
107130355Sjulianumtx_init(struct umtx *umtx)
108130355Sjulian{
109130355Sjulian	umtx->u_owner = UMTX_UNOWNED;
110130355Sjulian}
111130355Sjulian
112130355Sjulianstatic __inline u_long
113130355Sjulianumtx_owner(struct umtx *umtx)
114130355Sjulian{
115130355Sjulian	return (umtx->u_owner & ~LONG_MIN);
116130355Sjulian}
11799026Sjulian
118127794Smarcelstatic __inline int
119127794Smarcelumtx_lock(struct umtx *umtx, u_long id)
120127794Smarcel{
121127794Smarcel	if (atomic_cmpset_acq_long(&umtx->u_owner, UMTX_UNOWNED, id) == 0)
122127794Smarcel		if (_umtx_lock(umtx) == -1)
123127794Smarcel			return (errno);
124127794Smarcel	return (0);
125127794Smarcel}
126127794Smarcel
127127794Smarcelstatic __inline int
128127794Smarcelumtx_trylock(struct umtx *umtx, u_long id)
129127794Smarcel{
130127794Smarcel	if (atomic_cmpset_acq_long(&umtx->u_owner, UMTX_UNOWNED, id) == 0)
131127794Smarcel		return (EBUSY);
132130735Smarcel	return (0);
133127794Smarcel}
134127794Smarcel
135127794Smarcelstatic __inline int
136127794Smarcelumtx_timedlock(struct umtx *umtx, u_long id, const struct timespec *timeout)
137127794Smarcel{
138127794Smarcel	if (atomic_cmpset_acq_long(&umtx->u_owner, UMTX_UNOWNED, id) == 0)
139127794Smarcel		if (_umtx_op(umtx, UMTX_OP_LOCK, id, 0,
140127794Smarcel		    __DECONST(void *, timeout)) == -1)
141127794Smarcel			return (errno);
142127794Smarcel	return (0);
143127794Smarcel}
144107719Sjulian
14599026Sjulianstatic __inline int
146132987Sgreenumtx_unlock(struct umtx *umtx, u_long id)
147132987Sgreen{
14899026Sjulian	if (atomic_cmpset_rel_long(&umtx->u_owner, id, UMTX_UNOWNED) == 0)
14999026Sjulian		if (_umtx_unlock(umtx) == -1)
15099026Sjulian			return (errno);
15199026Sjulian	return (0);
152103216Sjulian}
153113339Sjulian
154130269Sjmallettstatic __inline int
155130269Sjmallettumtx_wait(u_long *p, long val, const struct timespec *timeout)
156130269Sjmallett{
157130269Sjmallett	if (_umtx_op(p, UMTX_OP_WAIT, val, 0,
158130269Sjmallett	    __DECONST(void *, timeout)) == -1)
159130269Sjmallett		return (errno);
160130269Sjmallett	return (0);
161130269Sjmallett}
162130269Sjmallett
163130269Sjmallett/* Wake threads waiting on a user address. */
164130269Sjmallettstatic __inline int
165130269Sjmallettumtx_wake(u_long *p, int nr_wakeup)
166130269Sjmallett{
167118442Sjhb	if (_umtx_op(p, UMTX_OP_WAKE, nr_wakeup, 0, 0) == -1)
168132987Sgreen		return (errno);
16999026Sjulian	return (0);
17099026Sjulian}
17199026Sjulian
17299026Sjulian#else
17399026Sjulian
17499026Sjulianstruct thread;
17599026Sjulian
17699026Sjulianstruct umtx_q *umtxq_alloc(void);
177127794Smarcelvoid umtxq_free(struct umtx_q *);
17899026Sjulianint kern_umtx_wake(struct thread *, void *, int, int);
17999026Sjulianvoid umtx_pi_adjust(struct thread *, u_char);
18099026Sjulianvoid umtx_thread_init(struct thread *);
18199026Sjulianvoid umtx_thread_fini(struct thread *);
18299026Sjulianvoid umtx_thread_alloc(struct thread *);
18399026Sjulianvoid umtx_thread_exit(struct thread *);
184103216Sjulian#endif /* !_KERNEL */
185103216Sjulian#endif /* !_SYS_UMTX_H_ */
186103216Sjulian