| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: pthread.c,v 1.160 2020/01/29 15:31:14 kamil Exp $ */ | | 1 | /* $NetBSD: pthread.c,v 1.161 2020/01/29 16:03:44 kamil Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2001, 2002, 2003, 2006, 2007, 2008, 2020 | | 4 | * Copyright (c) 2001, 2002, 2003, 2006, 2007, 2008, 2020 |
5 | * The NetBSD Foundation, Inc. | | 5 | * The NetBSD Foundation, Inc. |
6 | * All rights reserved. | | 6 | * All rights reserved. |
7 | * | | 7 | * |
8 | * This code is derived from software contributed to The NetBSD Foundation | | 8 | * This code is derived from software contributed to The NetBSD Foundation |
9 | * by Nathan J. Williams and Andrew Doran. | | 9 | * by Nathan J. Williams and Andrew Doran. |
10 | * | | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | | 11 | * Redistribution and use in source and binary forms, with or without |
12 | * modification, are permitted provided that the following conditions | | 12 | * modification, are permitted provided that the following conditions |
13 | * are met: | | 13 | * are met: |
14 | * 1. Redistributions of source code must retain the above copyright | | 14 | * 1. Redistributions of source code must retain the above copyright |
| @@ -21,27 +21,27 @@ | | | @@ -21,27 +21,27 @@ |
21 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | | 21 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | | 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | | 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
30 | * POSSIBILITY OF SUCH DAMAGE. | | 30 | * POSSIBILITY OF SUCH DAMAGE. |
31 | */ | | 31 | */ |
32 | | | 32 | |
33 | #include <sys/cdefs.h> | | 33 | #include <sys/cdefs.h> |
34 | __RCSID("$NetBSD: pthread.c,v 1.160 2020/01/29 15:31:14 kamil Exp $"); | | 34 | __RCSID("$NetBSD: pthread.c,v 1.161 2020/01/29 16:03:44 kamil Exp $"); |
35 | | | 35 | |
36 | #define __EXPOSE_STACK 1 | | 36 | #define __EXPOSE_STACK 1 |
37 | | | 37 | |
38 | #include <sys/param.h> | | 38 | #include <sys/param.h> |
39 | #include <sys/exec_elf.h> | | 39 | #include <sys/exec_elf.h> |
40 | #include <sys/mman.h> | | 40 | #include <sys/mman.h> |
41 | #include <sys/lwp.h> | | 41 | #include <sys/lwp.h> |
42 | #include <sys/lwpctl.h> | | 42 | #include <sys/lwpctl.h> |
43 | #include <sys/resource.h> | | 43 | #include <sys/resource.h> |
44 | #include <sys/sysctl.h> | | 44 | #include <sys/sysctl.h> |
45 | #include <sys/tls.h> | | 45 | #include <sys/tls.h> |
46 | #include <uvm/uvm_param.h> | | 46 | #include <uvm/uvm_param.h> |
47 | | | 47 | |
| @@ -587,40 +587,46 @@ pthread__create_tramp(void *cookie) | | | @@ -587,40 +587,46 @@ pthread__create_tramp(void *cookie) |
587 | retval = (*self->pt_func)(self->pt_arg); | | 587 | retval = (*self->pt_func)(self->pt_arg); |
588 | | | 588 | |
589 | pthread_exit(retval); | | 589 | pthread_exit(retval); |
590 | | | 590 | |
591 | /*NOTREACHED*/ | | 591 | /*NOTREACHED*/ |
592 | pthread__abort(); | | 592 | pthread__abort(); |
593 | } | | 593 | } |
594 | | | 594 | |
595 | int | | 595 | int |
596 | pthread_suspend_np(pthread_t thread) | | 596 | pthread_suspend_np(pthread_t thread) |
597 | { | | 597 | { |
598 | pthread_t self; | | 598 | pthread_t self; |
599 | | | 599 | |
| | | 600 | pthread__error(EINVAL, "Invalid thread", |
| | | 601 | thread->pt_magic == PT_MAGIC); |
| | | 602 | |
600 | self = pthread__self(); | | 603 | self = pthread__self(); |
601 | if (self == thread) { | | 604 | if (self == thread) { |
602 | return EDEADLK; | | 605 | return EDEADLK; |
603 | } | | 606 | } |
604 | if (pthread__find(thread) != 0) | | 607 | if (pthread__find(thread) != 0) |
605 | return ESRCH; | | 608 | return ESRCH; |
606 | if (_lwp_suspend(thread->pt_lid) == 0) | | 609 | if (_lwp_suspend(thread->pt_lid) == 0) |
607 | return 0; | | 610 | return 0; |
608 | return errno; | | 611 | return errno; |
609 | } | | 612 | } |
610 | | | 613 | |
611 | int | | 614 | int |
612 | pthread_resume_np(pthread_t thread) | | 615 | pthread_resume_np(pthread_t thread) |
613 | { | | 616 | { |
| | | 617 | |
| | | 618 | pthread__error(EINVAL, "Invalid thread", |
| | | 619 | thread->pt_magic == PT_MAGIC); |
614 | | | 620 | |
615 | if (pthread__find(thread) != 0) | | 621 | if (pthread__find(thread) != 0) |
616 | return ESRCH; | | 622 | return ESRCH; |
617 | if (_lwp_continue(thread->pt_lid) == 0) | | 623 | if (_lwp_continue(thread->pt_lid) == 0) |
618 | return 0; | | 624 | return 0; |
619 | return errno; | | 625 | return errno; |
620 | } | | 626 | } |
621 | | | 627 | |
622 | /* | | 628 | /* |
623 | * In case the thread is exiting at an inopportune time leaving waiters not | | 629 | * In case the thread is exiting at an inopportune time leaving waiters not |
624 | * awoken (because cancelled, for instance) make sure we have no waiters | | 630 | * awoken (because cancelled, for instance) make sure we have no waiters |
625 | * left. | | 631 | * left. |
626 | */ | | 632 | */ |
| @@ -692,34 +698,34 @@ pthread_exit(void *retval) | | | @@ -692,34 +698,34 @@ pthread_exit(void *retval) |
692 | | | 698 | |
693 | out: | | 699 | out: |
694 | /*NOTREACHED*/ | | 700 | /*NOTREACHED*/ |
695 | pthread__abort(); | | 701 | pthread__abort(); |
696 | exit(1); | | 702 | exit(1); |
697 | } | | 703 | } |
698 | | | 704 | |
699 | | | 705 | |
700 | int | | 706 | int |
701 | pthread_join(pthread_t thread, void **valptr) | | 707 | pthread_join(pthread_t thread, void **valptr) |
702 | { | | 708 | { |
703 | pthread_t self; | | 709 | pthread_t self; |
704 | | | 710 | |
| | | 711 | pthread__error(EINVAL, "Invalid thread", |
| | | 712 | thread->pt_magic == PT_MAGIC); |
| | | 713 | |
705 | self = pthread__self(); | | 714 | self = pthread__self(); |
706 | | | 715 | |
707 | if (pthread__find(thread) != 0) | | 716 | if (pthread__find(thread) != 0) |
708 | return ESRCH; | | 717 | return ESRCH; |
709 | | | 718 | |
710 | if (thread->pt_magic != PT_MAGIC) | | | |
711 | return EINVAL; | | | |
712 | | | | |
713 | if (thread == self) | | 719 | if (thread == self) |
714 | return EDEADLK; | | 720 | return EDEADLK; |
715 | | | 721 | |
716 | /* XXX temporary - kernel should handle. */ | | 722 | /* XXX temporary - kernel should handle. */ |
717 | if ((thread->pt_flags & PT_FLAG_DETACHED) != 0) | | 723 | if ((thread->pt_flags & PT_FLAG_DETACHED) != 0) |
718 | return EINVAL; | | 724 | return EINVAL; |
719 | | | 725 | |
720 | /* IEEE Std 1003.1 says pthread_join() never returns EINTR. */ | | 726 | /* IEEE Std 1003.1 says pthread_join() never returns EINTR. */ |
721 | for (;;) { | | 727 | for (;;) { |
722 | pthread__testcancel(self); | | 728 | pthread__testcancel(self); |
723 | if (_lwp_wait(thread->pt_lid, NULL) == 0) | | 729 | if (_lwp_wait(thread->pt_lid, NULL) == 0) |
724 | break; | | 730 | break; |
725 | if (errno != EINTR) | | 731 | if (errno != EINTR) |
| @@ -754,97 +760,104 @@ pthread__reap(pthread_t thread) | | | @@ -754,97 +760,104 @@ pthread__reap(pthread_t thread) |
754 | pthread_mutex_unlock(&thread->pt_lock); | | 760 | pthread_mutex_unlock(&thread->pt_lock); |
755 | | | 761 | |
756 | pthread_mutex_lock(&pthread__deadqueue_lock); | | 762 | pthread_mutex_lock(&pthread__deadqueue_lock); |
757 | PTQ_INSERT_HEAD(&pthread__deadqueue, thread, pt_deadq); | | 763 | PTQ_INSERT_HEAD(&pthread__deadqueue, thread, pt_deadq); |
758 | pthread_mutex_unlock(&pthread__deadqueue_lock); | | 764 | pthread_mutex_unlock(&pthread__deadqueue_lock); |
759 | | | 765 | |
760 | if (name != NULL) | | 766 | if (name != NULL) |
761 | free(name); | | 767 | free(name); |
762 | } | | 768 | } |
763 | | | 769 | |
764 | int | | 770 | int |
765 | pthread_equal(pthread_t t1, pthread_t t2) | | 771 | pthread_equal(pthread_t t1, pthread_t t2) |
766 | { | | 772 | { |
| | | 773 | |
767 | if (__predict_false(__uselibcstub)) | | 774 | if (__predict_false(__uselibcstub)) |
768 | return __libc_thr_equal_stub(t1, t2); | | 775 | return __libc_thr_equal_stub(t1, t2); |
769 | | | 776 | |
| | | 777 | pthread__error(EINVAL, "Invalid thread", |
| | | 778 | t1->pt_magic == PT_MAGIC); |
| | | 779 | |
| | | 780 | pthread__error(EINVAL, "Invalid thread", |
| | | 781 | t2->pt_magic == PT_MAGIC); |
| | | 782 | |
770 | /* Nothing special here. */ | | 783 | /* Nothing special here. */ |
771 | return (t1 == t2); | | 784 | return (t1 == t2); |
772 | } | | 785 | } |
773 | | | 786 | |
774 | | | 787 | |
775 | int | | 788 | int |
776 | pthread_detach(pthread_t thread) | | 789 | pthread_detach(pthread_t thread) |
777 | { | | 790 | { |
778 | int error; | | 791 | int error; |
779 | | | 792 | |
| | | 793 | pthread__error(EINVAL, "Invalid thread", |
| | | 794 | thread->pt_magic == PT_MAGIC); |
| | | 795 | |
780 | if (pthread__find(thread) != 0) | | 796 | if (pthread__find(thread) != 0) |
781 | return ESRCH; | | 797 | return ESRCH; |
782 | | | 798 | |
783 | if (thread->pt_magic != PT_MAGIC) | | | |
784 | return EINVAL; | | | |
785 | | | | |
786 | pthread_mutex_lock(&thread->pt_lock); | | 799 | pthread_mutex_lock(&thread->pt_lock); |
787 | if ((thread->pt_flags & PT_FLAG_DETACHED) != 0) { | | 800 | if ((thread->pt_flags & PT_FLAG_DETACHED) != 0) { |
788 | error = EINVAL; | | 801 | error = EINVAL; |
789 | } else { | | 802 | } else { |
790 | error = _lwp_detach(thread->pt_lid); | | 803 | error = _lwp_detach(thread->pt_lid); |
791 | if (error == 0) | | 804 | if (error == 0) |
792 | thread->pt_flags |= PT_FLAG_DETACHED; | | 805 | thread->pt_flags |= PT_FLAG_DETACHED; |
793 | else | | 806 | else |
794 | error = errno; | | 807 | error = errno; |
795 | } | | 808 | } |
796 | if (thread->pt_state == PT_STATE_ZOMBIE) { | | 809 | if (thread->pt_state == PT_STATE_ZOMBIE) { |
797 | /* pthread__reap() will drop the lock. */ | | 810 | /* pthread__reap() will drop the lock. */ |
798 | pthread__reap(thread); | | 811 | pthread__reap(thread); |
799 | } else | | 812 | } else |
800 | pthread_mutex_unlock(&thread->pt_lock); | | 813 | pthread_mutex_unlock(&thread->pt_lock); |
801 | return error; | | 814 | return error; |
802 | } | | 815 | } |
803 | | | 816 | |
804 | | | 817 | |
805 | int | | 818 | int |
806 | pthread_getname_np(pthread_t thread, char *name, size_t len) | | 819 | pthread_getname_np(pthread_t thread, char *name, size_t len) |
807 | { | | 820 | { |
808 | | | 821 | |
| | | 822 | pthread__error(EINVAL, "Invalid thread", |
| | | 823 | thread->pt_magic == PT_MAGIC); |
| | | 824 | |
809 | if (pthread__find(thread) != 0) | | 825 | if (pthread__find(thread) != 0) |
810 | return ESRCH; | | 826 | return ESRCH; |
811 | | | 827 | |
812 | if (thread->pt_magic != PT_MAGIC) | | | |
813 | return EINVAL; | | | |
814 | | | | |
815 | pthread_mutex_lock(&thread->pt_lock); | | 828 | pthread_mutex_lock(&thread->pt_lock); |
816 | if (thread->pt_name == NULL) | | 829 | if (thread->pt_name == NULL) |
817 | name[0] = '\0'; | | 830 | name[0] = '\0'; |
818 | else | | 831 | else |
819 | strlcpy(name, thread->pt_name, len); | | 832 | strlcpy(name, thread->pt_name, len); |
820 | pthread_mutex_unlock(&thread->pt_lock); | | 833 | pthread_mutex_unlock(&thread->pt_lock); |
821 | | | 834 | |
822 | return 0; | | 835 | return 0; |
823 | } | | 836 | } |
824 | | | 837 | |
825 | | | 838 | |
826 | int | | 839 | int |
827 | pthread_setname_np(pthread_t thread, const char *name, void *arg) | | 840 | pthread_setname_np(pthread_t thread, const char *name, void *arg) |
828 | { | | 841 | { |
829 | char *oldname, *cp, newname[PTHREAD_MAX_NAMELEN_NP]; | | 842 | char *oldname, *cp, newname[PTHREAD_MAX_NAMELEN_NP]; |
830 | int namelen; | | 843 | int namelen; |
831 | | | 844 | |
| | | 845 | pthread__error(EINVAL, "Invalid thread", |
| | | 846 | thread->pt_magic == PT_MAGIC); |
| | | 847 | |
832 | if (pthread__find(thread) != 0) | | 848 | if (pthread__find(thread) != 0) |
833 | return ESRCH; | | 849 | return ESRCH; |
834 | | | 850 | |
835 | if (thread->pt_magic != PT_MAGIC) | | | |
836 | return EINVAL; | | | |
837 | | | | |
838 | namelen = snprintf(newname, sizeof(newname), name, arg); | | 851 | namelen = snprintf(newname, sizeof(newname), name, arg); |
839 | if (namelen >= PTHREAD_MAX_NAMELEN_NP) | | 852 | if (namelen >= PTHREAD_MAX_NAMELEN_NP) |
840 | return EINVAL; | | 853 | return EINVAL; |
841 | | | 854 | |
842 | cp = strdup(newname); | | 855 | cp = strdup(newname); |
843 | if (cp == NULL) | | 856 | if (cp == NULL) |
844 | return ENOMEM; | | 857 | return ENOMEM; |
845 | | | 858 | |
846 | pthread_mutex_lock(&thread->pt_lock); | | 859 | pthread_mutex_lock(&thread->pt_lock); |
847 | oldname = thread->pt_name; | | 860 | oldname = thread->pt_name; |
848 | thread->pt_name = cp; | | 861 | thread->pt_name = cp; |
849 | (void)_lwp_setname(thread->pt_lid, cp); | | 862 | (void)_lwp_setname(thread->pt_lid, cp); |
850 | pthread_mutex_unlock(&thread->pt_lock); | | 863 | pthread_mutex_unlock(&thread->pt_lock); |
| @@ -860,26 +873,29 @@ pthread_t | | | @@ -860,26 +873,29 @@ pthread_t |
860 | pthread_self(void) | | 873 | pthread_self(void) |
861 | { | | 874 | { |
862 | if (__predict_false(__uselibcstub)) | | 875 | if (__predict_false(__uselibcstub)) |
863 | return (pthread_t)__libc_thr_self_stub(); | | 876 | return (pthread_t)__libc_thr_self_stub(); |
864 | | | 877 | |
865 | return pthread__self(); | | 878 | return pthread__self(); |
866 | } | | 879 | } |
867 | | | 880 | |
868 | | | 881 | |
869 | int | | 882 | int |
870 | pthread_cancel(pthread_t thread) | | 883 | pthread_cancel(pthread_t thread) |
871 | { | | 884 | { |
872 | | | 885 | |
| | | 886 | pthread__error(EINVAL, "Invalid thread", |
| | | 887 | thread->pt_magic == PT_MAGIC); |
| | | 888 | |
873 | if (pthread__find(thread) != 0) | | 889 | if (pthread__find(thread) != 0) |
874 | return ESRCH; | | 890 | return ESRCH; |
875 | pthread_mutex_lock(&thread->pt_lock); | | 891 | pthread_mutex_lock(&thread->pt_lock); |
876 | thread->pt_flags |= PT_FLAG_CS_PENDING; | | 892 | thread->pt_flags |= PT_FLAG_CS_PENDING; |
877 | if ((thread->pt_flags & PT_FLAG_CS_DISABLED) == 0) { | | 893 | if ((thread->pt_flags & PT_FLAG_CS_DISABLED) == 0) { |
878 | thread->pt_cancel = 1; | | 894 | thread->pt_cancel = 1; |
879 | pthread_mutex_unlock(&thread->pt_lock); | | 895 | pthread_mutex_unlock(&thread->pt_lock); |
880 | _lwp_wakeup(thread->pt_lid); | | 896 | _lwp_wakeup(thread->pt_lid); |
881 | } else | | 897 | } else |
882 | pthread_mutex_unlock(&thread->pt_lock); | | 898 | pthread_mutex_unlock(&thread->pt_lock); |
883 | | | 899 | |
884 | return 0; | | 900 | return 0; |
885 | } | | 901 | } |