4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #include <sys/types.h>
27 #include <sys/param.h>
29 #include <sys/thread.h>
30 #include <sys/cpuvar.h>
31 #include <sys/kstat.h>
32 #include <sys/uadmin.h>
33 #include <sys/systm.h>
34 #include <sys/errno.h>
35 #include <sys/cmn_err.h>
36 #include <sys/procset.h>
37 #include <sys/processor.h>
38 #include <sys/debug.h>
40 #include <sys/project.h>
42 #include <sys/contract_impl.h>
43 #include <sys/contract/process_impl.h>
46 * Bind all the threads of a process to a CPU.
49 cpu_bind_process(proc_t
*pp
, processorid_t bind
, processorid_t
*obind
,
57 ASSERT(MUTEX_HELD(&pidlock
));
59 /* skip kernel processes */
60 if (pp
->p_flag
& SSYS
) {
66 mutex_enter(&pp
->p_lock
);
71 i
= cpu_bind_thread(tp
, bind
, obind
, error
);
74 } while ((tp
= tp
->t_forw
) != fp
);
77 mutex_exit(&pp
->p_lock
);
82 * Bind all the processes of a task to a CPU.
85 cpu_bind_task(task_t
*tk
, processorid_t bind
, processorid_t
*obind
,
92 ASSERT(MUTEX_HELD(&pidlock
));
94 if ((p
= tk
->tk_memb_list
) == NULL
)
98 if (!(p
->p_flag
& SSYS
)) {
99 i
= cpu_bind_process(p
, bind
, obind
, error
);
103 } while ((p
= p
->p_tasknext
) != tk
->tk_memb_list
);
109 * Bind all the processes in a project to a CPU.
112 cpu_bind_project(kproject_t
*kpj
, processorid_t bind
, processorid_t
*obind
,
119 ASSERT(MUTEX_HELD(&pidlock
));
121 for (p
= practive
; p
!= NULL
; p
= p
->p_next
) {
122 if (p
->p_tlist
== NULL
)
124 if (p
->p_task
->tk_proj
== kpj
&& !(p
->p_flag
& SSYS
)) {
125 i
= cpu_bind_process(p
, bind
, obind
, error
);
134 * Bind all the processes in a zone to a CPU.
137 cpu_bind_zone(zone_t
*zptr
, processorid_t bind
, processorid_t
*obind
,
144 ASSERT(MUTEX_HELD(&pidlock
));
146 for (p
= practive
; p
!= NULL
; p
= p
->p_next
) {
147 if (p
->p_tlist
== NULL
)
149 if (p
->p_zone
== zptr
&& !(p
->p_flag
& SSYS
)) {
150 i
= cpu_bind_process(p
, bind
, obind
, error
);
159 * Bind all the processes in a process contract to a CPU.
162 cpu_bind_contract(cont_process_t
*ctp
, processorid_t bind
, processorid_t
*obind
,
169 ASSERT(MUTEX_HELD(&pidlock
));
171 for (p
= practive
; p
!= NULL
; p
= p
->p_next
) {
172 if (p
->p_tlist
== NULL
)
174 if (p
->p_ct_process
== ctp
) {
175 i
= cpu_bind_process(p
, bind
, obind
, error
);
184 * processor_bind(2) - Processor binding interfaces.
187 processor_bind(idtype_t idtype
, id_t id
, processorid_t bind
,
188 processorid_t
*obindp
)
190 processorid_t obind
= PBIND_NONE
;
202 * Since we might be making a binding to a processor, hold the
203 * cpu_lock so that the processor cannot be taken offline while
206 mutex_enter(&cpu_lock
);
209 * Check to be sure binding processor ID is valid.
213 if ((cp
= cpu_get(bind
)) == NULL
||
214 (cp
->cpu_flags
& (CPU_QUIESCED
| CPU_OFFLINE
)))
216 else if ((cp
->cpu_flags
& CPU_READY
) == 0)
224 case PBIND_QUERY_TYPE
:
229 mutex_exit(&cpu_lock
);
230 return (set_errno(ret
));
236 mutex_enter(&pp
->p_lock
);
238 ret
= cpu_bind_thread(curthread
, bind
, &obind
, &err
);
244 if (tp
->t_tid
== id
) {
245 ret
= cpu_bind_thread(tp
,
250 } while ((tp
= tp
->t_forw
) != pp
->p_tlist
);
254 mutex_exit(&pp
->p_lock
);
259 * Note. Cannot use dotoprocs here because it doesn't find
260 * system class processes, which are legal to query.
262 mutex_enter(&pidlock
);
264 ret
= cpu_bind_process(curproc
, bind
, &obind
, &err
);
265 } else if ((pp
= prfind(id
)) != NULL
) {
266 ret
= cpu_bind_process(pp
, bind
, &obind
, &err
);
270 mutex_exit(&pidlock
);
274 mutex_enter(&pidlock
);
277 id
= p
->p_task
->tk_tkid
;
280 if ((tk
= task_hold_by_id(id
)) != NULL
) {
281 ret
= cpu_bind_task(tk
, bind
, &obind
, &err
);
282 mutex_exit(&pidlock
);
285 mutex_exit(&pidlock
);
294 if ((kpj
= project_hold_by_id(id
, pp
->p_zone
,
295 PROJECT_HOLD_FIND
)) == NULL
) {
298 mutex_enter(&pidlock
);
299 ret
= cpu_bind_project(kpj
, bind
, &obind
, &err
);
300 mutex_exit(&pidlock
);
309 if ((zptr
= zone_find_by_id(id
)) == NULL
) {
312 mutex_enter(&pidlock
);
313 ret
= cpu_bind_zone(zptr
, bind
, &obind
, &err
);
314 mutex_exit(&pidlock
);
321 id
= PRCTID(curproc
);
323 if ((ct
= contract_type_ptr(process_type
, id
,
324 curproc
->p_zone
->zone_uniqid
)) == NULL
) {
327 mutex_enter(&pidlock
);
328 ret
= cpu_bind_contract(ct
->ct_data
,
330 mutex_exit(&pidlock
);
336 if (id
== P_MYID
|| bind
!= PBIND_NONE
|| cpu_get(id
) == NULL
)
339 ret
= cpu_unbind(id
, B_TRUE
);
343 if (id
== P_MYID
|| bind
!= PBIND_NONE
) {
347 cpu_t
*cp
= cpu_list
;
349 if ((cp
->cpu_flags
& CPU_EXISTS
) == 0)
351 i
= cpu_unbind(cp
->cpu_id
, B_TRUE
);
354 } while ((cp
= cp
->cpu_next
) != cpu_list
);
360 * Spec says this is invalid, even though we could
361 * handle other idtypes.
366 mutex_exit(&cpu_lock
);
369 * If no search error occurred, see if any permissions errors did.
374 if (ret
== 0 && obindp
!= NULL
)
375 if (copyout((caddr_t
)&obind
, (caddr_t
)obindp
,
376 sizeof (obind
)) == -1)
378 return (ret
? set_errno(ret
) : 0); /* return success or failure */