]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/kern/kern_cpuset.c
Restore r331606 with a bugfix to setup cpuset_domain[] earlier on all
[FreeBSD/FreeBSD.git] / sys / kern / kern_cpuset.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2008,  Jeffrey Roberson <jeff@freebsd.org>
5  * All rights reserved.
6  * 
7  * Copyright (c) 2008 Nokia Corporation
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice unmodified, this list of conditions, and the following
15  *    disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  *
31  */
32
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
35
36 #include "opt_ddb.h"
37
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/sysproto.h>
41 #include <sys/jail.h>
42 #include <sys/kernel.h>
43 #include <sys/lock.h>
44 #include <sys/malloc.h>
45 #include <sys/mutex.h>
46 #include <sys/priv.h>
47 #include <sys/proc.h>
48 #include <sys/refcount.h>
49 #include <sys/sched.h>
50 #include <sys/smp.h>
51 #include <sys/syscallsubr.h>
52 #include <sys/capsicum.h>
53 #include <sys/cpuset.h>
54 #include <sys/domainset.h>
55 #include <sys/sx.h>
56 #include <sys/queue.h>
57 #include <sys/libkern.h>
58 #include <sys/limits.h>
59 #include <sys/bus.h>
60 #include <sys/interrupt.h>
61 #include <sys/vmmeter.h>
62
63 #include <vm/uma.h>
64 #include <vm/vm.h>
65 #include <vm/vm_object.h>
66 #include <vm/vm_page.h>
67 #include <vm/vm_param.h>
68 #include <vm/vm_phys.h>
69
70 #ifdef DDB
71 #include <ddb/ddb.h>
72 #endif /* DDB */
73
74 /*
75  * cpusets provide a mechanism for creating and manipulating sets of
76  * processors for the purpose of constraining the scheduling of threads to
77  * specific processors.
78  *
79  * Each process belongs to an identified set, by default this is set 1.  Each
80  * thread may further restrict the cpus it may run on to a subset of this
81  * named set.  This creates an anonymous set which other threads and processes
82  * may not join by number.
83  *
84  * The named set is referred to herein as the 'base' set to avoid ambiguity.
85  * This set is usually a child of a 'root' set while the anonymous set may
86  * simply be referred to as a mask.  In the syscall api these are referred to
87  * as the ROOT, CPUSET, and MASK levels where CPUSET is called 'base' here.
88  *
89  * Threads inherit their set from their creator whether it be anonymous or
90  * not.  This means that anonymous sets are immutable because they may be
91  * shared.  To modify an anonymous set a new set is created with the desired
92  * mask and the same parent as the existing anonymous set.  This gives the
93  * illusion of each thread having a private mask.
94  *
95  * Via the syscall apis a user may ask to retrieve or modify the root, base,
96  * or mask that is discovered via a pid, tid, or setid.  Modifying a set
97  * modifies all numbered and anonymous child sets to comply with the new mask.
98  * Modifying a pid or tid's mask applies only to that tid but must still
99  * exist within the assigned parent set.
100  *
101  * A thread may not be assigned to a group separate from other threads in
102  * the process.  This is to remove ambiguity when the setid is queried with
103  * a pid argument.  There is no other technical limitation.
104  *
105  * This somewhat complex arrangement is intended to make it easy for
106  * applications to query available processors and bind their threads to
107  * specific processors while also allowing administrators to dynamically
108  * reprovision by changing sets which apply to groups of processes.
109  *
110  * A simple application should not concern itself with sets at all and
111  * rather apply masks to its own threads via CPU_WHICH_TID and a -1 id
112  * meaning 'curthread'.  It may query available cpus for that tid with a
113  * getaffinity call using (CPU_LEVEL_CPUSET, CPU_WHICH_PID, -1, ...).
114  */
115 static uma_zone_t cpuset_zone;
116 static uma_zone_t domainset_zone;
117 static struct mtx cpuset_lock;
118 static struct setlist cpuset_ids;
119 static struct domainlist cpuset_domains;
120 static struct unrhdr *cpuset_unr;
121 static struct cpuset *cpuset_zero, *cpuset_default;
122
123 /* Return the size of cpuset_t at the kernel level */
124 SYSCTL_INT(_kern_sched, OID_AUTO, cpusetsize, CTLFLAG_RD | CTLFLAG_CAPRD,
125     SYSCTL_NULL_INT_PTR, sizeof(cpuset_t), "sizeof(cpuset_t)");
126
127 cpuset_t *cpuset_root;
128 cpuset_t cpuset_domain[MAXMEMDOM];
129
130 static int domainset_valid(const struct domainset *, const struct domainset *);
131
132 /*
133  * Find the first non-anonymous set starting from 'set'.
134  */
135 static struct cpuset *
136 cpuset_getbase(struct cpuset *set)
137 {
138
139         if (set->cs_id == CPUSET_INVALID)
140                 set = set->cs_parent;
141         return (set);
142 }
143
144 /*
145  * Walks up the tree from 'set' to find the root.
146  */
147 static struct cpuset *
148 cpuset_getroot(struct cpuset *set)
149 {
150
151         while ((set->cs_flags & CPU_SET_ROOT) == 0 && set->cs_parent != NULL)
152                 set = set->cs_parent;
153         return (set);
154 }
155
156 /*
157  * Acquire a reference to a cpuset, all pointers must be tracked with refs.
158  */
159 struct cpuset *
160 cpuset_ref(struct cpuset *set)
161 {
162
163         refcount_acquire(&set->cs_ref);
164         return (set);
165 }
166
167 /*
168  * Walks up the tree from 'set' to find the root.  Returns the root
169  * referenced.
170  */
171 static struct cpuset *
172 cpuset_refroot(struct cpuset *set)
173 {
174
175         return (cpuset_ref(cpuset_getroot(set)));
176 }
177
178 /*
179  * Find the first non-anonymous set starting from 'set'.  Returns this set
180  * referenced.  May return the passed in set with an extra ref if it is
181  * not anonymous. 
182  */
183 static struct cpuset *
184 cpuset_refbase(struct cpuset *set)
185 {
186
187         return (cpuset_ref(cpuset_getbase(set)));
188 }
189
190 /*
191  * Release a reference in a context where it is safe to allocate.
192  */
193 void
194 cpuset_rel(struct cpuset *set)
195 {
196         cpusetid_t id;
197
198         if (refcount_release(&set->cs_ref) == 0)
199                 return;
200         mtx_lock_spin(&cpuset_lock);
201         LIST_REMOVE(set, cs_siblings);
202         id = set->cs_id;
203         if (id != CPUSET_INVALID)
204                 LIST_REMOVE(set, cs_link);
205         mtx_unlock_spin(&cpuset_lock);
206         cpuset_rel(set->cs_parent);
207         uma_zfree(cpuset_zone, set);
208         if (id != CPUSET_INVALID)
209                 free_unr(cpuset_unr, id);
210 }
211
212 /*
213  * Deferred release must be used when in a context that is not safe to
214  * allocate/free.  This places any unreferenced sets on the list 'head'.
215  */
216 static void
217 cpuset_rel_defer(struct setlist *head, struct cpuset *set)
218 {
219
220         if (refcount_release(&set->cs_ref) == 0)
221                 return;
222         mtx_lock_spin(&cpuset_lock);
223         LIST_REMOVE(set, cs_siblings);
224         if (set->cs_id != CPUSET_INVALID)
225                 LIST_REMOVE(set, cs_link);
226         LIST_INSERT_HEAD(head, set, cs_link);
227         mtx_unlock_spin(&cpuset_lock);
228 }
229
230 /*
231  * Complete a deferred release.  Removes the set from the list provided to
232  * cpuset_rel_defer.
233  */
234 static void
235 cpuset_rel_complete(struct cpuset *set)
236 {
237         LIST_REMOVE(set, cs_link);
238         cpuset_rel(set->cs_parent);
239         uma_zfree(cpuset_zone, set);
240 }
241
242 /*
243  * Find a set based on an id.  Returns it with a ref.
244  */
245 static struct cpuset *
246 cpuset_lookup(cpusetid_t setid, struct thread *td)
247 {
248         struct cpuset *set;
249
250         if (setid == CPUSET_INVALID)
251                 return (NULL);
252         mtx_lock_spin(&cpuset_lock);
253         LIST_FOREACH(set, &cpuset_ids, cs_link)
254                 if (set->cs_id == setid)
255                         break;
256         if (set)
257                 cpuset_ref(set);
258         mtx_unlock_spin(&cpuset_lock);
259
260         KASSERT(td != NULL, ("[%s:%d] td is NULL", __func__, __LINE__));
261         if (set != NULL && jailed(td->td_ucred)) {
262                 struct cpuset *jset, *tset;
263
264                 jset = td->td_ucred->cr_prison->pr_cpuset;
265                 for (tset = set; tset != NULL; tset = tset->cs_parent)
266                         if (tset == jset)
267                                 break;
268                 if (tset == NULL) {
269                         cpuset_rel(set);
270                         set = NULL;
271                 }
272         }
273
274         return (set);
275 }
276
277 /*
278  * Create a set in the space provided in 'set' with the provided parameters.
279  * The set is returned with a single ref.  May return EDEADLK if the set
280  * will have no valid cpu based on restrictions from the parent.
281  */
282 static int
283 _cpuset_create(struct cpuset *set, struct cpuset *parent,
284     const cpuset_t *mask, struct domainset *domain, cpusetid_t id)
285 {
286
287         if (domain == NULL)
288                 domain = parent->cs_domain;
289         if (mask == NULL)
290                 mask = &parent->cs_mask;
291         if (!CPU_OVERLAP(&parent->cs_mask, mask))
292                 return (EDEADLK);
293         /* The domain must be prepared ahead of time. */
294         if (!domainset_valid(parent->cs_domain, domain))
295                 return (EDEADLK);
296         CPU_COPY(mask, &set->cs_mask);
297         LIST_INIT(&set->cs_children);
298         refcount_init(&set->cs_ref, 1);
299         set->cs_flags = 0;
300         mtx_lock_spin(&cpuset_lock);
301         set->cs_domain = domain;
302         CPU_AND(&set->cs_mask, &parent->cs_mask);
303         set->cs_id = id;
304         set->cs_parent = cpuset_ref(parent);
305         LIST_INSERT_HEAD(&parent->cs_children, set, cs_siblings);
306         if (set->cs_id != CPUSET_INVALID)
307                 LIST_INSERT_HEAD(&cpuset_ids, set, cs_link);
308         mtx_unlock_spin(&cpuset_lock);
309
310         return (0);
311 }
312
313 /*
314  * Create a new non-anonymous set with the requested parent and mask.  May
315  * return failures if the mask is invalid or a new number can not be
316  * allocated.
317  */
318 static int
319 cpuset_create(struct cpuset **setp, struct cpuset *parent, const cpuset_t *mask)
320 {
321         struct cpuset *set;
322         cpusetid_t id;
323         int error;
324
325         id = alloc_unr(cpuset_unr);
326         if (id == -1)
327                 return (ENFILE);
328         *setp = set = uma_zalloc(cpuset_zone, M_WAITOK | M_ZERO);
329         error = _cpuset_create(set, parent, mask, NULL, id);
330         if (error == 0)
331                 return (0);
332         free_unr(cpuset_unr, id);
333         uma_zfree(cpuset_zone, set);
334
335         return (error);
336 }
337
338 static void
339 cpuset_freelist_add(struct setlist *list, int count)
340 {
341         struct cpuset *set;
342         int i;
343
344         for (i = 0; i < count; i++) {
345                 set = uma_zalloc(cpuset_zone, M_ZERO | M_WAITOK);
346                 LIST_INSERT_HEAD(list, set, cs_link);
347         }
348 }
349
350 static void
351 cpuset_freelist_init(struct setlist *list, int count)
352 {
353
354         LIST_INIT(list);
355         cpuset_freelist_add(list, count);
356 }
357
358 static void
359 cpuset_freelist_free(struct setlist *list)
360 {
361         struct cpuset *set;
362
363         while ((set = LIST_FIRST(list)) != NULL) {
364                 LIST_REMOVE(set, cs_link);
365                 uma_zfree(cpuset_zone, set);
366         }
367 }
368
369 static void
370 domainset_freelist_add(struct domainlist *list, int count)
371 {
372         struct domainset *set;
373         int i;
374
375         for (i = 0; i < count; i++) {
376                 set = uma_zalloc(domainset_zone, M_ZERO | M_WAITOK);
377                 LIST_INSERT_HEAD(list, set, ds_link);
378         }
379 }
380
381 static void
382 domainset_freelist_init(struct domainlist *list, int count)
383 {
384
385         LIST_INIT(list);
386         domainset_freelist_add(list, count);
387 }
388
389 static void
390 domainset_freelist_free(struct domainlist *list)
391 {
392         struct domainset *set;
393
394         while ((set = LIST_FIRST(list)) != NULL) {
395                 LIST_REMOVE(set, ds_link);
396                 uma_zfree(domainset_zone, set);
397         }
398 }
399
400 /* Copy a domainset preserving mask and policy. */
401 static void
402 domainset_copy(const struct domainset *from, struct domainset *to)
403 {
404
405         DOMAINSET_COPY(&from->ds_mask, &to->ds_mask);
406         to->ds_policy = from->ds_policy;
407         to->ds_prefer = from->ds_prefer;
408 }
409
410 /* Return 1 if mask and policy are equal, otherwise 0. */
411 static int
412 domainset_equal(const struct domainset *one, const struct domainset *two)
413 {
414
415         return (DOMAINSET_CMP(&one->ds_mask, &two->ds_mask) == 0 &&
416             one->ds_policy == two->ds_policy &&
417             one->ds_prefer == two->ds_prefer);
418 }
419
420 /* Return 1 if child is a valid subset of parent. */
421 static int
422 domainset_valid(const struct domainset *parent, const struct domainset *child)
423 {
424         if (child->ds_policy != DOMAINSET_POLICY_PREFER)
425                 return (DOMAINSET_SUBSET(&parent->ds_mask, &child->ds_mask));
426         return (DOMAINSET_ISSET(child->ds_prefer, &parent->ds_mask));
427 }
428
429 static int
430 domainset_restrict(const struct domainset *parent,
431     const struct domainset *child)
432 {
433         if (child->ds_policy != DOMAINSET_POLICY_PREFER)
434                 return (DOMAINSET_OVERLAP(&parent->ds_mask, &child->ds_mask));
435         return (DOMAINSET_ISSET(child->ds_prefer, &parent->ds_mask));
436 }
437
438 /*
439  * Lookup or create a domainset.  The key is provided in ds_mask and
440  * ds_policy.  If the domainset does not yet exist the storage in
441  * 'domain' is used to insert.  Otherwise this storage is freed to the
442  * domainset_zone and the existing domainset is returned.
443  */
444 static struct domainset *
445 _domainset_create(struct domainset *domain, struct domainlist *freelist)
446 {
447         struct domainset *ndomain;
448
449         mtx_lock_spin(&cpuset_lock);
450         LIST_FOREACH(ndomain, &cpuset_domains, ds_link)
451                 if (domainset_equal(ndomain, domain))
452                         break;
453         /*
454          * If the domain does not yet exist we insert it and initialize
455          * various iteration helpers which are not part of the key.
456          */
457         if (ndomain == NULL) {
458                 LIST_INSERT_HEAD(&cpuset_domains, domain, ds_link);
459                 domain->ds_cnt = DOMAINSET_COUNT(&domain->ds_mask);
460                 domain->ds_max = DOMAINSET_FLS(&domain->ds_mask) + 1;
461         }
462         mtx_unlock_spin(&cpuset_lock);
463         if (ndomain == NULL)
464                 return (domain);
465         if (freelist != NULL)
466                 LIST_INSERT_HEAD(freelist, domain, ds_link);
467         else
468                 uma_zfree(domainset_zone, domain);
469         return (ndomain);
470         
471 }
472
473 /*
474  * Create or lookup a domainset based on the key held in 'domain'.
475  */
476 static struct domainset *
477 domainset_create(const struct domainset *domain)
478 {
479         struct domainset *ndomain;
480
481         ndomain = uma_zalloc(domainset_zone, M_WAITOK | M_ZERO);
482         domainset_copy(domain, ndomain);
483         return _domainset_create(ndomain, NULL);
484 }
485
486 /*
487  * Update thread domainset pointers.
488  */
489 static void
490 domainset_notify(void)
491 {
492         struct thread *td;
493         struct proc *p;
494
495         sx_slock(&allproc_lock);
496         FOREACH_PROC_IN_SYSTEM(p) {
497                 PROC_LOCK(p);
498                 if (p->p_state == PRS_NEW) {
499                         PROC_UNLOCK(p);
500                         continue;
501                 }
502                 FOREACH_THREAD_IN_PROC(p, td) {
503                         thread_lock(td);
504                         td->td_domain.dr_policy = td->td_cpuset->cs_domain;
505                         thread_unlock(td);
506                 }
507                 PROC_UNLOCK(p);
508         }
509         sx_sunlock(&allproc_lock);
510         kernel_object->domain.dr_policy = cpuset_default->cs_domain;
511 }
512
513 /*
514  * Create a new set that is a subset of a parent.
515  */
516 static struct domainset *
517 domainset_shadow(const struct domainset *pdomain,
518     const struct domainset *domain, struct domainlist *freelist)
519 {
520         struct domainset *ndomain;
521
522         ndomain = LIST_FIRST(freelist);
523         LIST_REMOVE(ndomain, ds_link);
524
525         /*
526          * Initialize the key from the request.
527          */
528         domainset_copy(domain, ndomain);
529
530         /*
531          * Restrict the key by the parent.
532          */
533         DOMAINSET_AND(&ndomain->ds_mask, &pdomain->ds_mask);
534
535         return _domainset_create(ndomain, freelist);
536 }
537
538 /*
539  * Recursively check for errors that would occur from applying mask to
540  * the tree of sets starting at 'set'.  Checks for sets that would become
541  * empty as well as RDONLY flags.
542  */
543 static int
544 cpuset_testupdate(struct cpuset *set, cpuset_t *mask, int check_mask)
545 {
546         struct cpuset *nset;
547         cpuset_t newmask;
548         int error;
549
550         mtx_assert(&cpuset_lock, MA_OWNED);
551         if (set->cs_flags & CPU_SET_RDONLY)
552                 return (EPERM);
553         if (check_mask) {
554                 if (!CPU_OVERLAP(&set->cs_mask, mask))
555                         return (EDEADLK);
556                 CPU_COPY(&set->cs_mask, &newmask);
557                 CPU_AND(&newmask, mask);
558         } else
559                 CPU_COPY(mask, &newmask);
560         error = 0;
561         LIST_FOREACH(nset, &set->cs_children, cs_siblings) 
562                 if ((error = cpuset_testupdate(nset, &newmask, 1)) != 0)
563                         break;
564         return (error);
565 }
566
567 /*
568  * Applies the mask 'mask' without checking for empty sets or permissions.
569  */
570 static void
571 cpuset_update(struct cpuset *set, cpuset_t *mask)
572 {
573         struct cpuset *nset;
574
575         mtx_assert(&cpuset_lock, MA_OWNED);
576         CPU_AND(&set->cs_mask, mask);
577         LIST_FOREACH(nset, &set->cs_children, cs_siblings) 
578                 cpuset_update(nset, &set->cs_mask);
579
580         return;
581 }
582
583 /*
584  * Modify the set 'set' to use a copy of the mask provided.  Apply this new
585  * mask to restrict all children in the tree.  Checks for validity before
586  * applying the changes.
587  */
588 static int
589 cpuset_modify(struct cpuset *set, cpuset_t *mask)
590 {
591         struct cpuset *root;
592         int error;
593
594         error = priv_check(curthread, PRIV_SCHED_CPUSET);
595         if (error)
596                 return (error);
597         /*
598          * In case we are called from within the jail
599          * we do not allow modifying the dedicated root
600          * cpuset of the jail but may still allow to
601          * change child sets.
602          */
603         if (jailed(curthread->td_ucred) &&
604             set->cs_flags & CPU_SET_ROOT)
605                 return (EPERM);
606         /*
607          * Verify that we have access to this set of
608          * cpus.
609          */
610         root = cpuset_getroot(set);
611         mtx_lock_spin(&cpuset_lock);
612         if (root && !CPU_SUBSET(&root->cs_mask, mask)) {
613                 error = EINVAL;
614                 goto out;
615         }
616         error = cpuset_testupdate(set, mask, 0);
617         if (error)
618                 goto out;
619         CPU_COPY(mask, &set->cs_mask);
620         cpuset_update(set, mask);
621 out:
622         mtx_unlock_spin(&cpuset_lock);
623
624         return (error);
625 }
626
627 /*
628  * Recursively check for errors that would occur from applying mask to
629  * the tree of sets starting at 'set'.  Checks for sets that would become
630  * empty as well as RDONLY flags.
631  */
632 static int
633 cpuset_testupdate_domain(struct cpuset *set, struct domainset *dset,
634     struct domainset *orig, int *count, int check_mask)
635 {
636         struct cpuset *nset;
637         struct domainset *domain;
638         struct domainset newset;
639         int error;
640
641         mtx_assert(&cpuset_lock, MA_OWNED);
642         if (set->cs_flags & CPU_SET_RDONLY)
643                 return (EPERM);
644         domain = set->cs_domain;
645         domainset_copy(domain, &newset);
646         if (!domainset_equal(domain, orig)) {
647                 if (!domainset_restrict(domain, dset))
648                         return (EDEADLK);
649                 DOMAINSET_AND(&newset.ds_mask, &dset->ds_mask);
650                 /* Count the number of domains that are changing. */
651                 (*count)++;
652         }
653         error = 0;
654         LIST_FOREACH(nset, &set->cs_children, cs_siblings) 
655                 if ((error = cpuset_testupdate_domain(nset, &newset, domain,
656                     count, 1)) != 0)
657                         break;
658         return (error);
659 }
660
661 /*
662  * Applies the mask 'mask' without checking for empty sets or permissions.
663  */
664 static void
665 cpuset_update_domain(struct cpuset *set, struct domainset *domain,
666     struct domainset *orig, struct domainlist *domains)
667 {
668         struct cpuset *nset;
669
670         mtx_assert(&cpuset_lock, MA_OWNED);
671         /*
672          * If this domainset has changed from the parent we must calculate
673          * a new set.  Otherwise it simply inherits from the parent.  When
674          * we inherit from the parent we get a new mask and policy.  If the
675          * set is modified from the parent we keep the policy and only
676          * update the mask.
677          */
678         if (set->cs_domain != orig) {
679                 orig = set->cs_domain;
680                 set->cs_domain = domainset_shadow(domain, orig, domains);
681         } else
682                 set->cs_domain = domain;
683         LIST_FOREACH(nset, &set->cs_children, cs_siblings) 
684                 cpuset_update_domain(nset, set->cs_domain, orig, domains);
685
686         return;
687 }
688
689 /*
690  * Modify the set 'set' to use a copy the domainset provided.  Apply this new
691  * mask to restrict all children in the tree.  Checks for validity before
692  * applying the changes.
693  */
694 static int
695 cpuset_modify_domain(struct cpuset *set, struct domainset *domain)
696 {
697         struct domainlist domains;
698         struct domainset temp;
699         struct domainset *dset;
700         struct cpuset *root;
701         int ndomains, needed;
702         int error;
703
704         error = priv_check(curthread, PRIV_SCHED_CPUSET);
705         if (error)
706                 return (error);
707         /*
708          * In case we are called from within the jail
709          * we do not allow modifying the dedicated root
710          * cpuset of the jail but may still allow to
711          * change child sets.
712          */
713         if (jailed(curthread->td_ucred) &&
714             set->cs_flags & CPU_SET_ROOT)
715                 return (EPERM);
716         domainset_freelist_init(&domains, 0);
717         domain = domainset_create(domain);
718         ndomains = needed = 0;
719         do {
720                 if (ndomains < needed) {
721                         domainset_freelist_add(&domains, needed - ndomains);
722                         ndomains = needed;
723                 }
724                 root = cpuset_getroot(set);
725                 mtx_lock_spin(&cpuset_lock);
726                 dset = root->cs_domain;
727                 /*
728                  * Verify that we have access to this set of domains.
729                  */
730                 if (root && !domainset_valid(dset, domain)) {
731                         error = EINVAL;
732                         goto out;
733                 }
734                 /*
735                  * If applying prefer we keep the current set as the fallback.
736                  */
737                 if (domain->ds_policy == DOMAINSET_POLICY_PREFER)
738                         DOMAINSET_COPY(&set->cs_domain->ds_mask,
739                             &domain->ds_mask);
740                 /*
741                  * Determine whether we can apply this set of domains and
742                  * how many new domain structures it will require.
743                  */
744                 domainset_copy(domain, &temp);
745                 needed = 0;
746                 error = cpuset_testupdate_domain(set, &temp, set->cs_domain,
747                     &needed, 0);
748                 if (error)
749                         goto out;
750         } while (ndomains < needed);
751         dset = set->cs_domain;
752         cpuset_update_domain(set, domain, dset, &domains);
753 out:
754         mtx_unlock_spin(&cpuset_lock);
755         domainset_freelist_free(&domains);
756         if (error == 0)
757                 domainset_notify();
758
759         return (error);
760 }
761
762 /*
763  * Resolve the 'which' parameter of several cpuset apis.
764  *
765  * For WHICH_PID and WHICH_TID return a locked proc and valid proc/tid.  Also
766  * checks for permission via p_cansched().
767  *
768  * For WHICH_SET returns a valid set with a new reference.
769  *
770  * -1 may be supplied for any argument to mean the current proc/thread or
771  * the base set of the current thread.  May fail with ESRCH/EPERM.
772  */
773 int
774 cpuset_which(cpuwhich_t which, id_t id, struct proc **pp, struct thread **tdp,
775     struct cpuset **setp)
776 {
777         struct cpuset *set;
778         struct thread *td;
779         struct proc *p;
780         int error;
781
782         *pp = p = NULL;
783         *tdp = td = NULL;
784         *setp = set = NULL;
785         switch (which) {
786         case CPU_WHICH_PID:
787                 if (id == -1) {
788                         PROC_LOCK(curproc);
789                         p = curproc;
790                         break;
791                 }
792                 if ((p = pfind(id)) == NULL)
793                         return (ESRCH);
794                 break;
795         case CPU_WHICH_TID:
796                 if (id == -1) {
797                         PROC_LOCK(curproc);
798                         p = curproc;
799                         td = curthread;
800                         break;
801                 }
802                 td = tdfind(id, -1);
803                 if (td == NULL)
804                         return (ESRCH);
805                 p = td->td_proc;
806                 break;
807         case CPU_WHICH_CPUSET:
808                 if (id == -1) {
809                         thread_lock(curthread);
810                         set = cpuset_refbase(curthread->td_cpuset);
811                         thread_unlock(curthread);
812                 } else
813                         set = cpuset_lookup(id, curthread);
814                 if (set) {
815                         *setp = set;
816                         return (0);
817                 }
818                 return (ESRCH);
819         case CPU_WHICH_JAIL:
820         {
821                 /* Find `set' for prison with given id. */
822                 struct prison *pr;
823
824                 sx_slock(&allprison_lock);
825                 pr = prison_find_child(curthread->td_ucred->cr_prison, id);
826                 sx_sunlock(&allprison_lock);
827                 if (pr == NULL)
828                         return (ESRCH);
829                 cpuset_ref(pr->pr_cpuset);
830                 *setp = pr->pr_cpuset;
831                 mtx_unlock(&pr->pr_mtx);
832                 return (0);
833         }
834         case CPU_WHICH_IRQ:
835         case CPU_WHICH_DOMAIN:
836                 return (0);
837         default:
838                 return (EINVAL);
839         }
840         error = p_cansched(curthread, p);
841         if (error) {
842                 PROC_UNLOCK(p);
843                 return (error);
844         }
845         if (td == NULL)
846                 td = FIRST_THREAD_IN_PROC(p);
847         *pp = p;
848         *tdp = td;
849         return (0);
850 }
851
852 static int
853 cpuset_testshadow(struct cpuset *set, const cpuset_t *mask,
854     const struct domainset *domain)
855 {
856         struct cpuset *parent;
857         struct domainset *dset;
858
859         parent = cpuset_getbase(set);
860         /*
861          * If we are restricting a cpu mask it must be a subset of the
862          * parent or invalid CPUs have been specified.
863          */
864         if (mask != NULL && !CPU_SUBSET(&parent->cs_mask, mask))
865                 return (EINVAL);
866
867         /*
868          * If we are restricting a domain mask it must be a subset of the
869          * parent or invalid domains have been specified.
870          */
871         dset = parent->cs_domain;
872         if (domain != NULL && !domainset_valid(dset, domain))
873                 return (EINVAL);
874
875         return (0);
876 }
877
878 /*
879  * Create an anonymous set with the provided mask in the space provided by
880  * 'nset'.  If the passed in set is anonymous we use its parent otherwise
881  * the new set is a child of 'set'.
882  */
883 static int
884 cpuset_shadow(struct cpuset *set, struct cpuset **nsetp,
885    const cpuset_t *mask, const struct domainset *domain,
886    struct setlist *cpusets, struct domainlist *domains)
887 {
888         struct cpuset *parent;
889         struct cpuset *nset;
890         struct domainset *dset;
891         struct domainset *d;
892         int error;
893
894         error = cpuset_testshadow(set, mask, domain);
895         if (error)
896                 return (error);
897
898         parent = cpuset_getbase(set);
899         dset = parent->cs_domain;
900         if (mask == NULL)
901                 mask = &set->cs_mask;
902         if (domain != NULL)
903                 d = domainset_shadow(dset, domain, domains);
904         else
905                 d = set->cs_domain;
906         nset = LIST_FIRST(cpusets);
907         error = _cpuset_create(nset, parent, mask, d, CPUSET_INVALID);
908         if (error == 0) {
909                 LIST_REMOVE(nset, cs_link);
910                 *nsetp = nset;
911         }
912         return (error);
913 }
914
915 static struct cpuset *
916 cpuset_update_thread(struct thread *td, struct cpuset *nset)
917 {
918         struct cpuset *tdset;
919
920         tdset = td->td_cpuset;
921         td->td_cpuset = nset;
922         td->td_domain.dr_policy = nset->cs_domain;
923         sched_affinity(td);
924
925         return (tdset);
926 }
927
928 static int
929 cpuset_setproc_test_maskthread(struct cpuset *tdset, cpuset_t *mask,
930     struct domainset *domain)
931 {
932         struct cpuset *parent;
933
934         parent = cpuset_getbase(tdset);
935         if (mask == NULL)
936                 mask = &tdset->cs_mask;
937         if (domain == NULL)
938                 domain = tdset->cs_domain;
939         return cpuset_testshadow(parent, mask, domain);
940 }
941
942 static int
943 cpuset_setproc_maskthread(struct cpuset *tdset, cpuset_t *mask,
944     struct domainset *domain, struct cpuset **nsetp,
945     struct setlist *freelist, struct domainlist *domainlist)
946 {
947         struct cpuset *parent;
948
949         parent = cpuset_getbase(tdset);
950         if (mask == NULL)
951                 mask = &tdset->cs_mask;
952         if (domain == NULL)
953                 domain = tdset->cs_domain;
954         return cpuset_shadow(parent, nsetp, mask, domain, freelist,
955             domainlist);
956 }
957
958 static int
959 cpuset_setproc_setthread_mask(struct cpuset *tdset, struct cpuset *set,
960     cpuset_t *mask, struct domainset *domain)
961 {
962         struct cpuset *parent;
963
964         parent = cpuset_getbase(tdset);
965
966         /*
967          * If the thread restricted its mask then apply that same
968          * restriction to the new set, otherwise take it wholesale.
969          */
970         if (CPU_CMP(&tdset->cs_mask, &parent->cs_mask) != 0) {
971                 CPU_COPY(&tdset->cs_mask, mask);
972                 CPU_AND(mask, &set->cs_mask);
973         } else
974                 CPU_COPY(&set->cs_mask, mask);
975
976         /*
977          * If the thread restricted the domain then we apply the
978          * restriction to the new set but retain the policy.
979          */
980         if (tdset->cs_domain != parent->cs_domain) {
981                 domainset_copy(tdset->cs_domain, domain);
982                 DOMAINSET_AND(&domain->ds_mask, &set->cs_domain->ds_mask);
983         } else
984                 domainset_copy(set->cs_domain, domain);
985
986         if (CPU_EMPTY(mask) || DOMAINSET_EMPTY(&domain->ds_mask))
987                 return (EDEADLK);
988
989         return (0);
990 }
991
992 static int
993 cpuset_setproc_test_setthread(struct cpuset *tdset, struct cpuset *set)
994 {
995         struct domainset domain;
996         cpuset_t mask;
997
998         if (tdset->cs_id != CPUSET_INVALID)
999                 return (0);
1000         return cpuset_setproc_setthread_mask(tdset, set, &mask, &domain);
1001 }
1002
1003 static int
1004 cpuset_setproc_setthread(struct cpuset *tdset, struct cpuset *set,
1005     struct cpuset **nsetp, struct setlist *freelist,
1006     struct domainlist *domainlist)
1007 {
1008         struct domainset domain;
1009         cpuset_t mask;
1010         int error;
1011
1012         /*
1013          * If we're replacing on a thread that has not constrained the
1014          * original set we can simply accept the new set.
1015          */
1016         if (tdset->cs_id != CPUSET_INVALID) {
1017                 *nsetp = cpuset_ref(set);
1018                 return (0);
1019         }
1020         error = cpuset_setproc_setthread_mask(tdset, set, &mask, &domain);
1021         if (error)
1022                 return (error);
1023
1024         return cpuset_shadow(tdset, nsetp, &mask, &domain, freelist,
1025             domainlist);
1026 }
1027
1028 /*
1029  * Handle three cases for updating an entire process.
1030  *
1031  * 1) Set is non-null.  This reparents all anonymous sets to the provided
1032  *    set and replaces all non-anonymous td_cpusets with the provided set.
1033  * 2) Mask is non-null.  This replaces or creates anonymous sets for every
1034  *    thread with the existing base as a parent.
1035  * 3) domain is non-null.  This creates anonymous sets for every thread
1036  *    and replaces the domain set.
1037  *
1038  * This is overly complicated because we can't allocate while holding a 
1039  * spinlock and spinlocks must be held while changing and examining thread
1040  * state.
1041  */
1042 static int
1043 cpuset_setproc(pid_t pid, struct cpuset *set, cpuset_t *mask,
1044     struct domainset *domain)
1045 {
1046         struct setlist freelist;
1047         struct setlist droplist;
1048         struct domainlist domainlist;
1049         struct cpuset *nset;
1050         struct thread *td;
1051         struct proc *p;
1052         int threads;
1053         int nfree;
1054         int error;
1055
1056         /*
1057          * The algorithm requires two passes due to locking considerations.
1058          * 
1059          * 1) Lookup the process and acquire the locks in the required order.
1060          * 2) If enough cpusets have not been allocated release the locks and
1061          *    allocate them.  Loop.
1062          */
1063         cpuset_freelist_init(&freelist, 1);
1064         domainset_freelist_init(&domainlist, 1);
1065         nfree = 1;
1066         LIST_INIT(&droplist);
1067         nfree = 0;
1068         for (;;) {
1069                 error = cpuset_which(CPU_WHICH_PID, pid, &p, &td, &nset);
1070                 if (error)
1071                         goto out;
1072                 if (nfree >= p->p_numthreads)
1073                         break;
1074                 threads = p->p_numthreads;
1075                 PROC_UNLOCK(p);
1076                 if (nfree < threads) {
1077                         cpuset_freelist_add(&freelist, threads - nfree);
1078                         domainset_freelist_add(&domainlist, threads - nfree);
1079                         nfree = threads;
1080                 }
1081         }
1082         PROC_LOCK_ASSERT(p, MA_OWNED);
1083         /*
1084          * Now that the appropriate locks are held and we have enough cpusets,
1085          * make sure the operation will succeed before applying changes. The
1086          * proc lock prevents td_cpuset from changing between calls.
1087          */
1088         error = 0;
1089         FOREACH_THREAD_IN_PROC(p, td) {
1090                 thread_lock(td);
1091                 if (set != NULL)
1092                         error = cpuset_setproc_test_setthread(td->td_cpuset,
1093                             set);
1094                 else
1095                         error = cpuset_setproc_test_maskthread(td->td_cpuset,
1096                             mask, domain);
1097                 thread_unlock(td);
1098                 if (error)
1099                         goto unlock_out;
1100         }
1101         /*
1102          * Replace each thread's cpuset while using deferred release.  We
1103          * must do this because the thread lock must be held while operating
1104          * on the thread and this limits the type of operations allowed.
1105          */
1106         FOREACH_THREAD_IN_PROC(p, td) {
1107                 thread_lock(td);
1108                 if (set != NULL)
1109                         error = cpuset_setproc_setthread(td->td_cpuset, set,
1110                             &nset, &freelist, &domainlist);
1111                 else
1112                         error = cpuset_setproc_maskthread(td->td_cpuset, mask,
1113                             domain, &nset, &freelist, &domainlist);
1114                 if (error) {
1115                         thread_unlock(td);
1116                         break;
1117                 }
1118                 cpuset_rel_defer(&droplist, cpuset_update_thread(td, nset));
1119                 thread_unlock(td);
1120         }
1121 unlock_out:
1122         PROC_UNLOCK(p);
1123 out:
1124         while ((nset = LIST_FIRST(&droplist)) != NULL)
1125                 cpuset_rel_complete(nset);
1126         cpuset_freelist_free(&freelist);
1127         domainset_freelist_free(&domainlist);
1128         return (error);
1129 }
1130
1131 /*
1132  * Return a string representing a valid layout for a cpuset_t object.
1133  * It expects an incoming buffer at least sized as CPUSETBUFSIZ.
1134  */
1135 char *
1136 cpusetobj_strprint(char *buf, const cpuset_t *set)
1137 {
1138         char *tbuf;
1139         size_t i, bytesp, bufsiz;
1140
1141         tbuf = buf;
1142         bytesp = 0;
1143         bufsiz = CPUSETBUFSIZ;
1144
1145         for (i = 0; i < (_NCPUWORDS - 1); i++) {
1146                 bytesp = snprintf(tbuf, bufsiz, "%lx,", set->__bits[i]);
1147                 bufsiz -= bytesp;
1148                 tbuf += bytesp;
1149         }
1150         snprintf(tbuf, bufsiz, "%lx", set->__bits[_NCPUWORDS - 1]);
1151         return (buf);
1152 }
1153
1154 /*
1155  * Build a valid cpuset_t object from a string representation.
1156  * It expects an incoming buffer at least sized as CPUSETBUFSIZ.
1157  */
1158 int
1159 cpusetobj_strscan(cpuset_t *set, const char *buf)
1160 {
1161         u_int nwords;
1162         int i, ret;
1163
1164         if (strlen(buf) > CPUSETBUFSIZ - 1)
1165                 return (-1);
1166
1167         /* Allow to pass a shorter version of the mask when necessary. */
1168         nwords = 1;
1169         for (i = 0; buf[i] != '\0'; i++)
1170                 if (buf[i] == ',')
1171                         nwords++;
1172         if (nwords > _NCPUWORDS)
1173                 return (-1);
1174
1175         CPU_ZERO(set);
1176         for (i = 0; i < (nwords - 1); i++) {
1177                 ret = sscanf(buf, "%lx,", &set->__bits[i]);
1178                 if (ret == 0 || ret == -1)
1179                         return (-1);
1180                 buf = strstr(buf, ",");
1181                 if (buf == NULL)
1182                         return (-1);
1183                 buf++;
1184         }
1185         ret = sscanf(buf, "%lx", &set->__bits[nwords - 1]);
1186         if (ret == 0 || ret == -1)
1187                 return (-1);
1188         return (0);
1189 }
1190
1191 /*
1192  * Apply an anonymous mask or a domain to a single thread.
1193  */
1194 static int
1195 _cpuset_setthread(lwpid_t id, cpuset_t *mask, struct domainset *domain)
1196 {
1197         struct setlist cpusets;
1198         struct domainlist domainlist;
1199         struct cpuset *nset;
1200         struct cpuset *set;
1201         struct thread *td;
1202         struct proc *p;
1203         int error;
1204
1205         cpuset_freelist_init(&cpusets, 1);
1206         domainset_freelist_init(&domainlist, domain != NULL);
1207         error = cpuset_which(CPU_WHICH_TID, id, &p, &td, &set);
1208         if (error)
1209                 goto out;
1210         set = NULL;
1211         thread_lock(td);
1212         error = cpuset_shadow(td->td_cpuset, &nset, mask, domain,
1213             &cpusets, &domainlist);
1214         if (error == 0)
1215                 set = cpuset_update_thread(td, nset);
1216         thread_unlock(td);
1217         PROC_UNLOCK(p);
1218         if (set)
1219                 cpuset_rel(set);
1220 out:
1221         cpuset_freelist_free(&cpusets);
1222         domainset_freelist_free(&domainlist);
1223         return (error);
1224 }
1225
1226 /*
1227  * Apply an anonymous mask to a single thread.
1228  */
1229 int
1230 cpuset_setthread(lwpid_t id, cpuset_t *mask)
1231 {
1232
1233         return _cpuset_setthread(id, mask, NULL);
1234 }
1235
1236 /*
1237  * Apply new cpumask to the ithread.
1238  */
1239 int
1240 cpuset_setithread(lwpid_t id, int cpu)
1241 {
1242         struct setlist cpusets;
1243         struct cpuset *nset, *rset;
1244         struct cpuset *parent, *old_set;
1245         struct thread *td;
1246         struct proc *p;
1247         cpusetid_t cs_id;
1248         cpuset_t mask;
1249         int error;
1250
1251         cpuset_freelist_init(&cpusets, 1);
1252         rset = uma_zalloc(cpuset_zone, M_WAITOK | M_ZERO);
1253         cs_id = CPUSET_INVALID;
1254
1255         CPU_ZERO(&mask);
1256         if (cpu == NOCPU)
1257                 CPU_COPY(cpuset_root, &mask);
1258         else
1259                 CPU_SET(cpu, &mask);
1260
1261         error = cpuset_which(CPU_WHICH_TID, id, &p, &td, &old_set);
1262         if (error != 0 || ((cs_id = alloc_unr(cpuset_unr)) == CPUSET_INVALID))
1263                 goto out;
1264
1265         /* cpuset_which() returns with PROC_LOCK held. */
1266         old_set = td->td_cpuset;
1267
1268         if (cpu == NOCPU) {
1269                 nset = LIST_FIRST(&cpusets);
1270                 LIST_REMOVE(nset, cs_link);
1271
1272                 /*
1273                  * roll back to default set. We're not using cpuset_shadow()
1274                  * here because we can fail CPU_SUBSET() check. This can happen
1275                  * if default set does not contain all CPUs.
1276                  */
1277                 error = _cpuset_create(nset, cpuset_default, &mask, NULL,
1278                     CPUSET_INVALID);
1279
1280                 goto applyset;
1281         }
1282
1283         if (old_set->cs_id == 1 || (old_set->cs_id == CPUSET_INVALID &&
1284             old_set->cs_parent->cs_id == 1)) {
1285
1286                 /*
1287                  * Current set is either default (1) or
1288                  * shadowed version of default set.
1289                  *
1290                  * Allocate new root set to be able to shadow it
1291                  * with any mask.
1292                  */
1293                 error = _cpuset_create(rset, cpuset_zero,
1294                     &cpuset_zero->cs_mask, NULL, cs_id);
1295                 if (error != 0) {
1296                         PROC_UNLOCK(p);
1297                         goto out;
1298                 }
1299                 rset->cs_flags |= CPU_SET_ROOT;
1300                 parent = rset;
1301                 rset = NULL;
1302                 cs_id = CPUSET_INVALID;
1303         } else {
1304                 /* Assume existing set was already allocated by previous call */
1305                 parent = old_set;
1306                 old_set = NULL;
1307         }
1308
1309         error = cpuset_shadow(parent, &nset, &mask, NULL, &cpusets, NULL);
1310 applyset:
1311         if (error == 0) {
1312                 thread_lock(td);
1313                 old_set = cpuset_update_thread(td, nset);
1314                 thread_unlock(td);
1315         } else
1316                 old_set = NULL;
1317         PROC_UNLOCK(p);
1318         if (old_set != NULL)
1319                 cpuset_rel(old_set);
1320 out:
1321         cpuset_freelist_free(&cpusets);
1322         if (rset != NULL)
1323                 uma_zfree(cpuset_zone, rset);
1324         if (cs_id != CPUSET_INVALID)
1325                 free_unr(cpuset_unr, cs_id);
1326         return (error);
1327 }
1328
1329 static struct domainset domainset0;
1330
1331 void
1332 domainset_zero(void)
1333 {
1334         struct domainset *dset;
1335         int i;
1336
1337         mtx_init(&cpuset_lock, "cpuset", NULL, MTX_SPIN | MTX_RECURSE);
1338
1339         dset = &domainset0;
1340         DOMAINSET_ZERO(&dset->ds_mask);
1341         for (i = 0; i < vm_ndomains; i++)
1342                 DOMAINSET_SET(i, &dset->ds_mask);
1343         dset->ds_policy = DOMAINSET_POLICY_ROUNDROBIN;
1344         dset->ds_prefer = -1;
1345         curthread->td_domain.dr_policy = _domainset_create(dset, NULL);
1346         kernel_object->domain.dr_policy = curthread->td_domain.dr_policy;
1347 }
1348
1349 /*
1350  * Creates system-wide cpusets and the cpuset for thread0 including two
1351  * sets:
1352  * 
1353  * 0 - The root set which should represent all valid processors in the
1354  *     system.  It is initially created with a mask of all processors
1355  *     because we don't know what processors are valid until cpuset_init()
1356  *     runs.  This set is immutable.
1357  * 1 - The default set which all processes are a member of until changed.
1358  *     This allows an administrator to move all threads off of given cpus to
1359  *     dedicate them to high priority tasks or save power etc.
1360  */
1361 struct cpuset *
1362 cpuset_thread0(void)
1363 {
1364         struct cpuset *set;
1365         int error;
1366         int i;
1367
1368         cpuset_zone = uma_zcreate("cpuset", sizeof(struct cpuset), NULL, NULL,
1369             NULL, NULL, UMA_ALIGN_PTR, 0);
1370         domainset_zone = uma_zcreate("domainset", sizeof(struct domainset),
1371             NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
1372
1373         /*
1374          * Create the root system set for the whole machine.  Doesn't use
1375          * cpuset_create() due to NULL parent.
1376          */
1377         set = uma_zalloc(cpuset_zone, M_WAITOK | M_ZERO);
1378         CPU_COPY(&all_cpus, &set->cs_mask);
1379         LIST_INIT(&set->cs_children);
1380         LIST_INSERT_HEAD(&cpuset_ids, set, cs_link);
1381         set->cs_ref = 1;
1382         set->cs_flags = CPU_SET_ROOT | CPU_SET_RDONLY;
1383         set->cs_domain = &domainset0;
1384         cpuset_zero = set;
1385         cpuset_root = &set->cs_mask;
1386
1387         /*
1388          * Now derive a default, modifiable set from that to give out.
1389          */
1390         set = uma_zalloc(cpuset_zone, M_WAITOK | M_ZERO);
1391         error = _cpuset_create(set, cpuset_zero, NULL, NULL, 1);
1392         KASSERT(error == 0, ("Error creating default set: %d\n", error));
1393         cpuset_default = set;
1394
1395         /*
1396          * Initialize the unit allocator. 0 and 1 are allocated above.
1397          */
1398         cpuset_unr = new_unrhdr(2, INT_MAX, NULL);
1399
1400         /*
1401          * If MD code has not initialized per-domain cpusets, place all
1402          * CPUs in domain 0.
1403          */
1404         for (i = 0; i < MAXMEMDOM; i++)
1405                 if (!CPU_EMPTY(&cpuset_domain[i]))
1406                         goto domains_set;
1407         CPU_COPY(&all_cpus, &cpuset_domain[0]);
1408 domains_set:
1409
1410         return (set);
1411 }
1412
1413 /*
1414  * Create a cpuset, which would be cpuset_create() but
1415  * mark the new 'set' as root.
1416  *
1417  * We are not going to reparent the td to it.  Use cpuset_setproc_update_set()
1418  * for that.
1419  *
1420  * In case of no error, returns the set in *setp locked with a reference.
1421  */
1422 int
1423 cpuset_create_root(struct prison *pr, struct cpuset **setp)
1424 {
1425         struct cpuset *set;
1426         int error;
1427
1428         KASSERT(pr != NULL, ("[%s:%d] invalid pr", __func__, __LINE__));
1429         KASSERT(setp != NULL, ("[%s:%d] invalid setp", __func__, __LINE__));
1430
1431         error = cpuset_create(setp, pr->pr_cpuset, &pr->pr_cpuset->cs_mask);
1432         if (error)
1433                 return (error);
1434
1435         KASSERT(*setp != NULL, ("[%s:%d] cpuset_create returned invalid data",
1436             __func__, __LINE__));
1437
1438         /* Mark the set as root. */
1439         set = *setp;
1440         set->cs_flags |= CPU_SET_ROOT;
1441
1442         return (0);
1443 }
1444
1445 int
1446 cpuset_setproc_update_set(struct proc *p, struct cpuset *set)
1447 {
1448         int error;
1449
1450         KASSERT(p != NULL, ("[%s:%d] invalid proc", __func__, __LINE__));
1451         KASSERT(set != NULL, ("[%s:%d] invalid set", __func__, __LINE__));
1452
1453         cpuset_ref(set);
1454         error = cpuset_setproc(p->p_pid, set, NULL, NULL);
1455         if (error)
1456                 return (error);
1457         cpuset_rel(set);
1458         return (0);
1459 }
1460
1461 #ifndef _SYS_SYSPROTO_H_
1462 struct cpuset_args {
1463         cpusetid_t      *setid;
1464 };
1465 #endif
1466 int
1467 sys_cpuset(struct thread *td, struct cpuset_args *uap)
1468 {
1469         struct cpuset *root;
1470         struct cpuset *set;
1471         int error;
1472
1473         thread_lock(td);
1474         root = cpuset_refroot(td->td_cpuset);
1475         thread_unlock(td);
1476         error = cpuset_create(&set, root, &root->cs_mask);
1477         cpuset_rel(root);
1478         if (error)
1479                 return (error);
1480         error = copyout(&set->cs_id, uap->setid, sizeof(set->cs_id));
1481         if (error == 0)
1482                 error = cpuset_setproc(-1, set, NULL, NULL);
1483         cpuset_rel(set);
1484         return (error);
1485 }
1486
1487 #ifndef _SYS_SYSPROTO_H_
1488 struct cpuset_setid_args {
1489         cpuwhich_t      which;
1490         id_t            id;
1491         cpusetid_t      setid;
1492 };
1493 #endif
1494 int
1495 sys_cpuset_setid(struct thread *td, struct cpuset_setid_args *uap)
1496 {
1497
1498         return (kern_cpuset_setid(td, uap->which, uap->id, uap->setid));
1499 }
1500
1501 int
1502 kern_cpuset_setid(struct thread *td, cpuwhich_t which,
1503     id_t id, cpusetid_t setid)
1504 {
1505         struct cpuset *set;
1506         int error;
1507
1508         /*
1509          * Presently we only support per-process sets.
1510          */
1511         if (which != CPU_WHICH_PID)
1512                 return (EINVAL);
1513         set = cpuset_lookup(setid, td);
1514         if (set == NULL)
1515                 return (ESRCH);
1516         error = cpuset_setproc(id, set, NULL, NULL);
1517         cpuset_rel(set);
1518         return (error);
1519 }
1520
1521 #ifndef _SYS_SYSPROTO_H_
1522 struct cpuset_getid_args {
1523         cpulevel_t      level;
1524         cpuwhich_t      which;
1525         id_t            id;
1526         cpusetid_t      *setid;
1527 };
1528 #endif
1529 int
1530 sys_cpuset_getid(struct thread *td, struct cpuset_getid_args *uap)
1531 {
1532
1533         return (kern_cpuset_getid(td, uap->level, uap->which, uap->id,
1534             uap->setid));
1535 }
1536
1537 int
1538 kern_cpuset_getid(struct thread *td, cpulevel_t level, cpuwhich_t which,
1539     id_t id, cpusetid_t *setid)
1540 {
1541         struct cpuset *nset;
1542         struct cpuset *set;
1543         struct thread *ttd;
1544         struct proc *p;
1545         cpusetid_t tmpid;
1546         int error;
1547
1548         if (level == CPU_LEVEL_WHICH && which != CPU_WHICH_CPUSET)
1549                 return (EINVAL);
1550         error = cpuset_which(which, id, &p, &ttd, &set);
1551         if (error)
1552                 return (error);
1553         switch (which) {
1554         case CPU_WHICH_TID:
1555         case CPU_WHICH_PID:
1556                 thread_lock(ttd);
1557                 set = cpuset_refbase(ttd->td_cpuset);
1558                 thread_unlock(ttd);
1559                 PROC_UNLOCK(p);
1560                 break;
1561         case CPU_WHICH_CPUSET:
1562         case CPU_WHICH_JAIL:
1563                 break;
1564         case CPU_WHICH_IRQ:
1565         case CPU_WHICH_DOMAIN:
1566                 return (EINVAL);
1567         }
1568         switch (level) {
1569         case CPU_LEVEL_ROOT:
1570                 nset = cpuset_refroot(set);
1571                 cpuset_rel(set);
1572                 set = nset;
1573                 break;
1574         case CPU_LEVEL_CPUSET:
1575                 break;
1576         case CPU_LEVEL_WHICH:
1577                 break;
1578         }
1579         tmpid = set->cs_id;
1580         cpuset_rel(set);
1581         if (error == 0)
1582                 error = copyout(&tmpid, setid, sizeof(tmpid));
1583
1584         return (error);
1585 }
1586
1587 #ifndef _SYS_SYSPROTO_H_
1588 struct cpuset_getaffinity_args {
1589         cpulevel_t      level;
1590         cpuwhich_t      which;
1591         id_t            id;
1592         size_t          cpusetsize;
1593         cpuset_t        *mask;
1594 };
1595 #endif
1596 int
1597 sys_cpuset_getaffinity(struct thread *td, struct cpuset_getaffinity_args *uap)
1598 {
1599
1600         return (kern_cpuset_getaffinity(td, uap->level, uap->which,
1601             uap->id, uap->cpusetsize, uap->mask));
1602 }
1603
1604 int
1605 kern_cpuset_getaffinity(struct thread *td, cpulevel_t level, cpuwhich_t which,
1606     id_t id, size_t cpusetsize, cpuset_t *maskp)
1607 {
1608         struct thread *ttd;
1609         struct cpuset *nset;
1610         struct cpuset *set;
1611         struct proc *p;
1612         cpuset_t *mask;
1613         int error;
1614         size_t size;
1615
1616         if (cpusetsize < sizeof(cpuset_t) || cpusetsize > CPU_MAXSIZE / NBBY)
1617                 return (ERANGE);
1618         /* In Capability mode, you can only get your own CPU set. */
1619         if (IN_CAPABILITY_MODE(td)) {
1620                 if (level != CPU_LEVEL_WHICH)
1621                         return (ECAPMODE);
1622                 if (which != CPU_WHICH_TID && which != CPU_WHICH_PID)
1623                         return (ECAPMODE);
1624                 if (id != -1)
1625                         return (ECAPMODE);
1626         }
1627         size = cpusetsize;
1628         mask = malloc(size, M_TEMP, M_WAITOK | M_ZERO);
1629         error = cpuset_which(which, id, &p, &ttd, &set);
1630         if (error)
1631                 goto out;
1632         switch (level) {
1633         case CPU_LEVEL_ROOT:
1634         case CPU_LEVEL_CPUSET:
1635                 switch (which) {
1636                 case CPU_WHICH_TID:
1637                 case CPU_WHICH_PID:
1638                         thread_lock(ttd);
1639                         set = cpuset_ref(ttd->td_cpuset);
1640                         thread_unlock(ttd);
1641                         break;
1642                 case CPU_WHICH_CPUSET:
1643                 case CPU_WHICH_JAIL:
1644                         break;
1645                 case CPU_WHICH_IRQ:
1646                 case CPU_WHICH_INTRHANDLER:
1647                 case CPU_WHICH_ITHREAD:
1648                 case CPU_WHICH_DOMAIN:
1649                         error = EINVAL;
1650                         goto out;
1651                 }
1652                 if (level == CPU_LEVEL_ROOT)
1653                         nset = cpuset_refroot(set);
1654                 else
1655                         nset = cpuset_refbase(set);
1656                 CPU_COPY(&nset->cs_mask, mask);
1657                 cpuset_rel(nset);
1658                 break;
1659         case CPU_LEVEL_WHICH:
1660                 switch (which) {
1661                 case CPU_WHICH_TID:
1662                         thread_lock(ttd);
1663                         CPU_COPY(&ttd->td_cpuset->cs_mask, mask);
1664                         thread_unlock(ttd);
1665                         break;
1666                 case CPU_WHICH_PID:
1667                         FOREACH_THREAD_IN_PROC(p, ttd) {
1668                                 thread_lock(ttd);
1669                                 CPU_OR(mask, &ttd->td_cpuset->cs_mask);
1670                                 thread_unlock(ttd);
1671                         }
1672                         break;
1673                 case CPU_WHICH_CPUSET:
1674                 case CPU_WHICH_JAIL:
1675                         CPU_COPY(&set->cs_mask, mask);
1676                         break;
1677                 case CPU_WHICH_IRQ:
1678                 case CPU_WHICH_INTRHANDLER:
1679                 case CPU_WHICH_ITHREAD:
1680                         error = intr_getaffinity(id, which, mask);
1681                         break;
1682                 case CPU_WHICH_DOMAIN:
1683                         if (id < 0 || id >= MAXMEMDOM)
1684                                 error = ESRCH;
1685                         else
1686                                 CPU_COPY(&cpuset_domain[id], mask);
1687                         break;
1688                 }
1689                 break;
1690         default:
1691                 error = EINVAL;
1692                 break;
1693         }
1694         if (set)
1695                 cpuset_rel(set);
1696         if (p)
1697                 PROC_UNLOCK(p);
1698         if (error == 0)
1699                 error = copyout(mask, maskp, size);
1700 out:
1701         free(mask, M_TEMP);
1702         return (error);
1703 }
1704
1705 #ifndef _SYS_SYSPROTO_H_
1706 struct cpuset_setaffinity_args {
1707         cpulevel_t      level;
1708         cpuwhich_t      which;
1709         id_t            id;
1710         size_t          cpusetsize;
1711         const cpuset_t  *mask;
1712 };
1713 #endif
1714 int
1715 sys_cpuset_setaffinity(struct thread *td, struct cpuset_setaffinity_args *uap)
1716 {
1717
1718         return (kern_cpuset_setaffinity(td, uap->level, uap->which,
1719             uap->id, uap->cpusetsize, uap->mask));
1720 }
1721
1722 int
1723 kern_cpuset_setaffinity(struct thread *td, cpulevel_t level, cpuwhich_t which,
1724     id_t id, size_t cpusetsize, const cpuset_t *maskp)
1725 {
1726         struct cpuset *nset;
1727         struct cpuset *set;
1728         struct thread *ttd;
1729         struct proc *p;
1730         cpuset_t *mask;
1731         int error;
1732
1733         if (cpusetsize < sizeof(cpuset_t) || cpusetsize > CPU_MAXSIZE / NBBY)
1734                 return (ERANGE);
1735         /* In Capability mode, you can only set your own CPU set. */
1736         if (IN_CAPABILITY_MODE(td)) {
1737                 if (level != CPU_LEVEL_WHICH)
1738                         return (ECAPMODE);
1739                 if (which != CPU_WHICH_TID && which != CPU_WHICH_PID)
1740                         return (ECAPMODE);
1741                 if (id != -1)
1742                         return (ECAPMODE);
1743         }
1744         mask = malloc(cpusetsize, M_TEMP, M_WAITOK | M_ZERO);
1745         error = copyin(maskp, mask, cpusetsize);
1746         if (error)
1747                 goto out;
1748         /*
1749          * Verify that no high bits are set.
1750          */
1751         if (cpusetsize > sizeof(cpuset_t)) {
1752                 char *end;
1753                 char *cp;
1754
1755                 end = cp = (char *)&mask->__bits;
1756                 end += cpusetsize;
1757                 cp += sizeof(cpuset_t);
1758                 while (cp != end)
1759                         if (*cp++ != 0) {
1760                                 error = EINVAL;
1761                                 goto out;
1762                         }
1763
1764         }
1765         switch (level) {
1766         case CPU_LEVEL_ROOT:
1767         case CPU_LEVEL_CPUSET:
1768                 error = cpuset_which(which, id, &p, &ttd, &set);
1769                 if (error)
1770                         break;
1771                 switch (which) {
1772                 case CPU_WHICH_TID:
1773                 case CPU_WHICH_PID:
1774                         thread_lock(ttd);
1775                         set = cpuset_ref(ttd->td_cpuset);
1776                         thread_unlock(ttd);
1777                         PROC_UNLOCK(p);
1778                         break;
1779                 case CPU_WHICH_CPUSET:
1780                 case CPU_WHICH_JAIL:
1781                         break;
1782                 case CPU_WHICH_IRQ:
1783                 case CPU_WHICH_INTRHANDLER:
1784                 case CPU_WHICH_ITHREAD:
1785                 case CPU_WHICH_DOMAIN:
1786                         error = EINVAL;
1787                         goto out;
1788                 }
1789                 if (level == CPU_LEVEL_ROOT)
1790                         nset = cpuset_refroot(set);
1791                 else
1792                         nset = cpuset_refbase(set);
1793                 error = cpuset_modify(nset, mask);
1794                 cpuset_rel(nset);
1795                 cpuset_rel(set);
1796                 break;
1797         case CPU_LEVEL_WHICH:
1798                 switch (which) {
1799                 case CPU_WHICH_TID:
1800                         error = cpuset_setthread(id, mask);
1801                         break;
1802                 case CPU_WHICH_PID:
1803                         error = cpuset_setproc(id, NULL, mask, NULL);
1804                         break;
1805                 case CPU_WHICH_CPUSET:
1806                 case CPU_WHICH_JAIL:
1807                         error = cpuset_which(which, id, &p, &ttd, &set);
1808                         if (error == 0) {
1809                                 error = cpuset_modify(set, mask);
1810                                 cpuset_rel(set);
1811                         }
1812                         break;
1813                 case CPU_WHICH_IRQ:
1814                 case CPU_WHICH_INTRHANDLER:
1815                 case CPU_WHICH_ITHREAD:
1816                         error = intr_setaffinity(id, which, mask);
1817                         break;
1818                 default:
1819                         error = EINVAL;
1820                         break;
1821                 }
1822                 break;
1823         default:
1824                 error = EINVAL;
1825                 break;
1826         }
1827 out:
1828         free(mask, M_TEMP);
1829         return (error);
1830 }
1831
1832 #ifndef _SYS_SYSPROTO_H_
1833 struct cpuset_getdomain_args {
1834         cpulevel_t      level;
1835         cpuwhich_t      which;
1836         id_t            id;
1837         size_t          domainsetsize;
1838         domainset_t     *mask;
1839         int             *policy;
1840 };
1841 #endif
1842 int
1843 sys_cpuset_getdomain(struct thread *td, struct cpuset_getdomain_args *uap)
1844 {
1845
1846         return (kern_cpuset_getdomain(td, uap->level, uap->which,
1847             uap->id, uap->domainsetsize, uap->mask, uap->policy));
1848 }
1849
1850 int
1851 kern_cpuset_getdomain(struct thread *td, cpulevel_t level, cpuwhich_t which,
1852     id_t id, size_t domainsetsize, domainset_t *maskp, int *policyp)
1853 {
1854         struct domainset outset;
1855         struct thread *ttd;
1856         struct cpuset *nset;
1857         struct cpuset *set;
1858         struct domainset *dset;
1859         struct proc *p;
1860         domainset_t *mask;
1861         int error;
1862
1863         if (domainsetsize < sizeof(domainset_t) ||
1864             domainsetsize > DOMAINSET_MAXSIZE / NBBY)
1865                 return (ERANGE);
1866         /* In Capability mode, you can only get your own domain set. */
1867         if (IN_CAPABILITY_MODE(td)) {
1868                 if (level != CPU_LEVEL_WHICH)
1869                         return (ECAPMODE);
1870                 if (which != CPU_WHICH_TID && which != CPU_WHICH_PID)
1871                         return (ECAPMODE);
1872                 if (id != -1)
1873                         return (ECAPMODE);
1874         }
1875         mask = malloc(domainsetsize, M_TEMP, M_WAITOK | M_ZERO);
1876         bzero(&outset, sizeof(outset));
1877         error = cpuset_which(which, id, &p, &ttd, &set);
1878         if (error)
1879                 goto out;
1880         switch (level) {
1881         case CPU_LEVEL_ROOT:
1882         case CPU_LEVEL_CPUSET:
1883                 switch (which) {
1884                 case CPU_WHICH_TID:
1885                 case CPU_WHICH_PID:
1886                         thread_lock(ttd);
1887                         set = cpuset_ref(ttd->td_cpuset);
1888                         thread_unlock(ttd);
1889                         break;
1890                 case CPU_WHICH_CPUSET:
1891                 case CPU_WHICH_JAIL:
1892                         break;
1893                 case CPU_WHICH_IRQ:
1894                 case CPU_WHICH_INTRHANDLER:
1895                 case CPU_WHICH_ITHREAD:
1896                 case CPU_WHICH_DOMAIN:
1897                         error = EINVAL;
1898                         goto out;
1899                 }
1900                 if (level == CPU_LEVEL_ROOT)
1901                         nset = cpuset_refroot(set);
1902                 else
1903                         nset = cpuset_refbase(set);
1904                 domainset_copy(nset->cs_domain, &outset);
1905                 cpuset_rel(nset);
1906                 break;
1907         case CPU_LEVEL_WHICH:
1908                 switch (which) {
1909                 case CPU_WHICH_TID:
1910                         thread_lock(ttd);
1911                         domainset_copy(ttd->td_cpuset->cs_domain, &outset);
1912                         thread_unlock(ttd);
1913                         break;
1914                 case CPU_WHICH_PID:
1915                         FOREACH_THREAD_IN_PROC(p, ttd) {
1916                                 thread_lock(ttd);
1917                                 dset = ttd->td_cpuset->cs_domain;
1918                                 /* Show all domains in the proc. */
1919                                 DOMAINSET_OR(&outset.ds_mask, &dset->ds_mask);
1920                                 /* Last policy wins. */
1921                                 outset.ds_policy = dset->ds_policy;
1922                                 outset.ds_prefer = dset->ds_prefer;
1923                                 thread_unlock(ttd);
1924                         }
1925                         break;
1926                 case CPU_WHICH_CPUSET:
1927                 case CPU_WHICH_JAIL:
1928                         domainset_copy(set->cs_domain, &outset);
1929                         break;
1930                 case CPU_WHICH_IRQ:
1931                 case CPU_WHICH_INTRHANDLER:
1932                 case CPU_WHICH_ITHREAD:
1933                 case CPU_WHICH_DOMAIN:
1934                         error = EINVAL;
1935                         break;
1936                 }
1937                 break;
1938         default:
1939                 error = EINVAL;
1940                 break;
1941         }
1942         if (set)
1943                 cpuset_rel(set);
1944         if (p)
1945                 PROC_UNLOCK(p);
1946         /*
1947          * Translate prefer into a set containing only the preferred domain,
1948          * not the entire fallback set.
1949          */
1950         if (outset.ds_policy == DOMAINSET_POLICY_PREFER) {
1951                 DOMAINSET_ZERO(&outset.ds_mask);
1952                 DOMAINSET_SET(outset.ds_prefer, &outset.ds_mask);
1953         }
1954         DOMAINSET_COPY(&outset.ds_mask, mask);
1955         if (error == 0)
1956                 error = copyout(mask, maskp, domainsetsize);
1957         if (error == 0)
1958                 if (suword32(policyp, outset.ds_policy) != 0)
1959                         error = EFAULT;
1960 out:
1961         free(mask, M_TEMP);
1962         return (error);
1963 }
1964
1965 #ifndef _SYS_SYSPROTO_H_
1966 struct cpuset_setdomain_args {
1967         cpulevel_t      level;
1968         cpuwhich_t      which;
1969         id_t            id;
1970         size_t          domainsetsize;
1971         domainset_t     *mask;
1972         int             policy;
1973 };
1974 #endif
1975 int
1976 sys_cpuset_setdomain(struct thread *td, struct cpuset_setdomain_args *uap)
1977 {
1978
1979         return (kern_cpuset_setdomain(td, uap->level, uap->which,
1980             uap->id, uap->domainsetsize, uap->mask, uap->policy));
1981 }
1982
1983 int
1984 kern_cpuset_setdomain(struct thread *td, cpulevel_t level, cpuwhich_t which,
1985     id_t id, size_t domainsetsize, const domainset_t *maskp, int policy)
1986 {
1987         struct cpuset *nset;
1988         struct cpuset *set;
1989         struct thread *ttd;
1990         struct proc *p;
1991         struct domainset domain;
1992         domainset_t *mask;
1993         int error;
1994
1995         if (domainsetsize < sizeof(domainset_t) ||
1996             domainsetsize > DOMAINSET_MAXSIZE / NBBY)
1997                 return (ERANGE);
1998         /* In Capability mode, you can only set your own CPU set. */
1999         if (IN_CAPABILITY_MODE(td)) {
2000                 if (level != CPU_LEVEL_WHICH)
2001                         return (ECAPMODE);
2002                 if (which != CPU_WHICH_TID && which != CPU_WHICH_PID)
2003                         return (ECAPMODE);
2004                 if (id != -1)
2005                         return (ECAPMODE);
2006         }
2007         memset(&domain, 0, sizeof(domain));
2008         mask = malloc(domainsetsize, M_TEMP, M_WAITOK | M_ZERO);
2009         error = copyin(maskp, mask, domainsetsize);
2010         if (error)
2011                 goto out;
2012         /*
2013          * Verify that no high bits are set.
2014          */
2015         if (domainsetsize > sizeof(domainset_t)) {
2016                 char *end;
2017                 char *cp;
2018
2019                 end = cp = (char *)&mask->__bits;
2020                 end += domainsetsize;
2021                 cp += sizeof(domainset_t);
2022                 while (cp != end)
2023                         if (*cp++ != 0) {
2024                                 error = EINVAL;
2025                                 goto out;
2026                         }
2027
2028         }
2029         DOMAINSET_COPY(mask, &domain.ds_mask);
2030         domain.ds_policy = policy;
2031         if (policy <= DOMAINSET_POLICY_INVALID ||
2032             policy > DOMAINSET_POLICY_MAX)
2033                 return (EINVAL);
2034
2035         /* Translate preferred policy into a mask and fallback. */
2036         if (policy == DOMAINSET_POLICY_PREFER) {
2037                 /* Only support a single preferred domain. */
2038                 if (DOMAINSET_COUNT(&domain.ds_mask) != 1)
2039                         return (EINVAL);
2040                 domain.ds_prefer = DOMAINSET_FFS(&domain.ds_mask) - 1;
2041                 /* This will be constrained by domainset_shadow(). */
2042                 DOMAINSET_FILL(&domain.ds_mask);
2043         }
2044
2045         switch (level) {
2046         case CPU_LEVEL_ROOT:
2047         case CPU_LEVEL_CPUSET:
2048                 error = cpuset_which(which, id, &p, &ttd, &set);
2049                 if (error)
2050                         break;
2051                 switch (which) {
2052                 case CPU_WHICH_TID:
2053                 case CPU_WHICH_PID:
2054                         thread_lock(ttd);
2055                         set = cpuset_ref(ttd->td_cpuset);
2056                         thread_unlock(ttd);
2057                         PROC_UNLOCK(p);
2058                         break;
2059                 case CPU_WHICH_CPUSET:
2060                 case CPU_WHICH_JAIL:
2061                         break;
2062                 case CPU_WHICH_IRQ:
2063                 case CPU_WHICH_INTRHANDLER:
2064                 case CPU_WHICH_ITHREAD:
2065                 case CPU_WHICH_DOMAIN:
2066                         error = EINVAL;
2067                         goto out;
2068                 }
2069                 if (level == CPU_LEVEL_ROOT)
2070                         nset = cpuset_refroot(set);
2071                 else
2072                         nset = cpuset_refbase(set);
2073                 error = cpuset_modify_domain(nset, &domain);
2074                 cpuset_rel(nset);
2075                 cpuset_rel(set);
2076                 break;
2077         case CPU_LEVEL_WHICH:
2078                 switch (which) {
2079                 case CPU_WHICH_TID:
2080                         error = _cpuset_setthread(id, NULL, &domain);
2081                         break;
2082                 case CPU_WHICH_PID:
2083                         error = cpuset_setproc(id, NULL, NULL, &domain);
2084                         break;
2085                 case CPU_WHICH_CPUSET:
2086                 case CPU_WHICH_JAIL:
2087                         error = cpuset_which(which, id, &p, &ttd, &set);
2088                         if (error == 0) {
2089                                 error = cpuset_modify_domain(set, &domain);
2090                                 cpuset_rel(set);
2091                         }
2092                         break;
2093                 case CPU_WHICH_IRQ:
2094                 case CPU_WHICH_INTRHANDLER:
2095                 case CPU_WHICH_ITHREAD:
2096                 default:
2097                         error = EINVAL;
2098                         break;
2099                 }
2100                 break;
2101         default:
2102                 error = EINVAL;
2103                 break;
2104         }
2105 out:
2106         free(mask, M_TEMP);
2107         return (error);
2108 }
2109
2110 #ifdef DDB
2111 BITSET_DEFINE(bitset, 1);
2112 static void
2113 ddb_display_bitset(const struct bitset *set, int size)
2114 {
2115         int bit, once;
2116
2117         for (once = 0, bit = 0; bit < size; bit++) {
2118                 if (CPU_ISSET(bit, set)) {
2119                         if (once == 0) {
2120                                 db_printf("%d", bit);
2121                                 once = 1;
2122                         } else  
2123                                 db_printf(",%d", bit);
2124                 }
2125         }
2126         if (once == 0)
2127                 db_printf("<none>");
2128 }
2129
2130 void
2131 ddb_display_cpuset(const cpuset_t *set)
2132 {
2133         ddb_display_bitset((const struct bitset *)set, CPU_SETSIZE);
2134 }
2135
2136 static void
2137 ddb_display_domainset(const domainset_t *set)
2138 {
2139         ddb_display_bitset((const struct bitset *)set, DOMAINSET_SETSIZE);
2140 }
2141
2142 DB_SHOW_COMMAND(cpusets, db_show_cpusets)
2143 {
2144         struct cpuset *set;
2145
2146         LIST_FOREACH(set, &cpuset_ids, cs_link) {
2147                 db_printf("set=%p id=%-6u ref=%-6d flags=0x%04x parent id=%d\n",
2148                     set, set->cs_id, set->cs_ref, set->cs_flags,
2149                     (set->cs_parent != NULL) ? set->cs_parent->cs_id : 0);
2150                 db_printf("  cpu mask=");
2151                 ddb_display_cpuset(&set->cs_mask);
2152                 db_printf("\n");
2153                 db_printf("  domain policy %d prefer %d mask=",
2154                     set->cs_domain->ds_policy, set->cs_domain->ds_prefer);
2155                 ddb_display_domainset(&set->cs_domain->ds_mask);
2156                 db_printf("\n");
2157                 if (db_pager_quit)
2158                         break;
2159         }
2160 }
2161
2162 DB_SHOW_COMMAND(domainsets, db_show_domainsets)
2163 {
2164         struct domainset *set;
2165
2166         LIST_FOREACH(set, &cpuset_domains, ds_link) {
2167                 db_printf("set=%p policy %d prefer %d cnt %d max %d\n",
2168                     set, set->ds_policy, set->ds_prefer, set->ds_cnt,
2169                     set->ds_max);
2170                 db_printf("  mask =");
2171                 ddb_display_domainset(&set->ds_mask);
2172                 db_printf("\n");
2173         }
2174 }
2175 #endif /* DDB */