]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/sys/umtx.h
1. introduce umtx_owner to get an owner of a umtx.
[FreeBSD/FreeBSD.git] / sys / sys / umtx.h
1 /*
2  * Copyright (c) 2002, Jeffrey Roberson <jeff@freebsd.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice unmodified, this list of conditions, and the following
10  *    disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *
26  * $FreeBSD$
27  *
28  */
29
30 #ifndef _SYS_UMTX_H_
31 #define _SYS_UMTX_H_
32
33 #include <sys/limits.h>
34
35 /* 
36  * See pthread_*
37  */
38
39 #define UMTX_UNOWNED    0x0
40 #define UMTX_CONTESTED  LONG_MIN
41
42 struct umtx {
43         void    *u_owner;       /* Owner of the mutex. */
44 };
45
46 /* op code for _umtx_op */
47 #define UMTX_OP_LOCK            0
48 #define UMTX_OP_UNLOCK          1
49 #define UMTX_OP_UNLOCK_AND_WAIT 2
50 #define UMTX_OP_WAKE            3
51
52 #ifndef _KERNEL
53
54 /*
55  * System calls for acquiring and releasing contested mutexes.
56  */
57 /* deprecated becaues it can only use thread id */
58 int _umtx_lock(struct umtx *mtx);
59 /* deprecated becaues it can only use thread id */
60 int _umtx_unlock(struct umtx *mtx);
61 int _umtx_op(struct umtx *umtx, int op, long id, void *uaddr,
62         struct timespec *abstime);
63
64 /*
65  * Standard api.  Try uncontested acquire/release and asks the
66  * kernel to resolve failures.
67  */
68 static __inline void
69 umtx_init(struct umtx *umtx)
70 {
71         umtx->u_owner = UMTX_UNOWNED;
72 }
73
74 static __inline long
75 umtx_owner(struct umtx *umtx)
76 {
77         return ((long)umtx->u_owner & ~LONG_MIN);
78 }
79
80 static __inline int
81 umtx_lock(struct umtx *umtx, long id)
82 {
83         if (atomic_cmpset_acq_ptr(&umtx->u_owner, (void *)UMTX_UNOWNED,
84             (void *)id) == 0)
85                 if (_umtx_op(umtx, UMTX_OP_LOCK, id, 0, 0) == -1)
86                         return (errno);
87         return (0);
88 }
89
90 static __inline int
91 umtx_trylock(struct umtx *umtx, long id)
92 {
93         if (atomic_cmpset_acq_ptr(&umtx->u_owner, (void *)UMTX_UNOWNED,
94             (void *)id) == 0)
95                 return (EBUSY);
96         return (0);
97 }
98
99 static __inline int
100 umtx_timedlock(struct umtx *umtx, long id, const struct timespec *abstime)
101 {
102         if (atomic_cmpset_acq_ptr(&umtx->u_owner, (void *)UMTX_UNOWNED,
103             (void *)id) == 0)
104                 if (_umtx_op(umtx, UMTX_OP_LOCK, id, 0, (void *)abstime) == -1)
105                         return (errno);
106         return (0);
107 }
108
109 static __inline int
110 umtx_unlock(struct umtx *umtx, long id)
111 {
112         if (atomic_cmpset_rel_ptr(&umtx->u_owner, (void *)id,
113             (void *)UMTX_UNOWNED) == 0)
114                 if (_umtx_op(umtx, UMTX_OP_UNLOCK, id, 0, 0) == -1)
115                         return (errno);
116         return (0);
117 }
118
119 /* Unlock umtx and wait on a user address. */
120
121 static __inline int
122 umtx_wait(struct umtx *umtx, long id, void *uaddr)
123 {
124         if (_umtx_op(umtx, UMTX_OP_UNLOCK_AND_WAIT, id, uaddr, 0) == -1)
125                 return (errno);
126         return (0);
127 }
128
129 static __inline int
130 umtx_timedwait(struct umtx *umtx, long id, void *uaddr,
131         const struct timespec *abstime)
132 {
133         if (_umtx_op(umtx, UMTX_OP_UNLOCK_AND_WAIT, id, uaddr,
134                 (void *)abstime) == -1)
135                 return (errno);
136         return (0);
137 }
138
139 /* Wake threads waiting on a user address. */
140 static __inline int
141 umtx_wake(void *uaddr, int nr_wakeup)
142 {
143         /* return how many threads were woke up, -1 if error */
144         return _umtx_op(0, UMTX_OP_WAKE, nr_wakeup, uaddr, 0);
145 }
146
147 #endif /* !_KERNEL */
148 #endif /* !_SYS_UMTX_H_ */