svn commit: r330818 - in user/jeff/numa/sys: kern sys vm
Jeff Roberson
jeff at FreeBSD.org
Mon Mar 12 22:17:15 UTC 2018
Author: jeff
Date: Mon Mar 12 22:17:14 2018
New Revision: 330818
URL: https://svnweb.freebsd.org/changeset/base/330818
Log:
Provide convenience routines for manipulating domainsets in the kernel.
domainset_create() will take a key, validate it, and return a valid
domainset that can be placed on an object or other.
sysctl_handle_domainset() allows manipulation of policy from sysctl. Use
this to make a default vnode domainset.
Clean-up some header creep. Define a generic bitset type. Rewrite some
string functions to be more generic.
Modified:
user/jeff/numa/sys/kern/kern_cpuset.c
user/jeff/numa/sys/sys/_bitset.h
user/jeff/numa/sys/sys/domainset.h
user/jeff/numa/sys/sys/proc.h
user/jeff/numa/sys/vm/vnode_pager.c
Modified: user/jeff/numa/sys/kern/kern_cpuset.c
==============================================================================
--- user/jeff/numa/sys/kern/kern_cpuset.c Mon Mar 12 22:10:06 2018 (r330817)
+++ user/jeff/numa/sys/kern/kern_cpuset.c Mon Mar 12 22:17:14 2018 (r330818)
@@ -37,6 +37,8 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/sysctl.h>
+#include <sys/ctype.h>
#include <sys/sysproto.h>
#include <sys/jail.h>
#include <sys/kernel.h>
@@ -112,6 +114,9 @@ __FBSDID("$FreeBSD$");
* meaning 'curthread'. It may query available cpus for that tid with a
* getaffinity call using (CPU_LEVEL_CPUSET, CPU_WHICH_PID, -1, ...).
*/
+
+LIST_HEAD(domainlist, domainset);
+
static uma_zone_t cpuset_zone;
static uma_zone_t domainset_zone;
static struct mtx cpuset_lock;
@@ -119,6 +124,7 @@ static struct setlist cpuset_ids;
static struct domainlist cpuset_domains;
static struct unrhdr *cpuset_unr;
static struct cpuset *cpuset_zero, *cpuset_default, *cpuset_kernel;
+static struct domainset domainset0, domainset2;
/* Return the size of cpuset_t at the kernel level */
SYSCTL_INT(_kern_sched, OID_AUTO, cpusetsize, CTLFLAG_RD | CTLFLAG_CAPRD,
@@ -477,11 +483,24 @@ _domainset_create(struct domainset *domain, struct dom
/*
* Create or lookup a domainset based on the key held in 'domain'.
*/
-static struct domainset *
+struct domainset *
domainset_create(const struct domainset *domain)
{
struct domainset *ndomain;
+ /*
+ * Validate the policy. It must specify a useable policy number with
+ * only valid domains. Preferred must include the preferred domain
+ * in the mask.
+ */
+ if (domain->ds_policy <= DOMAINSET_POLICY_INVALID ||
+ domain->ds_policy > DOMAINSET_POLICY_MAX)
+ return (NULL);
+ if (domain->ds_policy == DOMAINSET_POLICY_PREFER &&
+ !DOMAINSET_ISSET(domain->ds_prefer, &domain->ds_mask))
+ return (NULL);
+ if (!DOMAINSET_SUBSET(&domainset0.ds_mask, &domain->ds_mask))
+ return (NULL);
ndomain = uma_zalloc(domainset_zone, M_WAITOK | M_ZERO);
domainset_copy(domain, ndomain);
return _domainset_create(ndomain, NULL);
@@ -1132,6 +1151,55 @@ out:
return (error);
}
+static int
+bitset_strprint(char *buf, size_t bufsiz, const struct bitset *set, int setlen)
+{
+ size_t bytes;
+ int i, once;
+ char *p;
+
+ once = 0;
+ p = buf;
+ for (i = 0; i < __bitset_words(setlen); i++) {
+ if (once != 0) {
+ if (bufsiz < 1)
+ return (0);
+ *p = ',';
+ p++;
+ bufsiz--;
+ } else
+ once = 1;
+ if (bufsiz < sizeof(__STRING(ULONG_MAX)))
+ return (0);
+ bytes = snprintf(p, bufsiz, "%lx", set->__bits[i]);
+ p += bytes;
+ bufsiz -= bytes;
+ }
+ return (p - buf);
+}
+
+static int
+bitset_strscan(struct bitset *set, int setlen, const char *buf)
+{
+ int i, ret;
+ const char *p;
+
+ BIT_ZERO(setlen, set);
+ p = buf;
+ for (i = 0; i < __bitset_words(setlen); i++) {
+ if (*p == ',') {
+ p++;
+ continue;
+ }
+ ret = sscanf(p, "%lx", &set->__bits[i]);
+ if (ret == 0 || ret == -1)
+ break;
+ while (isxdigit(*p))
+ p++;
+ }
+ return (p - buf);
+}
+
/*
* Return a string representing a valid layout for a cpuset_t object.
* It expects an incoming buffer at least sized as CPUSETBUFSIZ.
@@ -1139,19 +1207,9 @@ out:
char *
cpusetobj_strprint(char *buf, const cpuset_t *set)
{
- char *tbuf;
- size_t i, bytesp, bufsiz;
- tbuf = buf;
- bytesp = 0;
- bufsiz = CPUSETBUFSIZ;
-
- for (i = 0; i < (_NCPUWORDS - 1); i++) {
- bytesp = snprintf(tbuf, bufsiz, "%lx,", set->__bits[i]);
- bufsiz -= bytesp;
- tbuf += bytesp;
- }
- snprintf(tbuf, bufsiz, "%lx", set->__bits[_NCPUWORDS - 1]);
+ bitset_strprint(buf, CPUSETBUFSIZ, (const struct bitset *)set,
+ CPU_SETSIZE);
return (buf);
}
@@ -1162,37 +1220,71 @@ cpusetobj_strprint(char *buf, const cpuset_t *set)
int
cpusetobj_strscan(cpuset_t *set, const char *buf)
{
- u_int nwords;
- int i, ret;
+ char p;
if (strlen(buf) > CPUSETBUFSIZ - 1)
return (-1);
- /* Allow to pass a shorter version of the mask when necessary. */
- nwords = 1;
- for (i = 0; buf[i] != '\0'; i++)
- if (buf[i] == ',')
- nwords++;
- if (nwords > _NCPUWORDS)
+ p = buf[bitset_strscan((struct bitset *)set, CPU_SETSIZE, buf)];
+ if (p != '\0')
return (-1);
- CPU_ZERO(set);
- for (i = 0; i < (nwords - 1); i++) {
- ret = sscanf(buf, "%lx,", &set->__bits[i]);
- if (ret == 0 || ret == -1)
- return (-1);
- buf = strstr(buf, ",");
- if (buf == NULL)
- return (-1);
- buf++;
- }
- ret = sscanf(buf, "%lx", &set->__bits[nwords - 1]);
- if (ret == 0 || ret == -1)
- return (-1);
return (0);
}
/*
+ * Handle a domainset specifier in the sysctl tree. A poiner to a pointer to
+ * a domainset is in arg1. If the user specifies a valid domainset the
+ * pointer is updated.
+ *
+ * Format is:
+ * hex mask word 0,hex mask word 1,...:decimal policy:decimal preferred
+ */
+int
+sysctl_handle_domainset(SYSCTL_HANDLER_ARGS)
+{
+ char buf[DOMAINSETBUFSIZ];
+ struct domainset *dset;
+ struct domainset key;
+ char *p;
+ int error;
+
+ dset = *(struct domainset **)arg1;
+ error = 0;
+
+ if (dset != NULL) {
+ p = buf + bitset_strprint(buf, DOMAINSETBUFSIZ,
+ (const struct bitset *)&dset->ds_mask, DOMAINSET_SETSIZE);
+ sprintf(p, ":%d:%d", dset->ds_policy, dset->ds_prefer);
+ } else
+ sprintf(buf, "<NULL>");
+ error = sysctl_handle_string(oidp, buf, sizeof(buf), req);
+ if (error != 0 || req->newptr == NULL)
+ return (error);
+
+ /*
+ * Read in and validate the string.
+ */
+ memset(&key, 0, sizeof(key));
+ p = &buf[bitset_strscan((struct bitset *)&key.ds_mask,
+ DOMAINSET_SETSIZE, buf)];
+ if (p == buf)
+ return (EINVAL);
+ if (sscanf(p, ":%hd:%hhd", &key.ds_policy, &key.ds_prefer) != 2)
+ return (EINVAL);
+
+ /* Domainset_create() validates the policy.*/
+ dset = domainset_create(&key);
+ if (dset == NULL)
+ return (EINVAL);
+ *(struct domainset **)arg1 = dset;
+
+ return (error);
+}
+
+#ifdef DDB
+
+/*
* Apply an anonymous mask or a domain to a single thread.
*/
static int
@@ -1256,8 +1348,6 @@ cpuset_setithread(lwpid_t id, int cpu)
/*
* Create the domainset for cpuset 0, 1 and cpuset 2.
*/
-static struct domainset domainset0, domainset2;
-
void
domainset_zero(void)
{
@@ -2079,8 +2169,6 @@ out:
return (error);
}
-#ifdef DDB
-BITSET_DEFINE(bitset, 1);
static void
ddb_display_bitset(const struct bitset *set, int size)
{
Modified: user/jeff/numa/sys/sys/_bitset.h
==============================================================================
--- user/jeff/numa/sys/sys/_bitset.h Mon Mar 12 22:10:06 2018 (r330817)
+++ user/jeff/numa/sys/sys/_bitset.h Mon Mar 12 22:17:14 2018 (r330818)
@@ -57,4 +57,10 @@ struct t { \
*/
#define BITSET_DEFINE_VAR(t) BITSET_DEFINE(t, 1)
+/*
+ * Define a default type that can be used while manually specifying size
+ * to every call.
+ */
+BITSET_DEFINE(bitset, 1);
+
#endif /* !_SYS__BITSET_H_ */
Modified: user/jeff/numa/sys/sys/domainset.h
==============================================================================
--- user/jeff/numa/sys/sys/domainset.h Mon Mar 12 22:10:06 2018 (r330817)
+++ user/jeff/numa/sys/sys/domainset.h Mon Mar 12 22:17:14 2018 (r330818)
@@ -28,8 +28,8 @@
* $FreeBSD$
*/
-#ifndef _SYS_DOMAINSETSET_H_
-#define _SYS_DOMAINSETSET_H_
+#ifndef _SYS_DOMAINSET_H_
+#define _SYS_DOMAINSET_H_
#include <sys/_domainset.h>
@@ -38,8 +38,12 @@
#define _NDOMAINSETBITS _BITSET_BITS
#define _NDOMAINSETWORDS __bitset_words(DOMAINSET_SETSIZE)
-#define DOMAINSETSETBUFSIZ ((2 + sizeof(long) * 2) * _NDOMAINSETWORDS)
+#define DOMAINSETBUFSIZ \
+ (((2 + sizeof(long) * 2) * _NDOMAINSETWORDS) + \
+ sizeof("::") + sizeof(__XSTRING(DOMAINSET_POLICY_MAX)) + \
+ sizeof(__XSTRING(MAXMEMDOM)))
+
#define DOMAINSET_CLR(n, p) BIT_CLR(DOMAINSET_SETSIZE, n, p)
#define DOMAINSET_COPY(f, t) BIT_COPY(DOMAINSET_SETSIZE, f, t)
#define DOMAINSET_ISSET(n, p) BIT_ISSET(DOMAINSET_SETSIZE, n, p)
@@ -77,9 +81,6 @@
#define DOMAINSET_POLICY_MAX DOMAINSET_POLICY_INTERLEAVE
#ifdef _KERNEL
-#include <sys/queue.h>
-LIST_HEAD(domainlist, domainset);
-
#if MAXMEMDOM < 256
typedef uint8_t domainid_t;
#else
@@ -97,6 +98,16 @@ struct domainset {
void domainset_zero(void);
+/*
+ * Add a domainset to the system based on a key initializing policy, prefer,
+ * and mask. Do not create and directly use domainset structures. The
+ * returned value will not match the key pointer.
+ */
+struct domainset *domainset_create(const struct domainset *);
+#ifdef _SYS_SYSCTL_H_
+int sysctl_handle_domainset(SYSCTL_HANDLER_ARGS);
+#endif
+
#else
__BEGIN_DECLS
int cpuset_getdomain(cpulevel_t, cpuwhich_t, id_t, size_t, domainset_t *,
@@ -106,4 +117,4 @@ int cpuset_setdomain(cpulevel_t, cpuwhich_t, id_t, siz
__END_DECLS
#endif
-#endif /* !_SYS_DOMAINSETSET_H_ */
+#endif /* !_SYS_DOMAINSET_H_ */
Modified: user/jeff/numa/sys/sys/proc.h
==============================================================================
--- user/jeff/numa/sys/sys/proc.h Mon Mar 12 22:10:06 2018 (r330817)
+++ user/jeff/numa/sys/sys/proc.h Mon Mar 12 22:17:14 2018 (r330818)
@@ -67,7 +67,7 @@
#include <sys/ucontext.h>
#include <sys/ucred.h>
#include <sys/types.h>
-#include <sys/domainset.h>
+#include <sys/_domainset.h>
#include <machine/proc.h> /* Machine-dependent proc substruct. */
#ifdef _KERNEL
Modified: user/jeff/numa/sys/vm/vnode_pager.c
==============================================================================
--- user/jeff/numa/sys/vm/vnode_pager.c Mon Mar 12 22:10:06 2018 (r330817)
+++ user/jeff/numa/sys/vm/vnode_pager.c Mon Mar 12 22:17:14 2018 (r330818)
@@ -59,6 +59,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/sysctl.h>
#include <sys/proc.h>
#include <sys/vnode.h>
#include <sys/mount.h>
@@ -69,6 +70,7 @@ __FBSDID("$FreeBSD$");
#include <sys/conf.h>
#include <sys/rwlock.h>
#include <sys/sf_buf.h>
+#include <sys/domainset.h>
#include <machine/atomic.h>
@@ -108,6 +110,12 @@ struct pagerops vnodepagerops = {
int vnode_pbuf_freecnt;
int vnode_async_pbuf_freecnt;
+static struct domainset *vnode_domainset = NULL;
+
+SYSCTL_PROC(_debug, OID_AUTO, vnode_domainset, CTLTYPE_STRING | CTLFLAG_RW,
+ &vnode_domainset, 0, sysctl_handle_domainset, "A",
+ "Default vnode NUMA policy");
+
/* Create the VM system backing object for this vnode */
int
vnode_create_vobject(struct vnode *vp, off_t isize, struct thread *td)
@@ -242,6 +250,7 @@ retry:
object->un_pager.vnp.vnp_size = size;
object->un_pager.vnp.writemappings = 0;
object->iosize = vp->v_mount->mnt_stat.f_iosize;
+ object->domain.dr_policy = vnode_domainset;
object->handle = handle;
VI_LOCK(vp);
More information about the svn-src-user
mailing list