Lines 664-669
linux_sys_futex(struct thread *td, struct linux_sys_futex_args *args)
Link Here
|
664 |
struct timespec uts, *ts; |
664 |
struct timespec uts, *ts; |
665 |
int error, save; |
665 |
int error, save; |
666 |
uint32_t flags, val; |
666 |
uint32_t flags, val; |
|
|
667 |
int no_compare; |
667 |
|
668 |
|
668 |
if (args->op & LINUX_FUTEX_PRIVATE_FLAG) { |
669 |
if (args->op & LINUX_FUTEX_PRIVATE_FLAG) { |
669 |
flags = 0; |
670 |
flags = 0; |
Lines 688-693
linux_sys_futex(struct thread *td, struct linux_sys_futex_args *args)
Link Here
|
688 |
|
689 |
|
689 |
error = 0; |
690 |
error = 0; |
690 |
f = f2 = NULL; |
691 |
f = f2 = NULL; |
|
|
692 |
no_compare = 0; // for FUTEX_REQUEUE |
691 |
|
693 |
|
692 |
switch (args->op) { |
694 |
switch (args->op) { |
693 |
case LINUX_FUTEX_WAIT: |
695 |
case LINUX_FUTEX_WAIT: |
Lines 767-772
linux_sys_futex(struct thread *td, struct linux_sys_futex_args *args)
Link Here
|
767 |
futex_put(f, NULL); |
769 |
futex_put(f, NULL); |
768 |
break; |
770 |
break; |
769 |
|
771 |
|
|
|
772 |
case LINUX_FUTEX_REQUEUE: |
773 |
/* |
774 |
* Glibc does not use this operation since version 2.3.3, |
775 |
* as it is racy and replaced by FUTEX_CMP_REQUEUE operation. |
776 |
* Glibc versions prior to 2.3.3 fall back to FUTEX_WAKE when |
777 |
* FUTEX_REQUEUE returned EINVAL. |
778 |
*/ |
779 |
pem = pem_find(td->td_proc); |
780 |
if ((pem->flags & LINUX_XDEPR_REQUEUEOP) == 0) { |
781 |
linux_msg(td, "warn: deprecated FUTEX_REQUEUE"); |
782 |
pem->flags |= LINUX_XDEPR_REQUEUEOP; |
783 |
LIN_SDT_PROBE0(futex, linux_sys_futex, |
784 |
deprecated_requeue); |
785 |
} |
786 |
/* |
787 |
* The above is true, however musl libc does make use of the |
788 |
* futex requeue operation, so we add support for it. |
789 |
*/ |
790 |
no_compare = 1; |
791 |
/* FALLTHROUGH */ |
792 |
|
770 |
case LINUX_FUTEX_CMP_REQUEUE: |
793 |
case LINUX_FUTEX_CMP_REQUEUE: |
771 |
LIN_SDT_PROBE5(futex, linux_sys_futex, debug_cmp_requeue, |
794 |
LIN_SDT_PROBE5(futex, linux_sys_futex, debug_cmp_requeue, |
772 |
args->uaddr, args->val, args->val3, args->uaddr2, |
795 |
args->uaddr, args->val, args->val3, args->uaddr2, |
Lines 819-825
linux_sys_futex(struct thread *td, struct linux_sys_futex_args *args)
Link Here
|
819 |
error); |
842 |
error); |
820 |
return (error); |
843 |
return (error); |
821 |
} |
844 |
} |
822 |
if (val != args->val3) { |
845 |
if ((no_compare == 0) && val != args->val3) { |
823 |
LIN_SDT_PROBE2(futex, linux_sys_futex, |
846 |
LIN_SDT_PROBE2(futex, linux_sys_futex, |
824 |
debug_cmp_requeue_value_neq, args->val, val); |
847 |
debug_cmp_requeue_value_neq, args->val, val); |
825 |
LINUX_CTR2(sys_futex, "CMP_REQUEUE val 0x%x != uval 0x%x", |
848 |
LINUX_CTR2(sys_futex, "CMP_REQUEUE val 0x%x != uval 0x%x", |
Lines 931-952
linux_sys_futex(struct thread *td, struct linux_sys_futex_args *args)
Link Here
|
931 |
} |
954 |
} |
932 |
return (ENOSYS); |
955 |
return (ENOSYS); |
933 |
|
956 |
|
934 |
case LINUX_FUTEX_REQUEUE: |
|
|
935 |
/* |
936 |
* Glibc does not use this operation since version 2.3.3, |
937 |
* as it is racy and replaced by FUTEX_CMP_REQUEUE operation. |
938 |
* Glibc versions prior to 2.3.3 fall back to FUTEX_WAKE when |
939 |
* FUTEX_REQUEUE returned EINVAL. |
940 |
*/ |
941 |
pem = pem_find(td->td_proc); |
942 |
if ((pem->flags & LINUX_XDEPR_REQUEUEOP) == 0) { |
943 |
linux_msg(td, "unsupported FUTEX_REQUEUE"); |
944 |
pem->flags |= LINUX_XDEPR_REQUEUEOP; |
945 |
LIN_SDT_PROBE0(futex, linux_sys_futex, |
946 |
deprecated_requeue); |
947 |
} |
948 |
return (EINVAL); |
949 |
|
950 |
case LINUX_FUTEX_WAIT_REQUEUE_PI: |
957 |
case LINUX_FUTEX_WAIT_REQUEUE_PI: |
951 |
/* not yet implemented */ |
958 |
/* not yet implemented */ |
952 |
pem = pem_find(td->td_proc); |
959 |
pem = pem_find(td->td_proc); |