static int pset(int subcode, long arg1, long arg2, long arg3, long arg4) { switch (subcode) { case PSET_CREATE: return (pset_create((psetid_t *)arg1)); case PSET_DESTROY: return (pset_destroy((psetid_t)arg1)); case PSET_ASSIGN: return (pset_assign((psetid_t)arg1, (processorid_t)arg2, (psetid_t *)arg3, 0)); case PSET_INFO: return (pset_info((psetid_t)arg1, (int *)arg2, (uint_t *)arg3, (processorid_t *)arg4)); case PSET_BIND: return (pset_bind((psetid_t)arg1, (idtype_t)arg2, (id_t)arg3, (psetid_t *)arg4)); case PSET_GETLOADAVG: return (pset_getloadavg((psetid_t)arg1, (int *)arg2, (int)arg3)); case PSET_LIST: return (pset_list((psetid_t *)arg1, (uint_t *)arg2)); case PSET_SETATTR: return (pset_setattr((psetid_t)arg1, (uint_t)arg2)); case PSET_GETATTR: return (pset_getattr((psetid_t)arg1, (uint_t *)arg2)); case PSET_ASSIGN_FORCED: return (pset_assign((psetid_t)arg1, (processorid_t)arg2, (psetid_t *)arg3, 1)); default: return (set_errno(EINVAL)); } }
/****** shepherd_binding/bind_shepherd_to_pset() ******************************* * NAME * bind_shepherd_to_pset() -- Binds the current process to a processor set. * * SYNOPSIS * static bool bind_shepherd_to_pset(int pset_id) * * FUNCTION * Binds the current shepherd process to an existing processor set. * * INPUTS * int pset_id - Existing processor set id. * * RESULT * static bool - true in case the process was bound false otherwise * * NOTES * MT-NOTE: bind_shepherd_to_pset() is MT safe * *******************************************************************************/ static bool bind_shepherd_to_pset(int pset_id) { /* try to bind current process to processor set */ if (pset_bind((psetid_t)pset_id, P_PID, P_MYID, NULL) != 0) { /* binding was not successful */ return false; } /* successfully bound current process to processor set */ return true; }
/****** shepherd/pset/set_processor_range() *********************************** * NAME * set_processor_range() -- sets processor range according to string * * SYNOPSIS * int set_processor_range(char *crange, * int proc_set_num, * char *err_str) * * FUNCTION * Sets processor range according to string specification. * The unique processor set number will be stored in the file * "processor_set_number" located in the current working directory. * * Format: * n|[n][-[m]],... , n,m being int >= 0. * no blanks are allowed in between (this is supposed to be * handled by the queue configuration parsing routine) * * INPUTS * char *crange - String specifier of the range. Will be * modified via strtok internally. * int proc_set_num - The base for a unique processor set number. * This number is already supposed to be unique. * for the job (currently the job_id). * set_processor_range() manipulates it to make * sure that it is a unique processor set number. * char *err_str - The error message string to be used by the * calling routine retuns value != PROC_SET_OK * Also used for trace messages internally. * Passed to invoked subroutines. * * RESULT * int - error state * PROC_SET_OK - Ok * PROC_SET_ERROR - A critical error occurred; either during * execution of sysmp() calls or as returned * from range2proc_vec(). * PROC_SET_WARNING - A non-critical error occurred (e.g. the * procedure is executed as unpriveliged user) ******************************************************************************/ static int set_processor_range(char *crange, int proc_set_num, char *err_str) { #if defined(__sgi) || defined(ALPHA) int ret; #endif FILE *fp; #if defined(__sgi) || defined(ALPHA) sbv_t proc_vec; #endif #if defined(__sgi) || defined(ALPHA) if ((ret=range2proc_vec(crange, &proc_vec, err_str))) return ret; #endif #if defined(ALPHA) /* It is not possible to bind processor #0 to other psets than pset #0 * So if we get a pset with #0 contained in the range we do nothing. * The process gets not bound to a processor but it is guaranteed * that no other job will get processor #0 exclusively. It is upon * the administrator to prevent overlapping of the psets in different * queues */ if (!(proc_vec & 1)) { /* processor #0 not contained */ if ((proc_set_num = create_pset())<0) { print_pset_error(proc_set_num); /* prints error to stdout */ shepherd_trace("MPPS_CREATE: failed to setup a new processor set"); return PROC_SET_ERROR; } if (assign_cpu_to_pset(proc_vec, proc_set_num, 0)<0) { print_pset_error(proc_set_num); /* prints error to stdout */ shepherd_trace("MPPS_CREATE: failed assigning processors to processor set"); return PROC_SET_ERROR; } } else { /* use default pset (id #0) */ proc_set_num = 0; } #elif defined(SOLARIS64) || defined(SOLARISAMD64) /* * We do not create a processor set here * The system administrator is responsible to do this * We read one id from crange. This is the processor-set id we should use. */ if (crange) { char *tok, *next; if ((tok=strtok(crange, " \t\n"))) { proc_set_num = (int) strtol(tok, &next, 10); if (next == tok) { sprintf(err_str, "wrong processor set id format: %20.20s", crange); shepherd_trace(err_str); return PROC_SET_ERROR; } } } #endif /* dump to file for later use */ if ((fp = fopen("processor_set_number","w"))) { fprintf(fp,"%d\n",proc_set_num); FCLOSE(fp); } else { shepherd_trace("MPPS_CREATE: failed creating file processor_set_number"); return PROC_SET_ERROR; } #if defined(ALPHA) /* Now let's assign ourselves to the previously created processor set */ if (proc_set_num) { pid_t pid_list[1]; pid_list[0] = getpid(); if (assign_pid_to_pset(pid_list, 1, proc_set_num, PSET_EXCLUSIVE)<0) { print_pset_error(proc_set_num); /* prints error to stdout */ shepherd_trace("MPPS_CREATE: failed assigning processors to processor set"); return PROC_SET_ERROR; } } #elif defined(SOLARIS64) || defined(SOLARISAMD64) if (proc_set_num) { int local_ret; sprintf(err_str,"pset_bind: try to use processorset %d", proc_set_num); shepherd_trace(err_str); if (pset_bind(proc_set_num, P_PID, P_MYID, NULL)) { switch (errno) { case EFAULT: shepherd_trace("pset_bind: The location pointed to by opset was not" " NULL and not writable by the user"); local_ret = PROC_SET_ERROR; break; case EINVAL: shepherd_trace("pset_bind: invalid processor set was specified"); local_ret = PROC_SET_ERROR; break; case EPERM: shepherd_trace("pset_bind: The effective user of the calling " "process is not super-user"); local_ret = PROC_SET_ERROR; break; default: sprintf(err_str,"pset_bind: unexpected error - errno=%d", errno); shepherd_trace(err_str); local_ret = PROC_SET_ERROR; break; } return local_ret; } } #endif return PROC_SET_OK; FCLOSE_ERROR: shepherd_trace("MPPS_CREATE: failed creating file processor_set_number"); return PROC_SET_ERROR; }
static int cpustat(void) { cpc_setgrp_t *accum; cpc_set_t *start; int c, i, retval; int lwps = 0; psetid_t mypset, cpupset; char *errstr; cpc_buf_t **data1, **data2, **scratch; int nreqs; kstat_ctl_t *kc; ncpus = (int)sysconf(_SC_NPROCESSORS_CONF); if ((gstate = calloc(ncpus, sizeof (*gstate))) == NULL) { (void) fprintf(stderr, gettext( "%s: out of heap\n"), opts->pgmname); return (1); } max_chip_id = sysconf(_SC_CPUID_MAX); if ((chip_designees = malloc(max_chip_id * sizeof (int))) == NULL) { (void) fprintf(stderr, gettext( "%s: out of heap\n"), opts->pgmname); return (1); } for (i = 0; i < max_chip_id; i++) chip_designees[i] = -1; if (smt) { if ((kc = kstat_open()) == NULL) { (void) fprintf(stderr, gettext( "%s: kstat_open() failed: %s\n"), opts->pgmname, strerror(errno)); return (1); } } if (opts->dosoaker) if (priocntl(0, 0, PC_GETCID, &fxinfo) == -1) { (void) fprintf(stderr, gettext( "%s: couldn't get FX scheduler class: %s\n"), opts->pgmname, strerror(errno)); return (1); } /* * Only include processors that are participating in the system */ for (c = 0, i = 0; i < ncpus; c++) { switch (p_online(c, P_STATUS)) { case P_ONLINE: case P_NOINTR: if (smt) { gstate[i].chip_id = get_chipid(kc, c); if (gstate[i].chip_id != -1 && chip_designees[gstate[i].chip_id] == -1) chip_designees[gstate[i].chip_id] = c; } gstate[i++].cpuid = c; break; case P_OFFLINE: case P_POWEROFF: case P_FAULTED: case P_SPARE: gstate[i++].cpuid = -1; break; default: gstate[i++].cpuid = -1; (void) fprintf(stderr, gettext("%s: cpu%d in unknown state\n"), opts->pgmname, c); break; case -1: break; } } /* * Examine the processor sets; if we're in one, only attempt * to report on the set we're in. */ if (pset_bind(PS_QUERY, P_PID, P_MYID, &mypset) == -1) { errstr = strerror(errno); (void) fprintf(stderr, gettext("%s: pset_bind - %s\n"), opts->pgmname, errstr); } else { for (i = 0; i < ncpus; i++) { struct tstate *this = &gstate[i]; if (this->cpuid == -1) continue; if (pset_assign(PS_QUERY, this->cpuid, &cpupset) == -1) { errstr = strerror(errno); (void) fprintf(stderr, gettext("%s: pset_assign - %s\n"), opts->pgmname, errstr); continue; } if (mypset != cpupset) this->cpuid = -1; } } if (opts->dotitle) print_title(opts->master); zerotime(); for (i = 0; i < ncpus; i++) { struct tstate *this = &gstate[i]; if (this->cpuid == -1) continue; this->sgrp = cpc_setgrp_clone(opts->master); if (this->sgrp == NULL) { this->cpuid = -1; continue; } if (thr_create(NULL, 0, gtick, this, THR_BOUND|THR_NEW_LWP, &this->tid) == 0) lwps++; else { (void) fprintf(stderr, gettext("%s: cannot create thread for cpu%d\n"), opts->pgmname, this->cpuid); this->status = 4; } } if (lwps != 0) for (i = 0; i < ncpus; i++) (void) thr_join(gstate[i].tid, NULL, NULL); if ((accum = cpc_setgrp_clone(opts->master)) == NULL) { (void) fprintf(stderr, gettext("%s: out of heap\n"), opts->pgmname); return (1); } retval = 0; for (i = 0; i < ncpus; i++) { struct tstate *this = &gstate[i]; if (this->cpuid == -1) continue; cpc_setgrp_accum(accum, this->sgrp); cpc_setgrp_free(this->sgrp); this->sgrp = NULL; if (this->status != 0) retval = 1; } cpc_setgrp_reset(accum); start = cpc_setgrp_getset(accum); do { nreqs = cpc_setgrp_getbufs(accum, &data1, &data2, &scratch); print_total(lwps, *data1, nreqs, cpc_setgrp_getname(accum)); } while (cpc_setgrp_nextset(accum) != start); cpc_setgrp_free(accum); accum = NULL; free(gstate); return (retval); }
int pr_pset_bind(struct ps_prochandle *Pr, int pset, idtype_t idtype, id_t id, int *opset) { sysret_t rval; /* return value */ argdes_t argd[5]; /* arg descriptors */ argdes_t *adp = &argd[0]; /* first argument */ int error; if (Pr == NULL) /* no subject process */ return (pset_bind(pset, idtype, id, opset)); adp->arg_value = PSET_BIND; /* PSET_BIND */ adp->arg_object = NULL; adp->arg_type = AT_BYVAL; adp->arg_inout = AI_INPUT; adp->arg_size = 0; adp++; adp->arg_value = pset; /* pset */ adp->arg_object = NULL; adp->arg_type = AT_BYVAL; adp->arg_inout = AI_INPUT; adp->arg_size = 0; adp++; adp->arg_value = idtype; /* idtype */ adp->arg_object = NULL; adp->arg_type = AT_BYVAL; adp->arg_inout = AI_INPUT; adp->arg_size = 0; adp++; adp->arg_value = id; /* id */ adp->arg_object = NULL; adp->arg_type = AT_BYVAL; adp->arg_inout = AI_INPUT; adp->arg_size = 0; adp++; if (opset == NULL) { adp->arg_value = 0; /* opset */ adp->arg_object = NULL; adp->arg_type = AT_BYVAL; adp->arg_inout = AI_INPUT; adp->arg_size = 0; } else { adp->arg_value = 0; adp->arg_object = opset; adp->arg_type = AT_BYREF; adp->arg_inout = AI_INOUT; adp->arg_size = sizeof (int); } error = Psyscall(Pr, &rval, SYS_pset, 5, &argd[0]); if (error) { errno = (error < 0)? ENOSYS : error; return (-1); } return (rval.sys_rval1); }