/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lgroup interface
*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#include <sys/lgrp_user.h>
/*
* Fast trap for getting home lgroup of current thread
*/
extern lgrp_id_t _lgrp_home_fast(void);
/*
* lgroup system call
*/
/*
* Get generation ID of lgroup hierarchy given view
* which changes whenever the hierarchy changes (eg. DR or pset contents
* change for caller's view)
*/
static lgrp_gen_t
{
}
/*
* Get supported revision number of lgroup interface
*/
int
{
}
/*
* Get affinity for given lgroup
*/
{
}
/*
* Set affinity for given lgroup
*/
int
{
}
/*
* Get home lgroup for given process or thread
*/
{
/*
* Use fast trap to get home lgroup of current thread or process
* Otherwise, use system call for other process or thread
*/
return (_lgrp_home_fast());
else
}
/*
* Get a snapshot of the lgroup hierarchy
*/
static int
{
}
/*
* Find any orphan lgroups without parents and make them be children of
* root lgroup
*/
static int
{
int i;
int nlgrpsmax;
int orphan;
return (-1);
for (i = 0; i < nlgrpsmax; i++) {
int j;
/*
* Skip root lgroup
*/
continue;
continue;
/*
* Make sure parents bitmap is setup
*/
(i * BT_SIZEOFMAP(nlgrpsmax)));
/*
* Look for orphans (lgroups with no parents)
*/
orphan = 1;
if (parents[j] != 0) {
orphan = 0;
break;
}
/*
* Make root be parent of any orphans
*/
if (orphan) {
if (root->info_children) {
}
}
}
return (0);
}
/*
* Remove given lgroup from parent lgroup(s)
*/
static void
{
int i;
return;
return;
/*
* Update children of parents not to include given lgroup
*/
for (i = 0; i < snap->ss_nlgrps_max; i++) {
}
}
}
/*
* Prune any CPUs not in given array from specified lgroup
*/
static void
int ncpus)
{
int count;
int i;
int j;
int k;
return;
/*
* No CPUs to remove
*/
return;
/*
* Remove all CPUs from lgroup
*/
lgrp_info->info_ncpus = 0;
return;
}
/*
* Remove any CPUs from lgroup not in given list of CPUs
*/
i = 0;
/*
* Look for CPU in list
*/
for (j = 0; j < ncpus; j++)
break;
/*
* Go to next CPU if found this one in list
*/
if (j < ncpus) {
i++;
continue;
}
/*
* Remove this CPU and shift others into its place
* and decrement number of CPUs
*/
lgrp_info->info_ncpus--;
}
}
/*
* Prune lgroup hierarchy for caller's view
*/
static int
{
int i;
int nlgrps_max;
return (-1);
/*
* Get CPUs in caller's pset
*/
return (-1);
if (ncpus > 0) {
return (-1);
}
}
/*
* Remove any CPUs not in caller's pset from lgroup hierarchy
*/
for (i = 0; i < nlgrps_max; i++) {
}
if (ncpus > 0)
/*
* Change lgroup bitmask from just reflecting lgroups overlapping
* caller's pset to all lgroups available to caller, starting by
* filling in all lgroups and then removing any empty ones below
*/
for (i = 0; i < nlgrps_max; i++) {
continue;
}
/*
* Remove empty lgroups from lgroup hierarchy, removing it from its
* parents and decrementing nlgrps
*/
for (i = 0; i < nlgrps_max; i++) {
continue;
prune_child(snap, i);
}
}
return (0);
}
/*
* Initialize lgroup interface
*/
{
int i;
/*
* Check for legal view
*/
return (LGRP_COOKIE_NONE);
}
/*
* Try to take a consistent snapshot of lgroup hierarchy
*/
/*
* Get lgroup generation number before taking snapshot
*/
/*
* Get size of buffer needed for snapshot
*/
if (bufsize <= 0) {
return (LGRP_COOKIE_NONE);
continue;
}
/*
* Allocate buffer
*/
return (LGRP_COOKIE_NONE);
/*
* Take snapshot of lgroup hierarchy
*/
if (bufsize <= 0) {
return (LGRP_COOKIE_NONE);
continue;
}
/*
* See whether lgroup generation number changed
*/
break;
}
/*
* Remember generation number and view of this snapshot
*/
/*
* Keep caller's pset ID for caller's view
*/
if (view == LGRP_VIEW_CALLER) {
return ((uintptr_t)-1);
}
/*
* Find any orphan lgroups without parents and make them be children
* of the root lgroup
*/
(void) parent_orphans(snap);
/*
* Prune snapshot of lgroup hierarchy for caller's view
*/
if (view == LGRP_VIEW_CALLER)
(void) prune_tree(snap);
else {
/*
* Change lgroup bitmask from just reflecting lgroups
* overlapping caller's pset to all lgroups available
*/
for (i = 0; i < snap->ss_nlgrps_max; i++) {
continue;
}
}
}
/*
* Return whether given cookie is out-of-date (stale) or not
*/
int
{
/*
* Check for bad cookie
*/
return (-1);
}
/*
* Check generation number which changes when lgroup hierarchy changes
* or pset contents change for caller's view
*/
return (1);
/*
* See whether pset binding has changed for caller's view
*/
return (-1);
return (1);
}
return (0); /* cookie isn't stale */
}
/*
* Get view of lgroup hierarchy from snapshot represented by given cookie
*/
{
return (-1);
}
}
/*
* Get number of lgroups
*/
int
{
return (-1);
}
}
/*
* Return root lgroup ID
*/
{
return (-1);
}
}
/*
* Get parent lgroups of given lgroup
*/
int
{
int i;
int nlgrps_max;
int nparents;
/*
* Check for valid arguments
*/
return (-1);
}
/*
* See whether given lgroup exists
*/
return (-1);
}
/*
* No parents, since given lgroup is root lgroup or
* only one level in lgroup hierarchy (ie. SMP)
*/
return (0);
return (0);
}
/*
* Make sure that parents exist
*/
return (-1);
}
/*
* Given lgroup should have a parent
*/
if (lgrp_parents == NULL) {
return (-1);
}
/*
* Check lgroup parents bitmask, fill in parents array, and return
* number of parents
*/
nparents = 0;
for (i = 0; i < nlgrps_max; i++) {
if (BT_TEST(lgrp_parents, i)) {
}
nparents++;
}
}
return (nparents);
}
/*
* Get children lgroups of given lgroup
*/
int
{
int i;
int nlgrps_max;
int nchildren;
/*
* Check for valid arguments
*/
return (-1);
}
/*
* See whether given lgroup exists
*/
return (-1);
}
/*
* No children, since only one level in lgroup hierarchy (ie. SMP)
*/
return (0);
return (0);
}
/*
* Make sure that children exist
*/
return (-1);
}
/*
* Given lgroup may not have any children
*/
if (lgrp_children == NULL)
return (0);
/*
* Check lgroup children bitmask, fill in children array, and return
* number of children
*/
nchildren = 0;
for (i = 0; i < nlgrps_max; i++) {
if (BT_TEST(lgrp_children, i)) {
nchildren++;
}
}
return (nchildren);
}
/*
* Get all CPUs within given lgroup (hierarchy)
*/
static int
{
int i;
int j;
int ncpus;
int nlgrps_max;
int total;
/*
* Get lgroup info
*/
return (-1);
}
/*
* Check whether given lgroup contains any lgroups with CPU resources
*/
return (0);
/*
* Get all CPUs within this lgroup
*/
total = 0;
for (i = 0; i < nlgrps_max; i++) {
continue;
/*
* Get all CPUs within lgroup
*/
/*
* Copy as many CPU IDs into array that will fit
* and decrement count and increment array pointer
* as we go
*/
for (j = 0; j < ncpus; j++) {
if (*count) {
(*cpuids)++;
(*count)--;
}
}
}
}
return (total);
}
/*
* Get CPUs in given lgroup
*/
int
{
int i;
int ncpus;
/*
* Check for valid arguments
*/
(content != LGRP_CONTENT_DIRECT &&
content != LGRP_CONTENT_HIERARCHY)) {
return (-1);
}
/*
* See whether given lgroup exists
*/
return (-1);
}
/*
* Get lgroup info
*/
/*
* Get contents of lgroup
*/
switch (content) {
case LGRP_CONTENT_DIRECT:
/*
* Get CPUs contained directly within given lgroup
*/
/*
* No array to copy CPU IDs into,
* so just return number of CPUs.
*/
return (ncpus);
/*
* Copy as many CPU IDs into array that will fit
*/
for (i = 0; i < ncpus; i++)
if (i < count)
return (ncpus);
case LGRP_CONTENT_ALL:
default:
return (-1);
}
}
/*
* Return physical memory size in pages for given lgroup
*/
{
int i;
int nlgrps_max;
int pgsz;
/*
* Check for valid arguments
*/
return (-1);
}
/*
* See whether given lgroup exists
*/
return (-1);
}
pgsz = getpagesize();
/*
* Get lgroup info
*/
switch (content) {
case LGRP_CONTENT_DIRECT:
/*
* Get memory contained directly in this lgroup
*/
switch (type) {
case LGRP_MEM_SZ_FREE:
return (size);
case LGRP_MEM_SZ_INSTALLED:
return (size);
default:
return (-1);
}
case LGRP_CONTENT_ALL:
/*
* Get memory contained within this lgroup (and its children)
*/
/*
* Check whether given lgroup contains any lgroups with CPU
* resources
*/
return (0);
/*
* Add up memory in lgroup resources
*/
size = 0;
for (i = 0; i < nlgrps_max; i++) {
continue;
switch (type) {
case LGRP_MEM_SZ_FREE:
break;
case LGRP_MEM_SZ_INSTALLED:
break;
default:
return (-1);
}
}
return (size);
default:
return (-1);
}
}
/*
* Get resources for a particuliar lgroup
*/
int
{
int i;
int nlgrps;
int nlgrps_max;
/*
* Check for valid arguments
*/
return (-1);
}
/*
* See whether given lgroup exists
*/
return (-1);
}
/*
* Get lgroup info
*/
/*
* Count number lgroups contained within this lgroup and
* copy as many lgroup IDs into array that will fit
*/
nlgrps = 0;
for (i = 0; i < snap->ss_nlgrps_max; i++)
nlgrps++;
}
return (nlgrps);
}
/*
* Finish using lgroup interface
*/
int
{
return (-1);
}
return (0);
}
/*
* Return latency between "from" and "to" lgroups
*
* This latency number can only be used for relative comparison
* between lgroups on the running system, cannot be used across platforms,
* and may not reflect the actual latency. It is platform and implementation
* specific, so platform gets to decide its value. It would be nice if the
* number was at least proportional to make comparisons more meaningful though.
*/
int
{
int latency;
return (latency);
}
/*
* Return latency between "from" and "to" lgroups
*
* This latency number can only be used for relative comparison
* between lgroups on the running system, cannot be used across platforms,
* and may not reflect the actual latency. It is platform and implementation
* specific, so platform gets to decide its value. It would be nice if the
* number was at least proportional to make comparisons more meaningful though.
*/
int
{
int ncpus;
int nlgrps_max;
/*
* Check for valid snapshot, lgroup, and between flag
*/
between != LGRP_LAT_CPU_TO_MEM) {
return (-1);
}
/*
* Check whether lgroups exist
*/
return (-1);
}
/*
* Check whether "from" lgroup has any CPUs
*/
if (ncpus <= 0) {
if (ncpus == 0)
return (-1);
}
/*
* Check whether "to" lgroup has any memory
*/
if (nbytes <= 0) {
if (nbytes == 0)
return (-1);
}
return (lgrp_info->info_latency);
}
}