1*c6402783Sakolb /* 2*c6402783Sakolb * CDDL HEADER START 3*c6402783Sakolb * 4*c6402783Sakolb * The contents of this file are subject to the terms of the 5*c6402783Sakolb * Common Development and Distribution License (the "License"). 6*c6402783Sakolb * You may not use this file except in compliance with the License. 7*c6402783Sakolb * 8*c6402783Sakolb * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*c6402783Sakolb * or http://www.opensolaris.org/os/licensing. 10*c6402783Sakolb * See the License for the specific language governing permissions 11*c6402783Sakolb * and limitations under the License. 12*c6402783Sakolb * 13*c6402783Sakolb * When distributing Covered Code, include this CDDL HEADER in each 14*c6402783Sakolb * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*c6402783Sakolb * If applicable, add the following below this CDDL HEADER, with the 16*c6402783Sakolb * fields enclosed by brackets "[]" replaced with your own identifying 17*c6402783Sakolb * information: Portions Copyright [yyyy] [name of copyright owner] 18*c6402783Sakolb * 19*c6402783Sakolb * CDDL HEADER END 20*c6402783Sakolb */ 21*c6402783Sakolb 22*c6402783Sakolb /* 23*c6402783Sakolb * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24*c6402783Sakolb * Use is subject to license terms. 25*c6402783Sakolb */ 26*c6402783Sakolb 27*c6402783Sakolb #pragma ident "%Z%%M% %I% %E% SMI" 28*c6402783Sakolb 29*c6402783Sakolb /* 30*c6402783Sakolb * The plgrp utility allows a user to display and modify the home lgroup and 31*c6402783Sakolb * lgroup affinities of the specified threads 32*c6402783Sakolb */ 33*c6402783Sakolb 34*c6402783Sakolb #include <ctype.h> 35*c6402783Sakolb #include <errno.h> 36*c6402783Sakolb #include <libintl.h> 37*c6402783Sakolb #include <libproc.h> 38*c6402783Sakolb #include <locale.h> 39*c6402783Sakolb #include <signal.h> 40*c6402783Sakolb #include <stdio.h> 41*c6402783Sakolb #include <stdlib.h> 42*c6402783Sakolb #include <strings.h> 43*c6402783Sakolb #include <unistd.h> 44*c6402783Sakolb #include <libgen.h> 45*c6402783Sakolb #include <sys/lgrp_user.h> 46*c6402783Sakolb 47*c6402783Sakolb 48*c6402783Sakolb /* 49*c6402783Sakolb * Delimiters 50*c6402783Sakolb */ 51*c6402783Sakolb #define DELIMIT_AFF '/' /* lgroup affinity from lgroups */ 52*c6402783Sakolb #define DELIMIT_LGRP "," /* lgroups from each other */ 53*c6402783Sakolb #define DELIMIT_LWP "/" /* thread/LWP IDs from process ID */ 54*c6402783Sakolb #define DELIMIT_RANGE '-' /* range of IDs (eg. lgroup) */ 55*c6402783Sakolb #define DELIMIT_AFF_LST ',' /* list of affinities from another list */ 56*c6402783Sakolb 57*c6402783Sakolb /* 58*c6402783Sakolb * Exit values other than EXIT_{SUCCESS,FAILURE} 59*c6402783Sakolb */ 60*c6402783Sakolb #define EXIT_NONFATAL 2 /* non-fatal errors */ 61*c6402783Sakolb 62*c6402783Sakolb /* 63*c6402783Sakolb * Header and format strings 64*c6402783Sakolb */ 65*c6402783Sakolb #define HDR_PLGRP_AFF_GET " PID/LWPID HOME AFFINITY\n" 66*c6402783Sakolb #define HDR_PLGRP_AFF_SET " PID/LWPID HOME AFFINITY\n" 67*c6402783Sakolb #define HDR_PLGRP_HOME_GET " PID/LWPID HOME\n" 68*c6402783Sakolb #define HDR_PLGRP_HOME_SET " PID/LWPID HOME\n" 69*c6402783Sakolb 70*c6402783Sakolb /* 71*c6402783Sakolb * Part of the HDR_PLGRP_AFF_SET header used to calculate space needed to 72*c6402783Sakolb * represent changing home as old => new 73*c6402783Sakolb */ 74*c6402783Sakolb #define HDR_PLGRP_HOME_CHANGE "HOME " 75*c6402783Sakolb 76*c6402783Sakolb #define FMT_AFF "%d/%s" 77*c6402783Sakolb #define FMT_AFF_STR "%s" 78*c6402783Sakolb #define FMT_HOME "%-6d" 79*c6402783Sakolb #define FMT_NEWHOME "%d => %d" 80*c6402783Sakolb #define FMT_THREAD "%8d/%-8d" 81*c6402783Sakolb 82*c6402783Sakolb /* 83*c6402783Sakolb * How much to allocate for lgroup bitmap array as it grows 84*c6402783Sakolb */ 85*c6402783Sakolb #define LGRP_BITMAP_CHUNK 8 86*c6402783Sakolb 87*c6402783Sakolb /* 88*c6402783Sakolb * Strings that can be given for lgroups 89*c6402783Sakolb */ 90*c6402783Sakolb #define LGRP_ALL_STR "all" 91*c6402783Sakolb #define LGRP_LEAVES_STR "leaves" 92*c6402783Sakolb #define LGRP_ROOT_STR "root" 93*c6402783Sakolb 94*c6402783Sakolb /* 95*c6402783Sakolb * Strings corresponding to lgroup affinities 96*c6402783Sakolb */ 97*c6402783Sakolb #define LGRP_AFF_NONE_STR "none" 98*c6402783Sakolb #define LGRP_AFF_STRONG_STR "strong" 99*c6402783Sakolb #define LGRP_AFF_WEAK_STR "weak" 100*c6402783Sakolb 101*c6402783Sakolb /* 102*c6402783Sakolb * Invalid value for lgroup affinity 103*c6402783Sakolb */ 104*c6402783Sakolb #define LGRP_AFF_INVALID -1 105*c6402783Sakolb 106*c6402783Sakolb /* 107*c6402783Sakolb * Number of args needed for lgroup system call 108*c6402783Sakolb */ 109*c6402783Sakolb #define LGRPSYS_NARGS 3 110*c6402783Sakolb 111*c6402783Sakolb #ifndef TEXT_DOMAIN /* should be defined by cc -D */ 112*c6402783Sakolb #define TEXT_DOMAIN "SYS_TEST" /* use this only if it wasn't */ 113*c6402783Sakolb #endif 114*c6402783Sakolb 115*c6402783Sakolb /* 116*c6402783Sakolb * plgrp(1) operations 117*c6402783Sakolb */ 118*c6402783Sakolb typedef enum plgrp_ops { 119*c6402783Sakolb PLGRP_AFFINITY_GET, 120*c6402783Sakolb PLGRP_AFFINITY_SET, 121*c6402783Sakolb PLGRP_HOME_GET, 122*c6402783Sakolb PLGRP_HOME_SET, 123*c6402783Sakolb PLGRP_NO_OP 124*c6402783Sakolb } plgrp_ops_t; 125*c6402783Sakolb 126*c6402783Sakolb /* 127*c6402783Sakolb * Arguments specified to plgrp(1) and any state needed to do everything 128*c6402783Sakolb * that plgrp(1) does for one operation from inside Plwp_iter_all() 129*c6402783Sakolb */ 130*c6402783Sakolb typedef struct plgrp_args { 131*c6402783Sakolb struct ps_prochandle *Ph; /* proc handle for process */ 132*c6402783Sakolb const char *lwps; /* LWPs */ 133*c6402783Sakolb lgrp_id_t *lgrps; /* lgroups */ 134*c6402783Sakolb lgrp_affinity_t *affs; /* lgroup affinities */ 135*c6402783Sakolb int nlgrps; /* number of lgroups */ 136*c6402783Sakolb int nelements; /* number of elements */ 137*c6402783Sakolb int index; /* index */ 138*c6402783Sakolb int nthreads; /* threads processed */ 139*c6402783Sakolb plgrp_ops_t op; /* operation */ 140*c6402783Sakolb } plgrp_args_t; 141*c6402783Sakolb 142*c6402783Sakolb /* 143*c6402783Sakolb * How many signals caught from terminal 144*c6402783Sakolb * We bail out as soon as possible when interrupt is set 145*c6402783Sakolb */ 146*c6402783Sakolb static int interrupt = 0; 147*c6402783Sakolb 148*c6402783Sakolb /* 149*c6402783Sakolb * How many non-fatal errors ocurred 150*c6402783Sakolb */ 151*c6402783Sakolb static int nerrors = 0; 152*c6402783Sakolb 153*c6402783Sakolb /* 154*c6402783Sakolb * Name of this program 155*c6402783Sakolb */ 156*c6402783Sakolb static char *progname; 157*c6402783Sakolb 158*c6402783Sakolb /* 159*c6402783Sakolb * Root of the lgroup hierarchy 160*c6402783Sakolb */ 161*c6402783Sakolb static lgrp_id_t root = LGRP_NONE; 162*c6402783Sakolb 163*c6402783Sakolb /* 164*c6402783Sakolb * Bitmap of all lgroups in the system 165*c6402783Sakolb */ 166*c6402783Sakolb static char *lgrps_bitmap = NULL; 167*c6402783Sakolb 168*c6402783Sakolb /* 169*c6402783Sakolb * Size of lgrps_bitmap array 170*c6402783Sakolb */ 171*c6402783Sakolb static int lgrps_bitmap_nelements = 0; 172*c6402783Sakolb 173*c6402783Sakolb /* 174*c6402783Sakolb * Macro LGRP_VALID returns true when lgrp is present in the system. 175*c6402783Sakolb */ 176*c6402783Sakolb #define LGRP_VALID(lgrp) (lgrps_bitmap[lgrp] != 0) 177*c6402783Sakolb 178*c6402783Sakolb 179*c6402783Sakolb /* 180*c6402783Sakolb * Maximum lgroup value. 181*c6402783Sakolb */ 182*c6402783Sakolb static int max_lgrpid = LGRP_NONE; 183*c6402783Sakolb 184*c6402783Sakolb /* 185*c6402783Sakolb * Total possible number of lgroups 186*c6402783Sakolb */ 187*c6402783Sakolb #define NLGRPS (max_lgrpid + 1) 188*c6402783Sakolb 189*c6402783Sakolb 190*c6402783Sakolb static void 191*c6402783Sakolb usage(int rc) 192*c6402783Sakolb { 193*c6402783Sakolb (void) fprintf(stderr, 194*c6402783Sakolb gettext("Usage:\t%s [-h] <pid> | <core> [/lwps] ...\n"), progname); 195*c6402783Sakolb (void) fprintf(stderr, 196*c6402783Sakolb gettext("\t%s [-F] -a <lgroup list> <pid>[/lwps] ...\n"), progname); 197*c6402783Sakolb (void) fprintf(stderr, 198*c6402783Sakolb gettext("\t%s [-F] -A <lgroup list>/none|weak|strong[,...] " 199*c6402783Sakolb " <pid>[/lwps] ...\n"), progname); 200*c6402783Sakolb (void) fprintf(stderr, 201*c6402783Sakolb gettext("\t%s [-F] -H <lgroup list> <pid>[/lwps] ...\n"), progname); 202*c6402783Sakolb (void) fprintf(stderr, 203*c6402783Sakolb gettext("\n\twhere <lgroup list> is a comma separated list of\n" 204*c6402783Sakolb "\tone or more of the following:\n\n" 205*c6402783Sakolb "\t - lgroup ID\n" 206*c6402783Sakolb "\t - Range of lgroup IDs specified as\n" 207*c6402783Sakolb "\t\t<start lgroup ID>-<end lgroup ID>\n" 208*c6402783Sakolb "\t - \"all\"\n" 209*c6402783Sakolb "\t - \"root\"\n" 210*c6402783Sakolb "\t - \"leaves\"\n\n")); 211*c6402783Sakolb 212*c6402783Sakolb exit(rc); 213*c6402783Sakolb } 214*c6402783Sakolb 215*c6402783Sakolb /* 216*c6402783Sakolb * Handler for catching signals from terminal 217*c6402783Sakolb */ 218*c6402783Sakolb /* ARGSUSED */ 219*c6402783Sakolb static void 220*c6402783Sakolb intr(int sig) 221*c6402783Sakolb { 222*c6402783Sakolb interrupt++; 223*c6402783Sakolb } 224*c6402783Sakolb 225*c6402783Sakolb 226*c6402783Sakolb /* 227*c6402783Sakolb * Return string name for given lgroup affinity 228*c6402783Sakolb */ 229*c6402783Sakolb static char * 230*c6402783Sakolb lgrp_affinity_string(lgrp_affinity_t aff) 231*c6402783Sakolb { 232*c6402783Sakolb char *rc = "unknown"; 233*c6402783Sakolb 234*c6402783Sakolb switch (aff) { 235*c6402783Sakolb case LGRP_AFF_STRONG: 236*c6402783Sakolb rc = "strong"; 237*c6402783Sakolb break; 238*c6402783Sakolb case LGRP_AFF_WEAK: 239*c6402783Sakolb rc = "weak"; 240*c6402783Sakolb break; 241*c6402783Sakolb case LGRP_AFF_NONE: 242*c6402783Sakolb rc = "none"; 243*c6402783Sakolb break; 244*c6402783Sakolb default: 245*c6402783Sakolb break; 246*c6402783Sakolb } 247*c6402783Sakolb 248*c6402783Sakolb return (rc); 249*c6402783Sakolb } 250*c6402783Sakolb 251*c6402783Sakolb 252*c6402783Sakolb /* 253*c6402783Sakolb * Add a new lgroup into lgroup array in "arg", growing lgroup and affinity 254*c6402783Sakolb * arrays if necessary 255*c6402783Sakolb */ 256*c6402783Sakolb static void 257*c6402783Sakolb lgrps_add_lgrp(plgrp_args_t *arg, int id) 258*c6402783Sakolb { 259*c6402783Sakolb 260*c6402783Sakolb if (arg->nlgrps == arg->nelements) { 261*c6402783Sakolb arg->nelements += LGRP_BITMAP_CHUNK; 262*c6402783Sakolb 263*c6402783Sakolb arg->lgrps = realloc(arg->lgrps, 264*c6402783Sakolb arg->nelements * sizeof (lgrp_id_t)); 265*c6402783Sakolb if (arg->lgrps == NULL) { 266*c6402783Sakolb (void) fprintf(stderr, gettext("%s: out of memory\n"), 267*c6402783Sakolb progname); 268*c6402783Sakolb exit(EXIT_FAILURE); 269*c6402783Sakolb } 270*c6402783Sakolb 271*c6402783Sakolb arg->affs = realloc(arg->affs, 272*c6402783Sakolb arg->nelements * sizeof (lgrp_affinity_t)); 273*c6402783Sakolb 274*c6402783Sakolb if (arg->affs == NULL) { 275*c6402783Sakolb (void) fprintf(stderr, gettext("%s: out of memory\n"), 276*c6402783Sakolb progname); 277*c6402783Sakolb exit(EXIT_FAILURE); 278*c6402783Sakolb } 279*c6402783Sakolb } 280*c6402783Sakolb 281*c6402783Sakolb arg->lgrps[arg->nlgrps] = id; 282*c6402783Sakolb arg->affs[arg->nlgrps] = LGRP_AFF_INVALID; 283*c6402783Sakolb arg->nlgrps++; 284*c6402783Sakolb } 285*c6402783Sakolb 286*c6402783Sakolb 287*c6402783Sakolb /* 288*c6402783Sakolb * Return an array having '1' for each lgroup present in given subtree under 289*c6402783Sakolb * specified lgroup in lgroup hierarchy 290*c6402783Sakolb */ 291*c6402783Sakolb static void 292*c6402783Sakolb lgrps_bitmap_init(lgrp_cookie_t cookie, lgrp_id_t lgrpid, char **bitmap_array, 293*c6402783Sakolb int *bitmap_nelements) 294*c6402783Sakolb { 295*c6402783Sakolb lgrp_id_t *children; 296*c6402783Sakolb int i; 297*c6402783Sakolb int nchildren; 298*c6402783Sakolb 299*c6402783Sakolb if (lgrpid < 0) { 300*c6402783Sakolb lgrpid = lgrp_root(cookie); 301*c6402783Sakolb if (lgrpid < 0) 302*c6402783Sakolb return; 303*c6402783Sakolb } 304*c6402783Sakolb 305*c6402783Sakolb /* 306*c6402783Sakolb * If new lgroup cannot fit, grow the array and fill unused portion 307*c6402783Sakolb * with zeroes. 308*c6402783Sakolb */ 309*c6402783Sakolb while (lgrpid >= *bitmap_nelements) { 310*c6402783Sakolb *bitmap_nelements += LGRP_BITMAP_CHUNK; 311*c6402783Sakolb *bitmap_array = realloc(*bitmap_array, 312*c6402783Sakolb *bitmap_nelements * sizeof (char)); 313*c6402783Sakolb if (*bitmap_array == NULL) { 314*c6402783Sakolb (void) fprintf(stderr, gettext("%s: out of memory\n"), 315*c6402783Sakolb progname); 316*c6402783Sakolb exit(EXIT_FAILURE); 317*c6402783Sakolb } 318*c6402783Sakolb bzero(*bitmap_array + NLGRPS, 319*c6402783Sakolb (*bitmap_nelements - NLGRPS) * sizeof (char)); 320*c6402783Sakolb } 321*c6402783Sakolb 322*c6402783Sakolb /* 323*c6402783Sakolb * Insert lgroup into bitmap and update max lgroup ID seen so far 324*c6402783Sakolb */ 325*c6402783Sakolb (*bitmap_array)[lgrpid] = 1; 326*c6402783Sakolb if (lgrpid > max_lgrpid) 327*c6402783Sakolb max_lgrpid = lgrpid; 328*c6402783Sakolb 329*c6402783Sakolb /* 330*c6402783Sakolb * Get children of specified lgroup and insert descendants of each 331*c6402783Sakolb * of them 332*c6402783Sakolb */ 333*c6402783Sakolb nchildren = lgrp_children(cookie, lgrpid, NULL, 0); 334*c6402783Sakolb if (nchildren > 0) { 335*c6402783Sakolb children = malloc(nchildren * sizeof (lgrp_id_t)); 336*c6402783Sakolb if (children == NULL) { 337*c6402783Sakolb (void) fprintf(stderr, gettext("%s: out of memory\n"), 338*c6402783Sakolb progname); 339*c6402783Sakolb exit(EXIT_FAILURE); 340*c6402783Sakolb } 341*c6402783Sakolb if (lgrp_children(cookie, lgrpid, children, nchildren) != 342*c6402783Sakolb nchildren) { 343*c6402783Sakolb free(children); 344*c6402783Sakolb return; 345*c6402783Sakolb } 346*c6402783Sakolb 347*c6402783Sakolb for (i = 0; i < nchildren; i++) 348*c6402783Sakolb lgrps_bitmap_init(cookie, children[i], bitmap_array, 349*c6402783Sakolb bitmap_nelements); 350*c6402783Sakolb 351*c6402783Sakolb free(children); 352*c6402783Sakolb } 353*c6402783Sakolb } 354*c6402783Sakolb 355*c6402783Sakolb 356*c6402783Sakolb /* 357*c6402783Sakolb * Parse lgroup affinity from given string 358*c6402783Sakolb * 359*c6402783Sakolb * Return lgroup affinity or LGRP_AFF_INVALID if string doesn't match any 360*c6402783Sakolb * existing lgroup affinity and return pointer to position just after affinity 361*c6402783Sakolb * string. 362*c6402783Sakolb */ 363*c6402783Sakolb static lgrp_affinity_t 364*c6402783Sakolb parse_lgrp_affinity(char *string, char **next) 365*c6402783Sakolb { 366*c6402783Sakolb int rc = LGRP_AFF_INVALID; 367*c6402783Sakolb 368*c6402783Sakolb if (string == NULL) 369*c6402783Sakolb return (LGRP_AFF_INVALID); 370*c6402783Sakolb 371*c6402783Sakolb /* 372*c6402783Sakolb * Skip delimiter 373*c6402783Sakolb */ 374*c6402783Sakolb if (string[0] == DELIMIT_AFF) 375*c6402783Sakolb string++; 376*c6402783Sakolb 377*c6402783Sakolb /* 378*c6402783Sakolb * Return lgroup affinity matching string 379*c6402783Sakolb */ 380*c6402783Sakolb if (strncmp(string, LGRP_AFF_NONE_STR, strlen(LGRP_AFF_NONE_STR)) 381*c6402783Sakolb == 0) { 382*c6402783Sakolb rc = LGRP_AFF_NONE; 383*c6402783Sakolb *next = string + strlen(LGRP_AFF_NONE_STR); 384*c6402783Sakolb } else if (strncmp(string, 385*c6402783Sakolb LGRP_AFF_WEAK_STR, strlen(LGRP_AFF_WEAK_STR)) == 0) { 386*c6402783Sakolb rc = LGRP_AFF_WEAK; 387*c6402783Sakolb *next = string + strlen(LGRP_AFF_WEAK_STR); 388*c6402783Sakolb } else if (strncmp(string, LGRP_AFF_STRONG_STR, 389*c6402783Sakolb strlen(LGRP_AFF_STRONG_STR)) == 0) { 390*c6402783Sakolb rc = LGRP_AFF_STRONG; 391*c6402783Sakolb *next = string + strlen(LGRP_AFF_STRONG_STR); 392*c6402783Sakolb } 393*c6402783Sakolb 394*c6402783Sakolb return (rc); 395*c6402783Sakolb } 396*c6402783Sakolb 397*c6402783Sakolb 398*c6402783Sakolb /* 399*c6402783Sakolb * Parse lgroups from given string 400*c6402783Sakolb * Returns the set containing all lgroups parsed or NULL. 401*c6402783Sakolb */ 402*c6402783Sakolb static int 403*c6402783Sakolb parse_lgrps(lgrp_cookie_t cookie, plgrp_args_t *arg, char *s) 404*c6402783Sakolb { 405*c6402783Sakolb lgrp_id_t i; 406*c6402783Sakolb char *token; 407*c6402783Sakolb 408*c6402783Sakolb if (cookie == LGRP_COOKIE_NONE || s == NULL || NLGRPS <= 0) 409*c6402783Sakolb return (0); 410*c6402783Sakolb 411*c6402783Sakolb /* 412*c6402783Sakolb * Parse first lgroup (if any) 413*c6402783Sakolb */ 414*c6402783Sakolb token = strtok(s, DELIMIT_LGRP); 415*c6402783Sakolb if (token == NULL) 416*c6402783Sakolb return (-1); 417*c6402783Sakolb 418*c6402783Sakolb do { 419*c6402783Sakolb /* 420*c6402783Sakolb * Parse lgroups 421*c6402783Sakolb */ 422*c6402783Sakolb if (isdigit(*token)) { 423*c6402783Sakolb lgrp_id_t first; 424*c6402783Sakolb lgrp_id_t last; 425*c6402783Sakolb char *p; 426*c6402783Sakolb 427*c6402783Sakolb /* 428*c6402783Sakolb * lgroup ID(s) 429*c6402783Sakolb * 430*c6402783Sakolb * Can be <lgroup ID>[-<lgroup ID>] 431*c6402783Sakolb */ 432*c6402783Sakolb p = strchr(token, DELIMIT_RANGE); 433*c6402783Sakolb first = atoi(token); 434*c6402783Sakolb if (p == NULL) 435*c6402783Sakolb last = first; 436*c6402783Sakolb else 437*c6402783Sakolb last = atoi(++p); 438*c6402783Sakolb 439*c6402783Sakolb for (i = first; i <= last; i++) { 440*c6402783Sakolb /* 441*c6402783Sakolb * Add valid lgroups to lgroup array 442*c6402783Sakolb */ 443*c6402783Sakolb if ((i >= 0) && (i < NLGRPS) && LGRP_VALID(i)) 444*c6402783Sakolb lgrps_add_lgrp(arg, i); 445*c6402783Sakolb else { 446*c6402783Sakolb (void) fprintf(stderr, 447*c6402783Sakolb gettext("%s: bad lgroup %d\n"), 448*c6402783Sakolb progname, i); 449*c6402783Sakolb nerrors++; 450*c6402783Sakolb } 451*c6402783Sakolb } 452*c6402783Sakolb } else if (strncmp(token, LGRP_ALL_STR, 453*c6402783Sakolb strlen(LGRP_ALL_STR)) == 0) { 454*c6402783Sakolb /* 455*c6402783Sakolb * Add "all" lgroups to lgroups array 456*c6402783Sakolb */ 457*c6402783Sakolb for (i = 0; i < NLGRPS; i++) { 458*c6402783Sakolb if (LGRP_VALID(i)) 459*c6402783Sakolb lgrps_add_lgrp(arg, i); 460*c6402783Sakolb } 461*c6402783Sakolb } else if (strncmp(token, LGRP_ROOT_STR, 462*c6402783Sakolb strlen(LGRP_ROOT_STR)) == 0) { 463*c6402783Sakolb if (root < 0) 464*c6402783Sakolb root = lgrp_root(cookie); 465*c6402783Sakolb lgrps_add_lgrp(arg, root); 466*c6402783Sakolb } else if (strncmp(token, LGRP_LEAVES_STR, 467*c6402783Sakolb strlen(LGRP_LEAVES_STR)) == 0) { 468*c6402783Sakolb /* 469*c6402783Sakolb * Add leaf lgroups to lgroups array 470*c6402783Sakolb */ 471*c6402783Sakolb for (i = 0; i < NLGRPS; i++) { 472*c6402783Sakolb if (LGRP_VALID(i) && 473*c6402783Sakolb lgrp_children(cookie, i, NULL, 0) == 0) 474*c6402783Sakolb lgrps_add_lgrp(arg, i); 475*c6402783Sakolb } 476*c6402783Sakolb } else { 477*c6402783Sakolb return (-1); 478*c6402783Sakolb } 479*c6402783Sakolb } while (token = strtok(NULL, DELIMIT_LGRP)); 480*c6402783Sakolb 481*c6402783Sakolb return (0); 482*c6402783Sakolb } 483*c6402783Sakolb 484*c6402783Sakolb /* 485*c6402783Sakolb * Print array of lgroup IDs, collapsing any consecutive runs of IDs into a 486*c6402783Sakolb * range (eg. 2,3,4 into 2-4) 487*c6402783Sakolb */ 488*c6402783Sakolb static void 489*c6402783Sakolb print_lgrps(lgrp_id_t *lgrps, int nlgrps) 490*c6402783Sakolb { 491*c6402783Sakolb lgrp_id_t start; 492*c6402783Sakolb lgrp_id_t end; 493*c6402783Sakolb int i; 494*c6402783Sakolb 495*c6402783Sakolb /* 496*c6402783Sakolb * Initial range consists of the first element 497*c6402783Sakolb */ 498*c6402783Sakolb start = end = lgrps[0]; 499*c6402783Sakolb 500*c6402783Sakolb for (i = 1; i < nlgrps; i++) { 501*c6402783Sakolb lgrp_id_t lgrpid; 502*c6402783Sakolb 503*c6402783Sakolb lgrpid = lgrps[i]; 504*c6402783Sakolb if (lgrpid == end + 1) { 505*c6402783Sakolb /* 506*c6402783Sakolb * Got consecutive lgroup ID, so extend end of range 507*c6402783Sakolb * without printing anything since the range may extend 508*c6402783Sakolb * further 509*c6402783Sakolb */ 510*c6402783Sakolb end = lgrpid; 511*c6402783Sakolb } else { 512*c6402783Sakolb /* 513*c6402783Sakolb * Next lgroup ID is not consecutive, so print lgroup 514*c6402783Sakolb * IDs gotten so far. 515*c6402783Sakolb */ 516*c6402783Sakolb if (end == start) { /* same value */ 517*c6402783Sakolb (void) printf("%d,", (int)start); 518*c6402783Sakolb } else if (end > start + 1) { /* range */ 519*c6402783Sakolb (void) printf("%d-%d,", (int)start, (int)end); 520*c6402783Sakolb } else { /* different values */ 521*c6402783Sakolb (void) printf("%d,%d,", (int)start, (int)end); 522*c6402783Sakolb } 523*c6402783Sakolb 524*c6402783Sakolb /* 525*c6402783Sakolb * Try finding consecutive range starting from this 526*c6402783Sakolb * lgroup ID 527*c6402783Sakolb */ 528*c6402783Sakolb start = end = lgrpid; 529*c6402783Sakolb } 530*c6402783Sakolb } 531*c6402783Sakolb 532*c6402783Sakolb /* 533*c6402783Sakolb * Print last lgroup ID(s) 534*c6402783Sakolb */ 535*c6402783Sakolb if (end == start) { 536*c6402783Sakolb (void) printf("%d", (int)start); 537*c6402783Sakolb } else if (end > start + 1) { 538*c6402783Sakolb (void) printf("%d-%d", (int)start, (int)end); 539*c6402783Sakolb } else { 540*c6402783Sakolb (void) printf("%d,%d", (int)start, (int)end); 541*c6402783Sakolb } 542*c6402783Sakolb } 543*c6402783Sakolb 544*c6402783Sakolb /* 545*c6402783Sakolb * Print lgroup affinities given array of lgroups, corresponding array of 546*c6402783Sakolb * affinities, and number of elements. 547*c6402783Sakolb * Skip any lgroups set to LGRP_NONE or having invalid affinity. 548*c6402783Sakolb */ 549*c6402783Sakolb static void 550*c6402783Sakolb print_affinities(lgrp_id_t *lgrps, lgrp_affinity_t *affs, int nelements) 551*c6402783Sakolb { 552*c6402783Sakolb int i; 553*c6402783Sakolb lgrp_id_t *lgrps_none; 554*c6402783Sakolb lgrp_id_t *lgrps_strong; 555*c6402783Sakolb lgrp_id_t *lgrps_weak; 556*c6402783Sakolb int nlgrps_none; 557*c6402783Sakolb int nlgrps_strong; 558*c6402783Sakolb int nlgrps_weak; 559*c6402783Sakolb 560*c6402783Sakolb nlgrps_strong = nlgrps_weak = nlgrps_none = 0; 561*c6402783Sakolb 562*c6402783Sakolb lgrps_strong = malloc(nelements * sizeof (lgrp_id_t)); 563*c6402783Sakolb lgrps_weak = malloc(nelements * sizeof (lgrp_id_t)); 564*c6402783Sakolb lgrps_none = malloc(nelements * sizeof (lgrp_id_t)); 565*c6402783Sakolb 566*c6402783Sakolb if (lgrps_strong == NULL || lgrps_weak == NULL || lgrps_none == NULL) { 567*c6402783Sakolb (void) fprintf(stderr, gettext("%s: out of memory\n"), 568*c6402783Sakolb progname); 569*c6402783Sakolb interrupt = 1; 570*c6402783Sakolb return; 571*c6402783Sakolb } 572*c6402783Sakolb 573*c6402783Sakolb /* 574*c6402783Sakolb * Group lgroups by affinity 575*c6402783Sakolb */ 576*c6402783Sakolb for (i = 0; i < nelements; i++) { 577*c6402783Sakolb lgrp_id_t lgrpid = lgrps[i]; 578*c6402783Sakolb 579*c6402783Sakolb /* 580*c6402783Sakolb * Skip any lgroups set to LGRP_NONE 581*c6402783Sakolb */ 582*c6402783Sakolb if (lgrpid == LGRP_NONE) 583*c6402783Sakolb continue; 584*c6402783Sakolb 585*c6402783Sakolb switch (affs[i]) { 586*c6402783Sakolb case LGRP_AFF_STRONG: 587*c6402783Sakolb lgrps_strong[nlgrps_strong++] = lgrpid; 588*c6402783Sakolb break; 589*c6402783Sakolb case LGRP_AFF_WEAK: 590*c6402783Sakolb lgrps_weak[nlgrps_weak++] = lgrpid; 591*c6402783Sakolb break; 592*c6402783Sakolb case LGRP_AFF_NONE: 593*c6402783Sakolb lgrps_none[nlgrps_none++] = lgrpid; 594*c6402783Sakolb break; 595*c6402783Sakolb default: 596*c6402783Sakolb /* 597*c6402783Sakolb * Skip any lgroups with invalid affinity. 598*c6402783Sakolb */ 599*c6402783Sakolb break; 600*c6402783Sakolb } 601*c6402783Sakolb } 602*c6402783Sakolb 603*c6402783Sakolb /* 604*c6402783Sakolb * Print all lgroups with same affinity together 605*c6402783Sakolb */ 606*c6402783Sakolb if (nlgrps_strong) { 607*c6402783Sakolb print_lgrps(lgrps_strong, nlgrps_strong); 608*c6402783Sakolb (void) printf("/%s", lgrp_affinity_string(LGRP_AFF_STRONG)); 609*c6402783Sakolb if (nlgrps_weak || nlgrps_none) 610*c6402783Sakolb (void) printf("%c", DELIMIT_AFF_LST); 611*c6402783Sakolb } 612*c6402783Sakolb 613*c6402783Sakolb if (nlgrps_weak) { 614*c6402783Sakolb print_lgrps(lgrps_weak, nlgrps_weak); 615*c6402783Sakolb (void) printf("/%s", lgrp_affinity_string(LGRP_AFF_WEAK)); 616*c6402783Sakolb if (nlgrps_none) 617*c6402783Sakolb (void) printf("%c", DELIMIT_AFF_LST); 618*c6402783Sakolb } 619*c6402783Sakolb 620*c6402783Sakolb if (nlgrps_none) { 621*c6402783Sakolb print_lgrps(lgrps_none, nlgrps_none); 622*c6402783Sakolb (void) printf("/%s", lgrp_affinity_string(LGRP_AFF_NONE)); 623*c6402783Sakolb } 624*c6402783Sakolb 625*c6402783Sakolb free(lgrps_strong); 626*c6402783Sakolb free(lgrps_weak); 627*c6402783Sakolb free(lgrps_none); 628*c6402783Sakolb } 629*c6402783Sakolb 630*c6402783Sakolb 631*c6402783Sakolb /* 632*c6402783Sakolb * Print heading for specified operation 633*c6402783Sakolb */ 634*c6402783Sakolb static void 635*c6402783Sakolb print_heading(plgrp_ops_t op) 636*c6402783Sakolb { 637*c6402783Sakolb 638*c6402783Sakolb switch (op) { 639*c6402783Sakolb case PLGRP_AFFINITY_GET: 640*c6402783Sakolb (void) printf(HDR_PLGRP_AFF_GET); 641*c6402783Sakolb break; 642*c6402783Sakolb 643*c6402783Sakolb case PLGRP_AFFINITY_SET: 644*c6402783Sakolb (void) printf(HDR_PLGRP_AFF_SET); 645*c6402783Sakolb break; 646*c6402783Sakolb 647*c6402783Sakolb case PLGRP_HOME_GET: 648*c6402783Sakolb (void) printf(HDR_PLGRP_HOME_GET); 649*c6402783Sakolb break; 650*c6402783Sakolb 651*c6402783Sakolb case PLGRP_HOME_SET: 652*c6402783Sakolb (void) printf(HDR_PLGRP_HOME_SET); 653*c6402783Sakolb break; 654*c6402783Sakolb 655*c6402783Sakolb default: 656*c6402783Sakolb break; 657*c6402783Sakolb } 658*c6402783Sakolb } 659*c6402783Sakolb 660*c6402783Sakolb /* 661*c6402783Sakolb * Use /proc to call lgrp_affinity_get() in another process 662*c6402783Sakolb */ 663*c6402783Sakolb static lgrp_affinity_t 664*c6402783Sakolb Plgrp_affinity_get(struct ps_prochandle *Ph, idtype_t idtype, id_t id, 665*c6402783Sakolb lgrp_id_t lgrp) 666*c6402783Sakolb { 667*c6402783Sakolb lgrp_affinity_args_t args; 668*c6402783Sakolb argdes_t Pargd[3]; 669*c6402783Sakolb argdes_t *Pargdp; 670*c6402783Sakolb int Pnargs; 671*c6402783Sakolb int Pretval; 672*c6402783Sakolb sysret_t retval; 673*c6402783Sakolb int syscall; 674*c6402783Sakolb 675*c6402783Sakolb /* 676*c6402783Sakolb * Fill in arguments needed for syscall(SYS_lgrpsys, 677*c6402783Sakolb * LGRP_SYS_AFFINITY_GET, 0, &args) 678*c6402783Sakolb */ 679*c6402783Sakolb syscall = SYS_lgrpsys; 680*c6402783Sakolb 681*c6402783Sakolb args.idtype = idtype; 682*c6402783Sakolb args.id = id; 683*c6402783Sakolb args.lgrp = lgrp; 684*c6402783Sakolb args.aff = LGRP_AFF_INVALID; 685*c6402783Sakolb 686*c6402783Sakolb /* 687*c6402783Sakolb * Fill out /proc argument descriptors for syscall(SYS_lgrpsys, 688*c6402783Sakolb * LGRP_SYS_AFFINITY_GET, idtype, id) 689*c6402783Sakolb */ 690*c6402783Sakolb Pnargs = LGRPSYS_NARGS; 691*c6402783Sakolb Pargdp = &Pargd[0]; 692*c6402783Sakolb Pargdp->arg_value = LGRP_SYS_AFFINITY_GET; 693*c6402783Sakolb Pargdp->arg_object = NULL; 694*c6402783Sakolb Pargdp->arg_type = AT_BYVAL; 695*c6402783Sakolb Pargdp->arg_inout = AI_INPUT; 696*c6402783Sakolb Pargdp->arg_size = 0; 697*c6402783Sakolb Pargdp++; 698*c6402783Sakolb 699*c6402783Sakolb Pargdp->arg_value = 0; 700*c6402783Sakolb Pargdp->arg_object = NULL; 701*c6402783Sakolb Pargdp->arg_type = AT_BYVAL; 702*c6402783Sakolb Pargdp->arg_inout = AI_INPUT; 703*c6402783Sakolb Pargdp->arg_size = 0; 704*c6402783Sakolb Pargdp++; 705*c6402783Sakolb 706*c6402783Sakolb Pargdp->arg_value = 0; 707*c6402783Sakolb Pargdp->arg_object = &args; 708*c6402783Sakolb Pargdp->arg_type = AT_BYREF; 709*c6402783Sakolb Pargdp->arg_inout = AI_INPUT; 710*c6402783Sakolb Pargdp->arg_size = sizeof (lgrp_affinity_args_t); 711*c6402783Sakolb Pargdp++; 712*c6402783Sakolb 713*c6402783Sakolb /* 714*c6402783Sakolb * Have agent LWP call syscall with appropriate arguments in target 715*c6402783Sakolb * process 716*c6402783Sakolb */ 717*c6402783Sakolb Pretval = Psyscall(Ph, &retval, syscall, Pnargs, &Pargd[0]); 718*c6402783Sakolb if (Pretval) { 719*c6402783Sakolb errno = (Pretval < 0) ? ENOSYS : Pretval; 720*c6402783Sakolb return (LGRP_AFF_INVALID); 721*c6402783Sakolb } 722*c6402783Sakolb 723*c6402783Sakolb return (retval.sys_rval1); 724*c6402783Sakolb } 725*c6402783Sakolb 726*c6402783Sakolb 727*c6402783Sakolb /* 728*c6402783Sakolb * Use /proc to call lgrp_affinity_set() in another process 729*c6402783Sakolb */ 730*c6402783Sakolb static int 731*c6402783Sakolb Plgrp_affinity_set(struct ps_prochandle *Ph, idtype_t idtype, id_t id, 732*c6402783Sakolb lgrp_id_t lgrp, lgrp_affinity_t aff) 733*c6402783Sakolb { 734*c6402783Sakolb lgrp_affinity_args_t args; 735*c6402783Sakolb argdes_t Pargd[3]; 736*c6402783Sakolb argdes_t *Pargdp; 737*c6402783Sakolb int Pnargs; 738*c6402783Sakolb int Pretval; 739*c6402783Sakolb sysret_t retval; 740*c6402783Sakolb int syscall; 741*c6402783Sakolb 742*c6402783Sakolb /* 743*c6402783Sakolb * Fill in arguments needed for syscall(SYS_lgrpsys, 744*c6402783Sakolb * LGRP_SYS_AFFINITY_SET, 0, &args) 745*c6402783Sakolb */ 746*c6402783Sakolb syscall = SYS_lgrpsys; 747*c6402783Sakolb 748*c6402783Sakolb args.idtype = idtype; 749*c6402783Sakolb args.id = id; 750*c6402783Sakolb args.lgrp = lgrp; 751*c6402783Sakolb args.aff = aff; 752*c6402783Sakolb 753*c6402783Sakolb /* 754*c6402783Sakolb * Fill out /proc argument descriptors for syscall(SYS_lgrpsys, 755*c6402783Sakolb * LGRP_SYS_AFFINITY_SET, idtype, id) 756*c6402783Sakolb */ 757*c6402783Sakolb Pnargs = LGRPSYS_NARGS; 758*c6402783Sakolb Pargdp = &Pargd[0]; 759*c6402783Sakolb Pargdp->arg_value = LGRP_SYS_AFFINITY_SET; 760*c6402783Sakolb Pargdp->arg_object = NULL; 761*c6402783Sakolb Pargdp->arg_type = AT_BYVAL; 762*c6402783Sakolb Pargdp->arg_inout = AI_INPUT; 763*c6402783Sakolb Pargdp->arg_size = 0; 764*c6402783Sakolb Pargdp++; 765*c6402783Sakolb 766*c6402783Sakolb Pargdp->arg_value = 0; 767*c6402783Sakolb Pargdp->arg_object = NULL; 768*c6402783Sakolb Pargdp->arg_type = AT_BYVAL; 769*c6402783Sakolb Pargdp->arg_inout = AI_INPUT; 770*c6402783Sakolb Pargdp->arg_size = 0; 771*c6402783Sakolb Pargdp++; 772*c6402783Sakolb 773*c6402783Sakolb Pargdp->arg_value = 0; 774*c6402783Sakolb Pargdp->arg_object = &args; 775*c6402783Sakolb Pargdp->arg_type = AT_BYREF; 776*c6402783Sakolb Pargdp->arg_inout = AI_INPUT; 777*c6402783Sakolb Pargdp->arg_size = sizeof (lgrp_affinity_args_t); 778*c6402783Sakolb Pargdp++; 779*c6402783Sakolb 780*c6402783Sakolb /* 781*c6402783Sakolb * Have agent LWP call syscall with appropriate arguments in 782*c6402783Sakolb * target process 783*c6402783Sakolb */ 784*c6402783Sakolb Pretval = Psyscall(Ph, &retval, syscall, Pnargs, &Pargd[0]); 785*c6402783Sakolb if (Pretval) { 786*c6402783Sakolb errno = (Pretval < 0) ? ENOSYS : Pretval; 787*c6402783Sakolb return (-1); 788*c6402783Sakolb } 789*c6402783Sakolb 790*c6402783Sakolb return (retval.sys_rval1); 791*c6402783Sakolb } 792*c6402783Sakolb 793*c6402783Sakolb /* 794*c6402783Sakolb * Use /proc to call lgrp_home() in another process 795*c6402783Sakolb */ 796*c6402783Sakolb static lgrp_id_t 797*c6402783Sakolb Plgrp_home(struct ps_prochandle *Ph, idtype_t idtype, id_t id) 798*c6402783Sakolb { 799*c6402783Sakolb argdes_t Pargd[3]; 800*c6402783Sakolb argdes_t *Pargdp; 801*c6402783Sakolb int Pnargs; 802*c6402783Sakolb int Pretval; 803*c6402783Sakolb sysret_t retval; 804*c6402783Sakolb int syscall; 805*c6402783Sakolb 806*c6402783Sakolb /* 807*c6402783Sakolb * Fill in arguments needed for syscall(SYS_lgrpsys, 808*c6402783Sakolb * LGRP_SYS_HOME, idtype, id) 809*c6402783Sakolb */ 810*c6402783Sakolb syscall = SYS_lgrpsys; 811*c6402783Sakolb 812*c6402783Sakolb /* 813*c6402783Sakolb * Fill out /proc argument descriptors for syscall(SYS_lgrpsys, 814*c6402783Sakolb * LGRP_SYS_HOME, idtype, id) 815*c6402783Sakolb */ 816*c6402783Sakolb Pnargs = LGRPSYS_NARGS; 817*c6402783Sakolb Pargdp = &Pargd[0]; 818*c6402783Sakolb Pargdp->arg_value = LGRP_SYS_HOME; 819*c6402783Sakolb Pargdp->arg_object = NULL; 820*c6402783Sakolb Pargdp->arg_type = AT_BYVAL; 821*c6402783Sakolb Pargdp->arg_inout = AI_INPUT; 822*c6402783Sakolb Pargdp->arg_size = 0; 823*c6402783Sakolb Pargdp++; 824*c6402783Sakolb 825*c6402783Sakolb Pargdp->arg_value = idtype; 826*c6402783Sakolb Pargdp->arg_object = NULL; 827*c6402783Sakolb Pargdp->arg_type = AT_BYVAL; 828*c6402783Sakolb Pargdp->arg_inout = AI_INPUT; 829*c6402783Sakolb Pargdp->arg_size = 0; 830*c6402783Sakolb Pargdp++; 831*c6402783Sakolb 832*c6402783Sakolb Pargdp->arg_value = id; 833*c6402783Sakolb Pargdp->arg_object = NULL; 834*c6402783Sakolb Pargdp->arg_type = AT_BYVAL; 835*c6402783Sakolb Pargdp->arg_inout = AI_INPUT; 836*c6402783Sakolb Pargdp->arg_size = 0; 837*c6402783Sakolb Pargdp++; 838*c6402783Sakolb 839*c6402783Sakolb /* 840*c6402783Sakolb * Have agent LWP call syscall with appropriate arguments in 841*c6402783Sakolb * target process 842*c6402783Sakolb */ 843*c6402783Sakolb Pretval = Psyscall(Ph, &retval, syscall, Pnargs, &Pargd[0]); 844*c6402783Sakolb if (Pretval) { 845*c6402783Sakolb errno = (Pretval < 0) ? ENOSYS : Pretval; 846*c6402783Sakolb return (-1); 847*c6402783Sakolb } 848*c6402783Sakolb 849*c6402783Sakolb return (retval.sys_rval1); 850*c6402783Sakolb } 851*c6402783Sakolb 852*c6402783Sakolb /* 853*c6402783Sakolb * Use /proc to call lgrp_affinity_set(3LGRP) to set home lgroup of given 854*c6402783Sakolb * thread 855*c6402783Sakolb */ 856*c6402783Sakolb static int 857*c6402783Sakolb Plgrp_home_set(struct ps_prochandle *Ph, idtype_t idtype, id_t id, 858*c6402783Sakolb lgrp_id_t lgrp) 859*c6402783Sakolb { 860*c6402783Sakolb return (Plgrp_affinity_set(Ph, idtype, id, lgrp, 861*c6402783Sakolb LGRP_AFF_STRONG)); 862*c6402783Sakolb } 863*c6402783Sakolb 864*c6402783Sakolb 865*c6402783Sakolb /* 866*c6402783Sakolb * Do plgrp(1) operation on specified thread 867*c6402783Sakolb */ 868*c6402783Sakolb static int 869*c6402783Sakolb do_op(plgrp_args_t *plgrp_args, id_t pid, id_t lwpid, 870*c6402783Sakolb const lwpsinfo_t *lwpsinfo) 871*c6402783Sakolb { 872*c6402783Sakolb lgrp_affinity_t *affs; 873*c6402783Sakolb lgrp_affinity_t *cur_affs; 874*c6402783Sakolb lgrp_id_t home; 875*c6402783Sakolb int i; 876*c6402783Sakolb lgrp_affinity_t *init_affs; 877*c6402783Sakolb lgrp_id_t *lgrps; 878*c6402783Sakolb lgrp_id_t *lgrps_changed; 879*c6402783Sakolb int nlgrps; 880*c6402783Sakolb lgrp_id_t old_home; 881*c6402783Sakolb lgrp_id_t lgrpid; 882*c6402783Sakolb struct ps_prochandle *Ph; 883*c6402783Sakolb int nchanged; 884*c6402783Sakolb 885*c6402783Sakolb /* 886*c6402783Sakolb * No args, so nothing to do. 887*c6402783Sakolb */ 888*c6402783Sakolb if (plgrp_args == NULL) 889*c6402783Sakolb return (0); 890*c6402783Sakolb 891*c6402783Sakolb /* 892*c6402783Sakolb * Unpack plgrp(1) arguments and state needed to process this LWP 893*c6402783Sakolb */ 894*c6402783Sakolb Ph = plgrp_args->Ph; 895*c6402783Sakolb lgrps = plgrp_args->lgrps; 896*c6402783Sakolb affs = plgrp_args->affs; 897*c6402783Sakolb nlgrps = plgrp_args->nlgrps; 898*c6402783Sakolb 899*c6402783Sakolb switch (plgrp_args->op) { 900*c6402783Sakolb 901*c6402783Sakolb case PLGRP_HOME_GET: 902*c6402783Sakolb /* 903*c6402783Sakolb * Get and display home lgroup for given LWP 904*c6402783Sakolb */ 905*c6402783Sakolb home = lwpsinfo->pr_lgrp; 906*c6402783Sakolb (void) printf(FMT_HOME"\n", (int)home); 907*c6402783Sakolb break; 908*c6402783Sakolb 909*c6402783Sakolb case PLGRP_AFFINITY_GET: 910*c6402783Sakolb /* 911*c6402783Sakolb * Get and display this LWP's home lgroup and affinities 912*c6402783Sakolb * for specified lgroups 913*c6402783Sakolb */ 914*c6402783Sakolb home = lwpsinfo->pr_lgrp; 915*c6402783Sakolb (void) printf(FMT_HOME, (int)home); 916*c6402783Sakolb 917*c6402783Sakolb /* 918*c6402783Sakolb * Collect affinity values 919*c6402783Sakolb */ 920*c6402783Sakolb for (i = 0; i < nlgrps; i++) { 921*c6402783Sakolb affs[i] = Plgrp_affinity_get(Ph, P_LWPID, lwpid, 922*c6402783Sakolb lgrps[i]); 923*c6402783Sakolb 924*c6402783Sakolb if (affs[i] == LGRP_AFF_INVALID) { 925*c6402783Sakolb nerrors++; 926*c6402783Sakolb (void) fprintf(stderr, 927*c6402783Sakolb gettext("%s: cannot get affinity" 928*c6402783Sakolb " for lgroup %d for %d/%d: %s\n"), 929*c6402783Sakolb progname, lgrps[i], pid, lwpid, 930*c6402783Sakolb strerror(errno)); 931*c6402783Sakolb } 932*c6402783Sakolb } 933*c6402783Sakolb 934*c6402783Sakolb /* 935*c6402783Sakolb * Print affinities for each type. 936*c6402783Sakolb */ 937*c6402783Sakolb print_affinities(lgrps, affs, nlgrps); 938*c6402783Sakolb (void) printf("\n"); 939*c6402783Sakolb 940*c6402783Sakolb break; 941*c6402783Sakolb 942*c6402783Sakolb case PLGRP_HOME_SET: 943*c6402783Sakolb /* 944*c6402783Sakolb * Get home lgroup before and after setting it and display 945*c6402783Sakolb * change. If more than one lgroup and one LWP are specified, 946*c6402783Sakolb * then home LWPs to lgroups in round robin fashion. 947*c6402783Sakolb */ 948*c6402783Sakolb old_home = lwpsinfo->pr_lgrp; 949*c6402783Sakolb 950*c6402783Sakolb i = plgrp_args->index; 951*c6402783Sakolb if (Plgrp_home_set(Ph, P_LWPID, lwpid, lgrps[i]) != 0) { 952*c6402783Sakolb nerrors++; 953*c6402783Sakolb (void) fprintf(stderr, 954*c6402783Sakolb gettext("%s: cannot set home lgroup of %d/%d" 955*c6402783Sakolb " to lgroup %d: %s\n"), 956*c6402783Sakolb progname, pid, lwpid, lgrps[i], 957*c6402783Sakolb strerror(errno)); 958*c6402783Sakolb (void) printf("\n"); 959*c6402783Sakolb } else { 960*c6402783Sakolb int len; 961*c6402783Sakolb int width = strlen(HDR_PLGRP_HOME_CHANGE); 962*c6402783Sakolb 963*c6402783Sakolb home = Plgrp_home(Ph, P_LWPID, lwpid); 964*c6402783Sakolb 965*c6402783Sakolb if (home < 0) { 966*c6402783Sakolb (void) fprintf(stderr, 967*c6402783Sakolb gettext("%s cannot get home lgroup for" 968*c6402783Sakolb " %d/%d: %s\n"), 969*c6402783Sakolb progname, pid, lwpid, strerror(errno)); 970*c6402783Sakolb nerrors++; 971*c6402783Sakolb } 972*c6402783Sakolb 973*c6402783Sakolb len = printf(FMT_NEWHOME, (int)old_home, (int)home); 974*c6402783Sakolb if (len < width) 975*c6402783Sakolb (void) printf("%*c\n", (int)(width - len), ' '); 976*c6402783Sakolb } 977*c6402783Sakolb 978*c6402783Sakolb plgrp_args->index = (i + 1) % nlgrps; 979*c6402783Sakolb 980*c6402783Sakolb break; 981*c6402783Sakolb 982*c6402783Sakolb case PLGRP_AFFINITY_SET: 983*c6402783Sakolb /* 984*c6402783Sakolb * Set affinities for specified lgroups and print old and new 985*c6402783Sakolb * affinities and any resulting change in home lgroups 986*c6402783Sakolb */ 987*c6402783Sakolb 988*c6402783Sakolb /* 989*c6402783Sakolb * Get initial home lgroup as it may change. 990*c6402783Sakolb */ 991*c6402783Sakolb old_home = lwpsinfo->pr_lgrp; 992*c6402783Sakolb 993*c6402783Sakolb /* 994*c6402783Sakolb * Need to allocate arrays indexed by lgroup (ID) for 995*c6402783Sakolb * affinities and lgroups because user may specify affinity 996*c6402783Sakolb * for same lgroup multiple times.... 997*c6402783Sakolb * 998*c6402783Sakolb * Keeping these arrays by lgroup (ID) eliminates any 999*c6402783Sakolb * duplication and makes it easier to just print initial and 1000*c6402783Sakolb * final lgroup affinities (instead of trying to keep a list 1001*c6402783Sakolb * of lgroups specified which may include duplicates) 1002*c6402783Sakolb */ 1003*c6402783Sakolb init_affs = malloc(NLGRPS * sizeof (lgrp_affinity_t)); 1004*c6402783Sakolb cur_affs = malloc(NLGRPS * sizeof (lgrp_affinity_t)); 1005*c6402783Sakolb lgrps_changed = malloc(NLGRPS * sizeof (lgrp_id_t)); 1006*c6402783Sakolb 1007*c6402783Sakolb if (init_affs == NULL || cur_affs == NULL || 1008*c6402783Sakolb lgrps_changed == NULL) { 1009*c6402783Sakolb (void) fprintf(stderr, gettext("%s: out of memory\n"), 1010*c6402783Sakolb progname); 1011*c6402783Sakolb Prelease(Ph, PRELEASE_RETAIN); 1012*c6402783Sakolb exit(EXIT_NONFATAL); 1013*c6402783Sakolb } 1014*c6402783Sakolb 1015*c6402783Sakolb /* 1016*c6402783Sakolb * Initialize current and initial lgroup affinities and 1017*c6402783Sakolb * lgroups changed 1018*c6402783Sakolb */ 1019*c6402783Sakolb for (lgrpid = 0; lgrpid < NLGRPS; lgrpid++) { 1020*c6402783Sakolb 1021*c6402783Sakolb if (!LGRP_VALID(lgrpid)) { 1022*c6402783Sakolb init_affs[lgrpid] = LGRP_AFF_INVALID; 1023*c6402783Sakolb } else { 1024*c6402783Sakolb init_affs[lgrpid] = 1025*c6402783Sakolb Plgrp_affinity_get(Ph, P_LWPID, 1026*c6402783Sakolb lwpid, lgrpid); 1027*c6402783Sakolb 1028*c6402783Sakolb if (init_affs[lgrpid] == LGRP_AFF_INVALID) { 1029*c6402783Sakolb nerrors++; 1030*c6402783Sakolb (void) fprintf(stderr, 1031*c6402783Sakolb gettext("%s: cannot get" 1032*c6402783Sakolb " affinity for lgroup %d" 1033*c6402783Sakolb " for %d/%d: %s\n"), 1034*c6402783Sakolb progname, lgrpid, pid, lwpid, 1035*c6402783Sakolb strerror(errno)); 1036*c6402783Sakolb } 1037*c6402783Sakolb } 1038*c6402783Sakolb 1039*c6402783Sakolb cur_affs[lgrpid] = init_affs[lgrpid]; 1040*c6402783Sakolb lgrps_changed[lgrpid] = LGRP_NONE; 1041*c6402783Sakolb } 1042*c6402783Sakolb 1043*c6402783Sakolb /* 1044*c6402783Sakolb * Change affinities. 1045*c6402783Sakolb */ 1046*c6402783Sakolb for (i = 0; i < nlgrps; i++) { 1047*c6402783Sakolb lgrp_affinity_t aff = affs[i]; 1048*c6402783Sakolb 1049*c6402783Sakolb lgrpid = lgrps[i]; 1050*c6402783Sakolb 1051*c6402783Sakolb /* 1052*c6402783Sakolb * If the suggested affinity is the same as the current 1053*c6402783Sakolb * one, skip this lgroup. 1054*c6402783Sakolb */ 1055*c6402783Sakolb if (aff == cur_affs[lgrpid]) 1056*c6402783Sakolb continue; 1057*c6402783Sakolb 1058*c6402783Sakolb /* 1059*c6402783Sakolb * Set affinity to the new value 1060*c6402783Sakolb */ 1061*c6402783Sakolb if (Plgrp_affinity_set(Ph, P_LWPID, lwpid, lgrpid, 1062*c6402783Sakolb aff) < 0) { 1063*c6402783Sakolb nerrors++; 1064*c6402783Sakolb (void) fprintf(stderr, 1065*c6402783Sakolb gettext("%s: cannot set" 1066*c6402783Sakolb " %s affinity for lgroup %d" 1067*c6402783Sakolb " for %d/%d: %s\n"), 1068*c6402783Sakolb progname, lgrp_affinity_string(aff), 1069*c6402783Sakolb lgrpid, pid, lwpid, 1070*c6402783Sakolb strerror(errno)); 1071*c6402783Sakolb continue; 1072*c6402783Sakolb } 1073*c6402783Sakolb 1074*c6402783Sakolb /* 1075*c6402783Sakolb * Get the new value and verify that it changed as 1076*c6402783Sakolb * expected. 1077*c6402783Sakolb */ 1078*c6402783Sakolb cur_affs[lgrpid] = 1079*c6402783Sakolb Plgrp_affinity_get(Ph, P_LWPID, lwpid, lgrpid); 1080*c6402783Sakolb 1081*c6402783Sakolb if (cur_affs[lgrpid] == LGRP_AFF_INVALID) { 1082*c6402783Sakolb nerrors++; 1083*c6402783Sakolb (void) fprintf(stderr, 1084*c6402783Sakolb gettext("%s: cannot get" 1085*c6402783Sakolb " affinity for lgroup %d" 1086*c6402783Sakolb " for %d/%d: %s\n"), 1087*c6402783Sakolb progname, lgrpid, pid, lwpid, 1088*c6402783Sakolb strerror(errno)); 1089*c6402783Sakolb continue; 1090*c6402783Sakolb } 1091*c6402783Sakolb 1092*c6402783Sakolb if (aff != cur_affs[lgrpid]) { 1093*c6402783Sakolb (void) fprintf(stderr, 1094*c6402783Sakolb gettext("%s: affinity for" 1095*c6402783Sakolb " lgroup %d is set to %d instead of %d" 1096*c6402783Sakolb " for %d/%d\n"), 1097*c6402783Sakolb progname, lgrpid, cur_affs[lgrpid], aff, 1098*c6402783Sakolb pid, lwpid); 1099*c6402783Sakolb nerrors++; 1100*c6402783Sakolb } 1101*c6402783Sakolb } 1102*c6402783Sakolb 1103*c6402783Sakolb /* 1104*c6402783Sakolb * Compare current and initial affinities and mark lgroups with 1105*c6402783Sakolb * changed affinities. 1106*c6402783Sakolb */ 1107*c6402783Sakolb nchanged = 0; 1108*c6402783Sakolb for (lgrpid = 0; lgrpid < NLGRPS; lgrpid++) { 1109*c6402783Sakolb if (init_affs[lgrpid] != cur_affs[lgrpid]) { 1110*c6402783Sakolb lgrps_changed[lgrpid] = lgrpid; 1111*c6402783Sakolb nchanged++; 1112*c6402783Sakolb } 1113*c6402783Sakolb } 1114*c6402783Sakolb 1115*c6402783Sakolb if (nchanged == 0) { 1116*c6402783Sakolb /* 1117*c6402783Sakolb * Nothing changed, so just print current affinities for 1118*c6402783Sakolb * specified lgroups. 1119*c6402783Sakolb */ 1120*c6402783Sakolb for (i = 0; i < nlgrps; i++) { 1121*c6402783Sakolb lgrps_changed[lgrps[i]] = lgrps[i]; 1122*c6402783Sakolb } 1123*c6402783Sakolb 1124*c6402783Sakolb (void) printf("%-*d", 1125*c6402783Sakolb (int)strlen(HDR_PLGRP_HOME_CHANGE), 1126*c6402783Sakolb (int)old_home); 1127*c6402783Sakolb 1128*c6402783Sakolb print_affinities(lgrps_changed, cur_affs, NLGRPS); 1129*c6402783Sakolb (void) printf("\n"); 1130*c6402783Sakolb } else { 1131*c6402783Sakolb int width = strlen(HDR_PLGRP_HOME_CHANGE); 1132*c6402783Sakolb 1133*c6402783Sakolb /* 1134*c6402783Sakolb * Some lgroup affinities changed, so display old 1135*c6402783Sakolb * and new home lgroups for thread and its old and new 1136*c6402783Sakolb * affinities for affected lgroups 1137*c6402783Sakolb */ 1138*c6402783Sakolb home = Plgrp_home(Ph, P_LWPID, lwpid); 1139*c6402783Sakolb if (home < 0) { 1140*c6402783Sakolb (void) fprintf(stderr, 1141*c6402783Sakolb gettext("%s: cannot get home" 1142*c6402783Sakolb " for %d/%d: %s\n"), 1143*c6402783Sakolb progname, pid, lwpid, strerror(errno)); 1144*c6402783Sakolb nerrors++; 1145*c6402783Sakolb } 1146*c6402783Sakolb if (old_home != home) { 1147*c6402783Sakolb int len; 1148*c6402783Sakolb 1149*c6402783Sakolb /* 1150*c6402783Sakolb * Fit string into fixed width 1151*c6402783Sakolb */ 1152*c6402783Sakolb len = printf(FMT_NEWHOME, 1153*c6402783Sakolb (int)old_home, (int)home); 1154*c6402783Sakolb if (len < width) 1155*c6402783Sakolb (void) printf("%*c", width - len, ' '); 1156*c6402783Sakolb } else { 1157*c6402783Sakolb (void) printf("%-*d", width, (int)home); 1158*c6402783Sakolb } 1159*c6402783Sakolb 1160*c6402783Sakolb /* 1161*c6402783Sakolb * Print change in affinities from old to new 1162*c6402783Sakolb */ 1163*c6402783Sakolb print_affinities(lgrps_changed, init_affs, NLGRPS); 1164*c6402783Sakolb (void) printf(" => "); 1165*c6402783Sakolb print_affinities(lgrps_changed, cur_affs, NLGRPS); 1166*c6402783Sakolb (void) printf("\n"); 1167*c6402783Sakolb } 1168*c6402783Sakolb 1169*c6402783Sakolb free(lgrps_changed); 1170*c6402783Sakolb free(init_affs); 1171*c6402783Sakolb free(cur_affs); 1172*c6402783Sakolb 1173*c6402783Sakolb break; 1174*c6402783Sakolb 1175*c6402783Sakolb default: 1176*c6402783Sakolb break; 1177*c6402783Sakolb } 1178*c6402783Sakolb 1179*c6402783Sakolb return (0); 1180*c6402783Sakolb } 1181*c6402783Sakolb 1182*c6402783Sakolb 1183*c6402783Sakolb /* 1184*c6402783Sakolb * Routine called by Plwp_iter_all() as it iterates through LWPs of another 1185*c6402783Sakolb * process 1186*c6402783Sakolb */ 1187*c6402783Sakolb /* ARGSUSED */ 1188*c6402783Sakolb static int 1189*c6402783Sakolb Plwp_iter_handler(void *arg, const lwpstatus_t *lwpstatus, 1190*c6402783Sakolb const lwpsinfo_t *lwpsinfo) 1191*c6402783Sakolb { 1192*c6402783Sakolb id_t lwpid; 1193*c6402783Sakolb struct ps_prochandle *Ph; 1194*c6402783Sakolb const pstatus_t *pstatus; 1195*c6402783Sakolb plgrp_args_t *plgrp_args; 1196*c6402783Sakolb 1197*c6402783Sakolb /* 1198*c6402783Sakolb * Nothing to do if no arguments 1199*c6402783Sakolb */ 1200*c6402783Sakolb if (arg == NULL || interrupt) 1201*c6402783Sakolb return (0); 1202*c6402783Sakolb 1203*c6402783Sakolb /* 1204*c6402783Sakolb * Unpack plgrp(1) arguments and state needed to process this LWP 1205*c6402783Sakolb */ 1206*c6402783Sakolb plgrp_args = arg; 1207*c6402783Sakolb Ph = plgrp_args->Ph; 1208*c6402783Sakolb 1209*c6402783Sakolb /* 1210*c6402783Sakolb * Just return if no /proc handle for process 1211*c6402783Sakolb */ 1212*c6402783Sakolb if (Ph == NULL) 1213*c6402783Sakolb return (0); 1214*c6402783Sakolb 1215*c6402783Sakolb pstatus = Pstatus(Ph); 1216*c6402783Sakolb 1217*c6402783Sakolb /* 1218*c6402783Sakolb * Skip agent LWP and any LWPs that weren't specified 1219*c6402783Sakolb */ 1220*c6402783Sakolb lwpid = lwpsinfo->pr_lwpid; 1221*c6402783Sakolb if (lwpid == pstatus->pr_agentid || 1222*c6402783Sakolb !proc_lwp_in_set(plgrp_args->lwps, lwpid)) 1223*c6402783Sakolb return (0); 1224*c6402783Sakolb 1225*c6402783Sakolb plgrp_args->nthreads++; 1226*c6402783Sakolb 1227*c6402783Sakolb /* 1228*c6402783Sakolb * Do all plgrp(1) operations specified on given thread 1229*c6402783Sakolb */ 1230*c6402783Sakolb (void) printf(FMT_THREAD" ", (int)pstatus->pr_pid, (int)lwpid); 1231*c6402783Sakolb return (do_op(plgrp_args, pstatus->pr_pid, lwpid, lwpsinfo)); 1232*c6402783Sakolb } 1233*c6402783Sakolb 1234*c6402783Sakolb /* 1235*c6402783Sakolb * Get target process specified in "pidstring" argument to do operation(s) 1236*c6402783Sakolb * specified in "plgrp_todo" using /proc and agent LWP 1237*c6402783Sakolb */ 1238*c6402783Sakolb static void 1239*c6402783Sakolb do_process(char *pidstring, plgrp_args_t *plgrp_todo, int force) 1240*c6402783Sakolb { 1241*c6402783Sakolb int error; 1242*c6402783Sakolb const char *lwps; 1243*c6402783Sakolb struct ps_prochandle *Ph; 1244*c6402783Sakolb 1245*c6402783Sakolb /* 1246*c6402783Sakolb * Nothing to do, so return. 1247*c6402783Sakolb */ 1248*c6402783Sakolb if (plgrp_todo == NULL || interrupt) 1249*c6402783Sakolb return; 1250*c6402783Sakolb 1251*c6402783Sakolb /* 1252*c6402783Sakolb * Grab target process or core and return 1253*c6402783Sakolb * /proc handle for process and string of LWP 1254*c6402783Sakolb * IDs 1255*c6402783Sakolb */ 1256*c6402783Sakolb Ph = proc_arg_xgrab(pidstring, NULL, 1257*c6402783Sakolb PR_ARG_ANY, force | PGRAB_RETAIN | PGRAB_NOSTOP, &error, &lwps); 1258*c6402783Sakolb if (Ph == NULL) { 1259*c6402783Sakolb (void) fprintf(stderr, 1260*c6402783Sakolb gettext("%s: Unable to grab process %s: %s\n"), 1261*c6402783Sakolb progname, pidstring, Pgrab_error(error)); 1262*c6402783Sakolb nerrors++; 1263*c6402783Sakolb return; 1264*c6402783Sakolb } 1265*c6402783Sakolb 1266*c6402783Sakolb /* 1267*c6402783Sakolb * Fill in remaining plgrp(1) arguments and state needed to do 1268*c6402783Sakolb * plgrp(1) operation(s) on desired LWPs in our handler 1269*c6402783Sakolb * called by Plwp_iter_all() as it iterates over LWPs 1270*c6402783Sakolb * in given process 1271*c6402783Sakolb */ 1272*c6402783Sakolb plgrp_todo->Ph = Ph; 1273*c6402783Sakolb plgrp_todo->lwps = lwps; 1274*c6402783Sakolb 1275*c6402783Sakolb /* 1276*c6402783Sakolb * Iterate over LWPs in process and do specified 1277*c6402783Sakolb * operation(s) on those specified 1278*c6402783Sakolb */ 1279*c6402783Sakolb if (Plwp_iter_all(Ph, Plwp_iter_handler, plgrp_todo) != 0) { 1280*c6402783Sakolb (void) fprintf(stderr, 1281*c6402783Sakolb gettext("%s: error iterating over threads\n"), 1282*c6402783Sakolb progname); 1283*c6402783Sakolb nerrors++; 1284*c6402783Sakolb } 1285*c6402783Sakolb 1286*c6402783Sakolb Prelease(Ph, PRELEASE_RETAIN); 1287*c6402783Sakolb } 1288*c6402783Sakolb 1289*c6402783Sakolb 1290*c6402783Sakolb /* 1291*c6402783Sakolb * Parse command line and kick off any resulting actions 1292*c6402783Sakolb * 1293*c6402783Sakolb * plgrp(1) has the following command line syntax: 1294*c6402783Sakolb * 1295*c6402783Sakolb * plgrp [-h] <pid> | <core> [/lwps] ... 1296*c6402783Sakolb * plgrp [-F] -a <lgroup>,... <pid>[/lwps] ... 1297*c6402783Sakolb * plgrp [-F] -H <lgroup>,... <pid>[/lwps] ... 1298*c6402783Sakolb * plgrp [-F] -A <lgroup>,... [/none|weak|strong] ... <pid>[/lwps] ... 1299*c6402783Sakolb * 1300*c6402783Sakolb * where <lgroup> is an lgroup ID, "all", "root", "leaves". 1301*c6402783Sakolb */ 1302*c6402783Sakolb int 1303*c6402783Sakolb main(int argc, char *argv[]) 1304*c6402783Sakolb { 1305*c6402783Sakolb lgrp_affinity_t aff; 1306*c6402783Sakolb char *affstring; 1307*c6402783Sakolb int c; 1308*c6402783Sakolb lgrp_cookie_t cookie; 1309*c6402783Sakolb int Fflag; 1310*c6402783Sakolb int i; 1311*c6402783Sakolb int opt_seen; 1312*c6402783Sakolb plgrp_args_t plgrp_todo; 1313*c6402783Sakolb char *s; 1314*c6402783Sakolb 1315*c6402783Sakolb (void) setlocale(LC_ALL, ""); 1316*c6402783Sakolb (void) textdomain(TEXT_DOMAIN); 1317*c6402783Sakolb 1318*c6402783Sakolb opt_seen = 0; 1319*c6402783Sakolb 1320*c6402783Sakolb /* 1321*c6402783Sakolb * Get name of program 1322*c6402783Sakolb */ 1323*c6402783Sakolb progname = basename(argv[0]); 1324*c6402783Sakolb 1325*c6402783Sakolb /* 1326*c6402783Sakolb * Not much to do when only name of program given 1327*c6402783Sakolb */ 1328*c6402783Sakolb if (argc == 1) 1329*c6402783Sakolb usage(0); 1330*c6402783Sakolb 1331*c6402783Sakolb /* 1332*c6402783Sakolb * Catch signals from terminal, so they can be handled asynchronously 1333*c6402783Sakolb * when we're ready instead of when we're not (;-) 1334*c6402783Sakolb */ 1335*c6402783Sakolb if (sigset(SIGHUP, SIG_IGN) == SIG_DFL) 1336*c6402783Sakolb (void) sigset(SIGHUP, intr); 1337*c6402783Sakolb if (sigset(SIGINT, SIG_IGN) == SIG_DFL) 1338*c6402783Sakolb (void) sigset(SIGINT, intr); 1339*c6402783Sakolb if (sigset(SIGQUIT, SIG_IGN) == SIG_DFL) 1340*c6402783Sakolb (void) sigset(SIGQUIT, intr); 1341*c6402783Sakolb (void) sigset(SIGPIPE, intr); 1342*c6402783Sakolb (void) sigset(SIGTERM, intr); 1343*c6402783Sakolb 1344*c6402783Sakolb /* 1345*c6402783Sakolb * Take snapshot of lgroup hierarchy 1346*c6402783Sakolb */ 1347*c6402783Sakolb cookie = lgrp_init(LGRP_VIEW_OS); 1348*c6402783Sakolb if (cookie == LGRP_COOKIE_NONE) { 1349*c6402783Sakolb (void) fprintf(stderr, 1350*c6402783Sakolb gettext("%s: Fatal error: cannot get lgroup" 1351*c6402783Sakolb " information from the OS: %s\n"), 1352*c6402783Sakolb progname, strerror(errno)); 1353*c6402783Sakolb return (EXIT_FAILURE); 1354*c6402783Sakolb } 1355*c6402783Sakolb 1356*c6402783Sakolb root = lgrp_root(cookie); 1357*c6402783Sakolb lgrps_bitmap_init(cookie, root, &lgrps_bitmap, &lgrps_bitmap_nelements); 1358*c6402783Sakolb 1359*c6402783Sakolb /* 1360*c6402783Sakolb * Remember arguments and state needed to do plgrp(1) operation 1361*c6402783Sakolb * on desired LWPs 1362*c6402783Sakolb */ 1363*c6402783Sakolb bzero(&plgrp_todo, sizeof (plgrp_args_t)); 1364*c6402783Sakolb plgrp_todo.op = PLGRP_HOME_GET; 1365*c6402783Sakolb 1366*c6402783Sakolb /* 1367*c6402783Sakolb * Parse options 1368*c6402783Sakolb */ 1369*c6402783Sakolb opterr = 0; 1370*c6402783Sakolb Fflag = 0; 1371*c6402783Sakolb while (!interrupt && (c = getopt(argc, argv, "a:A:FhH:")) != -1) { 1372*c6402783Sakolb /* 1373*c6402783Sakolb * Parse option and only allow one option besides -F to be 1374*c6402783Sakolb * specified 1375*c6402783Sakolb */ 1376*c6402783Sakolb switch (c) { 1377*c6402783Sakolb 1378*c6402783Sakolb case 'h': /* Get home lgroup */ 1379*c6402783Sakolb /* 1380*c6402783Sakolb * Only allow one option (besides -F) to be specified 1381*c6402783Sakolb */ 1382*c6402783Sakolb if (opt_seen) 1383*c6402783Sakolb usage(EXIT_FAILURE); 1384*c6402783Sakolb opt_seen = 1; 1385*c6402783Sakolb 1386*c6402783Sakolb plgrp_todo.op = PLGRP_HOME_GET; 1387*c6402783Sakolb break; 1388*c6402783Sakolb 1389*c6402783Sakolb case 'H': /* Set home lgroup */ 1390*c6402783Sakolb 1391*c6402783Sakolb /* 1392*c6402783Sakolb * Fail if already specified option (besides -F) 1393*c6402783Sakolb * or no more arguments 1394*c6402783Sakolb */ 1395*c6402783Sakolb if (opt_seen || optind >= argc) { 1396*c6402783Sakolb usage(EXIT_FAILURE); 1397*c6402783Sakolb } 1398*c6402783Sakolb opt_seen = 1; 1399*c6402783Sakolb 1400*c6402783Sakolb plgrp_todo.op = PLGRP_HOME_SET; 1401*c6402783Sakolb 1402*c6402783Sakolb if (parse_lgrps(cookie, &plgrp_todo, optarg) < 0) 1403*c6402783Sakolb usage(EXIT_FAILURE); 1404*c6402783Sakolb 1405*c6402783Sakolb /* If there are no valid lgroups exit immediately */ 1406*c6402783Sakolb if (plgrp_todo.nlgrps == 0) { 1407*c6402783Sakolb (void) fprintf(stderr, 1408*c6402783Sakolb gettext("%s: no valid lgroups" 1409*c6402783Sakolb " specified for -%c\n\n"), 1410*c6402783Sakolb progname, c); 1411*c6402783Sakolb usage(EXIT_FAILURE); 1412*c6402783Sakolb } 1413*c6402783Sakolb 1414*c6402783Sakolb break; 1415*c6402783Sakolb 1416*c6402783Sakolb case 'a': /* Get lgroup affinity */ 1417*c6402783Sakolb 1418*c6402783Sakolb /* 1419*c6402783Sakolb * Fail if already specified option (besides -F) 1420*c6402783Sakolb * or no more arguments 1421*c6402783Sakolb */ 1422*c6402783Sakolb if (opt_seen || optind >= argc) { 1423*c6402783Sakolb usage(EXIT_FAILURE); 1424*c6402783Sakolb } 1425*c6402783Sakolb opt_seen = 1; 1426*c6402783Sakolb 1427*c6402783Sakolb plgrp_todo.op = PLGRP_AFFINITY_GET; 1428*c6402783Sakolb 1429*c6402783Sakolb if (parse_lgrps(cookie, &plgrp_todo, optarg) < 0) 1430*c6402783Sakolb usage(EXIT_FAILURE); 1431*c6402783Sakolb 1432*c6402783Sakolb /* If there are no valid lgroups exit immediately */ 1433*c6402783Sakolb if (plgrp_todo.nlgrps == 0) { 1434*c6402783Sakolb (void) fprintf(stderr, 1435*c6402783Sakolb gettext("%s: no valid lgroups specified" 1436*c6402783Sakolb " for -%c\n\n"), 1437*c6402783Sakolb progname, c); 1438*c6402783Sakolb usage(EXIT_FAILURE); 1439*c6402783Sakolb } 1440*c6402783Sakolb 1441*c6402783Sakolb break; 1442*c6402783Sakolb 1443*c6402783Sakolb case 'A': /* Set lgroup affinity */ 1444*c6402783Sakolb 1445*c6402783Sakolb /* 1446*c6402783Sakolb * Fail if already specified option (besides -F) 1447*c6402783Sakolb * or no more arguments 1448*c6402783Sakolb */ 1449*c6402783Sakolb if (opt_seen || optind >= argc) { 1450*c6402783Sakolb usage(EXIT_FAILURE); 1451*c6402783Sakolb } 1452*c6402783Sakolb opt_seen = 1; 1453*c6402783Sakolb 1454*c6402783Sakolb plgrp_todo.op = PLGRP_AFFINITY_SET; 1455*c6402783Sakolb 1456*c6402783Sakolb /* 1457*c6402783Sakolb * 'affstring' is the unparsed prtion of the affinity 1458*c6402783Sakolb * specification like 1,2/none,2/weak,0/strong 1459*c6402783Sakolb * 1460*c6402783Sakolb * 'next' is the next affinity specification to parse. 1461*c6402783Sakolb */ 1462*c6402783Sakolb affstring = optarg; 1463*c6402783Sakolb while (affstring != NULL && strlen(affstring) > 0) { 1464*c6402783Sakolb char *next; 1465*c6402783Sakolb 1466*c6402783Sakolb /* 1467*c6402783Sakolb * affstring points to the first affinity 1468*c6402783Sakolb * specification. Split the string by 1469*c6402783Sakolb * DELIMIT_AFF separator and parse lgroups and 1470*c6402783Sakolb * affinity value separately. 1471*c6402783Sakolb */ 1472*c6402783Sakolb s = strchr(affstring, DELIMIT_AFF); 1473*c6402783Sakolb if (s == NULL) { 1474*c6402783Sakolb (void) fprintf(stderr, 1475*c6402783Sakolb gettext("%s: invalid " 1476*c6402783Sakolb "syntax >%s<\n"), 1477*c6402783Sakolb progname, affstring); 1478*c6402783Sakolb usage(EXIT_FAILURE); 1479*c6402783Sakolb } 1480*c6402783Sakolb 1481*c6402783Sakolb aff = parse_lgrp_affinity(s, &next); 1482*c6402783Sakolb if (aff == LGRP_AFF_INVALID) { 1483*c6402783Sakolb (void) fprintf(stderr, 1484*c6402783Sakolb gettext("%s: invalid " 1485*c6402783Sakolb "affinity >%s<\n"), 1486*c6402783Sakolb progname, affstring); 1487*c6402783Sakolb usage(EXIT_FAILURE); 1488*c6402783Sakolb } 1489*c6402783Sakolb 1490*c6402783Sakolb /* 1491*c6402783Sakolb * next should either point to the empty string 1492*c6402783Sakolb * or to the DELIMIT_AFF_LST separator. 1493*c6402783Sakolb */ 1494*c6402783Sakolb if (*next != '\0') { 1495*c6402783Sakolb if (*next != DELIMIT_AFF_LST) { 1496*c6402783Sakolb (void) fprintf(stderr, 1497*c6402783Sakolb gettext("%s: invalid " 1498*c6402783Sakolb "syntax >%s<\n"), 1499*c6402783Sakolb progname, next); 1500*c6402783Sakolb usage(EXIT_FAILURE); 1501*c6402783Sakolb } 1502*c6402783Sakolb *next = '\0'; 1503*c6402783Sakolb next++; 1504*c6402783Sakolb } 1505*c6402783Sakolb 1506*c6402783Sakolb 1507*c6402783Sakolb /* 1508*c6402783Sakolb * Now parse the list of lgroups 1509*c6402783Sakolb */ 1510*c6402783Sakolb if (parse_lgrps(cookie, &plgrp_todo, 1511*c6402783Sakolb affstring) < 0) { 1512*c6402783Sakolb usage(EXIT_FAILURE); 1513*c6402783Sakolb } 1514*c6402783Sakolb 1515*c6402783Sakolb /* 1516*c6402783Sakolb * Set desired affinity for specified lgroup to 1517*c6402783Sakolb * the specified affinity. 1518*c6402783Sakolb */ 1519*c6402783Sakolb for (i = 0; i < plgrp_todo.nlgrps; i++) { 1520*c6402783Sakolb if (plgrp_todo.affs[i] == 1521*c6402783Sakolb LGRP_AFF_INVALID) 1522*c6402783Sakolb plgrp_todo.affs[i] = aff; 1523*c6402783Sakolb } 1524*c6402783Sakolb 1525*c6402783Sakolb /* 1526*c6402783Sakolb * We processed the leftmost element of the 1527*c6402783Sakolb * list. Advance affstr to the remaining part of 1528*c6402783Sakolb * the list. and repeat. 1529*c6402783Sakolb */ 1530*c6402783Sakolb affstring = next; 1531*c6402783Sakolb } 1532*c6402783Sakolb 1533*c6402783Sakolb /* 1534*c6402783Sakolb * If there are no valid lgroups, exit immediately 1535*c6402783Sakolb */ 1536*c6402783Sakolb if (plgrp_todo.nlgrps == 0) { 1537*c6402783Sakolb (void) fprintf(stderr, 1538*c6402783Sakolb gettext("%s: no valid lgroups specified " 1539*c6402783Sakolb "for -%c\n\n"), progname, c); 1540*c6402783Sakolb usage(EXIT_FAILURE); 1541*c6402783Sakolb } 1542*c6402783Sakolb 1543*c6402783Sakolb break; 1544*c6402783Sakolb 1545*c6402783Sakolb case 'F': /* Force */ 1546*c6402783Sakolb 1547*c6402783Sakolb /* 1548*c6402783Sakolb * Only allow one occurrence 1549*c6402783Sakolb */ 1550*c6402783Sakolb if (Fflag != 0) { 1551*c6402783Sakolb usage(EXIT_FAILURE); 1552*c6402783Sakolb } 1553*c6402783Sakolb 1554*c6402783Sakolb /* 1555*c6402783Sakolb * Set flag to force /proc to grab process even though 1556*c6402783Sakolb * it's been grabbed by another process already 1557*c6402783Sakolb */ 1558*c6402783Sakolb Fflag = PGRAB_FORCE; 1559*c6402783Sakolb break; 1560*c6402783Sakolb 1561*c6402783Sakolb case '?': /* Unrecognized option */ 1562*c6402783Sakolb default: 1563*c6402783Sakolb usage(EXIT_FAILURE); 1564*c6402783Sakolb break; 1565*c6402783Sakolb 1566*c6402783Sakolb } 1567*c6402783Sakolb } 1568*c6402783Sakolb 1569*c6402783Sakolb /* 1570*c6402783Sakolb * Should have more arguments left at least for PID or core 1571*c6402783Sakolb */ 1572*c6402783Sakolb if (optind >= argc) 1573*c6402783Sakolb usage(EXIT_FAILURE); 1574*c6402783Sakolb 1575*c6402783Sakolb (void) lgrp_fini(cookie); 1576*c6402783Sakolb 1577*c6402783Sakolb /* 1578*c6402783Sakolb * Print heading and process each [pid | core]/lwps argument 1579*c6402783Sakolb */ 1580*c6402783Sakolb print_heading(plgrp_todo.op); 1581*c6402783Sakolb for (i = optind; i < argc && !interrupt; i++) { 1582*c6402783Sakolb do_process(argv[i], &plgrp_todo, Fflag); 1583*c6402783Sakolb } 1584*c6402783Sakolb 1585*c6402783Sakolb if (plgrp_todo.nthreads == 0) { 1586*c6402783Sakolb (void) fprintf(stderr, gettext("%s: no matching LWPs found\n"), 1587*c6402783Sakolb progname); 1588*c6402783Sakolb } 1589*c6402783Sakolb 1590*c6402783Sakolb return ((nerrors ||interrupt) ? EXIT_NONFATAL : EXIT_SUCCESS); 1591*c6402783Sakolb } 1592