Sat Dec 31 07:38:31 2016 UTC ()
Pull up following revision(s) (requested by rin in ticket #1343):
	sys/compat/linux/common/linux_sched.c: revision 1.68
PR/50021: Rin Okuyama: Fix linux affinity syscalls


(snj)
diff -r1.66.4.1 -r1.66.4.2 src/sys/compat/linux/common/linux_sched.c

cvs diff -r1.66.4.1 -r1.66.4.2 src/sys/compat/linux/common/linux_sched.c (expand / switch to unified diff)

--- src/sys/compat/linux/common/linux_sched.c 2015/01/17 12:10:54 1.66.4.1
+++ src/sys/compat/linux/common/linux_sched.c 2016/12/31 07:38:31 1.66.4.2
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: linux_sched.c,v 1.66.4.1 2015/01/17 12:10:54 martin Exp $ */ 1/* $NetBSD: linux_sched.c,v 1.66.4.2 2016/12/31 07:38:31 snj Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1999 The NetBSD Foundation, Inc. 4 * Copyright (c) 1999 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9 * NASA Ames Research Center; by Matthias Scheler. 9 * NASA Ames Research Center; by Matthias Scheler.
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
@@ -25,27 +25,27 @@ @@ -25,27 +25,27 @@
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/* 33/*
34 * Linux compatibility module. Try to deal with scheduler related syscalls. 34 * Linux compatibility module. Try to deal with scheduler related syscalls.
35 */ 35 */
36 36
37#include <sys/cdefs.h> 37#include <sys/cdefs.h>
38__KERNEL_RCSID(0, "$NetBSD: linux_sched.c,v 1.66.4.1 2015/01/17 12:10:54 martin Exp $"); 38__KERNEL_RCSID(0, "$NetBSD: linux_sched.c,v 1.66.4.2 2016/12/31 07:38:31 snj Exp $");
39 39
40#include <sys/param.h> 40#include <sys/param.h>
41#include <sys/mount.h> 41#include <sys/mount.h>
42#include <sys/proc.h> 42#include <sys/proc.h>
43#include <sys/systm.h> 43#include <sys/systm.h>
44#include <sys/sysctl.h> 44#include <sys/sysctl.h>
45#include <sys/syscallargs.h> 45#include <sys/syscallargs.h>
46#include <sys/wait.h> 46#include <sys/wait.h>
47#include <sys/kauth.h> 47#include <sys/kauth.h>
48#include <sys/ptrace.h> 48#include <sys/ptrace.h>
49#include <sys/atomic.h> 49#include <sys/atomic.h>
50 50
51#include <sys/cpu.h> 51#include <sys/cpu.h>
@@ -55,26 +55,29 @@ __KERNEL_RCSID(0, "$NetBSD: linux_sched. @@ -55,26 +55,29 @@ __KERNEL_RCSID(0, "$NetBSD: linux_sched.
55#include <compat/linux/common/linux_emuldata.h> 55#include <compat/linux/common/linux_emuldata.h>
56#include <compat/linux/common/linux_ipc.h> 56#include <compat/linux/common/linux_ipc.h>
57#include <compat/linux/common/linux_sem.h> 57#include <compat/linux/common/linux_sem.h>
58#include <compat/linux/common/linux_exec.h> 58#include <compat/linux/common/linux_exec.h>
59#include <compat/linux/common/linux_machdep.h> 59#include <compat/linux/common/linux_machdep.h>
60 60
61#include <compat/linux/linux_syscallargs.h> 61#include <compat/linux/linux_syscallargs.h>
62 62
63#include <compat/linux/common/linux_sched.h> 63#include <compat/linux/common/linux_sched.h>
64 64
65static int linux_clone_nptl(struct lwp *, const struct linux_sys_clone_args *, 65static int linux_clone_nptl(struct lwp *, const struct linux_sys_clone_args *,
66 register_t *); 66 register_t *);
67 67
 68/* Unlike Linux, dynamically calculate CPU mask size */
 69#define LINUX_CPU_MASK_SIZE (sizeof(long) * ((ncpu + LONG_BIT - 1) / LONG_BIT))
 70
68#if DEBUG_LINUX 71#if DEBUG_LINUX
69#define DPRINTF(x) uprintf x 72#define DPRINTF(x) uprintf x
70#else 73#else
71#define DPRINTF(x) 74#define DPRINTF(x)
72#endif 75#endif
73 76
74static void 77static void
75linux_child_return(void *arg) 78linux_child_return(void *arg)
76{ 79{
77 struct lwp *l = arg; 80 struct lwp *l = arg;
78 struct proc *p = l->l_proc; 81 struct proc *p = l->l_proc;
79 struct linux_emuldata *led = l->l_emuldata; 82 struct linux_emuldata *led = l->l_emuldata;
80 void *ctp = led->led_child_tidptr; 83 void *ctp = led->led_child_tidptr;
@@ -617,80 +620,90 @@ linux_sys_set_tid_address(struct lwp *l, @@ -617,80 +620,90 @@ linux_sys_set_tid_address(struct lwp *l,
617 620
618 return 0; 621 return 0;
619} 622}
620 623
621/* ARGUSED1 */ 624/* ARGUSED1 */
622int 625int
623linux_sys_gettid(struct lwp *l, const void *v, register_t *retval) 626linux_sys_gettid(struct lwp *l, const void *v, register_t *retval)
624{ 627{
625 628
626 *retval = l->l_lid; 629 *retval = l->l_lid;
627 return 0; 630 return 0;
628} 631}
629 632
 633/*
 634 * The affinity syscalls assume that the layout of our cpu kcpuset is
 635 * the same as linux's: a linear bitmask.
 636 */
630int 637int
631linux_sys_sched_getaffinity(struct lwp *l, const struct linux_sys_sched_getaffinity_args *uap, register_t *retval) 638linux_sys_sched_getaffinity(struct lwp *l, const struct linux_sys_sched_getaffinity_args *uap, register_t *retval)
632{ 639{
633 /* { 640 /* {
634 syscallarg(linux_pid_t) pid; 641 syscallarg(linux_pid_t) pid;
635 syscallarg(unsigned int) len; 642 syscallarg(unsigned int) len;
636 syscallarg(unsigned long *) mask; 643 syscallarg(unsigned long *) mask;
637 } */ 644 } */
638 proc_t *p; 645 struct lwp *t;
639 unsigned long *lp, *data; 646 kcpuset_t *kcset;
640 int error, size, nb = ncpu; 647 size_t size;
 648 cpuid_t i;
 649 int error;
641 650
642 /* Unlike Linux, dynamically calculate cpu mask size */ 651 size = LINUX_CPU_MASK_SIZE;
643 size = sizeof(long) * ((ncpu + LONG_BIT - 1) / LONG_BIT); 
644 if (SCARG(uap, len) < size) 652 if (SCARG(uap, len) < size)
645 return EINVAL; 653 return EINVAL;
646 654
647 /* XXX: Pointless check. TODO: Actually implement this. */ 655 /* Lock the LWP */
648 mutex_enter(proc_lock); 656 t = lwp_find2(SCARG(uap, pid), l->l_lid);
649 p = proc_find(SCARG(uap, pid)); 657 if (t == NULL)
650 mutex_exit(proc_lock); 
651 if (p == NULL) { 
652 return ESRCH; 658 return ESRCH;
653 } 
654 
655 /*  
656 * return the actual number of CPU, tag all of them as available  
657 * The result is a mask, the first CPU being in the least significant 
658 * bit. 
659 */ 
660 data = kmem_zalloc(size, KM_SLEEP); 
661 lp = data; 
662 while (nb > LONG_BIT) { 
663 *lp++ = ~0UL; 
664 nb -= LONG_BIT; 
665 } 
666 if (nb) 
667 *lp = (1 << ncpu) - 1; 
668 659
669 error = copyout(data, SCARG(uap, mask), size); 660 /* Check the permission */
670 kmem_free(data, size); 661 if (kauth_authorize_process(l->l_cred,
 662 KAUTH_PROCESS_SCHEDULER_GETAFFINITY, t->l_proc, NULL, NULL, NULL)) {
 663 mutex_exit(t->l_proc->p_lock);
 664 return EPERM;
 665 }
 666
 667 kcpuset_create(&kcset, true);
 668 lwp_lock(t);
 669 if (t->l_affinity != NULL)
 670 kcpuset_copy(kcset, t->l_affinity);
 671 else {
 672 /*
 673 * All available CPUs should be masked when affinity has not
 674 * been set.
 675 */
 676 kcpuset_zero(kcset);
 677 for (i = 0; i < ncpu; i++)
 678 kcpuset_set(kcset, i);
 679 }
 680 lwp_unlock(t);
 681 mutex_exit(t->l_proc->p_lock);
 682 error = kcpuset_copyout(kcset, (cpuset_t *)SCARG(uap, mask), size);
 683 kcpuset_unuse(kcset, NULL);
671 *retval = size; 684 *retval = size;
672 return error; 685 return error;
673} 686}
674 687
675int 688int
676linux_sys_sched_setaffinity(struct lwp *l, const struct linux_sys_sched_setaffinity_args *uap, register_t *retval) 689linux_sys_sched_setaffinity(struct lwp *l, const struct linux_sys_sched_setaffinity_args *uap, register_t *retval)
677{ 690{
678 /* { 691 /* {
679 syscallarg(linux_pid_t) pid; 692 syscallarg(linux_pid_t) pid;
680 syscallarg(unsigned int) len; 693 syscallarg(unsigned int) len;
681 syscallarg(unsigned long *) mask; 694 syscallarg(unsigned long *) mask;
682 } */ 695 } */
683 proc_t *p; 696 struct sys__sched_setaffinity_args ssa;
 697 size_t size;
684 698
685 /* XXX: Pointless check. TODO: Actually implement this. */ 699 size = LINUX_CPU_MASK_SIZE;
686 mutex_enter(proc_lock); 700 if (SCARG(uap, len) < size)
687 p = proc_find(SCARG(uap, pid)); 701 return EINVAL;
688 mutex_exit(proc_lock); 
689 if (p == NULL) { 
690 return ESRCH; 
691 } 
692 702
693 /* Let's ignore it */ 703 SCARG(&ssa, pid) = SCARG(uap, pid);
694 DPRINTF(("%s\n", __func__)); 704 SCARG(&ssa, lid) = l->l_lid;
695 return 0; 705 SCARG(&ssa, size) = size;
 706 SCARG(&ssa, cpuset) = (cpuset_t *)SCARG(uap, mask);
 707
 708 return sys__sched_setaffinity(l, &ssa, retval);
696} 709}