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 --- |