Deleted Added
full compact
linux_futex.c (162182) linux_futex.c (166969)
1/* $NetBSD: linux_futex.c,v 1.5 2005/11/23 16:14:57 manu Exp $ */
2
3/*-
4 * Copyright (c) 2005 Emmanuel Dreyfus, all rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following 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 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by Emmanuel Dreyfus
1/* $NetBSD: linux_futex.c,v 1.5 2005/11/23 16:14:57 manu Exp $ */
2
3/*-
4 * Copyright (c) 2005 Emmanuel Dreyfus, all rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following 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 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by Emmanuel Dreyfus
17 * 4. The name of the author may not be used to endorse or promote
18 * products derived from this software without specific prior written
17 * 4. The name of the author may not be used to endorse or promote
18 * products derived from this software without specific prior written
19 * permission.
20 *
19 * permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE THE AUTHOR AND CONTRIBUTORS ``AS IS''
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THIS SOFTWARE IS PROVIDED BY THE THE AUTHOR AND CONTRIBUTORS ``AS IS''
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
23 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 */
33
34#include <sys/cdefs.h>
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 */
33
34#include <sys/cdefs.h>
35__FBSDID("$FreeBSD: head/sys/compat/linux/linux_futex.c 162182 2006-09-09 16:25:25Z netchild $");
35__FBSDID("$FreeBSD: head/sys/compat/linux/linux_futex.c 166969 2007-02-25 12:40:35Z netchild $");
36#if 0
36#if 0
37 __KERNEL_RCSID(1, "$NetBSD: linux_futex.c,v 1.5 2005/11/23 16:14:57 manu Exp $");
37__KERNEL_RCSID(1, "$NetBSD: linux_futex.c,v 1.5 2005/11/23 16:14:57 manu Exp $");
38#endif
39
40#include "opt_compat.h"
41
42#include <sys/param.h>
43#include <sys/types.h>
44#include <sys/time.h>
45#include <sys/systm.h>

--- 16 unchanged lines hidden (view full) ---

62struct futex;
63
64struct waiting_proc {
65 struct thread *wp_t;
66 struct futex *wp_new_futex;
67 TAILQ_ENTRY(waiting_proc) wp_list;
68};
69struct futex {
38#endif
39
40#include "opt_compat.h"
41
42#include <sys/param.h>
43#include <sys/types.h>
44#include <sys/time.h>
45#include <sys/systm.h>

--- 16 unchanged lines hidden (view full) ---

62struct futex;
63
64struct waiting_proc {
65 struct thread *wp_t;
66 struct futex *wp_new_futex;
67 TAILQ_ENTRY(waiting_proc) wp_list;
68};
69struct futex {
70 void *f_uaddr;
71 int f_refcount;
70 void *f_uaddr;
71 int f_refcount;
72 LIST_ENTRY(futex) f_list;
73 TAILQ_HEAD(lf_waiting_proc, waiting_proc) f_waiting_proc;
74};
75
76LIST_HEAD(futex_list, futex) futex_list;
77struct sx futex_sx; /* this protects the LIST of futexes */
78
79#define FUTEX_LOCK sx_xlock(&futex_sx)
80#define FUTEX_UNLOCK sx_xunlock(&futex_sx)
81
82#define FUTEX_LOCKED 1
83#define FUTEX_UNLOCKED 0
84
85#define FUTEX_SYSTEM_LOCK mtx_lock(&Giant)
86#define FUTEX_SYSTEM_UNLOCK mtx_unlock(&Giant)
87
72 LIST_ENTRY(futex) f_list;
73 TAILQ_HEAD(lf_waiting_proc, waiting_proc) f_waiting_proc;
74};
75
76LIST_HEAD(futex_list, futex) futex_list;
77struct sx futex_sx; /* this protects the LIST of futexes */
78
79#define FUTEX_LOCK sx_xlock(&futex_sx)
80#define FUTEX_UNLOCK sx_xunlock(&futex_sx)
81
82#define FUTEX_LOCKED 1
83#define FUTEX_UNLOCKED 0
84
85#define FUTEX_SYSTEM_LOCK mtx_lock(&Giant)
86#define FUTEX_SYSTEM_UNLOCK mtx_unlock(&Giant)
87
88static struct futex *futex_get(void *, int);
88static struct futex *futex_get(void *, int);
89static void futex_put(struct futex *);
90static int futex_sleep(struct futex *, struct thread *, unsigned long);
91static int futex_wake(struct futex *, int, struct futex *);
92#ifdef __i386__
93static int futex_atomic_op(struct thread *td, int encoded_op, caddr_t uaddr);
94#endif
95
96/* support.s */
97int futex_xchgl(int oparg, caddr_t uaddr, int *oldval);
98int futex_addl(int oparg, caddr_t uaddr, int *oldval);
99int futex_orl(int oparg, caddr_t uaddr, int *oldval);
100int futex_andnl(int oparg, caddr_t uaddr, int *oldval);
101int futex_xorl(int oparg, caddr_t uaddr, int *oldval);
102
103int
104linux_sys_futex(struct thread *td, struct linux_sys_futex_args *args)
105{
106 int val;
107 int ret;
89static void futex_put(struct futex *);
90static int futex_sleep(struct futex *, struct thread *, unsigned long);
91static int futex_wake(struct futex *, int, struct futex *);
92#ifdef __i386__
93static int futex_atomic_op(struct thread *td, int encoded_op, caddr_t uaddr);
94#endif
95
96/* support.s */
97int futex_xchgl(int oparg, caddr_t uaddr, int *oldval);
98int futex_addl(int oparg, caddr_t uaddr, int *oldval);
99int futex_orl(int oparg, caddr_t uaddr, int *oldval);
100int futex_andnl(int oparg, caddr_t uaddr, int *oldval);
101int futex_xorl(int oparg, caddr_t uaddr, int *oldval);
102
103int
104linux_sys_futex(struct thread *td, struct linux_sys_futex_args *args)
105{
106 int val;
107 int ret;
108 struct l_timespec timeout = { 0, 0 };
108 struct l_timespec timeout = {0, 0};
109 int error = 0;
110 struct futex *f;
111 struct futex *newf;
112 int timeout_hz;
113 struct timeval tv = {0, 0};
114#ifdef __i386__
115 struct futex *f2;
116 int op_ret;
117#endif
118
119#ifdef DEBUG
120 if (ldebug(sys_futex))
109 int error = 0;
110 struct futex *f;
111 struct futex *newf;
112 int timeout_hz;
113 struct timeval tv = {0, 0};
114#ifdef __i386__
115 struct futex *f2;
116 int op_ret;
117#endif
118
119#ifdef DEBUG
120 if (ldebug(sys_futex))
121 printf(ARGS(futex,"%p, %i, %i"), args->uaddr, args->op, args->val);
121 printf(ARGS(futex, "%p, %i, %i"), args->uaddr, args->op,
122 args->val);
122#endif
123
124 switch (args->op) {
125 case LINUX_FUTEX_WAIT:
123#endif
124
125 switch (args->op) {
126 case LINUX_FUTEX_WAIT:
126 FUTEX_SYSTEM_LOCK;
127 FUTEX_SYSTEM_LOCK;
127
128
128 if ((error = copyin(args->uaddr,
129 if ((error = copyin(args->uaddr,
129 &val, sizeof(val))) != 0) {
130 &val, sizeof(val))) != 0) {
130 FUTEX_SYSTEM_UNLOCK;
131 FUTEX_SYSTEM_UNLOCK;
131 return error;
132 }
133
134 if (val != args->val) {
132 return error;
133 }
134
135 if (val != args->val) {
135 FUTEX_SYSTEM_UNLOCK;
136 FUTEX_SYSTEM_UNLOCK;
136 return EWOULDBLOCK;
137 }
138
139 if (args->timeout != NULL) {
137 return EWOULDBLOCK;
138 }
139
140 if (args->timeout != NULL) {
140 if ((error = copyin(args->timeout,
141 if ((error = copyin(args->timeout,
141 &timeout, sizeof(timeout))) != 0) {
142 &timeout, sizeof(timeout))) != 0) {
142 FUTEX_SYSTEM_UNLOCK;
143 FUTEX_SYSTEM_UNLOCK;
143 return error;
144 }
145 }
146
147#ifdef DEBUG
148 if (ldebug(sys_futex))
144 return error;
145 }
146 }
147
148#ifdef DEBUG
149 if (ldebug(sys_futex))
149 printf("FUTEX_WAIT %d: val = %d, uaddr = %p, "
150 "*uaddr = %d, timeout = %d.%09lu\n",
151 td->td_proc->p_pid, args->val,
152 args->uaddr, val, timeout.tv_sec,
153 (unsigned long)timeout.tv_nsec);
150 printf("FUTEX_WAIT %d: val = %d, uaddr = %p, "
151 "*uaddr = %d, timeout = %d.%09lu\n",
152 td->td_proc->p_pid, args->val,
153 args->uaddr, val, timeout.tv_sec,
154 (unsigned long)timeout.tv_nsec);
154#endif
155 tv.tv_usec = timeout.tv_sec * 1000000 + timeout.tv_nsec / 1000;
156 timeout_hz = tvtohz(&tv);
157
158 if (timeout.tv_sec == 0 && timeout.tv_nsec == 0)
155#endif
156 tv.tv_usec = timeout.tv_sec * 1000000 + timeout.tv_nsec / 1000;
157 timeout_hz = tvtohz(&tv);
158
159 if (timeout.tv_sec == 0 && timeout.tv_nsec == 0)
159 timeout_hz = 0;
160 /*
161 * If the user process requests a non null timeout,
162 * make sure we do not turn it into an infinite
163 * timeout because timeout_hz gets null.
164 *
165 * We use a minimal timeout of 1/hz. Maybe it would
166 * make sense to just return ETIMEDOUT without sleeping.
167 */
168 if (((timeout.tv_sec != 0) || (timeout.tv_nsec != 0)) &&
169 (timeout_hz == 0))
170 timeout_hz = 1;
160 timeout_hz = 0;
161 /*
162 * If the user process requests a non null timeout,
163 * make sure we do not turn it into an infinite
164 * timeout because timeout_hz gets null.
165 *
166 * We use a minimal timeout of 1/hz. Maybe it would
167 * make sense to just return ETIMEDOUT without sleeping.
168 */
169 if (((timeout.tv_sec != 0) || (timeout.tv_nsec != 0)) &&
170 (timeout_hz == 0))
171 timeout_hz = 1;
171
172
173 f = futex_get(args->uaddr, FUTEX_UNLOCKED);
174 ret = futex_sleep(f, td, timeout_hz);
175 futex_put(f);
176
177#ifdef DEBUG
178 if (ldebug(sys_futex))
172
173
174 f = futex_get(args->uaddr, FUTEX_UNLOCKED);
175 ret = futex_sleep(f, td, timeout_hz);
176 futex_put(f);
177
178#ifdef DEBUG
179 if (ldebug(sys_futex))
179 printf("FUTEX_WAIT %d: uaddr = %p, "
180 "ret = %d\n", td->td_proc->p_pid, args->uaddr, ret);
180 printf("FUTEX_WAIT %d: uaddr = %p, "
181 "ret = %d\n", td->td_proc->p_pid, args->uaddr, ret);
181#endif
182
183 FUTEX_SYSTEM_UNLOCK;
184 switch (ret) {
185 case EWOULDBLOCK: /* timeout */
186 return ETIMEDOUT;
187 break;
188 case EINTR: /* signal */
189 return EINTR;
190 break;
182#endif
183
184 FUTEX_SYSTEM_UNLOCK;
185 switch (ret) {
186 case EWOULDBLOCK: /* timeout */
187 return ETIMEDOUT;
188 break;
189 case EINTR: /* signal */
190 return EINTR;
191 break;
191 case 0: /* FUTEX_WAKE received */
192 case 0: /* FUTEX_WAKE received */
192#ifdef DEBUG
193 if (ldebug(sys_futex))
194 printf("FUTEX_WAIT %d: uaddr = %p, got FUTEX_WAKE\n",
193#ifdef DEBUG
194 if (ldebug(sys_futex))
195 printf("FUTEX_WAIT %d: uaddr = %p, got FUTEX_WAKE\n",
195 td->td_proc->p_pid, args->uaddr);
196 td->td_proc->p_pid, args->uaddr);
196#endif
197 return 0;
198 break;
199 default:
200#ifdef DEBUG
201 if (ldebug(sys_futex))
197#endif
198 return 0;
199 break;
200 default:
201#ifdef DEBUG
202 if (ldebug(sys_futex))
202 printf("FUTEX_WAIT: unexpected ret = %d\n", ret);
203 printf("FUTEX_WAIT: unexpected ret = %d\n", ret);
203#endif
204 break;
205 }
206
207 /* NOTREACHED */
208 break;
204#endif
205 break;
206 }
207
208 /* NOTREACHED */
209 break;
209
210
210 case LINUX_FUTEX_WAKE:
211 FUTEX_SYSTEM_LOCK;
212
211 case LINUX_FUTEX_WAKE:
212 FUTEX_SYSTEM_LOCK;
213
213 /*
214 * XXX: Linux is able cope with different addresses
215 * corresponding to the same mapped memory in the sleeping
214 /*
215 * XXX: Linux is able cope with different addresses
216 * corresponding to the same mapped memory in the sleeping
216 * and the waker process.
217 */
218#ifdef DEBUG
219 if (ldebug(sys_futex))
217 * and the waker process.
218 */
219#ifdef DEBUG
220 if (ldebug(sys_futex))
220 printf("FUTEX_WAKE %d: uaddr = %p, val = %d\n",
221 td->td_proc->p_pid, args->uaddr, args->val);
221 printf("FUTEX_WAKE %d: uaddr = %p, val = %d\n",
222 td->td_proc->p_pid, args->uaddr, args->val);
222#endif
223 f = futex_get(args->uaddr, FUTEX_UNLOCKED);
224 td->td_retval[0] = futex_wake(f, args->val, NULL);
225 futex_put(f);
226
227 FUTEX_SYSTEM_UNLOCK;
228 break;
229
230 case LINUX_FUTEX_CMP_REQUEUE:
231 FUTEX_SYSTEM_LOCK;
232
223#endif
224 f = futex_get(args->uaddr, FUTEX_UNLOCKED);
225 td->td_retval[0] = futex_wake(f, args->val, NULL);
226 futex_put(f);
227
228 FUTEX_SYSTEM_UNLOCK;
229 break;
230
231 case LINUX_FUTEX_CMP_REQUEUE:
232 FUTEX_SYSTEM_LOCK;
233
233 if ((error = copyin(args->uaddr,
234 if ((error = copyin(args->uaddr,
234 &val, sizeof(val))) != 0) {
235 &val, sizeof(val))) != 0) {
235 FUTEX_SYSTEM_UNLOCK;
236 FUTEX_SYSTEM_UNLOCK;
236 return error;
237 }
238
239 if (val != args->val3) {
237 return error;
238 }
239
240 if (val != args->val3) {
240 FUTEX_SYSTEM_UNLOCK;
241 FUTEX_SYSTEM_UNLOCK;
241 return EAGAIN;
242 }
243
244 f = futex_get(args->uaddr, FUTEX_UNLOCKED);
245 newf = futex_get(args->uaddr2, FUTEX_UNLOCKED);
246 td->td_retval[0] = futex_wake(f, args->val, newf);
247 futex_put(f);
248 futex_put(newf);

--- 18 unchanged lines hidden (view full) ---

267 args->op);
268 break;
269
270 case LINUX_FUTEX_WAKE_OP:
271#ifdef __i386__
272 FUTEX_SYSTEM_LOCK;
273#ifdef DEBUG
274 if (ldebug(sys_futex))
242 return EAGAIN;
243 }
244
245 f = futex_get(args->uaddr, FUTEX_UNLOCKED);
246 newf = futex_get(args->uaddr2, FUTEX_UNLOCKED);
247 td->td_retval[0] = futex_wake(f, args->val, newf);
248 futex_put(f);
249 futex_put(newf);

--- 18 unchanged lines hidden (view full) ---

268 args->op);
269 break;
270
271 case LINUX_FUTEX_WAKE_OP:
272#ifdef __i386__
273 FUTEX_SYSTEM_LOCK;
274#ifdef DEBUG
275 if (ldebug(sys_futex))
275 printf("FUTEX_WAKE_OP: %d: uaddr = %p, op = %d, val = %d, uaddr2 = %p, val3 = %d\n",
276 td->td_proc->p_pid, args->uaddr, args->op, args->val, args->uaddr2, args->val3);
276 printf("FUTEX_WAKE_OP: %d: uaddr = %p, op = %d, val = %d, uaddr2 = %p, val3 = %d\n",
277 td->td_proc->p_pid, args->uaddr, args->op, args->val,
278 args->uaddr2, args->val3);
277#endif
278 f = futex_get(args->uaddr, FUTEX_UNLOCKED);
279 f2 = futex_get(args->uaddr2, FUTEX_UNLOCKED);
280
279#endif
280 f = futex_get(args->uaddr, FUTEX_UNLOCKED);
281 f2 = futex_get(args->uaddr2, FUTEX_UNLOCKED);
282
281 /* This function returns positive number as results
282 * and negative as errors
283 /*
284 * This function returns positive number as results and
285 * negative as errors
283 */
284 op_ret = futex_atomic_op(td, args->val3, args->uaddr2);
285 if (op_ret < 0) {
286
286 */
287 op_ret = futex_atomic_op(td, args->val3, args->uaddr2);
288 if (op_ret < 0) {
289
287 /* XXX: we dont handle the EFAULT yet */
288 if (op_ret != -EFAULT) {
289 futex_put(f);
290 futex_put(f2);
290 /* XXX: we dont handle the EFAULT yet */
291 if (op_ret != -EFAULT) {
292 futex_put(f);
293 futex_put(f2);
291 FUTEX_SYSTEM_UNLOCK;
294 FUTEX_SYSTEM_UNLOCK;
292 return (-op_ret);
295 return (-op_ret);
293 }
294
295 futex_put(f);
296 futex_put(f2);
297
296 }
297
298 futex_put(f);
299 futex_put(f2);
300
298 FUTEX_SYSTEM_UNLOCK;
301 FUTEX_SYSTEM_UNLOCK;
299 return (EFAULT);
300
301 }
302
303 ret = futex_wake(f, args->val, NULL);
304 futex_put(f);
305 if (op_ret > 0) {
306 op_ret = 0;

--- 23 unchanged lines hidden (view full) ---

330}
331
332static struct futex *
333futex_get(void *uaddr, int locked)
334{
335 struct futex *f;
336
337 if (locked == FUTEX_UNLOCKED)
302 return (EFAULT);
303
304 }
305
306 ret = futex_wake(f, args->val, NULL);
307 futex_put(f);
308 if (op_ret > 0) {
309 op_ret = 0;

--- 23 unchanged lines hidden (view full) ---

333}
334
335static struct futex *
336futex_get(void *uaddr, int locked)
337{
338 struct futex *f;
339
340 if (locked == FUTEX_UNLOCKED)
338 FUTEX_LOCK;
341 FUTEX_LOCK;
339 LIST_FOREACH(f, &futex_list, f_list) {
340 if (f->f_uaddr == uaddr) {
341 f->f_refcount++;
342 if (locked == FUTEX_UNLOCKED)
342 LIST_FOREACH(f, &futex_list, f_list) {
343 if (f->f_uaddr == uaddr) {
344 f->f_refcount++;
345 if (locked == FUTEX_UNLOCKED)
343 FUTEX_UNLOCK;
346 FUTEX_UNLOCK;
344 return f;
345 }
346 }
347
348 f = malloc(sizeof(*f), M_LINUX, M_WAITOK);
349 f->f_uaddr = uaddr;
350 f->f_refcount = 1;
351 TAILQ_INIT(&f->f_waiting_proc);
352 LIST_INSERT_HEAD(&futex_list, f, f_list);
353 if (locked == FUTEX_UNLOCKED)
347 return f;
348 }
349 }
350
351 f = malloc(sizeof(*f), M_LINUX, M_WAITOK);
352 f->f_uaddr = uaddr;
353 f->f_refcount = 1;
354 TAILQ_INIT(&f->f_waiting_proc);
355 LIST_INSERT_HEAD(&futex_list, f, f_list);
356 if (locked == FUTEX_UNLOCKED)
354 FUTEX_UNLOCK;
357 FUTEX_UNLOCK;
355
356 return f;
357}
358
358
359 return f;
360}
361
359static void
362static void
360futex_put(f)
361 struct futex *f;
362{
363futex_put(f)
364 struct futex *f;
365{
363 FUTEX_LOCK;
364 f->f_refcount--;
366 FUTEX_LOCK;
367 f->f_refcount--;
365 if (f->f_refcount == 0) {
366 LIST_REMOVE(f, f_list);
367 free(f, M_LINUX);
368 }
369 FUTEX_UNLOCK;
370
371 return;
372}
373
368 if (f->f_refcount == 0) {
369 LIST_REMOVE(f, f_list);
370 free(f, M_LINUX);
371 }
372 FUTEX_UNLOCK;
373
374 return;
375}
376
374static int
377static int
375futex_sleep(struct futex *f, struct thread *td, unsigned long timeout)
376{
377 struct waiting_proc *wp;
378 int ret;
379
380 wp = malloc(sizeof(*wp), M_LINUX, M_WAITOK);
381 wp->wp_t = td;
382 wp->wp_new_futex = NULL;
383 FUTEX_LOCK;
384 TAILQ_INSERT_TAIL(&f->f_waiting_proc, wp, wp_list);
385 FUTEX_UNLOCK;
386
387#ifdef DEBUG
388 if (ldebug(sys_futex))
378futex_sleep(struct futex *f, struct thread *td, unsigned long timeout)
379{
380 struct waiting_proc *wp;
381 int ret;
382
383 wp = malloc(sizeof(*wp), M_LINUX, M_WAITOK);
384 wp->wp_t = td;
385 wp->wp_new_futex = NULL;
386 FUTEX_LOCK;
387 TAILQ_INSERT_TAIL(&f->f_waiting_proc, wp, wp_list);
388 FUTEX_UNLOCK;
389
390#ifdef DEBUG
391 if (ldebug(sys_futex))
389 printf("FUTEX --> %d tlseep timeout = %ld\n", td->td_proc->p_pid,
390 timeout);
392 printf("FUTEX --> %d tlseep timeout = %ld\n", td->td_proc->p_pid,
393 timeout);
391#endif
394#endif
392 ret = tsleep(wp, PCATCH|PZERO, "linuxfutex", timeout);
395 ret = tsleep(wp, PCATCH | PZERO, "linuxfutex", timeout);
393
394 FUTEX_LOCK;
395 TAILQ_REMOVE(&f->f_waiting_proc, wp, wp_list);
396 FUTEX_UNLOCK;
397
398 if ((ret == 0) && (wp->wp_new_futex != NULL)) {
399 ret = futex_sleep(wp->wp_new_futex, td, timeout);
396
397 FUTEX_LOCK;
398 TAILQ_REMOVE(&f->f_waiting_proc, wp, wp_list);
399 FUTEX_UNLOCK;
400
401 if ((ret == 0) && (wp->wp_new_futex != NULL)) {
402 ret = futex_sleep(wp->wp_new_futex, td, timeout);
400 futex_put(wp->wp_new_futex); /* futex_get called in wakeup */
403 futex_put(wp->wp_new_futex); /* futex_get called in wakeup */
401 }
402
403 free(wp, M_LINUX);
404
405 return ret;
406}
407
408static int
409futex_wake(struct futex *f, int n, struct futex *newf)
410{
411 struct waiting_proc *wp;
404 }
405
406 free(wp, M_LINUX);
407
408 return ret;
409}
410
411static int
412futex_wake(struct futex *f, int n, struct futex *newf)
413{
414 struct waiting_proc *wp;
412 int count = 0;
415 int count = 0;
413
414 FUTEX_LOCK;
415 TAILQ_FOREACH(wp, &f->f_waiting_proc, wp_list) {
416 if (count <= n) {
417 wakeup_one(wp);
418 count++;
419 } else {
420 if (newf != NULL) {

--- 80 unchanged lines hidden ---
416
417 FUTEX_LOCK;
418 TAILQ_FOREACH(wp, &f->f_waiting_proc, wp_list) {
419 if (count <= n) {
420 wakeup_one(wp);
421 count++;
422 } else {
423 if (newf != NULL) {

--- 80 unchanged lines hidden ---