4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
30 #pragma ident "%Z%%M% %I% %E% SMI"
32 #include <sys/types.h>
33 #include <sys/procset.h>
34 #include <sys/priocntl.h>
35 #include <sys/fsspriocntl.h>
45 * This file contains the class specific code implementing the fair-share
46 * scheduler priocntl sub-command.
48 #define ADDKEYVAL(p, k, v) { (p[0]) = (k); (p[1]) = (v); p += 2; }
49 #define FSS_KEYCNT 2 /* max number of (key, value) pairs */
54 #define FSS_DOUPRILIM 0x01 /* user priority limit */
55 #define FSS_DOUPRI 0x02 /* user priority */
57 static void print_fssinfo(void);
58 static int print_fssprocs(void);
59 static int fss_priocntl(idtype_t
, id_t
, int, char *, uintptr_t *);
60 static int set_fssprocs(idtype_t
, int, char **, uint_t
, pri_t
, pri_t
);
61 static void exec_fsscmd(char **, uint_t
, pri_t
, pri_t
);
64 "usage: priocntl -l\n"
65 " priocntl -d [-d idtype] [idlist]\n"
66 " priocntl -s [-c FSS] [-m fssuprilim] [-p fssupri] [-i idtype] "
68 " priocntl -e [-c FSS] [-m fssuprilim] [-p fssupri] command [argument(s)]"
71 static char cmdpath
[MAXPATHLEN
];
72 static char basenm
[BASENMSZ
];
76 main(int argc
, char *argv
[])
79 int lflag
, dflag
, sflag
, mflag
, pflag
, eflag
, iflag
;
87 (void) strlcpy(cmdpath
, argv
[0], MAXPATHLEN
);
88 (void) strlcpy(basenm
, basename(argv
[0]), BASENMSZ
);
89 lflag
= dflag
= sflag
= mflag
= pflag
= eflag
= iflag
= 0;
90 while ((c
= getopt(argc
, argv
, "ldsm:p:ec:i:")) != -1) {
103 fssuprilim
= (pri_t
)str2num(optarg
, SHRT_MIN
, SHRT_MAX
);
105 fatalerr("%s: Specified user priority limit %s "
106 "out of configured range\n",
111 fssupri
= (pri_t
)str2num(optarg
, SHRT_MIN
, SHRT_MAX
);
113 fatalerr("%s: Specified user priority %s "
114 "out of configured range\n",
121 if (strcmp(optarg
, "FSS") != 0)
122 fatalerr("error: %s executed for %s class, %s "
123 "is actually sub-command for FSS class\n",
124 cmdpath
, optarg
, cmdpath
);
138 if (dflag
|| sflag
|| mflag
|| pflag
|| eflag
|| iflag
)
144 if (lflag
|| sflag
|| mflag
|| pflag
|| eflag
)
147 return (print_fssprocs());
150 if (lflag
|| dflag
|| eflag
)
154 if (str2idtyp(idtypnm
, &idtype
) == -1)
155 fatalerr("%s: Bad idtype %s\n", basenm
,
161 cflags
= (pflag
? FSS_DOUPRI
: 0);
164 cflags
|= FSS_DOUPRILIM
;
167 idargc
= argc
- optind
;
171 return (set_fssprocs(idtype
, idargc
, &argv
[optind
], cflags
,
172 fssuprilim
, fssupri
));
175 if (lflag
|| dflag
|| sflag
|| iflag
)
178 cflags
= (pflag
? FSS_DOUPRI
: 0);
181 cflags
|= FSS_DOUPRILIM
;
183 exec_fsscmd(&argv
[optind
], cflags
, fssuprilim
, fssupri
);
193 * Print our class name and the configured user priority range.
200 (void) strcpy(pcinfo
.pc_clname
, "FSS");
202 (void) printf("FSS (Fair Share)\n");
204 if (priocntl(0, 0, PC_GETCID
, (caddr_t
)&pcinfo
) == -1)
205 fatalerr("\tCan't get configured FSS user priority range\n");
207 (void) printf("\tConfigured FSS User Priority Range: -%d through %d\n",
208 ((fssinfo_t
*)pcinfo
.pc_clinfo
)->fss_maxupri
,
209 ((fssinfo_t
*)pcinfo
.pc_clinfo
)->fss_maxupri
);
213 * Read a list of pids from stdin and print the user priority and user
214 * priority limit for each of the corresponding processes.
222 char clname
[PC_CLNMSZ
];
228 * Read a list of pids from stdin.
230 if ((pidlist
= read_pidlist(&numread
, stdin
)) == NULL
)
231 fatalerr("%s: Can't read pidlist.\n", basenm
);
233 (void) printf("FAIR SHARING PROCESSES:\n"
234 " PID FSSUPRILIM FSSUPRI\n");
237 fatalerr("%s: No pids on input\n", basenm
);
239 for (i
= 0; i
< numread
; i
++) {
240 (void) printf("%7ld", pidlist
[i
]);
241 if (priocntl(P_PID
, pidlist
[i
], PC_GETXPARMS
, "FSS",
242 FSS_KY_UPRI
, &fssupri
,
243 FSS_KY_UPRILIM
, &fssuprilim
, 0) != -1) {
244 (void) printf(" %5d %5d\n",
245 fssuprilim
, fssupri
);
249 if (priocntl(P_PID
, pidlist
[i
], PC_GETXPARMS
, NULL
,
250 PC_KY_CLNAME
, clname
, 0) == -1 &&
251 strcmp(clname
, "FSS"))
253 * Process from some class other than fair
254 * sharing. It has probably changed class while
255 * priocntl command was executing (otherwise
256 * we wouldn't have been passed its pid).
257 * Print the little we know about it.
259 (void) printf("\tChanged to class %s while"
260 " priocntl command executing\n", clname
);
262 (void) printf("\tCan't get FSS user priority"
267 free_pidlist(pidlist
);
272 * Call priocntl() with command codes PC_SETXPARMS or PC_GETXPARMS. The
273 * first parameter behind the command code is always the class name.
274 * Each parameter is headed by a key, which detemines the meanin of the
275 * following value. There is maximum FSS_KEYCNT == 2 of (key, value) pairs.
278 fss_priocntl(idtype_t idtype
, id_t id
, int cmd
, char *clname
, uintptr_t *argsp
)
280 return (priocntl(idtype
, id
, cmd
, clname
, argsp
[0], argsp
[1],
281 argsp
[2], argsp
[3], 0));
285 * Set all processes in the set specified by idtype/idargv to fair-sharing
286 * (if they aren't already fair-sharing) and set their user priority limit
287 * and user priority to those specified by fssuprilim and fssupri.
290 set_fssprocs(idtype_t idtype
, int idargc
, char **idargv
, uint_t cflags
,
291 short fssuprilim
, short fssupri
)
294 uintptr_t args
[2 * FSS_KEYCNT
+ 1];
295 uintptr_t *argsp
= &args
[0];
297 char idtypnm
[PC_IDTYPNMSZ
];
303 * Get the fair sharing class ID and max configured user priority.
305 (void) strcpy(pcinfo
.pc_clname
, "FSS");
306 if (priocntl(0, 0, PC_GETCID
, (caddr_t
)&pcinfo
) == -1)
307 fatalerr("%s: Can't get FSS class ID, priocntl system call "
308 "failed (%s)\n", basenm
, strerror(errno
));
309 maxupri
= ((fssinfo_t
*)pcinfo
.pc_clinfo
)->fss_maxupri
;
312 * Validate the fssuprilim and fssupri arguments.
314 if ((cflags
& FSS_DOUPRILIM
) != 0) {
315 if (fssuprilim
> maxupri
|| fssuprilim
< -maxupri
)
316 fatalerr("%s: Specified user priority limit %d out of "
317 "configured range\n", basenm
, fssuprilim
);
318 ADDKEYVAL(argsp
, FSS_KY_UPRILIM
, fssuprilim
);
321 if ((cflags
& FSS_DOUPRI
) != 0) {
322 if (fssupri
> maxupri
|| fssupri
< -maxupri
)
323 fatalerr("%s: Specified user priority %d out of "
324 "configured range\n", basenm
, fssupri
);
325 ADDKEYVAL(argsp
, FSS_KY_UPRI
, fssupri
);
329 if (idtype
== P_ALL
) {
330 if (fss_priocntl(P_ALL
, 0, PC_SETXPARMS
, "FSS", args
) == -1) {
331 if (errno
== EPERM
) {
332 (void) fprintf(stderr
, "Permissions error "
333 "encountered on one or more processes.\n");
336 fatalerr("%s: Can't reset fair sharing "
337 "parameters\npriocntl system call failed "
338 "(%s)\n", basenm
, strerror(errno
));
340 } else if ((cflags
& (FSS_DOUPRILIM
|FSS_DOUPRI
)) ==
342 (void) verifyupri(idtype
, 0, "FSS", FSS_KY_UPRILIM
,
345 } else if (idargc
== 0) {
346 if (fss_priocntl(idtype
, P_MYID
, PC_SETXPARMS
, "FSS",
348 if (errno
== EPERM
) {
349 (void) idtyp2str(idtype
, idtypnm
);
350 (void) fprintf(stderr
, "Permissions error "
351 "encountered on current %s.\n", idtypnm
);
354 fatalerr("%s: Can't reset fair sharing "
355 "parameters\npriocntl system call failed "
356 "(%s)\n", basenm
, strerror(errno
));
358 } else if ((cflags
& (FSS_DOUPRILIM
|FSS_DOUPRI
)) ==
359 FSS_DOUPRI
&& getmyid(idtype
, &id
) != -1) {
360 (void) verifyupri(idtype
, id
, "FSS", FSS_KY_UPRILIM
,
364 (void) idtyp2str(idtype
, idtypnm
);
365 for (i
= 0; i
< idargc
; i
++) {
366 if (idtype
== P_CID
) {
367 (void) strcpy(pcinfo
.pc_clname
, idargv
[i
]);
368 if (priocntl(0, 0, PC_GETCID
,
369 (caddr_t
)&pcinfo
) == -1)
370 fatalerr("%s: Invalid or unconfigured "
371 "class %s, priocntl system call "
373 basenm
, pcinfo
.pc_clname
,
377 id
= (id_t
)str2num(idargv
[i
], INT_MIN
, INT_MAX
);
379 fatalerr("%s: Invalid id \"%s\"\n",
383 if (fss_priocntl(idtype
, id
, PC_SETXPARMS
, "FSS",
385 if (errno
== EPERM
) {
386 (void) fprintf(stderr
, "Permissions "
387 "error encountered on %s %s.\n",
391 fatalerr("%s: Can't reset fair sharing"
392 " parameters\npriocntl system call"
394 basenm
, strerror(errno
));
396 } else if ((cflags
& (FSS_DOUPRILIM
|FSS_DOUPRI
)) ==
398 (void) verifyupri(idtype
, id
, "FSS",
399 FSS_KY_UPRILIM
, fssupri
, basenm
);
408 * Execute the command pointed to by cmdargv as a fair-sharing process
409 * with the user priority limit given by fssuprilim and user priority fssupri.
412 exec_fsscmd(char **cmdargv
, uint_t cflags
, pri_t fssuprilim
, pri_t fssupri
)
415 uintptr_t args
[2 * FSS_KEYCNT
+ 1];
416 uintptr_t *argsp
= &args
[0];
421 * Get the fair sharing class ID and max configured user priority.
423 (void) strcpy(pcinfo
.pc_clname
, "FSS");
424 if (priocntl(0, 0, PC_GETCID
, (caddr_t
)&pcinfo
) == -1)
425 fatalerr("%s: Can't get FSS class ID, priocntl system call "
426 "failed (%s)\n", basenm
, strerror(errno
));
427 maxupri
= ((fssinfo_t
*)pcinfo
.pc_clinfo
)->fss_maxupri
;
429 if ((cflags
& FSS_DOUPRILIM
) != 0) {
430 if (fssuprilim
> maxupri
|| fssuprilim
< -maxupri
)
431 fatalerr("%s: Specified user priority limit %d out of "
432 "configured range\n", basenm
, fssuprilim
);
433 ADDKEYVAL(argsp
, FSS_KY_UPRILIM
, fssuprilim
);
436 if ((cflags
& FSS_DOUPRI
) != 0) {
437 if (fssupri
> maxupri
|| fssupri
< -maxupri
)
438 fatalerr("%s: Specified user priority %d out of "
439 "configured range\n", basenm
, fssupri
);
440 ADDKEYVAL(argsp
, FSS_KY_UPRI
, fssupri
);
444 if (fss_priocntl(P_PID
, P_MYID
, PC_SETXPARMS
, "FSS", args
) == -1)
445 fatalerr("%s: Can't reset fair sharing parameters\n"
446 "priocntl system call failed (%s)\n",
447 basenm
, strerror(errno
));
449 if ((cflags
& (FSS_DOUPRILIM
|FSS_DOUPRI
)) == FSS_DOUPRI
) {
450 if (priocntl(P_PID
, P_MYID
, PC_GETXPARMS
, "FSS",
451 FSS_KY_UPRILIM
, &uprilim
, 0) != -1 && fssupri
> uprilim
)
452 (void) fprintf(stderr
,
453 "%s: Specified user priority %d exceeds"
454 " limit %d; set to %d (pid %d)\n",
455 basenm
, fssupri
, uprilim
, uprilim
, (int)getpid());
458 (void) execvp(cmdargv
[0], cmdargv
);
459 fatalerr("%s: Can't execute %s, exec failed (%s)\n",
460 basenm
, cmdargv
[0], strerror(errno
));