cpupart.c revision fb2f18f820d90b001aea4fb27dd654bc1263c440
5aefb6555731130ca4fd295960123d71f2d21fe8rie * CDDL HEADER START
5aefb6555731130ca4fd295960123d71f2d21fe8rie * The contents of this file are subject to the terms of the
5aefb6555731130ca4fd295960123d71f2d21fe8rie * Common Development and Distribution License (the "License").
5aefb6555731130ca4fd295960123d71f2d21fe8rie * You may not use this file except in compliance with the License.
5aefb6555731130ca4fd295960123d71f2d21fe8rie * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
5aefb6555731130ca4fd295960123d71f2d21fe8rie * See the License for the specific language governing permissions
5aefb6555731130ca4fd295960123d71f2d21fe8rie * and limitations under the License.
5aefb6555731130ca4fd295960123d71f2d21fe8rie * When distributing Covered Code, include this CDDL HEADER in each
5aefb6555731130ca4fd295960123d71f2d21fe8rie * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
5aefb6555731130ca4fd295960123d71f2d21fe8rie * If applicable, add the following below this CDDL HEADER, with the
5aefb6555731130ca4fd295960123d71f2d21fe8rie * fields enclosed by brackets "[]" replaced with your own identifying
5aefb6555731130ca4fd295960123d71f2d21fe8rie * information: Portions Copyright [yyyy] [name of copyright owner]
5aefb6555731130ca4fd295960123d71f2d21fe8rie * CDDL HEADER END
5aefb6555731130ca4fd295960123d71f2d21fe8rie * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23a1ccea6aac035f084a7a4cdc968687d1b02dafRoger A. Faulkner * Use is subject to license terms.
5aefb6555731130ca4fd295960123d71f2d21fe8rie#pragma ident "%Z%%M% %I% %E% SMI"
5aefb6555731130ca4fd295960123d71f2d21fe8rie * Calling pool_lock() protects the pools configuration, which includes
23a1ccea6aac035f084a7a4cdc968687d1b02dafRoger A. Faulkner * CPU partitions. cpu_lock protects the CPU partition list, and prevents
5aefb6555731130ca4fd295960123d71f2d21fe8rie * partitions from being created or destroyed while the lock is held.
5aefb6555731130ca4fd295960123d71f2d21fe8rie * The lock ordering with respect to related locks is:
5aefb6555731130ca4fd295960123d71f2d21fe8rie * pool_lock() ---> cpu_lock ---> pidlock --> p_lock
5aefb6555731130ca4fd295960123d71f2d21fe8rie * Blocking memory allocations may be made while holding "pool_lock"
5aefb6555731130ca4fd295960123d71f2d21fe8rie * or cpu_lock.
5aefb6555731130ca4fd295960123d71f2d21fe8rie * The cp_default partition is allocated statically, but its lgroup load average
5aefb6555731130ca4fd295960123d71f2d21fe8rie * (lpl) list is allocated dynamically after kmem subsystem is initialized. This
5aefb6555731130ca4fd295960123d71f2d21fe8rie * saves some memory since the space allocated reflects the actual number of
5aefb6555731130ca4fd295960123d71f2d21fe8rie * lgroups supported by the platform. The lgrp facility provides a temporary
5aefb6555731130ca4fd295960123d71f2d21fe8rie * space to hold lpl information during system bootstrap.
5aefb6555731130ca4fd295960123d71f2d21fe8rie * Need to limit total number of partitions to avoid slowing down the
5aefb6555731130ca4fd295960123d71f2d21fe8rie * clock code too much. The clock code traverses the list of
5aefb6555731130ca4fd295960123d71f2d21fe8rie * partitions and needs to be able to execute in a reasonable amount
5aefb6555731130ca4fd295960123d71f2d21fe8rie * of time (less than 1/hz seconds). The maximum is sized based on
5aefb6555731130ca4fd295960123d71f2d21fe8rie * max_ncpus so it shouldn't be a problem unless there are large
5aefb6555731130ca4fd295960123d71f2d21fe8rie * numbers of empty partitions.
5aefb6555731130ca4fd295960123d71f2d21fe8rie * Processor sets and CPU partitions are different but related concepts.
5aefb6555731130ca4fd295960123d71f2d21fe8rie * A processor set is a user-level abstraction allowing users to create
5aefb6555731130ca4fd295960123d71f2d21fe8rie * sets of CPUs and bind threads exclusively to those sets. A CPU
5aefb6555731130ca4fd295960123d71f2d21fe8rie * partition is a kernel dispatcher object consisting of a set of CPUs
5aefb6555731130ca4fd295960123d71f2d21fe8rie * and a global dispatch queue. The processor set abstraction is
5aefb6555731130ca4fd295960123d71f2d21fe8rie * implemented via a CPU partition, and currently there is a 1-1
5aefb6555731130ca4fd295960123d71f2d21fe8rie * mapping between processor sets and partitions (excluding the default
5aefb6555731130ca4fd295960123d71f2d21fe8rie * partition, which is not visible as a processor set). Hence, the
5aefb6555731130ca4fd295960123d71f2d21fe8rie * numbering for processor sets and CPU partitions is identical. This
5aefb6555731130ca4fd295960123d71f2d21fe8rie * may not always be true in the future, and these macros could become
5aefb6555731130ca4fd295960123d71f2d21fe8rie * less trivial if we support e.g. a processor set containing multiple
5aefb6555731130ca4fd295960123d71f2d21fe8rie * CPU partitions.
5aefb6555731130ca4fd295960123d71f2d21fe8rie#define PSTOCP(psid) ((cpupartid_t)((psid) == PS_NONE ? CP_DEFAULT : (psid)))
5aefb6555731130ca4fd295960123d71f2d21fe8rie#define CPTOPS(cpid) ((psetid_t)((cpid) == CP_DEFAULT ? PS_NONE : (cpid)))
5aefb6555731130ca4fd295960123d71f2d21fe8rie * Find a CPU partition given a processor set ID.
5aefb6555731130ca4fd295960123d71f2d21fe8rie /* default partition not visible as a processor set */
return (NULL);
return (cp);
return (NULL);
return (NULL);
return (cp);
return (EACCES);
lgrp_id_t i;
for (i = 0; i < S_LOADAVG_SZ; i++) {
* to the correct lpl in the cp_default.cp_lgrploads list.
kthread_t *t;
proc_t *p;
int lgrp_diff_lpl;
int ret;
move_threads = 0;
return (EBUSY);
return (ret);
membar_enter();
if (move_threads) {
int loop_count;
return (EBUSY);
if (move_threads) {
start_cpus();
goto again;
if (move_threads) {
t = p->p_tlist;
if (t == NULL)
lgrp_diff_lpl = 0;
t->t_cpupart)) {
t = t->t_forw;
} while (t != p->p_tlist);
if (lgrp_diff_lpl)
t = curthread;
t = t->t_next;
} while (t != curthread);
start_cpus();
if (!ignore) {
return (EBUSY);
int ret;
return (EINVAL);
return (ret);
void *zonebuf)
return (EINVAL);
lgrp_id_t i;
KM_SLEEP);
return (ENOMEM);
cp_numparts++;
cp_id_next++;
start_cpus();
int err = 0;
kthread_t *t;
proc_t *p;
return (EINVAL);
t = curthread;
if (ttoproc(t) != p) {
goto again;
if (err) {
return (err);
t = t->t_next;
} while (t != curthread);
return (err);
start_cpus();
cp_numparts--;
return (err);
int err;
return (EINVAL);
return (EINVAL);
return (err);
cpu_t *c;
return (EINVAL);
if (numcpus) {
*numcpus = t;
if (cpulist) {
for (i = 0; i < ncpus; i++) {
c = c->cpu_next_part;
return (EINVAL);
for (i = 0; i < nelem; i++)
return (numpart);
return (EINVAL);
return (EINVAL);
return (EINVAL);