svn commit: r327507 - in user/jeff/numa: sys/kern sys/sys sys/vm usr.bin/cpuset
Jeff Roberson
jeff at FreeBSD.org
Wed Jan 3 01:00:49 UTC 2018
Author: jeff
Date: Wed Jan 3 01:00:47 2018
New Revision: 327507
URL: https://svnweb.freebsd.org/changeset/base/327507
Log:
Implement a preferred domain policy
Modified:
user/jeff/numa/sys/kern/kern_cpuset.c
user/jeff/numa/sys/sys/domainset.h
user/jeff/numa/sys/vm/vm_domainset.c
user/jeff/numa/usr.bin/cpuset/cpuset.c
Modified: user/jeff/numa/sys/kern/kern_cpuset.c
==============================================================================
--- user/jeff/numa/sys/kern/kern_cpuset.c Wed Jan 3 01:00:20 2018 (r327506)
+++ user/jeff/numa/sys/kern/kern_cpuset.c Wed Jan 3 01:00:47 2018 (r327507)
@@ -127,6 +127,8 @@ SYSCTL_INT(_kern_sched, OID_AUTO, cpusetsize, CTLFLAG_
cpuset_t *cpuset_root;
cpuset_t cpuset_domain[MAXMEMDOM];
+static int domainset_valid(const struct domainset *, const struct domainset *);
+
/*
* Find the first non-anonymous set starting from 'set'.
*/
@@ -289,7 +291,7 @@ _cpuset_create(struct cpuset *set, struct cpuset *pare
if (!CPU_OVERLAP(&parent->cs_mask, mask))
return (EDEADLK);
/* The domain must be prepared ahead of time. */
- if (!DOMAINSET_SUBSET(&parent->cs_domain->ds_mask, &domain->ds_mask))
+ if (!domainset_valid(parent->cs_domain, domain))
return (EDEADLK);
CPU_COPY(mask, &set->cs_mask);
LIST_INIT(&set->cs_children);
@@ -402,6 +404,7 @@ domainset_copy(const struct domainset *from, struct do
DOMAINSET_COPY(&from->ds_mask, &to->ds_mask);
to->ds_policy = from->ds_policy;
+ to->ds_prefer = from->ds_prefer;
}
/* Return 1 if mask and policy are equal, otherwise 0. */
@@ -410,9 +413,19 @@ domainset_equal(const struct domainset *one, const str
{
return (DOMAINSET_CMP(&one->ds_mask, &two->ds_mask) == 0 &&
- one->ds_policy == two->ds_policy);
+ one->ds_policy == two->ds_policy &&
+ one->ds_prefer == two->ds_prefer);
}
+/* Return 1 if child is a valid subset of parent. */
+static int
+domainset_valid(const struct domainset *parent, const struct domainset *child)
+{
+ if (child->ds_policy != DOMAINSET_POLICY_PREFER)
+ return (DOMAINSET_SUBSET(&parent->ds_mask, &child->ds_mask));
+ return (DOMAINSET_ISSET(child->ds_prefer, &parent->ds_mask));
+}
+
/*
* Lookup or create a domainset. The key is provided in ds_mask and
* ds_policy. If the domainset does not yet exist the storage in
@@ -705,12 +718,17 @@ cpuset_modify_domain(struct cpuset *set, struct domain
/*
* Verify that we have access to this set of domains.
*/
- if (root &&
- !DOMAINSET_SUBSET(&dset->ds_mask, &domain->ds_mask)) {
+ if (root && !domainset_valid(dset, domain)) {
error = EINVAL;
goto out;
}
/*
+ * If applying prefer we keep the current set as the fallback.
+ */
+ if (domain->ds_policy == DOMAINSET_POLICY_PREFER)
+ DOMAINSET_COPY(&set->cs_domain->ds_mask,
+ &domain->ds_mask);
+ /*
* Determine whether we can apply this set of domains and
* how many new domain structures it will require.
*/
@@ -842,8 +860,7 @@ cpuset_testshadow(struct cpuset *set, const cpuset_t *
* parent or invalid domains have been specified.
*/
dset = parent->cs_domain;
- if (domain != NULL &&
- !DOMAINSET_SUBSET(&dset->ds_mask, &domain->ds_mask))
+ if (domain != NULL && !domainset_valid(dset, domain))
return (EINVAL);
return (0);
@@ -1315,6 +1332,7 @@ domainset_zero(void)
for (i = 0; i < vm_ndomains; i++)
DOMAINSET_SET(i, &dset->ds_mask);
dset->ds_policy = DOMAINSET_POLICY_ROUNDROBIN;
+ dset->ds_prefer = -1;
curthread->td_domain.dr_policy = _domainset_create(dset, NULL);
kernel_object->domain.dr_policy = curthread->td_domain.dr_policy;
}
@@ -1841,13 +1859,13 @@ int
kern_cpuset_getdomain(struct thread *td, cpulevel_t level, cpuwhich_t which,
id_t id, size_t domainsetsize, domainset_t *maskp, int *policyp)
{
+ struct domainset outset;
struct thread *ttd;
struct cpuset *nset;
struct cpuset *set;
struct domainset *dset;
struct proc *p;
domainset_t *mask;
- int policy;
int error;
size_t size;
@@ -1863,9 +1881,9 @@ kern_cpuset_getdomain(struct thread *td, cpulevel_t le
if (id != -1)
return (ECAPMODE);
}
- policy = 0;
size = domainsetsize;
mask = malloc(size, M_TEMP, M_WAITOK | M_ZERO);
+ bzero(&outset, sizeof(outset));
error = cpuset_which(which, id, &p, &ttd, &set);
if (error)
goto out;
@@ -1894,9 +1912,7 @@ kern_cpuset_getdomain(struct thread *td, cpulevel_t le
else
nset = cpuset_refbase(set);
/* Fetch once for a coherent result. */
- dset = nset->cs_domain;
- DOMAINSET_COPY(&dset->ds_mask, mask);
- policy = dset->ds_policy;
+ domainset_copy(nset->cs_domain, &outset);
cpuset_rel(nset);
break;
case CPU_LEVEL_WHICH:
@@ -1904,9 +1920,7 @@ kern_cpuset_getdomain(struct thread *td, cpulevel_t le
case CPU_WHICH_TID:
thread_lock(ttd);
/* Fetch once for a coherent result. */
- dset = ttd->td_cpuset->cs_domain;
- DOMAINSET_COPY(&dset->ds_mask, mask);
- policy = dset->ds_policy;
+ domainset_copy(ttd->td_cpuset->cs_domain, &outset);
thread_unlock(ttd);
break;
case CPU_WHICH_PID:
@@ -1914,17 +1928,16 @@ kern_cpuset_getdomain(struct thread *td, cpulevel_t le
thread_lock(ttd);
dset = ttd->td_cpuset->cs_domain;
/* Show all domains in the proc. */
- DOMAINSET_OR(mask, &dset->ds_mask);
+ DOMAINSET_OR(&outset.ds_mask, &dset->ds_mask);
/* Last policy wins. */
- policy = dset->ds_policy;
+ outset.ds_policy = dset->ds_policy;
+ outset.ds_prefer = dset->ds_prefer;
thread_unlock(ttd);
}
break;
case CPU_WHICH_CPUSET:
case CPU_WHICH_JAIL:
- dset = set->cs_domain;
- policy = dset->ds_policy;
- DOMAINSET_OR(mask, &dset->ds_mask);
+ domainset_copy(set->cs_domain, &outset);
break;
case CPU_WHICH_IRQ:
case CPU_WHICH_INTRHANDLER:
@@ -1942,10 +1955,19 @@ kern_cpuset_getdomain(struct thread *td, cpulevel_t le
cpuset_rel(set);
if (p)
PROC_UNLOCK(p);
+ /*
+ * Translate prefer into a set containing only the preferred domain,
+ * not the entire fallback set.
+ */
+ if (outset.ds_policy == DOMAINSET_POLICY_PREFER) {
+ DOMAINSET_ZERO(&outset.ds_mask);
+ DOMAINSET_SET(outset.ds_prefer, &outset.ds_mask);
+ }
+ DOMAINSET_COPY(&outset.ds_mask, mask);
if (error == 0)
error = copyout(mask, maskp, size);
if (error == 0)
- error = copyout(&policy, policyp, sizeof(*policyp));
+ error = copyout(&outset.ds_policy, policyp, sizeof(*policyp));
out:
free(mask, M_TEMP);
return (error);
@@ -2022,6 +2044,16 @@ kern_cpuset_setdomain(struct thread *td, cpulevel_t le
policy > DOMAINSET_POLICY_MAX)
return (EINVAL);
+ /* Translate preferred policy into a mask and fallback. */
+ if (policy == DOMAINSET_POLICY_PREFER) {
+ /* Only support a single preferred domain. */
+ if (DOMAINSET_COUNT(&domain.ds_mask) != 1)
+ return (EINVAL);
+ domain.ds_prefer = DOMAINSET_FFS(&domain.ds_mask) - 1;
+ /* This will be constrained by domainset_shadow(). */
+ DOMAINSET_FILL(&domain.ds_mask);
+ }
+
switch (level) {
case CPU_LEVEL_ROOT:
case CPU_LEVEL_CPUSET:
@@ -2130,8 +2162,8 @@ DB_SHOW_COMMAND(cpusets, db_show_cpusets)
db_printf(" cpu mask=");
ddb_display_cpuset(&set->cs_mask);
db_printf("\n");
- db_printf(" domain policy %d mask=",
- set->cs_domain->ds_policy);
+ db_printf(" domain policy %d prefer %d mask=",
+ set->cs_domain->ds_policy, set->cs_domain->ds_prefer);
ddb_display_domainset(&set->cs_domain->ds_mask);
db_printf("\n");
if (db_pager_quit)
@@ -2144,8 +2176,9 @@ DB_SHOW_COMMAND(domainsets, db_show_domainsets)
struct domainset *set;
LIST_FOREACH(set, &cpuset_domains, ds_link) {
- db_printf("set=%p policy %d cnt %d max %d\n",
- set, set->ds_policy, set->ds_cnt, set->ds_max);
+ db_printf("set=%p policy %d prefer %d cnt %d max %d\n",
+ set, set->ds_policy, set->ds_prefer, set->ds_cnt,
+ set->ds_max);
db_printf(" mask =");
ddb_display_domainset(&set->ds_mask);
db_printf("\n");
Modified: user/jeff/numa/sys/sys/domainset.h
==============================================================================
--- user/jeff/numa/sys/sys/domainset.h Wed Jan 3 01:00:20 2018 (r327506)
+++ user/jeff/numa/sys/sys/domainset.h Wed Jan 3 01:00:47 2018 (r327507)
@@ -72,7 +72,8 @@
#define DOMAINSET_POLICY_INVALID 0
#define DOMAINSET_POLICY_ROUNDROBIN 1
#define DOMAINSET_POLICY_FIRSTTOUCH 2
-#define DOMAINSET_POLICY_MAX DOMAINSET_POLICY_FIRSTTOUCH
+#define DOMAINSET_POLICY_PREFER 3
+#define DOMAINSET_POLICY_MAX DOMAINSET_POLICY_PREFER
#ifdef _KERNEL
#include <sys/queue.h>
@@ -81,9 +82,10 @@ LIST_HEAD(domainlist, domainset);
struct domainset {
LIST_ENTRY(domainset) ds_link;
domainset_t ds_mask; /* allowed domains. */
+ uint16_t ds_policy; /* Policy type. */
+ int16_t ds_prefer; /* Preferred domain or -1. */
uint16_t ds_cnt; /* popcnt from above. */
uint16_t ds_max; /* Maximum domain in set. */
- uint16_t ds_policy; /* Policy type. */
};
void domainset_zero(void);
Modified: user/jeff/numa/sys/vm/vm_domainset.c
==============================================================================
--- user/jeff/numa/sys/vm/vm_domainset.c Wed Jan 3 01:00:20 2018 (r327506)
+++ user/jeff/numa/sys/vm/vm_domainset.c Wed Jan 3 01:00:47 2018 (r327507)
@@ -90,6 +90,19 @@ vm_domainset_iter_rr(struct vm_domainset_iter *di, int
}
static void
+vm_domainset_iter_prefer(struct vm_domainset_iter *di, int *domain)
+{
+ int d;
+
+ d = *di->di_iter;
+ do {
+ d = (d + 1) % di->di_domain->ds_max;
+ } while (!DOMAINSET_ISSET(d, &di->di_domain->ds_mask) ||
+ d == di->di_domain->ds_prefer);
+ *di->di_iter = *domain = d;
+}
+
+static void
vm_domainset_iter_next(struct vm_domainset_iter *di, int *domain)
{
@@ -103,6 +116,9 @@ vm_domainset_iter_next(struct vm_domainset_iter *di, i
case DOMAINSET_POLICY_ROUNDROBIN:
vm_domainset_iter_rr(di, domain);
break;
+ case DOMAINSET_POLICY_PREFER:
+ vm_domainset_iter_prefer(di, domain);
+ break;
default:
panic("vm_domainset_iter_first: Unknown policy %d",
di->di_domain->ds_policy);
@@ -130,6 +146,10 @@ vm_domainset_iter_first(struct vm_domainset_iter *di,
case DOMAINSET_POLICY_ROUNDROBIN:
di->di_n = di->di_domain->ds_cnt;
vm_domainset_iter_rr(di, domain);
+ break;
+ case DOMAINSET_POLICY_PREFER:
+ *domain = di->di_domain->ds_prefer;
+ di->di_n = di->di_domain->ds_cnt;
break;
default:
panic("vm_domainset_iter_first: Unknown policy %d",
Modified: user/jeff/numa/usr.bin/cpuset/cpuset.c
==============================================================================
--- user/jeff/numa/usr.bin/cpuset/cpuset.c Wed Jan 3 01:00:20 2018 (r327506)
+++ user/jeff/numa/usr.bin/cpuset/cpuset.c Wed Jan 3 01:00:47 2018 (r327507)
@@ -78,6 +78,7 @@ static struct numa_policy policies[] = {
{ "rr", DOMAINSET_POLICY_ROUNDROBIN },
{ "first-touch", DOMAINSET_POLICY_FIRSTTOUCH },
{ "ft", DOMAINSET_POLICY_FIRSTTOUCH },
+ { "prefer", DOMAINSET_POLICY_PREFER },
{ NULL, DOMAINSET_POLICY_INVALID }
};
@@ -235,7 +236,8 @@ printset(struct bitset *mask, int size)
static const char *whichnames[] = { NULL, "tid", "pid", "cpuset", "irq", "jail",
"domain" };
static const char *levelnames[] = { NULL, " root", " cpuset", "" };
-static const char *policynames[] = { "invalid", "round-robin", "first-touch" };
+static const char *policynames[] = { "invalid", "round-robin", "first-touch",
+ "prefer" };
static void
printaffinity(void)
More information about the svn-src-user
mailing list