Module Name: src
Committed By: rmind
Date: Sun Aug 7 13:33:03 UTC 2011
Modified Files:
src/common/lib/libc/sys: cpuset.c
src/distrib/sets/lists/comp: mi
src/sys/conf: files
src/sys/kern: init_main.c kern_cpu.c kern_runq.c subr_pserialize.c
sys_pset.c sys_sched.c
src/sys/sys: Makefile cpu.h lwp.h sched.h
Added Files:
src/sys/kern: subr_kcpuset.c
src/sys/sys: kcpuset.h
Log Message:
Add kcpuset(9) - a reworked dynamic CPU set implementation for kernel.
Suitable for use during the early boot. MD and other implementations
should be replaced with this interface.
Discussed on: tech-kern@
To generate a diff of this commit:
cvs rdiff -u -r1.16 -r1.17 src/common/lib/libc/sys/cpuset.c
cvs rdiff -u -r1.1657 -r1.1658 src/distrib/sets/lists/comp/mi
cvs rdiff -u -r1.1022 -r1.1023 src/sys/conf/files
cvs rdiff -u -r1.434 -r1.435 src/sys/kern/init_main.c
cvs rdiff -u -r1.47 -r1.48 src/sys/kern/kern_cpu.c
cvs rdiff -u -r1.30 -r1.31 src/sys/kern/kern_runq.c
cvs rdiff -u -r0 -r1.1 src/sys/kern/subr_kcpuset.c
cvs rdiff -u -r1.2 -r1.3 src/sys/kern/subr_pserialize.c
cvs rdiff -u -r1.15 -r1.16 src/sys/kern/sys_pset.c
cvs rdiff -u -r1.35 -r1.36 src/sys/kern/sys_sched.c
cvs rdiff -u -r1.136 -r1.137 src/sys/sys/Makefile
cvs rdiff -u -r1.32 -r1.33 src/sys/sys/cpu.h
cvs rdiff -u -r0 -r1.1 src/sys/sys/kcpuset.h
cvs rdiff -u -r1.152 -r1.153 src/sys/sys/lwp.h
cvs rdiff -u -r1.72 -r1.73 src/sys/sys/sched.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/common/lib/libc/sys/cpuset.c
diff -u src/common/lib/libc/sys/cpuset.c:1.16 src/common/lib/libc/sys/cpuset.c:1.17
--- src/common/lib/libc/sys/cpuset.c:1.16 Tue Sep 21 02:03:29 2010
+++ src/common/lib/libc/sys/cpuset.c Sun Aug 7 13:33:02 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: cpuset.c,v 1.16 2010/09/21 02:03:29 rmind Exp $ */
+/* $NetBSD: cpuset.c,v 1.17 2011/08/07 13:33:02 rmind Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -32,7 +32,7 @@
#ifndef _STANDALONE
#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: cpuset.c,v 1.16 2010/09/21 02:03:29 rmind Exp $");
+__RCSID("$NetBSD: cpuset.c,v 1.17 2011/08/07 13:33:02 rmind Exp $");
#endif /* LIBC_SCCS and not lint */
#include <sys/param.h>
@@ -64,24 +64,11 @@
uint32_t bits[0];
};
-#ifdef _KERNEL
-struct _kcpuset {
- unsigned int nused;
- struct _kcpuset *next;
- uint32_t bits[0];
-};
-#define KCPUSET_SIZE(n) (sizeof( \
- struct { \
- unsigned int nused; \
- struct _kcpuset *next; \
- uint32_t bits[0]; \
- }) + sizeof(uint32_t) * (n))
-#endif
+#ifndef _KERNEL
static size_t cpuset_size = 0;
static size_t cpuset_nentries = 0;
-#ifndef _KERNEL
size_t
/*ARGSUSED*/
_cpuset_size(const cpuset_t *c)
@@ -161,150 +148,5 @@
free(c);
}
-#else
-
-kcpuset_t *
-kcpuset_create(void)
-{
- kcpuset_t *c;
-
- if (cpuset_size == 0) {
- cpuset_nentries = CPUSET_NENTRIES(MAXCPUS);
- cpuset_size = KCPUSET_SIZE(cpuset_nentries);
- }
- c = kmem_zalloc(cpuset_size, KM_SLEEP);
- c->next = NULL;
- c->nused = 1;
- return c;
-}
-
-void
-kcpuset_destroy(kcpuset_t *c)
-{
- kcpuset_t *nc;
-
- while (c) {
- KASSERT(c->nused == 0);
- nc = c->next;
- kmem_free(c, cpuset_size);
- c = nc;
- }
-}
-
-void
-kcpuset_copy(kcpuset_t *d, const kcpuset_t *s)
-{
-
- KASSERT(d->nused == 1);
- memcpy(d->bits, s->bits, cpuset_nentries * sizeof(s->bits[0]));
-}
-
-void
-kcpuset_use(kcpuset_t *c)
-{
-
- atomic_inc_uint(&c->nused);
-}
-
-void
-kcpuset_unuse(kcpuset_t *c, kcpuset_t **lst)
-{
-
- if (atomic_dec_uint_nv(&c->nused) != 0)
- return;
- KASSERT(c->nused == 0);
- KASSERT(c->next == NULL);
- if (lst == NULL) {
- kcpuset_destroy(c);
- return;
- }
- c->next = *lst;
- *lst = c;
-}
-
-int
-kcpuset_copyin(const cpuset_t *u, kcpuset_t *k, size_t len)
-{
-
- KASSERT(k->nused > 0);
- KASSERT(k->next == NULL);
- if (len != CPUSET_SIZE(cpuset_nentries))
- return EINVAL;
- return copyin(u->bits, k->bits, cpuset_nentries * sizeof(k->bits[0]));
-}
-
-int
-kcpuset_copyout(const kcpuset_t *k, cpuset_t *u, size_t len)
-{
-
- KASSERT(k->nused > 0);
- KASSERT(k->next == NULL);
- if (len != CPUSET_SIZE(cpuset_nentries))
- return EINVAL;
- return copyout(k->bits, u->bits, cpuset_nentries * sizeof(u->bits[0]));
-}
-
-void
-kcpuset_zero(kcpuset_t *c)
-{
-
- KASSERT(c->nused > 0);
- KASSERT(c->next == NULL);
- memset(c->bits, 0, cpuset_nentries * sizeof(c->bits[0]));
-}
-
-void
-kcpuset_fill(kcpuset_t *c)
-{
-
- KASSERT(c->nused > 0);
- KASSERT(c->next == NULL);
- memset(c->bits, ~0, cpuset_nentries * sizeof(c->bits[0]));
-}
-
-void
-kcpuset_set(cpuid_t i, kcpuset_t *c)
-{
- const unsigned long j = i >> CPUSET_SHIFT;
-
- KASSERT(c->next == NULL);
- KASSERT(j < cpuset_nentries);
- c->bits[j] |= 1 << (i & CPUSET_MASK);
-}
-
-int
-kcpuset_isset(cpuid_t i, const kcpuset_t *c)
-{
- const unsigned long j = i >> CPUSET_SHIFT;
-
- KASSERT(c != NULL);
- KASSERT(c->nused > 0);
- KASSERT(c->next == NULL);
- KASSERT(j < cpuset_nentries);
- return ((1 << (i & CPUSET_MASK)) & c->bits[j]) != 0;
-}
-
-bool
-kcpuset_iszero(const kcpuset_t *c)
-{
- unsigned long j;
-
- for (j = 0; j < cpuset_nentries; j++)
- if (c->bits[j] != 0)
- return false;
- return true;
-}
-
-bool
-kcpuset_match(const kcpuset_t *c1, const kcpuset_t *c2)
-{
- unsigned long j;
-
- for (j = 0; j < cpuset_nentries; j++)
- if ((c1->bits[j] & c2->bits[j]) != c2->bits[j])
- return false;
- return true;
-}
-
#endif
#endif
Index: src/distrib/sets/lists/comp/mi
diff -u src/distrib/sets/lists/comp/mi:1.1657 src/distrib/sets/lists/comp/mi:1.1658
--- src/distrib/sets/lists/comp/mi:1.1657 Sat Aug 6 17:17:39 2011
+++ src/distrib/sets/lists/comp/mi Sun Aug 7 13:33:02 2011
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.1657 2011/08/06 17:17:39 jruoho Exp $
+# $NetBSD: mi,v 1.1658 2011/08/07 13:33:02 rmind Exp $
#
# Note: don't delete entries from here - mark them as "obsolete" instead.
#
@@ -2385,6 +2385,7 @@
./usr/include/sys/ipc.h comp-c-include
./usr/include/sys/joystick.h comp-c-include
./usr/include/sys/kcore.h comp-c-include
+./usr/include/sys/kcpuset.h comp-c-include
./usr/include/sys/kernel.h comp-obsolete obsolete
./usr/include/sys/keylock.h comp-obsolete obsolete
./usr/include/sys/kgdb.h comp-c-include
Index: src/sys/conf/files
diff -u src/sys/conf/files:1.1022 src/sys/conf/files:1.1023
--- src/sys/conf/files:1.1022 Sat Jul 30 17:01:04 2011
+++ src/sys/conf/files Sun Aug 7 13:33:01 2011
@@ -1,4 +1,4 @@
-# $NetBSD: files,v 1.1022 2011/07/30 17:01:04 christos Exp $
+# $NetBSD: files,v 1.1023 2011/08/07 13:33:01 rmind Exp $
# @(#)files.newconf 7.5 (Berkeley) 5/10/93
version 20100430
@@ -1530,6 +1530,7 @@
file kern/subr_hash.c
file kern/subr_humanize.c
file kern/subr_iostat.c
+file kern/subr_kcpuset.c
file kern/subr_kmem.c
file kern/subr_kobj.c
file kern/subr_kobj_vfs.c
Index: src/sys/kern/init_main.c
diff -u src/sys/kern/init_main.c:1.434 src/sys/kern/init_main.c:1.435
--- src/sys/kern/init_main.c:1.434 Sat Jul 30 17:01:04 2011
+++ src/sys/kern/init_main.c Sun Aug 7 13:33:01 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: init_main.c,v 1.434 2011/07/30 17:01:04 christos Exp $ */
+/* $NetBSD: init_main.c,v 1.435 2011/08/07 13:33:01 rmind Exp $ */
/*-
* Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@@ -97,7 +97,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: init_main.c,v 1.434 2011/07/30 17:01:04 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: init_main.c,v 1.435 2011/08/07 13:33:01 rmind Exp $");
#include "opt_ddb.h"
#include "opt_ipsec.h"
@@ -167,6 +167,7 @@
#include <sys/event.h>
#include <sys/lockf.h>
#include <sys/once.h>
+#include <sys/kcpuset.h>
#include <sys/ksyms.h>
#include <sys/uidinfo.h>
#include <sys/kprintf.h>
@@ -310,6 +311,7 @@
evcnt_init();
uvm_init();
+ kcpuset_sysinit();
prop_kern_init();
Index: src/sys/kern/kern_cpu.c
diff -u src/sys/kern/kern_cpu.c:1.47 src/sys/kern/kern_cpu.c:1.48
--- src/sys/kern/kern_cpu.c:1.47 Wed Jun 29 06:22:21 2011
+++ src/sys/kern/kern_cpu.c Sun Aug 7 13:33:01 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: kern_cpu.c,v 1.47 2011/06/29 06:22:21 matt Exp $ */
+/* $NetBSD: kern_cpu.c,v 1.48 2011/08/07 13:33:01 rmind Exp $ */
/*-
* Copyright (c) 2007, 2008, 2009, 2010 The NetBSD Foundation, Inc.
@@ -56,7 +56,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_cpu.c,v 1.47 2011/06/29 06:22:21 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_cpu.c,v 1.48 2011/08/07 13:33:01 rmind Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -107,6 +107,9 @@
int ncpu __read_mostly;
int ncpuonline __read_mostly;
bool mp_online __read_mostly;
+
+kcpuset_t * kcpuset_attached __read_mostly;
+
struct cpuqueue cpu_queue __cacheline_aligned
= CIRCLEQ_HEAD_INITIALIZER(cpu_queue);
@@ -131,8 +134,11 @@
if (__predict_false(cpu_infos == NULL)) {
cpu_infos =
kmem_zalloc(sizeof(cpu_infos[0]) * maxcpus, KM_SLEEP);
+ kcpuset_create(&kcpuset_attached);
+ kcpuset_zero(kcpuset_attached);
}
cpu_infos[cpu_index(ci)] = ci;
+ kcpuset_set(kcpuset_attached, ci->ci_index);
sched_cpuattach(ci);
@@ -315,7 +321,7 @@
for (CPU_INFO_FOREACH(cii, mci)) {
mspc = &mci->ci_schedstate;
if ((mspc->spc_flags & SPCF_OFFLINE) == 0 &&
- kcpuset_isset(cpu_index(mci), l->l_affinity))
+ kcpuset_isset(l->l_affinity, cpu_index(mci)))
break;
}
if (mci == NULL) {
Index: src/sys/kern/kern_runq.c
diff -u src/sys/kern/kern_runq.c:1.30 src/sys/kern/kern_runq.c:1.31
--- src/sys/kern/kern_runq.c:1.30 Wed Mar 3 00:47:30 2010
+++ src/sys/kern/kern_runq.c Sun Aug 7 13:33:01 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: kern_runq.c,v 1.30 2010/03/03 00:47:30 yamt Exp $ */
+/* $NetBSD: kern_runq.c,v 1.31 2011/08/07 13:33:01 rmind Exp $ */
/*
* Copyright (c) 2007, 2008 Mindaugas Rasiukevicius <rmind at NetBSD org>
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_runq.c,v 1.30 2010/03/03 00:47:30 yamt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_runq.c,v 1.31 2011/08/07 13:33:01 rmind Exp $");
#include <sys/param.h>
#include <sys/kernel.h>
@@ -352,7 +352,7 @@
/* Affinity bind */
if (__predict_false(l->l_flag & LW_AFFINITY))
- return kcpuset_isset(cpu_index(ci), l->l_affinity);
+ return kcpuset_isset(l->l_affinity, cpu_index(ci));
/* Processor-set */
return (spc->spc_psid == l->l_psid);
Index: src/sys/kern/subr_pserialize.c
diff -u src/sys/kern/subr_pserialize.c:1.2 src/sys/kern/subr_pserialize.c:1.3
--- src/sys/kern/subr_pserialize.c:1.2 Mon Aug 1 15:26:31 2011
+++ src/sys/kern/subr_pserialize.c Sun Aug 7 13:33:01 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: subr_pserialize.c,v 1.2 2011/08/01 15:26:31 he Exp $ */
+/* $NetBSD: subr_pserialize.c,v 1.3 2011/08/07 13:33:01 rmind Exp $ */
/*-
* Copyright (c) 2010, 2011 The NetBSD Foundation, Inc.
@@ -38,7 +38,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: subr_pserialize.c,v 1.2 2011/08/01 15:26:31 he Exp $");
+__KERNEL_RCSID(0, "$NetBSD: subr_pserialize.c,v 1.3 2011/08/07 13:33:01 rmind Exp $");
#include <sys/param.h>
@@ -103,8 +103,8 @@
psz = kmem_zalloc(sizeof(struct pserialize), KM_SLEEP);
cv_init(&psz->psz_notifier, "psrlz");
- psz->psz_target = kcpuset_create();
- psz->psz_pass = kcpuset_create();
+ kcpuset_create(&psz->psz_target);
+ kcpuset_create(&psz->psz_pass);
psz->psz_owner = NULL;
return psz;
@@ -147,7 +147,6 @@
return;
}
KASSERT(psz->psz_owner == NULL);
- KASSERT(kcpuset_iszero(psz->psz_target));
KASSERT(ncpu > 0);
/*
@@ -157,7 +156,7 @@
* other processors.
*/
psz->psz_owner = curlwp;
- kcpuset_fill(psz->psz_target);
+ kcpuset_copy(psz->psz_target, kcpuset_attached);
kcpuset_zero(psz->psz_pass);
mutex_spin_enter(&psz_lock);
@@ -234,7 +233,7 @@
for (psz = TAILQ_FIRST(&psz_queue1); psz != NULL; psz = next) {
next = TAILQ_NEXT(psz, psz_chain);
if (!kcpuset_match(psz->psz_pass, psz->psz_target)) {
- kcpuset_set(cid, psz->psz_pass);
+ kcpuset_set(psz->psz_pass, cid);
continue;
}
kcpuset_zero(psz->psz_pass);
@@ -248,7 +247,7 @@
for (psz = TAILQ_FIRST(&psz_queue0); psz != NULL; psz = next) {
next = TAILQ_NEXT(psz, psz_chain);
if (!kcpuset_match(psz->psz_pass, psz->psz_target)) {
- kcpuset_set(cid, psz->psz_pass);
+ kcpuset_set(psz->psz_pass, cid);
continue;
}
kcpuset_zero(psz->psz_pass);
Index: src/sys/kern/sys_pset.c
diff -u src/sys/kern/sys_pset.c:1.15 src/sys/kern/sys_pset.c:1.16
--- src/sys/kern/sys_pset.c:1.15 Thu Jul 1 02:38:31 2010
+++ src/sys/kern/sys_pset.c Sun Aug 7 13:33:01 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: sys_pset.c,v 1.15 2010/07/01 02:38:31 rmind Exp $ */
+/* $NetBSD: sys_pset.c,v 1.16 2011/08/07 13:33:01 rmind Exp $ */
/*
* Copyright (c) 2008, Mindaugas Rasiukevicius <rmind at NetBSD org>
@@ -36,7 +36,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sys_pset.c,v 1.15 2010/07/01 02:38:31 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sys_pset.c,v 1.16 2011/08/07 13:33:01 rmind Exp $");
#include <sys/param.h>
@@ -373,7 +373,7 @@
lwp_unlock(t);
continue;
}
- if (kcpuset_isset(cpu_index(ci), t->l_affinity)) {
+ if (kcpuset_isset(t->l_affinity, cpu_index(ci))) {
lwp_unlock(t);
mutex_exit(proc_lock);
mutex_exit(&cpu_lock);
Index: src/sys/kern/sys_sched.c
diff -u src/sys/kern/sys_sched.c:1.35 src/sys/kern/sys_sched.c:1.36
--- src/sys/kern/sys_sched.c:1.35 Thu Jul 1 02:38:31 2010
+++ src/sys/kern/sys_sched.c Sun Aug 7 13:33:01 2011
@@ -1,7 +1,7 @@
-/* $NetBSD: sys_sched.c,v 1.35 2010/07/01 02:38:31 rmind Exp $ */
+/* $NetBSD: sys_sched.c,v 1.36 2011/08/07 13:33:01 rmind Exp $ */
/*
- * Copyright (c) 2008, Mindaugas Rasiukevicius <rmind at NetBSD org>
+ * Copyright (c) 2008, 2011 Mindaugas Rasiukevicius <rmind at NetBSD org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -42,7 +42,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sys_sched.c,v 1.35 2010/07/01 02:38:31 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sys_sched.c,v 1.36 2011/08/07 13:33:01 rmind Exp $");
#include <sys/param.h>
@@ -298,12 +298,16 @@
static int
genkcpuset(kcpuset_t **dset, const cpuset_t *sset, size_t size)
{
+ kcpuset_t *kset;
int error;
- *dset = kcpuset_create();
- error = kcpuset_copyin(sset, *dset, size);
- if (error != 0)
- kcpuset_unuse(*dset, NULL);
+ kcpuset_create(&kset);
+ error = kcpuset_copyin(sset, kset, size);
+ if (error) {
+ kcpuset_unuse(kset, NULL);
+ } else {
+ *dset = kset;
+ }
return error;
}
@@ -320,7 +324,7 @@
syscallarg(size_t) size;
syscallarg(const cpuset_t *) cpuset;
} */
- kcpuset_t *cpuset, *cpulst = NULL;
+ kcpuset_t *kcset, *kcpulst = NULL;
struct cpu_info *ici, *ci;
struct proc *p;
struct lwp *t;
@@ -330,7 +334,7 @@
u_int lcnt;
int error;
- error = genkcpuset(&cpuset, SCARG(uap, cpuset), SCARG(uap, size));
+ error = genkcpuset(&kcset, SCARG(uap, cpuset), SCARG(uap, size));
if (error)
return error;
@@ -349,7 +353,7 @@
for (CPU_INFO_FOREACH(cii, ici)) {
struct schedstate_percpu *ispc;
- if (kcpuset_isset(cpu_index(ici), cpuset) == 0)
+ if (kcpuset_isset(kcset, cpu_index(ici)) == 0)
continue;
ispc = &ici->ci_schedstate;
@@ -375,8 +379,8 @@
goto out;
}
/* Empty set */
- kcpuset_unuse(cpuset, &cpulst);
- cpuset = NULL;
+ kcpuset_unuse(kcset, &kcpulst);
+ kcset = NULL;
}
if (SCARG(uap, pid) != 0) {
@@ -433,33 +437,42 @@
lwp_unlock(t);
continue;
}
- if (cpuset) {
+ if (kcset) {
/* Set the affinity flag and new CPU set */
t->l_flag |= LW_AFFINITY;
- kcpuset_use(cpuset);
+ kcpuset_use(kcset);
if (t->l_affinity != NULL)
- kcpuset_unuse(t->l_affinity, &cpulst);
- t->l_affinity = cpuset;
+ kcpuset_unuse(t->l_affinity, &kcpulst);
+ t->l_affinity = kcset;
/* Migrate to another CPU, unlocks LWP */
lwp_migrate(t, ci);
} else {
/* Unset the affinity flag */
t->l_flag &= ~LW_AFFINITY;
if (t->l_affinity != NULL)
- kcpuset_unuse(t->l_affinity, &cpulst);
+ kcpuset_unuse(t->l_affinity, &kcpulst);
t->l_affinity = NULL;
lwp_unlock(t);
}
lcnt++;
}
mutex_exit(p->p_lock);
- if (lcnt == 0)
+ if (lcnt == 0) {
error = ESRCH;
+ }
out:
mutex_exit(&cpu_lock);
- if (cpuset != NULL)
- kcpuset_unuse(cpuset, &cpulst);
- kcpuset_destroy(cpulst);
+
+ /*
+ * Drop the initial reference (LWPs, if any, have the ownership now),
+ * and destroy whatever is in the G/C list, if filled.
+ */
+ if (kcset) {
+ kcpuset_unuse(kcset, &kcpulst);
+ }
+ if (kcpulst) {
+ kcpuset_destroy(kcpulst);
+ }
return error;
}
@@ -477,10 +490,10 @@
syscallarg(cpuset_t *) cpuset;
} */
struct lwp *t;
- kcpuset_t *cpuset;
+ kcpuset_t *kcset;
int error;
- error = genkcpuset(&cpuset, SCARG(uap, cpuset), SCARG(uap, size));
+ error = genkcpuset(&kcset, SCARG(uap, cpuset), SCARG(uap, size));
if (error)
return error;
@@ -500,15 +513,16 @@
lwp_lock(t);
if (t->l_flag & LW_AFFINITY) {
KASSERT(t->l_affinity != NULL);
- kcpuset_copy(cpuset, t->l_affinity);
- } else
- kcpuset_zero(cpuset);
+ kcpuset_copy(kcset, t->l_affinity);
+ } else {
+ kcpuset_zero(kcset);
+ }
lwp_unlock(t);
mutex_exit(t->l_proc->p_lock);
- error = kcpuset_copyout(cpuset, SCARG(uap, cpuset), SCARG(uap, size));
+ error = kcpuset_copyout(kcset, SCARG(uap, cpuset), SCARG(uap, size));
out:
- kcpuset_unuse(cpuset, NULL);
+ kcpuset_unuse(kcset, NULL);
return error;
}
Index: src/sys/sys/Makefile
diff -u src/sys/sys/Makefile:1.136 src/sys/sys/Makefile:1.137
--- src/sys/sys/Makefile:1.136 Sun Jul 17 20:54:54 2011
+++ src/sys/sys/Makefile Sun Aug 7 13:33:02 2011
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.136 2011/07/17 20:54:54 joerg Exp $
+# $NetBSD: Makefile,v 1.137 2011/08/07 13:33:02 rmind Exp $
.include <bsd.sys.mk>
@@ -19,7 +19,7 @@
flashio.h float_ieee754.h fstypes.h gcq.h gmon.h gpio.h hash.h \
ieee754.h inttypes.h ioccom.h ioctl.h ioctl_compat.h iostat.h ipc.h \
joystick.h \
- kcore.h kgdb.h kmem.h ksem.h ksyms.h ktrace.h \
+ kcore.h kcpuset.h kgdb.h kmem.h ksem.h ksyms.h ktrace.h \
localedef.h lock.h lockf.h lwp.h lwpctl.h \
malloc.h mallocvar.h mbuf.h md4.h md5.h midiio.h \
mman.h module.h mount.h mqueue.h msg.h msgbuf.h mtio.h mutex.h \
Index: src/sys/sys/cpu.h
diff -u src/sys/sys/cpu.h:1.32 src/sys/sys/cpu.h:1.33
--- src/sys/sys/cpu.h:1.32 Mon Dec 20 04:27:35 2010
+++ src/sys/sys/cpu.h Sun Aug 7 13:33:02 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: cpu.h,v 1.32 2010/12/20 04:27:35 christos Exp $ */
+/* $NetBSD: cpu.h,v 1.33 2011/08/07 13:33:02 rmind Exp $ */
/*-
* Copyright (c) 2007 YAMAMOTO Takashi,
@@ -89,6 +89,7 @@
extern kmutex_t cpu_lock;
extern u_int maxcpus;
extern struct cpuqueue cpu_queue;
+extern kcpuset_t *kcpuset_attached;
static inline u_int
cpu_index(struct cpu_info *ci)
Index: src/sys/sys/lwp.h
diff -u src/sys/sys/lwp.h:1.152 src/sys/sys/lwp.h:1.153
--- src/sys/sys/lwp.h:1.152 Thu May 19 03:07:29 2011
+++ src/sys/sys/lwp.h Sun Aug 7 13:33:02 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: lwp.h,v 1.152 2011/05/19 03:07:29 rmind Exp $ */
+/* $NetBSD: lwp.h,v 1.153 2011/08/07 13:33:02 rmind Exp $ */
/*-
* Copyright (c) 2001, 2006, 2007, 2008, 2009, 2010
@@ -37,6 +37,7 @@
#include <sys/time.h>
#include <sys/queue.h>
#include <sys/callout.h>
+#include <sys/kcpuset.h>
#include <sys/mutex.h>
#include <sys/condvar.h>
#include <sys/signalvar.h>
Index: src/sys/sys/sched.h
diff -u src/sys/sys/sched.h:1.72 src/sys/sys/sched.h:1.73
--- src/sys/sys/sched.h:1.72 Fri Apr 16 03:21:49 2010
+++ src/sys/sys/sched.h Sun Aug 7 13:33:02 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: sched.h,v 1.72 2010/04/16 03:21:49 rmind Exp $ */
+/* $NetBSD: sched.h,v 1.73 2011/08/07 13:33:02 rmind Exp $ */
/*-
* Copyright (c) 1999, 2000, 2001, 2002, 2007, 2008 The NetBSD Foundation, Inc.
@@ -96,25 +96,8 @@
* Interface of CPU-sets.
*/
typedef struct _cpuset cpuset_t;
-typedef struct _kcpuset kcpuset_t; /* XXX: lwp.h included from userland */
-#ifdef _KERNEL
-
-kcpuset_t *kcpuset_create(void);
-void kcpuset_destroy(kcpuset_t *);
-void kcpuset_copy(kcpuset_t *, const kcpuset_t *);
-void kcpuset_use(kcpuset_t *);
-void kcpuset_unuse(kcpuset_t *, kcpuset_t **);
-int kcpuset_copyin(const cpuset_t *, kcpuset_t *, size_t);
-int kcpuset_copyout(const kcpuset_t *, cpuset_t *, size_t);
-void kcpuset_zero(kcpuset_t *);
-void kcpuset_fill(kcpuset_t *);
-void kcpuset_set(cpuid_t, kcpuset_t *);
-int kcpuset_isset(cpuid_t, const kcpuset_t *);
-bool kcpuset_iszero(const kcpuset_t *);
-bool kcpuset_match(const kcpuset_t *, const kcpuset_t *);
-
-#else
+#ifndef _KERNEL
#define cpuset_create() _cpuset_create()
#define cpuset_destroy(c) _cpuset_destroy(c)
Added files:
Index: src/sys/kern/subr_kcpuset.c
diff -u /dev/null src/sys/kern/subr_kcpuset.c:1.1
--- /dev/null Sun Aug 7 13:33:04 2011
+++ src/sys/kern/subr_kcpuset.c Sun Aug 7 13:33:01 2011
@@ -0,0 +1,386 @@
+/* $NetBSD: subr_kcpuset.c,v 1.1 2011/08/07 13:33:01 rmind Exp $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Mindaugas Rasiukevicius.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Kernel CPU set implementation.
+ *
+ * Interface can be used by kernel subsystems as a unified dynamic CPU
+ * bitset implementation handling many CPUs. Facility also supports early
+ * use by MD code on boot, as it fixups bitsets on further boot.
+ *
+ * TODO:
+ * - Handle "reverse" bitset on fixup/grow.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: subr_kcpuset.c,v 1.1 2011/08/07 13:33:01 rmind Exp $");
+
+#include <sys/param.h>
+#include <sys/types.h>
+
+#include <sys/atomic.h>
+#include <sys/sched.h>
+#include <sys/kcpuset.h>
+#include <sys/pool.h>
+
+/* Number of CPUs to support. */
+#define KC_MAXCPUS roundup2(MAXCPUS, 32)
+
+/*
+ * Structure of dynamic CPU set in the kernel.
+ */
+struct kcpuset {
+ uint32_t bits[0];
+};
+
+typedef struct kcpuset_impl {
+ /* Reference count. */
+ u_int kc_refcnt;
+ /* Next to free, if non-NULL (used when multiple references). */
+ struct kcpuset * kc_next;
+ /* Actual variable-sized field of bits. */
+ struct kcpuset kc_field;
+} kcpuset_impl_t;
+
+#define KC_BITS_OFF (offsetof(struct kcpuset_impl, kc_field))
+#define KC_GETSTRUCT(b) ((kcpuset_impl_t *)((char *)(b) - KC_BITS_OFF))
+
+/* Sizes of a single bitset. */
+#define KC_SHIFT 5
+#define KC_MASK 31
+
+/* An array of noted early kcpuset creations and data. */
+#define KC_SAVE_NITEMS 8
+
+/* Structures for early boot mechanism (must be statically initialised). */
+static kcpuset_t ** kc_noted_early[KC_SAVE_NITEMS];
+static uint32_t kc_bits_early[KC_SAVE_NITEMS];
+static int kc_last_idx = 0;
+static bool kc_initialised = false;
+
+#define KC_BITSIZE_EARLY sizeof(kc_bits_early[0])
+#define KC_NFIELDS_EARLY (KC_BITSIZE_EARLY >> KC_SHIFT)
+
+/*
+ * The size of whole bitset fields and amount of fields.
+ * The whole size must statically initialise for early case.
+ */
+static size_t kc_bitsize __read_mostly = KC_BITSIZE_EARLY;
+static size_t kc_nfields __read_mostly = KC_NFIELDS_EARLY;
+
+static pool_cache_t kc_cache __read_mostly;
+
+static kcpuset_t * kcpuset_create_raw(void);
+
+/*
+ * kcpuset_sysinit: initialize the subsystem, transfer early boot cases
+ * to dynamically allocated sets.
+ */
+void
+kcpuset_sysinit(void)
+{
+ kcpuset_t *kc_dynamic[KC_SAVE_NITEMS], *kcp;
+ int i, s;
+
+ /* Set a kcpuset_t sizes. */
+ kc_nfields = (KC_MAXCPUS >> KC_SHIFT);
+ kc_bitsize = sizeof(uint32_t) * kc_nfields;
+
+ kc_cache = pool_cache_init(sizeof(kcpuset_impl_t) + kc_bitsize,
+ coherency_unit, 0, 0, "kcpuset", NULL, IPL_NONE, NULL, NULL, NULL);
+
+ /* First, pre-allocate kcpuset entries. */
+ for (i = 0; i < kc_last_idx; i++) {
+ kcp = kcpuset_create_raw();
+ kcpuset_zero(kcp);
+ kc_dynamic[i] = kcp;
+ }
+
+ /*
+ * Prepare to convert all early noted kcpuset uses to dynamic sets.
+ * All processors, except the one we are currently running (primary),
+ * must not be spinned yet. Since MD facilities can use kcpuset,
+ * raise the IPL to high.
+ */
+ KASSERT(mp_online == false);
+
+ s = splhigh();
+ for (i = 0; i < kc_last_idx; i++) {
+ /*
+ * Transfer the bits from early static storage to the kcpuset.
+ */
+ KASSERT(kc_bitsize >= KC_BITSIZE_EARLY);
+ memcpy(kc_dynamic[i], &kc_bits_early[i], KC_BITSIZE_EARLY);
+
+ /*
+ * Store the new pointer, pointing to the allocated kcpuset.
+ * Note: we are not in an interrupt context and it is the only
+ * CPU running - thus store is safe (e.g. no need for pointer
+ * variable to be volatile).
+ */
+ *kc_noted_early[i] = kc_dynamic[i];
+ }
+ kc_initialised = true;
+ kc_last_idx = 0;
+ splx(s);
+}
+
+/*
+ * kcpuset_early_ptr: note an early boot use by saving the pointer and
+ * returning a pointer to a static, temporary bit field.
+ */
+static kcpuset_t *
+kcpuset_early_ptr(kcpuset_t **kcptr)
+{
+ kcpuset_t *kcp;
+ int s;
+
+ s = splhigh();
+ if (kc_last_idx < KC_SAVE_NITEMS) {
+ /*
+ * Save the pointer, return pointer to static early field.
+ * Need to zero it out.
+ */
+ kc_noted_early[kc_last_idx++] = kcptr;
+ kcp = (kcpuset_t *)&kc_bits_early[kc_last_idx];
+ memset(kcp, 0, KC_BITSIZE_EARLY);
+ KASSERT(kc_bitsize == KC_BITSIZE_EARLY);
+ } else {
+ panic("kcpuset(9): all early-use entries exhausted; "
+ "increase KC_SAVE_NITEMS\n");
+ }
+ splx(s);
+
+ return kcp;
+}
+
+/*
+ * Routines to create or destroy the CPU set.
+ * Early boot case is handled.
+ */
+
+static kcpuset_t *
+kcpuset_create_raw(void)
+{
+ kcpuset_impl_t *kc;
+
+ kc = pool_cache_get(kc_cache, PR_WAITOK);
+ kc->kc_refcnt = 1;
+ kc->kc_next = NULL;
+
+ /* Note: return pointer to the actual field of bits. */
+ KASSERT((uint8_t *)kc + KC_BITS_OFF == (uint8_t *)&kc->kc_field);
+ return &kc->kc_field;
+}
+
+void
+kcpuset_create(kcpuset_t **retkcp)
+{
+
+ if (__predict_false(!kc_initialised)) {
+ /* Early boot use - special case. */
+ *retkcp = kcpuset_early_ptr(retkcp);
+ return;
+ }
+ *retkcp = kcpuset_create_raw();
+}
+
+void
+kcpuset_destroy(kcpuset_t *kcp)
+{
+ kcpuset_impl_t *kc, *nkc;
+
+ KASSERT(kc_initialised);
+ KASSERT(kcp != NULL);
+
+ kc = KC_GETSTRUCT(kcp);
+ do {
+ nkc = KC_GETSTRUCT(kc->kc_next);
+ pool_cache_put(kc_cache, kc);
+ kc = nkc;
+ } while (kc);
+}
+
+/*
+ * Routines to copy or reference/unreference the CPU set.
+ * Note: early boot case is not supported by these routines.
+ */
+
+void
+kcpuset_copy(kcpuset_t *dkcp, kcpuset_t *skcp)
+{
+
+ KASSERT(kc_initialised);
+ KASSERT(KC_GETSTRUCT(dkcp)->kc_refcnt == 1);
+ memcpy(dkcp, skcp, kc_bitsize);
+}
+
+void
+kcpuset_use(kcpuset_t *kcp)
+{
+ kcpuset_impl_t *kc = KC_GETSTRUCT(kcp);
+
+ KASSERT(kc_initialised);
+ atomic_inc_uint(&kc->kc_refcnt);
+}
+
+void
+kcpuset_unuse(kcpuset_t *kcp, kcpuset_t **lst)
+{
+ kcpuset_impl_t *kc = KC_GETSTRUCT(kcp);
+
+ KASSERT(kc_initialised);
+ KASSERT(kc->kc_refcnt > 0);
+
+ if (atomic_dec_uint_nv(&kc->kc_refcnt) != 0) {
+ return;
+ }
+ KASSERT(kc->kc_next == NULL);
+ if (lst == NULL) {
+ kcpuset_destroy(kcp);
+ return;
+ }
+ kc->kc_next = *lst;
+ *lst = kcp;
+}
+
+/*
+ * Routines to transfer the CPU set from / to userspace.
+ * Note: early boot case is not supported by these routines.
+ */
+
+int
+kcpuset_copyin(const cpuset_t *ucp, kcpuset_t *kcp, size_t len)
+{
+ kcpuset_impl_t *kc = KC_GETSTRUCT(kcp);
+
+ KASSERT(kc_initialised);
+ KASSERT(kc->kc_refcnt > 0);
+ KASSERT(kc->kc_next == NULL);
+ (void)kc;
+
+ if (len != kc_bitsize) { /* XXX */
+ return EINVAL;
+ }
+ return copyin(ucp, kcp, kc_bitsize);
+}
+
+int
+kcpuset_copyout(kcpuset_t *kcp, cpuset_t *ucp, size_t len)
+{
+ kcpuset_impl_t *kc = KC_GETSTRUCT(kcp);
+
+ KASSERT(kc_initialised);
+ KASSERT(kc->kc_refcnt > 0);
+ KASSERT(kc->kc_next == NULL);
+ (void)kc;
+
+ if (len != kc_bitsize) { /* XXX */
+ return EINVAL;
+ }
+ return copyout(kcp, ucp, kc_bitsize);
+}
+
+/*
+ * Routines to change bit field - zero, fill, set, unset, etc.
+ */
+
+void
+kcpuset_zero(kcpuset_t *kcp)
+{
+
+ KASSERT(!kc_initialised || KC_GETSTRUCT(kcp)->kc_refcnt > 0);
+ KASSERT(!kc_initialised || KC_GETSTRUCT(kcp)->kc_next == NULL);
+ memset(kcp, 0, kc_bitsize);
+}
+
+void
+kcpuset_fill(kcpuset_t *kcp)
+{
+
+ KASSERT(!kc_initialised || KC_GETSTRUCT(kcp)->kc_refcnt > 0);
+ KASSERT(!kc_initialised || KC_GETSTRUCT(kcp)->kc_next == NULL);
+ memset(kcp, ~0, kc_bitsize);
+}
+
+void
+kcpuset_set(kcpuset_t *kcp, cpuid_t i)
+{
+ const size_t j = i >> KC_SHIFT;
+
+ KASSERT(!kc_initialised || KC_GETSTRUCT(kcp)->kc_next == NULL);
+ KASSERT(j < kc_nfields);
+
+ kcp->bits[j] |= 1 << (i & KC_MASK);
+}
+
+void
+kcpuset_clear(kcpuset_t *kcp, cpuid_t i)
+{
+ const size_t j = i >> KC_SHIFT;
+
+ KASSERT(!kc_initialised || KC_GETSTRUCT(kcp)->kc_next == NULL);
+ KASSERT(j < kc_nfields);
+
+ kcp->bits[j] &= ~(1 << (i & KC_MASK));
+}
+
+int
+kcpuset_isset(kcpuset_t *kcp, cpuid_t i)
+{
+ const size_t j = i >> KC_SHIFT;
+
+ KASSERT(kcp != NULL);
+ KASSERT(!kc_initialised || KC_GETSTRUCT(kcp)->kc_refcnt > 0);
+ KASSERT(!kc_initialised || KC_GETSTRUCT(kcp)->kc_next == NULL);
+ KASSERT(j < kc_nfields);
+
+ return ((1 << (i & KC_MASK)) & kcp->bits[j]) != 0;
+}
+
+bool
+kcpuset_iszero(kcpuset_t *kcp)
+{
+
+ for (size_t j = 0; j < kc_nfields; j++) {
+ if (kcp->bits[j] != 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool
+kcpuset_match(const kcpuset_t *kcp1, const kcpuset_t *kcp2)
+{
+
+ return memcmp(kcp1, kcp2, kc_bitsize) == 0;
+}
Index: src/sys/sys/kcpuset.h
diff -u /dev/null src/sys/sys/kcpuset.h:1.1
--- /dev/null Sun Aug 7 13:33:04 2011
+++ src/sys/sys/kcpuset.h Sun Aug 7 13:33:02 2011
@@ -0,0 +1,63 @@
+/* $NetBSD: kcpuset.h,v 1.1 2011/08/07 13:33:02 rmind Exp $ */
+
+/*-
+ * Copyright (c) 2008, 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas and Mindaugas Rasiukevicius.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _SYS_KCPUSET_H_
+#define _SYS_KCPUSET_H_
+
+struct kcpuset;
+typedef struct kcpuset kcpuset_t;
+
+#ifdef _KERNEL
+
+void kcpuset_sysinit(void);
+
+void kcpuset_create(kcpuset_t **);
+void kcpuset_destroy(kcpuset_t *);
+void kcpuset_copy(kcpuset_t *, kcpuset_t *);
+
+void kcpuset_use(kcpuset_t *);
+void kcpuset_unuse(kcpuset_t *, kcpuset_t **);
+
+int kcpuset_copyin(const cpuset_t *, kcpuset_t *, size_t);
+int kcpuset_copyout(kcpuset_t *, cpuset_t *, size_t);
+
+void kcpuset_zero(kcpuset_t *);
+void kcpuset_fill(kcpuset_t *);
+void kcpuset_set(kcpuset_t *, cpuid_t);
+void kcpuset_clear(kcpuset_t *, cpuid_t);
+
+int kcpuset_isset(kcpuset_t *, cpuid_t);
+bool kcpuset_iszero(kcpuset_t *);
+bool kcpuset_match(const kcpuset_t *, const kcpuset_t *);
+
+#endif
+
+#endif /* _SYS_KCPUSET_H_ */