Date: Tue, 03 Jun 2014 22:13:33 +0400 From: "Alexander V. Chernikov" <melifaro@FreeBSD.org> To: Konstantin Belousov <kostikbel@gmail.com> Cc: hackers@freebsd.org Subject: Re: Permit init(8) use its own cpuset group. Message-ID: <538E104D.3000904@FreeBSD.org> In-Reply-To: <20140602164850.GS3991@kib.kiev.ua> References: <538C8F9A.4020301@FreeBSD.org> <20140602164850.GS3991@kib.kiev.ua>
next in thread | previous in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format. --------------040501050600090800020807 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit On 02.06.2014 20:48, Konstantin Belousov wrote: > On Mon, Jun 02, 2014 at 06:52:10PM +0400, Alexander V. Chernikov wrote: >> Hello list! >> >> Currently init(8) uses group 1 which is root group. >> Modifications of this group affects both kernel and userland threads. >> Additionally, such modifications are impossible, for example, in presence >> of multi-queue NIC drivers (like igb or ixgbe) which binds their threads to >> particular cpus. >> >> Proposed change ("init_cpuset" loader tunable) permits changing cpu >> masks for >> userland more easily. Restricting user processes to migrate to/from CPU >> cores >> used for network traffic processing is one of the cases. >> >> Phabricator: https://phabric.freebsd.org/D141 (the same version attached >> inline) >> >> If there are no objections, I'll commit this next week. > Why is the tunable needed ? IMO it is more reasonable to create a new > cpuset always, at least I cannot explain why the existing behaviour Initially I've planned to make this behavior to be default. However I though someone will complain on changing defaults. That's why I've introduced the tunable for that. > is useful. If creating new cpuset unconditionally, you could consider > doing it in kernel in start_init(). You would also need to update the > cpuset(2) man page, which states that cpuset 1 is set for all processes. Please take a look on the new version doing this (also updated in phabricator, https://phabric.freebsd.org/D141 ). > > Still, see comments below for the patch. > >> Index: sbin/init/init.c >> =================================================================== >> --- sbin/init/init.c (revision 266306) >> +++ sbin/init/init.c (working copy) >> @@ -47,6 +47,8 @@ static const char rcsid[] = >> #include <sys/param.h> >> #include <sys/ioctl.h> >> #include <sys/mount.h> >> +#include <sys/param.h> >> +#include <sys/cpuset.h> >> #include <sys/sysctl.h> >> #include <sys/wait.h> >> #include <sys/stat.h> >> @@ -320,6 +322,19 @@ invalid: >> warning("Can't chroot to %s: %m", kenv_value); >> } >> >> + if (kenv(KENV_GET, "init_cpuset", kenv_value, sizeof(kenv_value)) > 0) { >> + if (getpid() == 1) { > If you use the && operator for conditionals instead of two if()s, the nesting > level of the block can be reduced. > >> + cpusetid_t setid; > The variable must be declared at the function start. > >> + >> + setid = -1; > Why do you need to initialize the variable ? > >> + if (cpuset(&setid) != 0) { >> + warning("cpu set alloc failed: %m"); >> + } else { >> + if (cpuset_setid(CPU_WHICH_PID, 1, setid) != 0) > This could be else if () again to reduce indentation. > >> + warning("cpuset_setsid failed: %m"); >> + } >> + } >> + } >> /* >> * Additional check if devfs needs to be mounted: >> * If "/" and "/dev" have the same device number, >> _______________________________________________ >> freebsd-hackers@freebsd.org mailing list >> http://lists.freebsd.org/mailman/listinfo/freebsd-hackers >> To unsubscribe, send any mail to "freebsd-hackers-unsubscribe@freebsd.org" --------------040501050600090800020807 Content-Type: text/x-patch; name="D141.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="D141.diff" Index: lib/libc/sys/cpuset.2 =================================================================== --- lib/libc/sys/cpuset.2 +++ lib/libc/sys/cpuset.2 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd February 14, 2014 +.Dd June 03, 2014 .Dt CPUSET 2 .Os .Sh NAME @@ -52,7 +52,9 @@ Processor sets contain lists of CPUs that members may run on and exist only as long as some process is a member of the set. All processes in the system have an assigned set. -The default set for all processes in the system is the set numbered 1. +Kernel and userland processes uses different ones. +Kernel processes are started in set 1 while userland processes are started +in set 2. Threads belong to the same set as the process which contains them, however, they may further restrict their set with the anonymous per-thread mask. Index: sys/kern/init_main.c =================================================================== --- sys/kern/init_main.c +++ sys/kern/init_main.c @@ -702,6 +702,7 @@ GIANT_REQUIRED; td = curthread; + td->td_cpuset = cpuset_pid1(); p = td->td_proc; vfs_mountroot(); Index: sys/kern/kern_cpuset.c =================================================================== --- sys/kern/kern_cpuset.c +++ sys/kern/kern_cpuset.c @@ -722,7 +722,7 @@ * system. It is initially created with a mask of all processors * because we don't know what processors are valid until cpuset_init() * runs. This set is immutable. - * 1 - The default set which all processes are a member of until changed. + * 1 - The default set which all kernel processes are a member of until changed. * This allows an administrator to move all threads off of given cpus to * dedicate them to high priority tasks or save power etc. */ @@ -752,16 +752,38 @@ */ set = uma_zalloc(cpuset_zone, M_WAITOK); error = _cpuset_create(set, cpuset_zero, &cpuset_zero->cs_mask, 1); - KASSERT(error == 0, ("Error creating default set: %d\n", error)); + KASSERT(error == 0, ("Error creating default kernel cpuset: %d\n", + error)); /* * Initialize the unit allocator. 0 and 1 are allocated above. + * Set 2 is reserved for init. */ - cpuset_unr = new_unrhdr(2, INT_MAX, NULL); + cpuset_unr = new_unrhdr(3, INT_MAX, NULL); return (set); } /* + * Creates another cpuset for init process. + * + * 2 - The default set which all userland processes are a member of until + * changed. This allows an administrator to move all threads off of given + * cpus to dedicate them to high priority tasks or save power etc. + */ +struct cpuset * +cpuset_pid1(void) +{ + struct cpuset *set; + int error; + + set = uma_zalloc(cpuset_zone, M_WAITOK); + error = _cpuset_create(set, cpuset_zero, &cpuset_zero->cs_mask, 2); + KASSERT(error == 0, ("Error creating default userland cpuset: %d\n", + error)); + return (set); +} + +/* * Create a cpuset, which would be cpuset_create() but * mark the new 'set' as root. * Index: sys/sys/cpuset.h =================================================================== --- sys/sys/cpuset.h +++ sys/sys/cpuset.h @@ -115,6 +115,7 @@ struct proc; struct cpuset *cpuset_thread0(void); +struct cpuset *cpuset_pid1(void); struct cpuset *cpuset_ref(struct cpuset *); void cpuset_rel(struct cpuset *); int cpuset_setthread(lwpid_t id, cpuset_t *); Index: usr.bin/cpuset/cpuset.1 =================================================================== --- usr.bin/cpuset/cpuset.1 +++ usr.bin/cpuset/cpuset.1 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd January 14, 2011 +.Dd June 03, 2014 .Dt CPUSET 1 .Os .Sh NAME @@ -81,7 +81,9 @@ .Pp There are two sets applicable to each process and one private mask per thread. Every process in the system belongs to a cpuset. -By default processes are started in set 1. +Kernel and userland processes uses different default sets. +Kernel processes are started in set 1. +Userland processes are started in set 2. The mask or id may be queried using .Fl c . Each thread also has a private mask of CPUs it is allowed to run @@ -163,9 +165,9 @@ belongs to restricting it to CPUs 0 and 2: .Dl cpuset -l 0,2 -c -p <sh pid> .Pp -Modify the cpuset all threads are in by default to contain only +Modify the cpuset all userland threads are in by default to contain only the first 4 CPUs, leaving the rest idle: -.Dl cpuset -l 0-3 -s 1 +.Dl cpuset -l 0-3 -s 2 .Pp Print the id of the cpuset .Pa /bin/sh --------------040501050600090800020807--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?538E104D.3000904>