| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: linux_futex.c,v 1.18.4.1 2009/02/26 20:40:52 snj Exp $ */ | | 1 | /* $NetBSD: linux_futex.c,v 1.18.4.2 2009/03/16 01:20:37 snj Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2005 Emmanuel Dreyfus, all rights reserved. | | 4 | * Copyright (c) 2005 Emmanuel Dreyfus, all rights reserved. |
5 | * | | 5 | * |
6 | * Redistribution and use in source and binary forms, with or without | | 6 | * Redistribution and use in source and binary forms, with or without |
7 | * modification, are permitted provided that the following conditions | | 7 | * modification, are permitted provided that the following conditions |
8 | * are met: | | 8 | * are met: |
9 | * 1. Redistributions of source code must retain the above copyright | | 9 | * 1. Redistributions of source code must retain the above copyright |
10 | * notice, this list of conditions and the following disclaimer. | | 10 | * notice, this list of conditions and the following disclaimer. |
11 | * 2. Redistributions in binary form must reproduce the above copyright | | 11 | * 2. Redistributions in binary form must reproduce the above copyright |
12 | * notice, this list of conditions and the following disclaimer in the | | 12 | * notice, this list of conditions and the following disclaimer in the |
13 | * documentation and/or other materials provided with the distribution. | | 13 | * documentation and/or other materials provided with the distribution. |
14 | * 3. All advertising materials mentioning features or use of this software | | 14 | * 3. All advertising materials mentioning features or use of this software |
| @@ -22,27 +22,27 @@ | | | @@ -22,27 +22,27 @@ |
22 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | | 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 | | 25 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 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 | | 28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 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 | | 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
31 | * POSSIBILITY OF SUCH DAMAGE. | | 31 | * POSSIBILITY OF SUCH DAMAGE. |
32 | */ | | 32 | */ |
33 | | | 33 | |
34 | #include <sys/cdefs.h> | | 34 | #include <sys/cdefs.h> |
35 | __KERNEL_RCSID(1, "$NetBSD: linux_futex.c,v 1.18.4.1 2009/02/26 20:40:52 snj Exp $"); | | 35 | __KERNEL_RCSID(1, "$NetBSD: linux_futex.c,v 1.18.4.2 2009/03/16 01:20:37 snj Exp $"); |
36 | | | 36 | |
37 | #include <sys/param.h> | | 37 | #include <sys/param.h> |
38 | #include <sys/time.h> | | 38 | #include <sys/time.h> |
39 | #include <sys/systm.h> | | 39 | #include <sys/systm.h> |
40 | #include <sys/proc.h> | | 40 | #include <sys/proc.h> |
41 | #include <sys/lwp.h> | | 41 | #include <sys/lwp.h> |
42 | #include <sys/queue.h> | | 42 | #include <sys/queue.h> |
43 | #include <sys/condvar.h> | | 43 | #include <sys/condvar.h> |
44 | #include <sys/mutex.h> | | 44 | #include <sys/mutex.h> |
45 | #include <sys/once.h> | | 45 | #include <sys/once.h> |
46 | #include <sys/kmem.h> | | 46 | #include <sys/kmem.h> |
47 | #include <sys/kernel.h> | | 47 | #include <sys/kernel.h> |
48 | #include <sys/atomic.h> | | 48 | #include <sys/atomic.h> |
| @@ -488,62 +488,63 @@ futex_atomic_op(lwp_t *l, int encoded_op | | | @@ -488,62 +488,63 @@ futex_atomic_op(lwp_t *l, int encoded_op |
488 | return (oldval > cmparg); | | 488 | return (oldval > cmparg); |
489 | default: | | 489 | default: |
490 | return -ENOSYS; | | 490 | return -ENOSYS; |
491 | } | | 491 | } |
492 | } | | 492 | } |
493 | | | 493 | |
494 | int | | 494 | int |
495 | linux_sys_set_robust_list(struct lwp *l, | | 495 | linux_sys_set_robust_list(struct lwp *l, |
496 | const struct linux_sys_set_robust_list_args *uap, register_t *retval) | | 496 | const struct linux_sys_set_robust_list_args *uap, register_t *retval) |
497 | { | | 497 | { |
498 | struct proc *p = l->l_proc; | | 498 | struct proc *p = l->l_proc; |
499 | struct linux_emuldata *led = p->p_emuldata; | | 499 | struct linux_emuldata *led = p->p_emuldata; |
500 | | | 500 | |
| | | 501 | if (SCARG(uap, len) != sizeof(*(led->robust_futexes))) |
| | | 502 | return EINVAL; |
501 | led->robust_futexes = SCARG(uap, head); | | 503 | led->robust_futexes = SCARG(uap, head); |
502 | *retval = 0; | | 504 | *retval = 0; |
503 | return 0; | | 505 | return 0; |
504 | } | | 506 | } |
505 | | | 507 | |
506 | int | | 508 | int |
507 | linux_sys_get_robust_list(struct lwp *l, | | 509 | linux_sys_get_robust_list(struct lwp *l, |
508 | const struct linux_sys_get_robust_list_args *uap, register_t *retval) | | 510 | const struct linux_sys_get_robust_list_args *uap, register_t *retval) |
509 | { | | 511 | { |
510 | struct linux_emuldata *led; | | 512 | struct linux_emuldata *led; |
511 | struct linux_robust_list_head *head; | | 513 | struct linux_robust_list_head **head; |
512 | size_t len = sizeof(struct linux_robust_list_head); | | 514 | size_t len = sizeof(*led->robust_futexes); |
513 | int error = 0; | | 515 | int error = 0; |
514 | | | 516 | |
515 | if (!SCARG(uap, pid)) { | | 517 | if (!SCARG(uap, pid)) { |
516 | led = l->l_proc->p_emuldata; | | 518 | led = l->l_proc->p_emuldata; |
517 | head = led->robust_futexes; | | 519 | head = &led->robust_futexes; |
518 | } else { | | 520 | } else { |
519 | struct proc *p; | | 521 | struct proc *p; |
520 | | | 522 | |
521 | mutex_enter(proc_lock); | | 523 | mutex_enter(proc_lock); |
522 | if ((p = p_find(SCARG(uap, pid), PFIND_LOCKED)) == NULL || | | 524 | if ((p = p_find(SCARG(uap, pid), PFIND_LOCKED)) == NULL || |
523 | p->p_emul != &emul_linux) { | | 525 | p->p_emul != &emul_linux) { |
524 | mutex_exit(proc_lock); | | 526 | mutex_exit(proc_lock); |
525 | return ESRCH; | | 527 | return ESRCH; |
526 | } | | 528 | } |
527 | led = p->p_emuldata; | | 529 | led = p->p_emuldata; |
528 | head = led->robust_futexes; | | 530 | head = &led->robust_futexes; |
529 | mutex_exit(proc_lock); | | 531 | mutex_exit(proc_lock); |
530 | } | | 532 | } |
531 | | | 533 | |
532 | error = copyout(&len, SCARG(uap, len), sizeof(size_t)); | | 534 | error = copyout(&len, SCARG(uap, len), sizeof(len)); |
533 | if (error) | | 535 | if (error) |
534 | return error; | | 536 | return error; |
535 | return copyout(head, SCARG(uap, head), | | 537 | return copyout(head, SCARG(uap, head), sizeof(*head)); |
536 | sizeof(struct linux_robust_list_head)); | | | |
537 | } | | 538 | } |
538 | | | 539 | |
539 | static int | | 540 | static int |
540 | handle_futex_death(void *uaddr, pid_t pid, int pi) | | 541 | handle_futex_death(void *uaddr, pid_t pid, int pi) |
541 | { | | 542 | { |
542 | int uval, nval, mval; | | 543 | int uval, nval, mval; |
543 | struct futex *f; | | 544 | struct futex *f; |
544 | | | 545 | |
545 | retry: | | 546 | retry: |
546 | if (copyin(uaddr, &uval, 4)) | | 547 | if (copyin(uaddr, &uval, 4)) |
547 | return EFAULT; | | 548 | return EFAULT; |
548 | | | 549 | |
549 | if ((uval & FUTEX_TID_MASK) == pid) { | | 550 | if ((uval & FUTEX_TID_MASK) == pid) { |
| @@ -574,49 +575,50 @@ fetch_robust_entry(struct linux_robust_l | | | @@ -574,49 +575,50 @@ fetch_robust_entry(struct linux_robust_l |
574 | if (copyin((const void *)head, &uentry, sizeof(unsigned long))) | | 575 | if (copyin((const void *)head, &uentry, sizeof(unsigned long))) |
575 | return EFAULT; | | 576 | return EFAULT; |
576 | | | 577 | |
577 | *entry = (void *)(uentry & ~1UL); | | 578 | *entry = (void *)(uentry & ~1UL); |
578 | *pi = uentry & 1; | | 579 | *pi = uentry & 1; |
579 | | | 580 | |
580 | return 0; | | 581 | return 0; |
581 | } | | 582 | } |
582 | | | 583 | |
583 | /* This walks the list of robust futexes, releasing them. */ | | 584 | /* This walks the list of robust futexes, releasing them. */ |
584 | void | | 585 | void |
585 | release_futexes(struct proc *p) | | 586 | release_futexes(struct proc *p) |
586 | { | | 587 | { |
587 | struct linux_robust_list_head *head = NULL; | | 588 | struct linux_robust_list_head head; |
588 | struct linux_robust_list *entry, *next_entry, *pending; | | 589 | struct linux_robust_list *entry, *next_entry, *pending; |
589 | unsigned int limit = 2048, pi, next_pi, pip; | | 590 | unsigned int limit = 2048, pi, next_pi, pip; |
590 | struct linux_emuldata *led; | | 591 | struct linux_emuldata *led; |
591 | unsigned long futex_offset; | | 592 | unsigned long futex_offset; |
592 | int rc; | | 593 | int rc; |
593 | | | 594 | |
594 | led = p->p_emuldata; | | 595 | led = p->p_emuldata; |
595 | head = led->robust_futexes; | | 596 | if (led->robust_futexes == NULL) |
| | | 597 | return; |
596 | | | 598 | |
597 | if (head == NULL) | | 599 | if (copyin(led->robust_futexes, &head, sizeof(head))) |
598 | return; | | 600 | return; |
599 | | | 601 | |
600 | if (fetch_robust_entry(&entry, &head->list.next, &pi)) | | 602 | if (fetch_robust_entry(&entry, &head.list.next, &pi)) |
601 | return; | | 603 | return; |
602 | | | 604 | |
603 | if (copyin(&head->futex_offset, &futex_offset, sizeof(unsigned long))) | | 605 | if (copyin(&head.futex_offset, &futex_offset, sizeof(unsigned long))) |
604 | return; | | 606 | return; |
605 | | | 607 | |
606 | if (fetch_robust_entry(&pending, &head->pending_list, &pip)) | | 608 | if (fetch_robust_entry(&pending, &head.pending_list, &pip)) |
607 | return; | | 609 | return; |
608 | | | 610 | |
609 | while (entry != &head->list) { | | 611 | while (entry != &head.list) { |
610 | rc = fetch_robust_entry(&next_entry, &entry->next, &next_pi); | | 612 | rc = fetch_robust_entry(&next_entry, &entry->next, &next_pi); |
611 | | | 613 | |
612 | if (entry != pending) | | 614 | if (entry != pending) |
613 | if (handle_futex_death((char *)entry + futex_offset, | | 615 | if (handle_futex_death((char *)entry + futex_offset, |
614 | p->p_pid, pi)) | | 616 | p->p_pid, pi)) |
615 | return; | | 617 | return; |
616 | | | 618 | |
617 | if (rc) | | 619 | if (rc) |
618 | return; | | 620 | return; |
619 | | | 621 | |
620 | entry = next_entry; | | 622 | entry = next_entry; |
621 | pi = next_pi; | | 623 | pi = next_pi; |
622 | | | 624 | |