#include <ctype.h>
#include <errno.h>
#include <libintl.h>
#include <libproc.h>
#include <locale.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#include <libgen.h>
#include <sys/lgrp_user.h>
#define DELIMIT_AFF '/'
#define DELIMIT_LGRP ","
#define DELIMIT_LWP "/"
#define DELIMIT_RANGE '-'
#define DELIMIT_AFF_LST ','
#define EXIT_NONFATAL 2
#define HDR_PLGRP_AFF_GET " PID/LWPID HOME AFFINITY\n"
#define HDR_PLGRP_AFF_SET " PID/LWPID HOME AFFINITY\n"
#define HDR_PLGRP_HOME_GET " PID/LWPID HOME\n"
#define HDR_PLGRP_HOME_SET " PID/LWPID HOME\n"
#define HDR_PLGRP_HOME_CHANGE "HOME "
#define FMT_AFF "%d/%s"
#define FMT_AFF_STR "%s"
#define FMT_HOME "%-6d"
#define FMT_NEWHOME "%d => %d"
#define FMT_THREAD "%8d/%-8d"
#define LGRP_BITMAP_CHUNK 8
#define LGRP_ALL_STR "all"
#define LGRP_LEAVES_STR "leaves"
#define LGRP_ROOT_STR "root"
#define LGRP_AFF_NONE_STR "none"
#define LGRP_AFF_STRONG_STR "strong"
#define LGRP_AFF_WEAK_STR "weak"
#define LGRP_AFF_INVALID -1
#define LGRPSYS_NARGS 3
#ifndef TEXT_DOMAIN
#define TEXT_DOMAIN "SYS_TEST"
#endif
typedef enum plgrp_ops {
PLGRP_AFFINITY_GET,
PLGRP_AFFINITY_SET,
PLGRP_HOME_GET,
PLGRP_HOME_SET,
PLGRP_NO_OP
} plgrp_ops_t;
typedef struct plgrp_args {
struct ps_prochandle *Ph;
const char *lwps;
lgrp_id_t *lgrps;
lgrp_affinity_t *affs;
int nlgrps;
int nelements;
int index;
int nthreads;
plgrp_ops_t op;
} plgrp_args_t;
static int interrupt = 0;
static int nerrors = 0;
static char *progname;
static lgrp_id_t root = LGRP_NONE;
static char *lgrps_bitmap = NULL;
static int lgrps_bitmap_nelements = 0;
#define LGRP_VALID(lgrp) (lgrps_bitmap[lgrp] != 0)
static int max_lgrpid = LGRP_NONE;
#define NLGRPS (max_lgrpid + 1)
static void
usage(int rc)
{
(void) fprintf(stderr,
gettext("Usage:\t%s [-h] <pid> | <core> [/lwps] ...\n"), progname);
(void) fprintf(stderr,
gettext("\t%s [-F] -a <lgroup list> <pid>[/lwps] ...\n"), progname);
(void) fprintf(stderr,
gettext("\t%s [-F] -A <lgroup list>/none|weak|strong[,...] "
" <pid>[/lwps] ...\n"), progname);
(void) fprintf(stderr,
gettext("\t%s [-F] -H <lgroup list> <pid>[/lwps] ...\n"), progname);
(void) fprintf(stderr,
gettext("\n\twhere <lgroup list> is a comma separated list of\n"
"\tone or more of the following:\n\n"
"\t - lgroup ID\n"
"\t - Range of lgroup IDs specified as\n"
"\t\t<start lgroup ID>-<end lgroup ID>\n"
"\t - \"all\"\n"
"\t - \"root\"\n"
"\t - \"leaves\"\n\n"));
exit(rc);
}
static void
intr(int sig)
{
interrupt++;
}
static char *
lgrp_affinity_string(lgrp_affinity_t aff)
{
char *rc = "unknown";
switch (aff) {
case LGRP_AFF_STRONG:
rc = "strong";
break;
case LGRP_AFF_WEAK:
rc = "weak";
break;
case LGRP_AFF_NONE:
rc = "none";
break;
default:
break;
}
return (rc);
}
static void
lgrps_add_lgrp(plgrp_args_t *arg, int id)
{
if (arg->nlgrps == arg->nelements) {
arg->nelements += LGRP_BITMAP_CHUNK;
arg->lgrps = realloc(arg->lgrps,
arg->nelements * sizeof (lgrp_id_t));
if (arg->lgrps == NULL) {
(void) fprintf(stderr, gettext("%s: out of memory\n"),
progname);
exit(EXIT_FAILURE);
}
arg->affs = realloc(arg->affs,
arg->nelements * sizeof (lgrp_affinity_t));
if (arg->affs == NULL) {
(void) fprintf(stderr, gettext("%s: out of memory\n"),
progname);
exit(EXIT_FAILURE);
}
}
arg->lgrps[arg->nlgrps] = id;
arg->affs[arg->nlgrps] = LGRP_AFF_INVALID;
arg->nlgrps++;
}
static void
lgrps_bitmap_init(lgrp_cookie_t cookie, lgrp_id_t lgrpid, char **bitmap_array,
int *bitmap_nelements)
{
lgrp_id_t *children;
int i;
int nchildren;
if (lgrpid < 0) {
lgrpid = lgrp_root(cookie);
if (lgrpid < 0)
return;
}
while (lgrpid >= *bitmap_nelements) {
*bitmap_nelements += LGRP_BITMAP_CHUNK;
*bitmap_array = realloc(*bitmap_array,
*bitmap_nelements * sizeof (char));
if (*bitmap_array == NULL) {
(void) fprintf(stderr, gettext("%s: out of memory\n"),
progname);
exit(EXIT_FAILURE);
}
bzero(*bitmap_array + NLGRPS,
(*bitmap_nelements - NLGRPS) * sizeof (char));
}
(*bitmap_array)[lgrpid] = 1;
if (lgrpid > max_lgrpid)
max_lgrpid = lgrpid;
nchildren = lgrp_children(cookie, lgrpid, NULL, 0);
if (nchildren > 0) {
children = malloc(nchildren * sizeof (lgrp_id_t));
if (children == NULL) {
(void) fprintf(stderr, gettext("%s: out of memory\n"),
progname);
exit(EXIT_FAILURE);
}
if (lgrp_children(cookie, lgrpid, children, nchildren) !=
nchildren) {
free(children);
return;
}
for (i = 0; i < nchildren; i++)
lgrps_bitmap_init(cookie, children[i], bitmap_array,
bitmap_nelements);
free(children);
}
}
static lgrp_affinity_t
parse_lgrp_affinity(char *string, char **next)
{
int rc = LGRP_AFF_INVALID;
if (string == NULL)
return (LGRP_AFF_INVALID);
if (string[0] == DELIMIT_AFF)
string++;
if (strncmp(string, LGRP_AFF_NONE_STR, strlen(LGRP_AFF_NONE_STR))
== 0) {
rc = LGRP_AFF_NONE;
*next = string + strlen(LGRP_AFF_NONE_STR);
} else if (strncmp(string,
LGRP_AFF_WEAK_STR, strlen(LGRP_AFF_WEAK_STR)) == 0) {
rc = LGRP_AFF_WEAK;
*next = string + strlen(LGRP_AFF_WEAK_STR);
} else if (strncmp(string, LGRP_AFF_STRONG_STR,
strlen(LGRP_AFF_STRONG_STR)) == 0) {
rc = LGRP_AFF_STRONG;
*next = string + strlen(LGRP_AFF_STRONG_STR);
}
return (rc);
}
static int
parse_lgrps(lgrp_cookie_t cookie, plgrp_args_t *arg, char *s)
{
lgrp_id_t i;
char *token;
if (cookie == LGRP_COOKIE_NONE || s == NULL || NLGRPS <= 0)
return (0);
token = strtok(s, DELIMIT_LGRP);
if (token == NULL)
return (-1);
do {
if (isdigit(*token)) {
lgrp_id_t first;
lgrp_id_t last;
char *p;
p = strchr(token, DELIMIT_RANGE);
first = atoi(token);
if (p == NULL)
last = first;
else
last = atoi(++p);
for (i = first; i <= last; i++) {
if ((i >= 0) && (i < NLGRPS) && LGRP_VALID(i))
lgrps_add_lgrp(arg, i);
else {
(void) fprintf(stderr,
gettext("%s: bad lgroup %d\n"),
progname, i);
nerrors++;
}
}
} else if (strncmp(token, LGRP_ALL_STR,
strlen(LGRP_ALL_STR)) == 0) {
for (i = 0; i < NLGRPS; i++) {
if (LGRP_VALID(i))
lgrps_add_lgrp(arg, i);
}
} else if (strncmp(token, LGRP_ROOT_STR,
strlen(LGRP_ROOT_STR)) == 0) {
if (root < 0)
root = lgrp_root(cookie);
lgrps_add_lgrp(arg, root);
} else if (strncmp(token, LGRP_LEAVES_STR,
strlen(LGRP_LEAVES_STR)) == 0) {
for (i = 0; i < NLGRPS; i++) {
if (LGRP_VALID(i) &&
lgrp_children(cookie, i, NULL, 0) == 0)
lgrps_add_lgrp(arg, i);
}
} else {
return (-1);
}
} while (token = strtok(NULL, DELIMIT_LGRP));
return (0);
}
static void
print_lgrps(lgrp_id_t *lgrps, int nlgrps)
{
lgrp_id_t start;
lgrp_id_t end;
int i;
start = end = lgrps[0];
for (i = 1; i < nlgrps; i++) {
lgrp_id_t lgrpid;
lgrpid = lgrps[i];
if (lgrpid == end + 1) {
end = lgrpid;
} else {
if (end == start) {
(void) printf("%d,", (int)start);
} else if (end > start + 1) {
(void) printf("%d-%d,", (int)start, (int)end);
} else {
(void) printf("%d,%d,", (int)start, (int)end);
}
start = end = lgrpid;
}
}
if (end == start) {
(void) printf("%d", (int)start);
} else if (end > start + 1) {
(void) printf("%d-%d", (int)start, (int)end);
} else {
(void) printf("%d,%d", (int)start, (int)end);
}
}
static void
print_affinities(lgrp_id_t *lgrps, lgrp_affinity_t *affs, int nelements)
{
int i;
lgrp_id_t *lgrps_none;
lgrp_id_t *lgrps_strong;
lgrp_id_t *lgrps_weak;
int nlgrps_none;
int nlgrps_strong;
int nlgrps_weak;
nlgrps_strong = nlgrps_weak = nlgrps_none = 0;
lgrps_strong = malloc(nelements * sizeof (lgrp_id_t));
lgrps_weak = malloc(nelements * sizeof (lgrp_id_t));
lgrps_none = malloc(nelements * sizeof (lgrp_id_t));
if (lgrps_strong == NULL || lgrps_weak == NULL || lgrps_none == NULL) {
(void) fprintf(stderr, gettext("%s: out of memory\n"),
progname);
interrupt = 1;
return;
}
for (i = 0; i < nelements; i++) {
lgrp_id_t lgrpid = lgrps[i];
if (lgrpid == LGRP_NONE)
continue;
switch (affs[i]) {
case LGRP_AFF_STRONG:
lgrps_strong[nlgrps_strong++] = lgrpid;
break;
case LGRP_AFF_WEAK:
lgrps_weak[nlgrps_weak++] = lgrpid;
break;
case LGRP_AFF_NONE:
lgrps_none[nlgrps_none++] = lgrpid;
break;
default:
break;
}
}
if (nlgrps_strong) {
print_lgrps(lgrps_strong, nlgrps_strong);
(void) printf("/%s", lgrp_affinity_string(LGRP_AFF_STRONG));
if (nlgrps_weak || nlgrps_none)
(void) printf("%c", DELIMIT_AFF_LST);
}
if (nlgrps_weak) {
print_lgrps(lgrps_weak, nlgrps_weak);
(void) printf("/%s", lgrp_affinity_string(LGRP_AFF_WEAK));
if (nlgrps_none)
(void) printf("%c", DELIMIT_AFF_LST);
}
if (nlgrps_none) {
print_lgrps(lgrps_none, nlgrps_none);
(void) printf("/%s", lgrp_affinity_string(LGRP_AFF_NONE));
}
free(lgrps_strong);
free(lgrps_weak);
free(lgrps_none);
}
static void
print_heading(plgrp_ops_t op)
{
switch (op) {
case PLGRP_AFFINITY_GET:
(void) printf(HDR_PLGRP_AFF_GET);
break;
case PLGRP_AFFINITY_SET:
(void) printf(HDR_PLGRP_AFF_SET);
break;
case PLGRP_HOME_GET:
(void) printf(HDR_PLGRP_HOME_GET);
break;
case PLGRP_HOME_SET:
(void) printf(HDR_PLGRP_HOME_SET);
break;
default:
break;
}
}
static lgrp_affinity_t
Plgrp_affinity_get(struct ps_prochandle *Ph, idtype_t idtype, id_t id,
lgrp_id_t lgrp)
{
lgrp_affinity_args_t args;
argdes_t Pargd[3];
argdes_t *Pargdp;
int Pnargs;
int Pretval;
sysret_t retval;
int syscall;
syscall = SYS_lgrpsys;
args.idtype = idtype;
args.id = id;
args.lgrp = lgrp;
args.aff = LGRP_AFF_INVALID;
Pnargs = LGRPSYS_NARGS;
Pargdp = &Pargd[0];
Pargdp->arg_value = LGRP_SYS_AFFINITY_GET;
Pargdp->arg_object = NULL;
Pargdp->arg_type = AT_BYVAL;
Pargdp->arg_inout = AI_INPUT;
Pargdp->arg_size = 0;
Pargdp++;
Pargdp->arg_value = 0;
Pargdp->arg_object = NULL;
Pargdp->arg_type = AT_BYVAL;
Pargdp->arg_inout = AI_INPUT;
Pargdp->arg_size = 0;
Pargdp++;
Pargdp->arg_value = 0;
Pargdp->arg_object = &args;
Pargdp->arg_type = AT_BYREF;
Pargdp->arg_inout = AI_INPUT;
Pargdp->arg_size = sizeof (lgrp_affinity_args_t);
Pargdp++;
Pretval = Psyscall(Ph, &retval, syscall, Pnargs, &Pargd[0]);
if (Pretval) {
errno = (Pretval < 0) ? ENOSYS : Pretval;
return (LGRP_AFF_INVALID);
}
return (retval.sys_rval1);
}
static int
Plgrp_affinity_set(struct ps_prochandle *Ph, idtype_t idtype, id_t id,
lgrp_id_t lgrp, lgrp_affinity_t aff)
{
lgrp_affinity_args_t args;
argdes_t Pargd[3];
argdes_t *Pargdp;
int Pnargs;
int Pretval;
sysret_t retval;
int syscall;
syscall = SYS_lgrpsys;
args.idtype = idtype;
args.id = id;
args.lgrp = lgrp;
args.aff = aff;
Pnargs = LGRPSYS_NARGS;
Pargdp = &Pargd[0];
Pargdp->arg_value = LGRP_SYS_AFFINITY_SET;
Pargdp->arg_object = NULL;
Pargdp->arg_type = AT_BYVAL;
Pargdp->arg_inout = AI_INPUT;
Pargdp->arg_size = 0;
Pargdp++;
Pargdp->arg_value = 0;
Pargdp->arg_object = NULL;
Pargdp->arg_type = AT_BYVAL;
Pargdp->arg_inout = AI_INPUT;
Pargdp->arg_size = 0;
Pargdp++;
Pargdp->arg_value = 0;
Pargdp->arg_object = &args;
Pargdp->arg_type = AT_BYREF;
Pargdp->arg_inout = AI_INPUT;
Pargdp->arg_size = sizeof (lgrp_affinity_args_t);
Pargdp++;
Pretval = Psyscall(Ph, &retval, syscall, Pnargs, &Pargd[0]);
if (Pretval) {
errno = (Pretval < 0) ? ENOSYS : Pretval;
return (-1);
}
return (retval.sys_rval1);
}
static lgrp_id_t
Plgrp_home(struct ps_prochandle *Ph, idtype_t idtype, id_t id)
{
argdes_t Pargd[3];
argdes_t *Pargdp;
int Pnargs;
int Pretval;
sysret_t retval;
int syscall;
syscall = SYS_lgrpsys;
Pnargs = LGRPSYS_NARGS;
Pargdp = &Pargd[0];
Pargdp->arg_value = LGRP_SYS_HOME;
Pargdp->arg_object = NULL;
Pargdp->arg_type = AT_BYVAL;
Pargdp->arg_inout = AI_INPUT;
Pargdp->arg_size = 0;
Pargdp++;
Pargdp->arg_value = idtype;
Pargdp->arg_object = NULL;
Pargdp->arg_type = AT_BYVAL;
Pargdp->arg_inout = AI_INPUT;
Pargdp->arg_size = 0;
Pargdp++;
Pargdp->arg_value = id;
Pargdp->arg_object = NULL;
Pargdp->arg_type = AT_BYVAL;
Pargdp->arg_inout = AI_INPUT;
Pargdp->arg_size = 0;
Pargdp++;
Pretval = Psyscall(Ph, &retval, syscall, Pnargs, &Pargd[0]);
if (Pretval) {
errno = (Pretval < 0) ? ENOSYS : Pretval;
return (-1);
}
return (retval.sys_rval1);
}
static int
Plgrp_home_set(struct ps_prochandle *Ph, idtype_t idtype, id_t id,
lgrp_id_t lgrp)
{
return (Plgrp_affinity_set(Ph, idtype, id, lgrp,
LGRP_AFF_STRONG));
}
static int
do_op(plgrp_args_t *plgrp_args, id_t pid, id_t lwpid,
const lwpsinfo_t *lwpsinfo)
{
lgrp_affinity_t *affs;
lgrp_affinity_t *cur_affs;
lgrp_id_t home;
int i;
lgrp_affinity_t *init_affs;
lgrp_id_t *lgrps;
lgrp_id_t *lgrps_changed;
int nlgrps;
lgrp_id_t old_home;
lgrp_id_t lgrpid;
struct ps_prochandle *Ph;
int nchanged;
if (plgrp_args == NULL)
return (0);
Ph = plgrp_args->Ph;
lgrps = plgrp_args->lgrps;
affs = plgrp_args->affs;
nlgrps = plgrp_args->nlgrps;
switch (plgrp_args->op) {
case PLGRP_HOME_GET:
home = lwpsinfo->pr_lgrp;
(void) printf(FMT_HOME"\n", (int)home);
break;
case PLGRP_AFFINITY_GET:
home = lwpsinfo->pr_lgrp;
(void) printf(FMT_HOME, (int)home);
for (i = 0; i < nlgrps; i++) {
affs[i] = Plgrp_affinity_get(Ph, P_LWPID, lwpid,
lgrps[i]);
if (affs[i] == LGRP_AFF_INVALID) {
nerrors++;
(void) fprintf(stderr,
gettext("%s: cannot get affinity"
" for lgroup %d for %d/%d: %s\n"),
progname, lgrps[i], pid, lwpid,
strerror(errno));
}
}
print_affinities(lgrps, affs, nlgrps);
(void) printf("\n");
break;
case PLGRP_HOME_SET:
old_home = lwpsinfo->pr_lgrp;
i = plgrp_args->index;
if (Plgrp_home_set(Ph, P_LWPID, lwpid, lgrps[i]) != 0) {
nerrors++;
(void) fprintf(stderr,
gettext("%s: cannot set home lgroup of %d/%d"
" to lgroup %d: %s\n"),
progname, pid, lwpid, lgrps[i],
strerror(errno));
(void) printf("\n");
} else {
int len;
int width = strlen(HDR_PLGRP_HOME_CHANGE);
home = Plgrp_home(Ph, P_LWPID, lwpid);
if (home < 0) {
(void) fprintf(stderr,
gettext("%s cannot get home lgroup for"
" %d/%d: %s\n"),
progname, pid, lwpid, strerror(errno));
nerrors++;
}
len = printf(FMT_NEWHOME, (int)old_home, (int)home);
if (len < width)
(void) printf("%*c\n", (int)(width - len), ' ');
}
plgrp_args->index = (i + 1) % nlgrps;
break;
case PLGRP_AFFINITY_SET:
old_home = lwpsinfo->pr_lgrp;
init_affs = malloc(NLGRPS * sizeof (lgrp_affinity_t));
cur_affs = malloc(NLGRPS * sizeof (lgrp_affinity_t));
lgrps_changed = malloc(NLGRPS * sizeof (lgrp_id_t));
if (init_affs == NULL || cur_affs == NULL ||
lgrps_changed == NULL) {
(void) fprintf(stderr, gettext("%s: out of memory\n"),
progname);
Prelease(Ph, PRELEASE_RETAIN);
if (init_affs != NULL)
free(init_affs);
if (cur_affs != NULL)
free(cur_affs);
nerrors++;
return (EXIT_NONFATAL);
}
for (lgrpid = 0; lgrpid < NLGRPS; lgrpid++) {
if (!LGRP_VALID(lgrpid)) {
init_affs[lgrpid] = LGRP_AFF_INVALID;
} else {
init_affs[lgrpid] =
Plgrp_affinity_get(Ph, P_LWPID,
lwpid, lgrpid);
if (init_affs[lgrpid] == LGRP_AFF_INVALID) {
nerrors++;
(void) fprintf(stderr,
gettext("%s: cannot get"
" affinity for lgroup %d"
" for %d/%d: %s\n"),
progname, lgrpid, pid, lwpid,
strerror(errno));
}
}
cur_affs[lgrpid] = init_affs[lgrpid];
lgrps_changed[lgrpid] = LGRP_NONE;
}
for (i = 0; i < nlgrps; i++) {
lgrp_affinity_t aff = affs[i];
lgrpid = lgrps[i];
if (aff == cur_affs[lgrpid])
continue;
if (Plgrp_affinity_set(Ph, P_LWPID, lwpid, lgrpid,
aff) < 0) {
nerrors++;
(void) fprintf(stderr,
gettext("%s: cannot set"
" %s affinity for lgroup %d"
" for %d/%d: %s\n"),
progname, lgrp_affinity_string(aff),
lgrpid, pid, lwpid,
strerror(errno));
continue;
}
cur_affs[lgrpid] =
Plgrp_affinity_get(Ph, P_LWPID, lwpid, lgrpid);
if (cur_affs[lgrpid] == LGRP_AFF_INVALID) {
nerrors++;
(void) fprintf(stderr,
gettext("%s: cannot get"
" affinity for lgroup %d"
" for %d/%d: %s\n"),
progname, lgrpid, pid, lwpid,
strerror(errno));
continue;
}
if (aff != cur_affs[lgrpid]) {
(void) fprintf(stderr,
gettext("%s: affinity for"
" lgroup %d is set to %d instead of %d"
" for %d/%d\n"),
progname, lgrpid, cur_affs[lgrpid], aff,
pid, lwpid);
nerrors++;
}
}
nchanged = 0;
for (lgrpid = 0; lgrpid < NLGRPS; lgrpid++) {
if (init_affs[lgrpid] != cur_affs[lgrpid]) {
lgrps_changed[lgrpid] = lgrpid;
nchanged++;
}
}
if (nchanged == 0) {
for (i = 0; i < nlgrps; i++) {
lgrps_changed[lgrps[i]] = lgrps[i];
}
(void) printf("%-*d",
(int)strlen(HDR_PLGRP_HOME_CHANGE),
(int)old_home);
print_affinities(lgrps_changed, cur_affs, NLGRPS);
(void) printf("\n");
} else {
int width = strlen(HDR_PLGRP_HOME_CHANGE);
home = Plgrp_home(Ph, P_LWPID, lwpid);
if (home < 0) {
(void) fprintf(stderr,
gettext("%s: cannot get home"
" for %d/%d: %s\n"),
progname, pid, lwpid, strerror(errno));
nerrors++;
}
if (old_home != home) {
int len;
len = printf(FMT_NEWHOME,
(int)old_home, (int)home);
if (len < width)
(void) printf("%*c", width - len, ' ');
} else {
(void) printf("%-*d", width, (int)home);
}
print_affinities(lgrps_changed, init_affs, NLGRPS);
(void) printf(" => ");
print_affinities(lgrps_changed, cur_affs, NLGRPS);
(void) printf("\n");
}
free(lgrps_changed);
free(init_affs);
free(cur_affs);
break;
default:
break;
}
return (0);
}
static int
Plwp_iter_handler(void *arg, const lwpstatus_t *lwpstatus,
const lwpsinfo_t *lwpsinfo)
{
id_t lwpid;
struct ps_prochandle *Ph;
const pstatus_t *pstatus;
plgrp_args_t *plgrp_args;
if (arg == NULL || interrupt)
return (0);
plgrp_args = arg;
Ph = plgrp_args->Ph;
if (Ph == NULL)
return (0);
pstatus = Pstatus(Ph);
lwpid = lwpsinfo->pr_lwpid;
if (lwpid == pstatus->pr_agentid ||
!proc_lwp_in_set(plgrp_args->lwps, lwpid))
return (0);
plgrp_args->nthreads++;
(void) printf(FMT_THREAD" ", (int)pstatus->pr_pid, (int)lwpid);
return (do_op(plgrp_args, pstatus->pr_pid, lwpid, lwpsinfo));
}
static void
do_process(char *pidstring, plgrp_args_t *plgrp_todo, int force)
{
int error;
const char *lwps;
struct ps_prochandle *Ph;
if (plgrp_todo == NULL || interrupt)
return;
Ph = proc_arg_xgrab(pidstring, NULL,
PR_ARG_ANY, force | PGRAB_RETAIN | PGRAB_NOSTOP, &error, &lwps);
if (Ph == NULL) {
(void) fprintf(stderr,
gettext("%s: Unable to grab process %s: %s\n"),
progname, pidstring, Pgrab_error(error));
nerrors++;
return;
}
plgrp_todo->Ph = Ph;
plgrp_todo->lwps = lwps;
if (Plwp_iter_all(Ph, Plwp_iter_handler, plgrp_todo) != 0) {
(void) fprintf(stderr,
gettext("%s: error iterating over threads\n"),
progname);
nerrors++;
}
Prelease(Ph, PRELEASE_RETAIN);
}
int
main(int argc, char *argv[])
{
lgrp_affinity_t aff;
char *affstring;
int c;
lgrp_cookie_t cookie;
int Fflag;
int i;
int opt_seen;
plgrp_args_t plgrp_todo;
char *s;
(void) setlocale(LC_ALL, "");
(void) textdomain(TEXT_DOMAIN);
opt_seen = 0;
progname = basename(argv[0]);
if (argc == 1)
usage(0);
if (sigset(SIGHUP, SIG_IGN) == SIG_DFL)
(void) sigset(SIGHUP, intr);
if (sigset(SIGINT, SIG_IGN) == SIG_DFL)
(void) sigset(SIGINT, intr);
if (sigset(SIGQUIT, SIG_IGN) == SIG_DFL)
(void) sigset(SIGQUIT, intr);
(void) sigset(SIGPIPE, intr);
(void) sigset(SIGTERM, intr);
cookie = lgrp_init(LGRP_VIEW_OS);
if (cookie == LGRP_COOKIE_NONE) {
(void) fprintf(stderr,
gettext("%s: Fatal error: cannot get lgroup"
" information from the OS: %s\n"),
progname, strerror(errno));
return (EXIT_FAILURE);
}
root = lgrp_root(cookie);
lgrps_bitmap_init(cookie, root, &lgrps_bitmap, &lgrps_bitmap_nelements);
bzero(&plgrp_todo, sizeof (plgrp_args_t));
plgrp_todo.op = PLGRP_HOME_GET;
opterr = 0;
Fflag = 0;
while (!interrupt && (c = getopt(argc, argv, "a:A:FhH:")) != -1) {
switch (c) {
case 'h':
if (opt_seen)
usage(EXIT_FAILURE);
opt_seen = 1;
plgrp_todo.op = PLGRP_HOME_GET;
break;
case 'H':
if (opt_seen || optind >= argc) {
usage(EXIT_FAILURE);
}
opt_seen = 1;
plgrp_todo.op = PLGRP_HOME_SET;
if (parse_lgrps(cookie, &plgrp_todo, optarg) < 0)
usage(EXIT_FAILURE);
if (plgrp_todo.nlgrps == 0) {
(void) fprintf(stderr,
gettext("%s: no valid lgroups"
" specified for -%c\n\n"),
progname, c);
usage(EXIT_FAILURE);
}
break;
case 'a':
if (opt_seen || optind >= argc) {
usage(EXIT_FAILURE);
}
opt_seen = 1;
plgrp_todo.op = PLGRP_AFFINITY_GET;
if (parse_lgrps(cookie, &plgrp_todo, optarg) < 0)
usage(EXIT_FAILURE);
if (plgrp_todo.nlgrps == 0) {
(void) fprintf(stderr,
gettext("%s: no valid lgroups specified"
" for -%c\n\n"),
progname, c);
usage(EXIT_FAILURE);
}
break;
case 'A':
if (opt_seen || optind >= argc) {
usage(EXIT_FAILURE);
}
opt_seen = 1;
plgrp_todo.op = PLGRP_AFFINITY_SET;
affstring = optarg;
while (affstring != NULL && strlen(affstring) > 0) {
char *next;
s = strchr(affstring, DELIMIT_AFF);
if (s == NULL) {
(void) fprintf(stderr,
gettext("%s: invalid "
"syntax >%s<\n"),
progname, affstring);
usage(EXIT_FAILURE);
}
aff = parse_lgrp_affinity(s, &next);
if (aff == LGRP_AFF_INVALID) {
(void) fprintf(stderr,
gettext("%s: invalid "
"affinity >%s<\n"),
progname, affstring);
usage(EXIT_FAILURE);
}
if (*next != '\0') {
if (*next != DELIMIT_AFF_LST) {
(void) fprintf(stderr,
gettext("%s: invalid "
"syntax >%s<\n"),
progname, next);
usage(EXIT_FAILURE);
}
*next = '\0';
next++;
}
if (parse_lgrps(cookie, &plgrp_todo,
affstring) < 0) {
usage(EXIT_FAILURE);
}
for (i = 0; i < plgrp_todo.nlgrps; i++) {
if (plgrp_todo.affs[i] ==
LGRP_AFF_INVALID)
plgrp_todo.affs[i] = aff;
}
affstring = next;
}
if (plgrp_todo.nlgrps == 0) {
(void) fprintf(stderr,
gettext("%s: no valid lgroups specified "
"for -%c\n\n"), progname, c);
usage(EXIT_FAILURE);
}
break;
case 'F':
if (Fflag != 0) {
usage(EXIT_FAILURE);
}
Fflag = PGRAB_FORCE;
break;
case '?':
default:
usage(EXIT_FAILURE);
break;
}
}
if (optind >= argc)
usage(EXIT_FAILURE);
(void) lgrp_fini(cookie);
print_heading(plgrp_todo.op);
(void) proc_initstdio();
for (i = optind; i < argc && !interrupt; i++) {
(void) proc_flushstdio();
do_process(argv[i], &plgrp_todo, Fflag);
}
(void) proc_finistdio();
if (plgrp_todo.nthreads == 0) {
(void) fprintf(stderr, gettext("%s: no matching LWPs found\n"),
progname);
}
return ((nerrors ||interrupt) ? EXIT_NONFATAL : EXIT_SUCCESS);
}