31 #include <sys/cdefs.h>
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/sysproto.h>
40 #include <sys/kernel.h>
42 #include <sys/malloc.h>
43 #include <sys/mutex.h>
46 #include <sys/refcount.h>
47 #include <sys/sched.h>
49 #include <sys/syscallsubr.h>
50 #include <sys/cpuset.h>
52 #include <sys/queue.h>
53 #include <sys/libkern.h>
54 #include <sys/limits.h>
56 #include <sys/interrupt.h>
112 SYSCTL_INT(_kern_sched, OID_AUTO, cpusetsize, CTLFLAG_RD,
113 SYSCTL_NULL_INT_PTR,
sizeof(cpuset_t),
"sizeof(cpuset_t)");
124 refcount_acquire(&set->cs_ref);
132 static struct cpuset *
136 for (; set->cs_parent != NULL; set = set->cs_parent)
137 if (set->cs_flags & CPU_SET_ROOT)
149 static struct cpuset *
153 if (set->cs_id == CPUSET_INVALID)
154 set = set->cs_parent;
168 if (refcount_release(&set->cs_ref) == 0)
171 LIST_REMOVE(set, cs_siblings);
173 if (
id != CPUSET_INVALID)
174 LIST_REMOVE(set, cs_link);
178 if (
id != CPUSET_INVALID)
190 if (refcount_release(&set->cs_ref) == 0)
193 LIST_REMOVE(set, cs_siblings);
194 if (set->cs_id != CPUSET_INVALID)
195 LIST_REMOVE(set, cs_link);
196 LIST_INSERT_HEAD(head, set, cs_link);
207 LIST_REMOVE(set, cs_link);
215 static struct cpuset *
220 if (setid == CPUSET_INVALID)
224 if (set->cs_id == setid)
230 KASSERT(td != NULL, (
"[%s:%d] td is NULL", __func__, __LINE__));
231 if (set != NULL &&
jailed(td->td_ucred)) {
232 struct cpuset *jset, *tset;
234 jset = td->td_ucred->cr_prison->pr_cpuset;
235 for (tset = set; tset != NULL; tset = tset->cs_parent)
257 if (!CPU_OVERLAP(&parent->cs_mask, mask))
259 CPU_COPY(mask, &set->cs_mask);
260 LIST_INIT(&set->cs_children);
261 refcount_init(&set->cs_ref, 1);
264 CPU_AND(&set->cs_mask, &parent->cs_mask);
267 LIST_INSERT_HEAD(&parent->cs_children, set, cs_siblings);
268 if (set->cs_id != CPUSET_INVALID)
313 if (set->cs_flags & CPU_SET_RDONLY)
316 if (!CPU_OVERLAP(&set->cs_mask, mask))
318 CPU_COPY(&set->cs_mask, &newmask);
319 CPU_AND(&newmask, mask);
321 CPU_COPY(mask, &newmask);
323 LIST_FOREACH(nset, &set->cs_children, cs_siblings)
338 CPU_AND(&set->cs_mask, mask);
339 LIST_FOREACH(nset, &set->cs_children, cs_siblings)
356 error =
priv_check(curthread, PRIV_SCHED_CPUSET);
365 if (
jailed(curthread->td_ucred) &&
366 set->cs_flags & CPU_SET_ROOT)
372 root = set->cs_parent;
373 if (root && !CPU_SUBSET(&root->cs_mask, mask))
379 CPU_COPY(mask, &set->cs_mask);
399 cpuset_which(cpuwhich_t which, id_t
id,
struct proc **pp,
struct thread **tdp,
400 struct cpuset **setp)
417 if ((p =
pfind(
id)) == NULL)
432 case CPU_WHICH_CPUSET:
434 thread_lock(curthread);
436 thread_unlock(curthread);
455 *setp = pr->pr_cpuset;
456 mtx_unlock(&pr->pr_mtx);
470 td = FIRST_THREAD_IN_PROC(p);
486 if (set->cs_id == CPUSET_INVALID)
487 parent = set->cs_parent;
490 if (!CPU_SUBSET(&parent->cs_mask, mask))
511 struct setlist freelist;
512 struct setlist droplist;
513 struct cpuset *tdset;
527 LIST_INIT(&freelist);
528 LIST_INIT(&droplist);
531 error =
cpuset_which(CPU_WHICH_PID, pid, &p, &td, &nset);
534 if (nfree >= p->p_numthreads)
536 threads = p->p_numthreads;
538 for (; nfree < threads; nfree++) {
540 LIST_INSERT_HEAD(&freelist, nset, cs_link);
543 PROC_LOCK_ASSERT(p, MA_OWNED);
550 FOREACH_THREAD_IN_PROC(p, td) {
552 tdset = td->td_cpuset;
558 if (tdset->cs_id == CPUSET_INVALID)
559 tdset = tdset->cs_parent;
560 if (!CPU_SUBSET(&tdset->cs_mask, mask))
567 }
else if (tdset->cs_id == CPUSET_INVALID) {
568 if (!CPU_OVERLAP(&set->cs_mask, &tdset->cs_mask))
580 FOREACH_THREAD_IN_PROC(p, td) {
590 tdset = td->td_cpuset;
591 if (tdset->cs_id == CPUSET_INVALID || mask) {
592 nset = LIST_FIRST(&freelist);
593 LIST_REMOVE(nset, cs_link);
598 &tdset->cs_mask, CPUSET_INVALID);
600 LIST_INSERT_HEAD(&freelist, nset, cs_link);
607 td->td_cpuset = nset;
614 while ((nset = LIST_FIRST(&droplist)) != NULL)
616 while ((nset = LIST_FIRST(&freelist)) != NULL) {
617 LIST_REMOVE(nset, cs_link);
633 for (i = 0; i < _NCPUWORDS; i++) {
634 if (set->__bits[i] != 0) {
635 cbit = ffsl(set->__bits[i]);
636 cbit += i * _NCPUBITS;
651 size_t i, bytesp, bufsiz;
655 bufsiz = CPUSETBUFSIZ;
657 for (i = _NCPUWORDS - 1; i > 0; i--) {
658 bytesp =
snprintf(tbuf, bufsiz,
"%lx, ", set->__bits[i]);
662 snprintf(tbuf, bufsiz,
"%lx", set->__bits[0]);
676 if (strlen(buf) > CPUSETBUFSIZ - 1)
681 for (i = 0; buf[i] !=
'\0'; i++)
684 if (nwords > _NCPUWORDS)
688 for (i = nwords - 1; i > 0; i--) {
689 ret =
sscanf(buf,
"%lx, ", &set->__bits[i]);
690 if (ret == 0 || ret == -1)
692 buf = strstr(buf,
" ");
697 ret =
sscanf(buf,
"%lx", &set->__bits[0]);
698 if (ret == 0 || ret == -1)
724 td->td_cpuset = nset;
755 cpuset_zone = uma_zcreate(
"cpuset",
sizeof(
struct cpuset), NULL, NULL,
756 NULL, NULL, UMA_ALIGN_PTR, 0);
763 CPU_FILL(&set->cs_mask);
764 LIST_INIT(&set->cs_children);
767 set->cs_flags = CPU_SET_ROOT;
769 cpuset_root = &set->cs_mask;
775 KASSERT(error == 0, (
"Error creating default set: %d\n", error));
799 KASSERT(pr != NULL, (
"[%s:%d] invalid pr", __func__, __LINE__));
800 KASSERT(setp != NULL, (
"[%s:%d] invalid setp", __func__, __LINE__));
802 error =
cpuset_create(setp, pr->pr_cpuset, &pr->pr_cpuset->cs_mask);
806 KASSERT(*setp != NULL, (
"[%s:%d] cpuset_create returned invalid data",
807 __func__, __LINE__));
811 set->cs_flags |= CPU_SET_ROOT;
821 KASSERT(p != NULL, (
"[%s:%d] invalid proc", __func__, __LINE__));
822 KASSERT(set != NULL, (
"[%s:%d] invalid set", __func__, __LINE__));
843 panic(
"Can't set initial cpuset mask.\n");
848 #ifndef _SYS_SYSPROTO_H_
867 error = copyout(&set->cs_id, uap->
setid,
sizeof(set->cs_id));
874 #ifndef _SYS_SYSPROTO_H_
890 if (uap->
which != CPU_WHICH_PID)
900 #ifndef _SYS_SYSPROTO_H_
901 struct cpuset_getid_args {
908 sys_cpuset_getid(
struct thread *td,
struct cpuset_getid_args *uap)
917 if (uap->level == CPU_LEVEL_WHICH && uap->which != CPU_WHICH_CPUSET)
919 error =
cpuset_which(uap->which, uap->id, &p, &ttd, &set);
922 switch (uap->which) {
930 case CPU_WHICH_CPUSET:
936 switch (uap->level) {
942 case CPU_LEVEL_CPUSET:
944 case CPU_LEVEL_WHICH:
950 error = copyout(&
id, uap->setid,
sizeof(
id));
955 #ifndef _SYS_SYSPROTO_H_
956 struct cpuset_getaffinity_args {
965 sys_cpuset_getaffinity(
struct thread *td,
struct cpuset_getaffinity_args *uap)
975 if (uap->cpusetsize <
sizeof(cpuset_t) ||
976 uap->cpusetsize > CPU_MAXSIZE / NBBY)
978 size = uap->cpusetsize;
979 mask =
malloc(size, M_TEMP, M_WAITOK | M_ZERO);
980 error =
cpuset_which(uap->which, uap->id, &p, &ttd, &set);
983 switch (uap->level) {
985 case CPU_LEVEL_CPUSET:
986 switch (uap->which) {
993 case CPU_WHICH_CPUSET:
1000 if (uap->level == CPU_LEVEL_ROOT)
1004 CPU_COPY(&nset->cs_mask, mask);
1007 case CPU_LEVEL_WHICH:
1008 switch (uap->which) {
1011 CPU_COPY(&ttd->td_cpuset->cs_mask, mask);
1015 FOREACH_THREAD_IN_PROC(p, ttd) {
1017 CPU_OR(mask, &ttd->td_cpuset->cs_mask);
1021 case CPU_WHICH_CPUSET:
1022 case CPU_WHICH_JAIL:
1023 CPU_COPY(&set->cs_mask, mask);
1039 error = copyout(mask, uap->mask, size);
1045 #ifndef _SYS_SYSPROTO_H_
1046 struct cpuset_setaffinity_args {
1051 const cpuset_t *
mask;
1055 sys_cpuset_setaffinity(
struct thread *td,
struct cpuset_setaffinity_args *uap)
1057 struct cpuset *nset;
1064 if (uap->cpusetsize <
sizeof(cpuset_t) ||
1065 uap->cpusetsize > CPU_MAXSIZE / NBBY)
1067 mask =
malloc(uap->cpusetsize, M_TEMP, M_WAITOK | M_ZERO);
1068 error = copyin(uap->mask, mask, uap->cpusetsize);
1074 if (uap->cpusetsize >
sizeof(cpuset_t)) {
1078 end = cp = (
char *)&mask->__bits;
1079 end += uap->cpusetsize;
1080 cp +=
sizeof(cpuset_t);
1088 switch (uap->level) {
1089 case CPU_LEVEL_ROOT:
1090 case CPU_LEVEL_CPUSET:
1091 error =
cpuset_which(uap->which, uap->id, &p, &ttd, &set);
1094 switch (uap->which) {
1102 case CPU_WHICH_CPUSET:
1103 case CPU_WHICH_JAIL:
1109 if (uap->level == CPU_LEVEL_ROOT)
1117 case CPU_LEVEL_WHICH:
1118 switch (uap->which) {
1125 case CPU_WHICH_CPUSET:
1126 case CPU_WHICH_JAIL:
1153 ddb_display_cpuset(
const cpuset_t *set)
1157 for (once = 0, cpu = 0; cpu < CPU_SETSIZE; cpu++) {
1158 if (CPU_ISSET(cpu, set)) {
1160 db_printf(
"%d", cpu);
1163 db_printf(
",%d", cpu);
1167 db_printf(
"<none>");
1170 DB_SHOW_COMMAND(cpusets, db_show_cpusets)
1175 db_printf(
"set=%p id=%-6u ref=%-6d flags=0x%04x parent id=%d\n",
1176 set, set->cs_id, set->cs_ref, set->cs_flags,
1177 (set->cs_parent != NULL) ? set->cs_parent->cs_id : 0);
1178 db_printf(
" mask=");
1179 ddb_display_cpuset(&set->cs_mask);
static struct cpuset * cpuset_refroot(struct cpuset *set)
int sys_cpuset(struct thread *td, struct cpuset_args *uap)
static int cpuset_setproc(pid_t pid, struct cpuset *set, cpuset_t *mask)
SYSINIT(cpuset, SI_SUB_SMP, SI_ORDER_ANY, cpuset_init, NULL)
static struct setlist cpuset_ids
int snprintf(char *str, size_t size, const char *format,...)
static int cpuset_modify(struct cpuset *set, cpuset_t *mask)
static void cpuset_rel_defer(struct setlist *head, struct cpuset *set)
static int cpuset_which(cpuwhich_t which, id_t id, struct proc **pp, struct thread **tdp, struct cpuset **setp)
int intr_getaffinity(int irq, void *m)
void * malloc(unsigned long size, struct malloc_type *mtp, int flags)
void panic(const char *fmt,...)
static int cpuset_create(struct cpuset **setp, struct cpuset *parent, const cpuset_t *mask)
static struct mtx cpuset_lock
int alloc_unr(struct unrhdr *uh)
int sys_cpuset_setid(struct thread *td, struct cpuset_setid_args *uap)
static void cpuset_rel_complete(struct cpuset *set)
int priv_check(struct thread *td, int priv)
struct proc * pfind(pid_t pid)
struct prison * prison_find_child(struct prison *mypr, int prid)
static struct cpuset * cpuset_lookup(cpusetid_t setid, struct thread *td)
struct cpuset * cpuset_ref(struct cpuset *set)
int jailed(struct ucred *cred)
void cpuset_rel(struct cpuset *set)
int cpuset_setproc_update_set(struct proc *p, struct cpuset *set)
int cpuset_create_root(struct prison *pr, struct cpuset **setp)
static int cpuset_shadow(struct cpuset *set, struct cpuset *fset, const cpuset_t *mask)
void sched_affinity(struct thread *td)
struct cpuset * cpuset_thread0(void)
struct unrhdr * new_unrhdr(int low, int high, struct mtx *mutex)
int intr_setaffinity(int irq, void *m)
void free(void *addr, struct malloc_type *mtp)
int cpusetobj_strscan(cpuset_t *set, const char *buf)
static int _cpuset_create(struct cpuset *set, struct cpuset *parent, const cpuset_t *mask, cpusetid_t id)
static struct cpuset * cpuset_zero
void mtx_init(struct mtx *m, const char *name, const char *type, int opts)
static void cpuset_update(struct cpuset *set, cpuset_t *mask)
int sscanf(const char *ibuf, const char *fmt,...)
static void cpuset_init(void *arg)
int cpuset_setthread(lwpid_t id, cpuset_t *mask)
struct thread * tdfind(lwpid_t tid, pid_t pid)
char * cpusetobj_strprint(char *buf, const cpuset_t *set)
int cpusetobj_ffs(const cpuset_t *set)
static struct cpuset * cpuset_refbase(struct cpuset *set)
static struct unrhdr * cpuset_unr
static int cpuset_testupdate(struct cpuset *set, cpuset_t *mask, int check_mask)
static uma_zone_t cpuset_zone
static struct pollrec pr[POLL_LIST_LEN]
void free_unr(struct unrhdr *uh, u_int item)
int p_cansched(struct thread *td, struct proc *p)
SYSCTL_INT(_kern_sched, OID_AUTO, cpusetsize, CTLFLAG_RD, SYSCTL_NULL_INT_PTR, sizeof(cpuset_t),"sizeof(cpuset_t)")
const struct cf_level * level