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 617 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
628 | 628 |
629 int linux_sigprocmask(int how, | 629 int linux_sigprocmask(int how, |
630 const linux_sigset_t *set, | 630 const linux_sigset_t *set, |
631 linux_sigset_t *oset) { | 631 linux_sigset_t *oset) { |
632 return errno_value_call( | 632 return errno_value_call( |
633 linux_syscall4(__NR_rt_sigprocmask, how, | 633 linux_syscall4(__NR_rt_sigprocmask, how, |
634 (uintptr_t) set, (uintptr_t) oset, | 634 (uintptr_t) set, (uintptr_t) oset, |
635 sizeof(*set))); | 635 sizeof(*set))); |
636 } | 636 } |
637 | 637 |
| 638 int linux_tgkill(int tgid, int tid, int sig) { |
| 639 return errno_value_call( |
| 640 linux_syscall3(__NR_tgkill, tgid, tid, sig)); |
| 641 } |
| 642 |
638 /* | 643 /* |
639 * Obtain Linux signal number from portable signal number. | 644 * Obtain Linux signal number from portable signal number. |
640 */ | 645 */ |
641 static int nacl_signum_to_linux_signum(int signum) { | 646 static int nacl_signum_to_linux_signum(int signum) { |
642 /* SIGSTKFLT is not defined in newlib, hence no mapping. */ | 647 /* SIGSTKFLT is not defined in newlib, hence no mapping. */ |
643 #define HANDLE_SIGNUM(SIGNUM) case SIGNUM: return LINUX_##SIGNUM; | 648 #define HANDLE_SIGNUM(SIGNUM) case SIGNUM: return LINUX_##SIGNUM; |
644 switch(signum) { | 649 switch(signum) { |
645 HANDLE_SIGNUM(SIGHUP); | 650 HANDLE_SIGNUM(SIGHUP); |
646 HANDLE_SIGNUM(SIGINT); | 651 HANDLE_SIGNUM(SIGINT); |
647 HANDLE_SIGNUM(SIGQUIT); | 652 HANDLE_SIGNUM(SIGQUIT); |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
763 /* | 768 /* |
764 * This function is called only from clone() below or | 769 * This function is called only from clone() below or |
765 * nacl_irt_thread_create() defined in linux_pthread_private.c. | 770 * nacl_irt_thread_create() defined in linux_pthread_private.c. |
766 * In both cases, |child_stack| will never be NULL, although it is allowed | 771 * In both cases, |child_stack| will never be NULL, although it is allowed |
767 * for direct clone() syscall. So, we skip that case's implementation for | 772 * for direct clone() syscall. So, we skip that case's implementation for |
768 * simplicity here. | 773 * simplicity here. |
769 * | 774 * |
770 * Here we reserve 6 * 4 bytes for three purposes described below: | 775 * Here we reserve 6 * 4 bytes for three purposes described below: |
771 * 1) At the beginning of the child process, we call fn(arg). To pass | 776 * 1) At the beginning of the child process, we call fn(arg). To pass |
772 * the function pointer and arguments, we use |stack| for |arg|, | 777 * the function pointer and arguments, we use |stack| for |arg|, |
773 * |stack - 4| for |fn|. Here, we need 4-byte extra memory on top of | 778 * |stack + 4| for |fn|. |
774 * stack for |arg|. | |
775 * 2) Our syscall() implementation reads six 4-byte arguments regardless | 779 * 2) Our syscall() implementation reads six 4-byte arguments regardless |
776 * of its actual arguments. | 780 * of its actual arguments. |
777 * 3) Similar to 2), our clone() implementation reads three 4-byte arguments | 781 * 3) Similar to 2), our clone() implementation reads three 4-byte arguments |
778 * regardless of its actual arguments. | 782 * regardless of its actual arguments. |
779 * So, here we need max size of those three cases (= 6 * 4 bytes) on top of | 783 * So, here we need max size of those three cases (= 6 * 4 bytes) on top of |
780 * the stack, with 16-byte alignment. | 784 * the stack, with 16-byte alignment. |
781 */ | 785 */ |
782 static const int kStackAlignmentMask = ~15; | 786 static const int kStackAlignmentMask = ~15; |
783 void *stack = (void *) (((uintptr_t) child_stack - sizeof(uintptr_t) * 6) & | 787 void *stack = (void *) (((uintptr_t) child_stack - sizeof(uintptr_t) * 6) & |
784 kStackAlignmentMask); | 788 kStackAlignmentMask); |
785 /* Put |fn| and |arg| on child process's stack. */ | 789 /* Put |fn| and |arg| on child process's stack. */ |
786 ((uintptr_t *) stack)[-1] = fn; | |
787 ((uintptr_t *) stack)[0] = arg; | 790 ((uintptr_t *) stack)[0] = arg; |
| 791 ((uintptr_t *) stack)[1] = fn; |
788 | 792 |
789 #if defined(__i386__) | 793 #if defined(__i386__) |
790 uint32_t result; | 794 uint32_t result; |
791 __asm__ __volatile__("int $0x80\n" | 795 __asm__ __volatile__("int $0x80\n" |
792 /* | 796 /* |
793 * If the return value of clone is non-zero, we are | 797 * If the return value of clone is non-zero, we are |
794 * in the parent thread of clone. | 798 * in the parent thread of clone. |
795 */ | 799 */ |
796 "cmp $0, %%eax\n" | 800 "cmp $0, %%eax\n" |
797 "jne 0f\n" | 801 "jne 0f\n" |
798 /* | 802 /* |
799 * In child thread. Clear the frame pointer to | 803 * In child thread. Clear the frame pointer to |
800 * prevent debuggers from unwinding beyond this. | 804 * prevent debuggers from unwinding beyond this. |
801 */ | 805 */ |
802 "mov $0, %%ebp\n" | 806 "mov $0, %%ebp\n" |
803 /* | 807 /* |
804 * Call fn(arg). Note that |arg| is already ready on top | 808 * Call fn(arg). Note that |arg| is already ready on top |
805 * of the stack, here. | 809 * of the stack, here. |
806 */ | 810 */ |
807 "call *-4(%%esp)\n" | 811 "call *4(%%esp)\n" |
808 /* Then call _exit(2) with the return value. */ | 812 /* Then call _exit(2) with the return value. */ |
809 "mov %%eax, %%ebx\n" | 813 "mov %%eax, %%ebx\n" |
810 "mov %[exit_sysno], %%eax\n" | 814 "mov %[exit_sysno], %%eax\n" |
811 "int $0x80\n" | 815 "int $0x80\n" |
812 /* _exit(2) will never return. */ | 816 /* _exit(2) will never return. */ |
813 "hlt\n" | 817 "hlt\n" |
814 "0:\n" | 818 "0:\n" |
815 : "=a"(result) | 819 : "=a"(result) |
816 : "a"(__NR_clone), "b"(flags), "c"(stack), | 820 : "a"(__NR_clone), "b"(flags), "c"(stack), |
817 "d"(ptid), "S"(&desc), "D"(ctid), | 821 "d"(ptid), "S"(&desc), "D"(ctid), |
(...skipping 15 matching lines...) Expand all Loading... |
833 "cmp r0, #0\n" | 837 "cmp r0, #0\n" |
834 "bne 0f\n" | 838 "bne 0f\n" |
835 /* | 839 /* |
836 * In child thread. Clear the frame pointer to | 840 * In child thread. Clear the frame pointer to |
837 * prevent debuggers from unwinding beyond this, | 841 * prevent debuggers from unwinding beyond this, |
838 * load start_func from the stack and call it. | 842 * load start_func from the stack and call it. |
839 */ | 843 */ |
840 "mov fp, #0\n" | 844 "mov fp, #0\n" |
841 /* Load |arg| to r0 register, then call |fn|. */ | 845 /* Load |arg| to r0 register, then call |fn|. */ |
842 "ldr r0, [sp]\n" | 846 "ldr r0, [sp]\n" |
843 "ldr r1, [sp, #-4]\n" | 847 "ldr r1, [sp, #4]\n" |
844 "blx r1\n" | 848 "blx r1\n" |
845 /* | 849 /* |
846 * Then, call _exit(2) with the returned value. | 850 * Then, call _exit(2) with the returned value. |
847 * r0 keeps the return value of |fn(arg)|. | 851 * r0 keeps the return value of |fn(arg)|. |
848 */ | 852 */ |
849 "mov r7, %[exit_sysno]\n" | 853 "mov r7, %[exit_sysno]\n" |
850 "svc #0\n" | 854 "svc #0\n" |
851 /* _exit(2) will never return. */ | 855 /* _exit(2) will never return. */ |
852 "bkpt #0\n" | 856 "bkpt #0\n" |
853 "0:\n" | 857 "0:\n" |
(...skipping 22 matching lines...) Expand all Loading... |
876 va_list ap; | 880 va_list ap; |
877 va_start(ap, arg); | 881 va_start(ap, arg); |
878 void *ptid = va_arg(ap, void *); | 882 void *ptid = va_arg(ap, void *); |
879 void *tls = va_arg(ap, void *); | 883 void *tls = va_arg(ap, void *); |
880 void *ctid = va_arg(ap, void *); | 884 void *ctid = va_arg(ap, void *); |
881 va_end(ap); | 885 va_end(ap); |
882 | 886 |
883 return errno_value_call(linux_clone_wrapper( | 887 return errno_value_call(linux_clone_wrapper( |
884 (uintptr_t) fn, (uintptr_t) arg, flags, child_stack, ptid, tls, ctid)); | 888 (uintptr_t) fn, (uintptr_t) arg, flags, child_stack, ptid, tls, ctid)); |
885 } | 889 } |
OLD | NEW |