OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2014 The Native Client Authors. All rights reserved. | 2 * Copyright (c) 2014 The Native Client Authors. All rights reserved. |
3 * Use of this source code is governed by a BSD-style license that can be | 3 * Use of this source code is governed by a BSD-style license that can be |
4 * found in the LICENSE file. | 4 * found in the LICENSE file. |
5 */ | 5 */ |
6 | 6 |
7 /* | 7 /* |
8 * This file defines various POSIX-like functions directly using Linux | 8 * This file defines various POSIX-like functions directly using Linux |
9 * syscalls. This is analogous to src/untrusted/nacl/sys_private.c, which | 9 * syscalls. This is analogous to src/untrusted/nacl/sys_private.c, which |
10 * defines functions using NaCl syscalls directly. | 10 * defines functions using NaCl syscalls directly. |
(...skipping 592 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
603 | 603 |
604 int linux_sigprocmask(int how, | 604 int linux_sigprocmask(int how, |
605 const linux_sigset_t *set, | 605 const linux_sigset_t *set, |
606 linux_sigset_t *oset) { | 606 linux_sigset_t *oset) { |
607 return errno_value_call( | 607 return errno_value_call( |
608 linux_syscall4(__NR_rt_sigprocmask, how, | 608 linux_syscall4(__NR_rt_sigprocmask, how, |
609 (uintptr_t) set, (uintptr_t) oset, | 609 (uintptr_t) set, (uintptr_t) oset, |
610 sizeof(*set))); | 610 sizeof(*set))); |
611 } | 611 } |
612 | 612 |
| 613 int linux_tgkill(int tgid, int tid, int sig) { |
| 614 return errno_value_call( |
| 615 linux_syscall3(__NR_tgkill, tgid, tid, sig)); |
| 616 } |
| 617 |
613 /* | 618 /* |
614 * Obtain Linux signal number from portable signal number. | 619 * Obtain Linux signal number from portable signal number. |
615 */ | 620 */ |
616 static int nacl_signum_to_linux_signum(int signum) { | 621 static int nacl_signum_to_linux_signum(int signum) { |
617 /* SIGSTKFLT is not defined in newlib, hence no mapping. */ | 622 /* SIGSTKFLT is not defined in newlib, hence no mapping. */ |
618 #define HANDLE_SIGNUM(SIGNUM) case SIGNUM: return LINUX_##SIGNUM; | 623 #define HANDLE_SIGNUM(SIGNUM) case SIGNUM: return LINUX_##SIGNUM; |
619 switch(signum) { | 624 switch(signum) { |
620 HANDLE_SIGNUM(SIGHUP); | 625 HANDLE_SIGNUM(SIGHUP); |
621 HANDLE_SIGNUM(SIGINT); | 626 HANDLE_SIGNUM(SIGINT); |
622 HANDLE_SIGNUM(SIGQUIT); | 627 HANDLE_SIGNUM(SIGQUIT); |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
738 /* | 743 /* |
739 * This function is called only from clone() below or | 744 * This function is called only from clone() below or |
740 * nacl_irt_thread_create() defined in linux_pthread_private.c. | 745 * nacl_irt_thread_create() defined in linux_pthread_private.c. |
741 * In both cases, |child_stack| will never be NULL, although it is allowed | 746 * In both cases, |child_stack| will never be NULL, although it is allowed |
742 * for direct clone() syscall. So, we skip that case's implementation for | 747 * for direct clone() syscall. So, we skip that case's implementation for |
743 * simplicity here. | 748 * simplicity here. |
744 * | 749 * |
745 * Here we reserve 6 * 4 bytes for three purposes described below: | 750 * Here we reserve 6 * 4 bytes for three purposes described below: |
746 * 1) At the beginning of the child process, we call fn(arg). To pass | 751 * 1) At the beginning of the child process, we call fn(arg). To pass |
747 * the function pointer and arguments, we use |stack| for |arg|, | 752 * the function pointer and arguments, we use |stack| for |arg|, |
748 * |stack - 4| for |fn|. Here, we need 4-byte extra memory on top of | 753 * |stack + 4| for |fn|. |
749 * stack for |arg|. | |
750 * 2) Our syscall() implementation reads six 4-byte arguments regardless | 754 * 2) Our syscall() implementation reads six 4-byte arguments regardless |
751 * of its actual arguments. | 755 * of its actual arguments. |
752 * 3) Similar to 2), our clone() implementation reads three 4-byte arguments | 756 * 3) Similar to 2), our clone() implementation reads three 4-byte arguments |
753 * regardless of its actual arguments. | 757 * regardless of its actual arguments. |
754 * So, here we need max size of those three cases (= 6 * 4 bytes) on top of | 758 * So, here we need max size of those three cases (= 6 * 4 bytes) on top of |
755 * the stack, with 16-byte alignment. | 759 * the stack, with 16-byte alignment. |
756 */ | 760 */ |
757 static const int kStackAlignmentMask = ~15; | 761 static const int kStackAlignmentMask = ~15; |
758 void *stack = (void *) (((uintptr_t) child_stack - sizeof(uintptr_t) * 6) & | 762 void *stack = (void *) (((uintptr_t) child_stack - sizeof(uintptr_t) * 6) & |
759 kStackAlignmentMask); | 763 kStackAlignmentMask); |
760 /* Put |fn| and |arg| on child process's stack. */ | 764 /* Put |fn| and |arg| on child process's stack. */ |
761 ((uintptr_t *) stack)[-1] = fn; | |
762 ((uintptr_t *) stack)[0] = arg; | 765 ((uintptr_t *) stack)[0] = arg; |
| 766 ((uintptr_t *) stack)[1] = fn; |
763 | 767 |
764 #if defined(__i386__) | 768 #if defined(__i386__) |
765 uint32_t result; | 769 uint32_t result; |
766 __asm__ __volatile__("int $0x80\n" | 770 __asm__ __volatile__("int $0x80\n" |
767 /* | 771 /* |
768 * If the return value of clone is non-zero, we are | 772 * If the return value of clone is non-zero, we are |
769 * in the parent thread of clone. | 773 * in the parent thread of clone. |
770 */ | 774 */ |
771 "cmp $0, %%eax\n" | 775 "cmp $0, %%eax\n" |
772 "jne 0f\n" | 776 "jne 0f\n" |
773 /* | 777 /* |
774 * In child thread. Clear the frame pointer to | 778 * In child thread. Clear the frame pointer to |
775 * prevent debuggers from unwinding beyond this. | 779 * prevent debuggers from unwinding beyond this. |
776 */ | 780 */ |
777 "mov $0, %%ebp\n" | 781 "mov $0, %%ebp\n" |
778 /* | 782 /* |
779 * Call fn(arg). Note that |arg| is already ready on top | 783 * Call fn(arg). Note that |arg| is already ready on top |
780 * of the stack, here. | 784 * of the stack, here. |
781 */ | 785 */ |
782 "call *-4(%%esp)\n" | 786 "call *4(%%esp)\n" |
783 /* Then call _exit(2) with the return value. */ | 787 /* Then call _exit(2) with the return value. */ |
784 "mov %%eax, %%ebx\n" | 788 "mov %%eax, %%ebx\n" |
785 "mov %[exit_sysno], %%eax\n" | 789 "mov %[exit_sysno], %%eax\n" |
786 "int $0x80\n" | 790 "int $0x80\n" |
787 /* _exit(2) will never return. */ | 791 /* _exit(2) will never return. */ |
788 "hlt\n" | 792 "hlt\n" |
789 "0:\n" | 793 "0:\n" |
790 : "=a"(result) | 794 : "=a"(result) |
791 : "a"(__NR_clone), "b"(flags), "c"(stack), | 795 : "a"(__NR_clone), "b"(flags), "c"(stack), |
792 "d"(ptid), "S"(&desc), "D"(ctid), | 796 "d"(ptid), "S"(&desc), "D"(ctid), |
(...skipping 15 matching lines...) Expand all Loading... |
808 "cmp r0, #0\n" | 812 "cmp r0, #0\n" |
809 "bne 0f\n" | 813 "bne 0f\n" |
810 /* | 814 /* |
811 * In child thread. Clear the frame pointer to | 815 * In child thread. Clear the frame pointer to |
812 * prevent debuggers from unwinding beyond this, | 816 * prevent debuggers from unwinding beyond this, |
813 * load start_func from the stack and call it. | 817 * load start_func from the stack and call it. |
814 */ | 818 */ |
815 "mov fp, #0\n" | 819 "mov fp, #0\n" |
816 /* Load |arg| to r0 register, then call |fn|. */ | 820 /* Load |arg| to r0 register, then call |fn|. */ |
817 "ldr r0, [sp]\n" | 821 "ldr r0, [sp]\n" |
818 "ldr r1, [sp, #-4]\n" | 822 "ldr r1, [sp, #4]\n" |
819 "blx r1\n" | 823 "blx r1\n" |
820 /* | 824 /* |
821 * Then, call _exit(2) with the returned value. | 825 * Then, call _exit(2) with the returned value. |
822 * r0 keeps the return value of |fn(arg)|. | 826 * r0 keeps the return value of |fn(arg)|. |
823 */ | 827 */ |
824 "mov r7, %[exit_sysno]\n" | 828 "mov r7, %[exit_sysno]\n" |
825 "svc #0\n" | 829 "svc #0\n" |
826 /* _exit(2) will never return. */ | 830 /* _exit(2) will never return. */ |
827 "bkpt #0\n" | 831 "bkpt #0\n" |
828 "0:\n" | 832 "0:\n" |
(...skipping 22 matching lines...) Expand all Loading... |
851 va_list ap; | 855 va_list ap; |
852 va_start(ap, arg); | 856 va_start(ap, arg); |
853 void *ptid = va_arg(ap, void *); | 857 void *ptid = va_arg(ap, void *); |
854 void *tls = va_arg(ap, void *); | 858 void *tls = va_arg(ap, void *); |
855 void *ctid = va_arg(ap, void *); | 859 void *ctid = va_arg(ap, void *); |
856 va_end(ap); | 860 va_end(ap); |
857 | 861 |
858 return errno_value_call(linux_clone_wrapper( | 862 return errno_value_call(linux_clone_wrapper( |
859 (uintptr_t) fn, (uintptr_t) arg, flags, child_stack, ptid, tls, ctid)); | 863 (uintptr_t) fn, (uintptr_t) arg, flags, child_stack, ptid, tls, ctid)); |
860 } | 864 } |
OLD | NEW |