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 2001-2002 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"
36 #include <sys/types.h>
37 #include <sys/procset.h>
38 #include <sys/priocntl.h>
39 #include <sys/fxpriocntl.h>
46 * This file contains the class specific code implementing
47 * the fixed-priority priocntl sub-command.
50 #define ADDKEYVAL(p, k, v) { (p[0]) = (k); (p[1]) = (v); p += 2; }
52 #define FX_KEYCNT 4 /* maximal number of (key, value) pairs */
57 #define FX_DOUPRILIM 0x01 /* user priority limit */
58 #define FX_DOUPRI 0x02 /* user priority */
59 #define FX_DOTQ 0x04 /* time quantum */
63 static void print_fxinfo();
64 static int print_fxprocs();
65 static int set_fxprocs(idtype_t
, int, char **, uint_t
, pri_t
, pri_t
, long,
67 static void exec_fxcmd(char **, uint_t
, pri_t
, pri_t
, long, long);
68 static int fx_priocntl(idtype_t
, id_t
, int, char *, uintptr_t *);
71 "usage: priocntl -l\n\
72 priocntl -d [-d idtype] [idlist]\n\
73 priocntl -s [-c FX] [-m fxuprilim] [-p fxupri] [-t tqntm [-r res]] \
74 [-i idtype] [idlist]\n\
75 priocntl -e [-c FX] [-m fxuprilim] [-p fxupri] [-t tqntm [-r res]] \
76 command [argument(s)]\n";
78 static char cmdpath
[MAXPATHLEN
];
79 static char basenm
[BASENMSZ
];
82 main(int argc
, char *argv
[])
88 int lflag
, dflag
, sflag
, mflag
, pflag
, eflag
, iflag
, tflag
;
99 (void) strlcpy(cmdpath
, argv
[0], MAXPATHLEN
);
100 (void) strlcpy(basenm
, basename(argv
[0]), BASENMSZ
);
101 lflag
= dflag
= sflag
= mflag
= pflag
= eflag
= iflag
= tflag
= 0;
103 while ((c
= getopt(argc
, argv
, "ldsm:p:ec:i:t:r:")) != -1) {
120 fxuprilim
= (pri_t
)str2num(optarg
, SHRT_MIN
, SHRT_MAX
);
122 fatalerr("%s: Specified user priority limit %s"
123 " out of configured range\n",
129 fxupri
= (pri_t
)str2num(optarg
, SHRT_MIN
, SHRT_MAX
);
131 fatalerr("%s: Specified user priority %s out of"
132 " configured range\n", basenm
, optarg
);
140 if (strcmp(optarg
, "FX") != 0)
141 fatalerr("error: %s executed for %s class, %s"
142 " is actually sub-command for FX class\n",
143 cmdpath
, optarg
, cmdpath
);
152 tqntm
= str2num(optarg
, 1, INT_MAX
);
154 fatalerr("%s: Invalid time quantum specified;"
155 " time quantum must be positive\n", basenm
);
160 res
= str2num(optarg
, 1, 1000000000);
162 fatalerr("%s: Invalid resolution specified;"
163 " resolution must be between"
164 " 1 and 1,000,000,000\n", basenm
);
177 if (dflag
|| sflag
|| mflag
|| pflag
|| eflag
|| iflag
||
184 if (sflag
|| mflag
|| pflag
|| eflag
)
187 return (print_fxprocs());
194 if (str2idtyp(idtypnm
, &idtype
) == -1)
195 fatalerr("%s: Bad idtype %s\n", basenm
,
200 cflags
= (pflag
? FX_DOUPRI
: 0);
203 cflags
|= FX_DOUPRILIM
;
212 idargc
= argc
- optind
;
216 return (set_fxprocs(idtype
, idargc
, &argv
[optind
], cflags
,
217 fxuprilim
, fxupri
, tqntm
, res
));
223 cflags
= (pflag
? FX_DOUPRI
: 0);
226 cflags
|= FX_DOUPRILIM
;
234 exec_fxcmd(&argv
[optind
], cflags
, fxuprilim
, fxupri
, tqntm
,
245 * Print our class name and the configured user priority range.
252 (void) strcpy(pcinfo
.pc_clname
, "FX");
254 (void) printf("FX (Fixed priority)\n");
256 if (priocntl(0, 0, PC_GETCID
, (caddr_t
)&pcinfo
) == -1)
257 fatalerr("\tCan't get configured FX user priority range\n");
259 (void) printf("\tConfigured FX User Priority Range: 0 through %d\n",
260 ((fxinfo_t
*)pcinfo
.pc_clinfo
)->fx_maxupri
);
265 * Read a list of pids from stdin and print the user priority and user
266 * priority limit for each of the corresponding processes.
274 char clname
[PC_CLNMSZ
];
283 * Read a list of pids from stdin.
285 if ((pidlist
= read_pidlist(&numread
, stdin
)) == NULL
)
286 fatalerr("%s: Can't read pidlist.\n", basenm
);
288 (void) printf("FIXED PRIORITY PROCESSES:\n PID FXUPRILIM "
292 fatalerr("%s: No pids on input\n", basenm
);
295 for (i
= 0; i
< numread
; i
++) {
296 (void) printf("%7ld", pidlist
[i
]);
297 if (priocntl(P_PID
, pidlist
[i
], PC_GETXPARMS
, "FX",
298 FX_KY_UPRI
, &fx_upri
, FX_KY_UPRILIM
, &fx_uprilim
,
299 FX_KY_TQSECS
, &fx_tqsecs
, FX_KY_TQNSECS
,
300 &fx_tqnsecs
, 0) != -1) {
301 (void) printf(" %5d %5d", fx_uprilim
, fx_upri
);
303 if (fx_tqnsecs
== FX_TQINF
)
304 (void) printf(" FX_TQINF\n");
306 (void) printf(" %11lld\n",
307 (longlong_t
)fx_tqsecs
* 1000 +
308 fx_tqnsecs
/ 1000000);
313 if (priocntl(P_PID
, pidlist
[i
], PC_GETXPARMS
, NULL
,
314 PC_KY_CLNAME
, clname
, 0) != -1 &&
315 strcmp(clname
, "FX")) {
317 * Process from some class other than fixed priority.
318 * It has probably changed class while priocntl
319 * command was executing (otherwise we wouldn't
320 * have been passed its pid). Print the little
323 (void) printf("\tChanged to class %s while priocntl"
324 " command executing\n", clname
);
326 (void) printf("\tCan't get FX user priority\n");
331 free_pidlist(pidlist
);
336 * Call priocntl() with command codes PC_SETXPARMS or PC_GETXPARMS.
337 * The first parameter behind the command code is always the class name.
338 * Each parameter is headed by a key, which determines the meaning of the
339 * following value. There are maximal FX_KEYCNT = 4 (key, value) pairs.
342 fx_priocntl(idtype_t idtype
, id_t id
, int cmd
, char *clname
, uintptr_t *argsp
)
344 return (priocntl(idtype
, id
, cmd
, clname
, argsp
[0], argsp
[1],
345 argsp
[2], argsp
[3], argsp
[4], argsp
[5], argsp
[6], argsp
[7], 0));
349 * Set all processes in the set specified by idtype/idargv to fixed-priority
350 * (if they aren't already fixed-priority) and set their user priority limit
351 * and user priority to those specified by fxuprilim and fxupri.
354 set_fxprocs(idtype_t idtype
, int idargc
, char **idargv
, uint_t cflags
,
355 pri_t fxuprilim
, pri_t fxupri
, long tqntm
, long res
)
358 uintptr_t args
[2*FX_KEYCNT
+1];
359 uintptr_t *argsp
= &args
[0];
361 char idtypnm
[PC_IDTYPNMSZ
];
368 * Get the fixed priority class ID and max configured user priority.
370 (void) strcpy(pcinfo
.pc_clname
, "FX");
371 if (priocntl(0, 0, PC_GETCID
, (caddr_t
)&pcinfo
) == -1)
372 fatalerr("%s: Can't get FX class ID, priocntl system call"
373 " failed with errno %d\n", basenm
, errno
);
374 maxupri
= ((fxinfo_t
*)pcinfo
.pc_clinfo
)->fx_maxupri
;
377 * Validate the fxuprilim and fxupri arguments.
379 if ((cflags
& FX_DOUPRILIM
) != 0) {
380 if (fxuprilim
> maxupri
|| fxuprilim
< 0) {
381 fatalerr("%s: Specified user priority limit %d out of"
382 " configured range\n", basenm
, fxuprilim
);
384 ADDKEYVAL(argsp
, FX_KY_UPRILIM
, fxuprilim
);
387 if ((cflags
& FX_DOUPRI
) != 0) {
388 if (fxupri
> maxupri
|| fxupri
< 0)
389 fatalerr("%s: Specified user priority %d out of "
390 "configured range\n", basenm
, fxupri
);
391 ADDKEYVAL(argsp
, FX_KY_UPRI
, fxupri
);
395 if (cflags
& FX_DOTQ
) {
397 hrtime
.hrt_rem
= tqntm
;
398 hrtime
.hrt_res
= res
;
399 if (_hrtnewres(&hrtime
, NANOSEC
, HRT_RNDUP
) == -1)
400 fatalerr("%s: Can't convert resolution.\n", basenm
);
401 ADDKEYVAL(argsp
, FX_KY_TQSECS
, hrtime
.hrt_secs
);
402 ADDKEYVAL(argsp
, FX_KY_TQNSECS
, hrtime
.hrt_rem
);
407 if (idtype
== P_ALL
) {
408 if (fx_priocntl(P_ALL
, 0, PC_SETXPARMS
, "FX", args
) == -1) {
409 if (errno
== EPERM
) {
410 (void) fprintf(stderr
,
411 "Permissions error encountered "
412 "on one or more processes.\n");
415 fatalerr("%s: Can't reset fixed priority"
416 " parameters\npriocntl system call failed "
417 " with errno %d\n", basenm
, errno
);
419 } else if ((cflags
& (FX_DOUPRILIM
|FX_DOUPRI
)) == FX_DOUPRI
) {
420 (void) verifyupri(idtype
, 0, "FX", FX_KY_UPRILIM
,
423 } else if (idargc
== 0) {
424 if (fx_priocntl(idtype
, P_MYID
, PC_SETXPARMS
, "FX",
426 if (errno
== EPERM
) {
427 (void) idtyp2str(idtype
, idtypnm
);
428 (void) fprintf(stderr
, "Permissions error"
429 " encountered on current %s.\n", idtypnm
);
432 fatalerr("%s: Can't reset fixed priority"
433 " parameters\npriocntl system call failed"
434 " with errno %d\n", basenm
, errno
);
436 } else if ((cflags
& (FX_DOUPRILIM
|FX_DOUPRI
)) == FX_DOUPRI
&&
437 getmyid(idtype
, &id
) != -1) {
438 (void) verifyupri(idtype
, id
, "FX", FX_KY_UPRILIM
,
442 (void) idtyp2str(idtype
, idtypnm
);
443 for (i
= 0; i
< idargc
; i
++) {
444 if (idtype
== P_CID
) {
445 (void) strcpy(pcinfo
.pc_clname
, idargv
[i
]);
446 if (priocntl(0, 0, PC_GETCID
,
447 (caddr_t
)&pcinfo
) == -1)
448 fatalerr("%s: Invalid or unconfigured"
449 " class %s, priocntl system call"
450 " failed with errno %d\n",
451 basenm
, pcinfo
.pc_clname
, errno
);
454 id
= (id_t
)str2num(idargv
[i
], INT_MIN
, INT_MAX
);
457 if (fx_priocntl(idtype
, id
, PC_SETXPARMS
, "FX", args
)
459 if (errno
== EPERM
) {
460 (void) fprintf(stderr
,
461 "Permissions error encountered on"
462 " %s %s.\n", idtypnm
, idargv
[i
]);
465 fatalerr("%s: Can't reset fixed "
467 " parameters\npriocntl system call"
468 " failed with errno %d\n",
471 } else if ((cflags
& (FX_DOUPRILIM
|FX_DOUPRI
)) ==
473 (void) verifyupri(idtype
, id
, "FX",
474 FX_KY_UPRILIM
, fxupri
, basenm
);
484 * Execute the command pointed to by cmdargv as a fixed-priority process
485 * with the user priority limit given by fxuprilim and user priority fxupri.
488 exec_fxcmd(char **cmdargv
, uint_t cflags
, pri_t fxuprilim
, pri_t fxupri
,
489 long tqntm
, long res
)
492 uintptr_t args
[2*FX_KEYCNT
+1];
493 uintptr_t *argsp
= &args
[0];
500 * Get the fixed priority class ID and max configured user priority.
502 (void) strcpy(pcinfo
.pc_clname
, "FX");
503 if (priocntl(0, 0, PC_GETCID
, (caddr_t
)&pcinfo
) == -1)
504 fatalerr("%s: Can't get FX class ID, priocntl system call"
505 " failed with errno %d\n", basenm
, errno
);
506 maxupri
= ((fxinfo_t
*)pcinfo
.pc_clinfo
)->fx_maxupri
;
508 if ((cflags
& FX_DOUPRILIM
) != 0) {
509 if (fxuprilim
> maxupri
|| fxuprilim
< 0)
510 fatalerr("%s: Specified user priority limit %d out of"
511 " configured range\n", basenm
, fxuprilim
);
512 ADDKEYVAL(argsp
, FX_KY_UPRILIM
, fxuprilim
);
515 if ((cflags
& FX_DOUPRI
) != 0) {
516 if (fxupri
> maxupri
|| fxupri
< 0)
517 fatalerr("%s: Specified user priority %d out of"
518 " configured range\n", basenm
, fxupri
);
519 ADDKEYVAL(argsp
, FX_KY_UPRI
, fxupri
);
522 if ((cflags
& FX_DOTQ
) != 0) {
524 hrtime
.hrt_rem
= tqntm
;
525 hrtime
.hrt_res
= res
;
526 if (_hrtnewres(&hrtime
, NANOSEC
, HRT_RNDUP
) == -1)
527 fatalerr("%s: Can't convert resolution.\n", basenm
);
528 ADDKEYVAL(argsp
, FX_KY_TQSECS
, hrtime
.hrt_secs
);
529 ADDKEYVAL(argsp
, FX_KY_TQNSECS
, hrtime
.hrt_rem
);
533 if (fx_priocntl(P_PID
, P_MYID
, PC_SETXPARMS
, "FX", args
) == -1)
534 fatalerr("%s: Can't reset fixed priority parameters\n"
535 " priocntl system call failed with errno %d\n",
538 if ((cflags
& (FX_DOUPRILIM
|FX_DOUPRI
)) == FX_DOUPRI
) {
539 if (priocntl(P_PID
, P_MYID
, PC_GETXPARMS
, "FX",
540 FX_KY_UPRILIM
, &uprilim
, 0) != -1 && fxupri
> uprilim
)
541 (void) fprintf(stderr
,
542 "%s: Specified user priority %d exceeds"
543 " limit %d; set to %d (pid %d)\n",
544 basenm
, fxupri
, uprilim
, uprilim
, (int)getpid());
547 (void) execvp(cmdargv
[0], cmdargv
);
548 fatalerr("%s: Can't execute %s, exec failed with errno %d\n",
549 basenm
, cmdargv
[0], errno
);