1 /* 2 * CDDL HEADER START 3 * 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 7 * with the License. 8 * 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. 13 * 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] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 #pragma ident "%Z%%M% %I% %E% SMI" 31 32 #include <stdio.h> 33 #include <stdlib.h> 34 #include <string.h> 35 #include <unistd.h> 36 #include <errno.h> 37 #include <sys/types.h> 38 #include <sys/priocntl.h> 39 #include <sys/iapriocntl.h> 40 #include <sys/param.h> 41 #include <sys/ia.h> 42 43 #include "dispadmin.h" 44 45 /* 46 * This file contains the class specific code implementing 47 * the interactive dispadmin sub-command. 48 */ 49 50 #define BASENMSZ 16 51 52 extern char *basename(); 53 54 static void get_iadptbl(), set_iadptbl(); 55 56 static char usage[] = 57 "usage: dispadmin -l\n\ 58 dispadmin -c IA -g [-r res]\n\ 59 dispadmin -c IA -s infile\n"; 60 61 static char basenm[BASENMSZ]; 62 static char cmdpath[256]; 63 64 65 int 66 main(int argc, char **argv) 67 { 68 extern char *optarg; 69 70 int c; 71 int lflag, gflag, rflag, sflag; 72 ulong_t res; 73 char *infile; 74 75 (void) strcpy(cmdpath, argv[0]); 76 (void) strcpy(basenm, basename(argv[0])); 77 lflag = gflag = rflag = sflag = 0; 78 while ((c = getopt(argc, argv, "lc:gr:s:")) != -1) { 79 switch (c) { 80 81 case 'l': 82 lflag++; 83 break; 84 85 case 'c': 86 if (strcmp(optarg, "IA") != 0) 87 fatalerr("error: %s executed for %s class, " 88 "%s is actually sub-command for IA class\n", 89 cmdpath, optarg, cmdpath); 90 break; 91 92 case 'g': 93 gflag++; 94 break; 95 96 case 'r': 97 rflag++; 98 res = strtoul(optarg, (char **)NULL, 10); 99 break; 100 101 case 's': 102 sflag++; 103 infile = optarg; 104 break; 105 106 case '?': 107 fatalerr(usage); 108 109 default: 110 break; 111 } 112 } 113 114 if (lflag) { 115 if (gflag || rflag || sflag) 116 fatalerr(usage); 117 118 (void) printf("IA\t(Interactive)\n"); 119 return (0); 120 121 } else if (gflag) { 122 if (lflag || sflag) 123 fatalerr(usage); 124 125 if (rflag == 0) 126 res = 1000; 127 128 get_iadptbl(res); 129 return (0); 130 131 } else if (sflag) { 132 if (lflag || gflag || rflag) 133 fatalerr(usage); 134 135 set_iadptbl(infile); 136 return (0); 137 138 } else { 139 fatalerr(usage); 140 } 141 return (1); 142 } 143 144 145 /* 146 * Retrieve the current ia_dptbl from memory, convert the time quantum 147 * values to the resolution specified by res and write the table to stdout. 148 */ 149 static void 150 get_iadptbl(ulong_t res) 151 { 152 int i; 153 int iadpsz; 154 pcinfo_t pcinfo; 155 pcadmin_t pcadmin; 156 iaadmin_t iaadmin; 157 iadpent_t *ia_dptbl; 158 hrtimer_t hrtime; 159 160 (void) strcpy(pcinfo.pc_clname, "IA"); 161 if (priocntl(0, 0, PC_GETCID, (caddr_t)&pcinfo) == -1) 162 fatalerr("%s: Can't get IA class ID, priocntl system " 163 "call failed with errno %d\n", 164 basenm, errno); 165 166 pcadmin.pc_cid = pcinfo.pc_cid; 167 pcadmin.pc_cladmin = (char *)&iaadmin; 168 iaadmin.ia_cmd = IA_GETDPSIZE; 169 170 if (priocntl(0, 0, PC_ADMIN, (caddr_t)&pcadmin) == -1) 171 fatalerr("%s: Can't get ia_dptbl size, priocntl system " 172 "call failed with errno %d\n", 173 basenm, errno); 174 175 iadpsz = iaadmin.ia_ndpents * sizeof (iadpent_t); 176 if ((ia_dptbl = (iadpent_t *)malloc(iadpsz)) == NULL) 177 fatalerr("%s: Can't allocate memory for ia_dptbl\n", basenm); 178 179 iaadmin.ia_dpents = ia_dptbl; 180 181 iaadmin.ia_cmd = IA_GETDPTBL; 182 if (priocntl(0, 0, PC_ADMIN, (caddr_t)&pcadmin) == -1) 183 fatalerr("%s: Can't get ia_dptbl, priocntl system call " 184 "call failed with errno %d\n", 185 basenm, errno); 186 187 (void) printf("# Interactive Dispatcher Configuration\n"); 188 (void) printf("RES=%ld\n\n", res); 189 (void) printf("# ia_quantum ia_tqexp ia_slpret ia_maxwait ia_lwait \ 190 PRIORITY LEVEL\n"); 191 192 for (i = 0; i < iaadmin.ia_ndpents; i++) { 193 if (res != HZ) { 194 hrtime.hrt_secs = 0; 195 hrtime.hrt_rem = ia_dptbl[i].ia_quantum; 196 hrtime.hrt_res = HZ; 197 if (_hrtnewres(&hrtime, res, HRT_RNDUP) == -1) 198 fatalerr("%s: Can't convert to requested " 199 "resolution\n", basenm); 200 if ((ia_dptbl[i].ia_quantum = hrtconvert(&hrtime)) 201 == -1) 202 fatalerr("%s: Can't express time quantum in " 203 "requested resolution,\n" 204 "try coarser resolution\n", 205 basenm); 206 } 207 (void) printf("%10ld%10d%10d%12d%10d # %3d\n", 208 ia_dptbl[i].ia_quantum, ia_dptbl[i].ia_tqexp, 209 ia_dptbl[i].ia_slpret, ia_dptbl[i].ia_maxwait, 210 ia_dptbl[i].ia_lwait, i); 211 } 212 } 213 214 215 /* 216 * Read the ia_dptbl values from infile, convert the time quantum values 217 * to HZ resolution, do a little sanity checking and overwrite the table 218 * in memory with the values from the file. 219 */ 220 static void 221 set_iadptbl(infile) 222 char *infile; 223 { 224 int i; 225 int niadpents; 226 char *tokp; 227 pcinfo_t pcinfo; 228 pcadmin_t pcadmin; 229 iaadmin_t iaadmin; 230 iadpent_t *ia_dptbl; 231 int linenum; 232 ulong_t res; 233 hrtimer_t hrtime; 234 FILE *fp; 235 char buf[512]; 236 int wslength; 237 238 (void) strcpy(pcinfo.pc_clname, "IA"); 239 if (priocntl(0, 0, PC_GETCID, (caddr_t)&pcinfo) == -1) 240 fatalerr("%s: Can't get IA class ID, priocntl system " 241 "call failed with errno %d\n", basenm, errno); 242 243 pcadmin.pc_cid = pcinfo.pc_cid; 244 pcadmin.pc_cladmin = (char *)&iaadmin; 245 iaadmin.ia_cmd = IA_GETDPSIZE; 246 247 if (priocntl(0, 0, PC_ADMIN, (caddr_t)&pcadmin) == -1) 248 fatalerr("%s: Can't get ia_dptbl size, priocntl system " 249 "call failed with errno %d\n", basenm, errno); 250 251 niadpents = iaadmin.ia_ndpents; 252 if ((ia_dptbl = 253 (iadpent_t *)malloc(niadpents * sizeof (iadpent_t))) == NULL) 254 fatalerr("%s: Can't allocate memory for ia_dptbl\n", basenm); 255 256 if ((fp = fopen(infile, "r")) == NULL) 257 fatalerr("%s: Can't open %s for input\n", basenm, infile); 258 259 linenum = 0; 260 261 /* 262 * Find the first non-blank, non-comment line. A comment line 263 * is any line with '#' as the first non-white-space character. 264 */ 265 do { 266 if (fgets(buf, sizeof (buf), fp) == NULL) 267 fatalerr("%s: Too few lines in input table\n", basenm); 268 linenum++; 269 } while (buf[0] == '#' || buf[0] == '\0' || 270 (wslength = strspn(buf, " \t\n")) == strlen(buf) || 271 strchr(buf, '#') == buf + wslength); 272 273 if ((tokp = strtok(buf, " \t")) == NULL) 274 fatalerr("%s: Bad RES specification, line %d of input file\n", 275 basenm, linenum); 276 if ((int)strlen(tokp) > 4) { 277 if (strncmp(tokp, "RES=", 4) != 0) 278 fatalerr("%s: Bad RES specification, \ 279 line %d of input file\n", basenm, linenum); 280 if (tokp[4] == '-') 281 fatalerr("%s: Bad RES specification, \ 282 line %d of input file\n", basenm, linenum); 283 res = strtoul(&tokp[4], (char **)NULL, 10); 284 } else if (strlen(tokp) == 4) { 285 if (strcmp(tokp, "RES=") != 0) 286 fatalerr("%s: Bad RES specification, \ 287 line %d of input file\n", basenm, linenum); 288 if ((tokp = strtok(NULL, " \t")) == NULL) 289 fatalerr("%s: Bad RES specification, \ 290 line %d of input file\n", basenm, linenum); 291 if (tokp[0] == '-') 292 fatalerr("%s: Bad RES specification, \ 293 line %d of input file\n", basenm, linenum); 294 res = strtoul(tokp, (char **)NULL, 10); 295 } else if (strlen(tokp) == 3) { 296 if (strcmp(tokp, "RES") != 0) 297 fatalerr("%s: Bad RES specification, \ 298 line %d of input file\n", basenm, linenum); 299 if ((tokp = strtok(NULL, " \t")) == NULL) 300 fatalerr("%s: Bad RES specification, \ 301 line %d of input file\n", basenm, linenum); 302 if ((int)strlen(tokp) > 1) { 303 if (strncmp(tokp, "=", 1) != 0) 304 fatalerr("%s: Bad RES specification, \ 305 line %d of input file\n", basenm, linenum); 306 if (tokp[1] == '-') 307 fatalerr("%s: Bad RES specification, \ 308 line %d of input file\n", basenm, linenum); 309 res = strtoul(&tokp[1], (char **)NULL, 10); 310 } else if (strlen(tokp) == 1) { 311 if ((tokp = strtok(NULL, " \t")) == NULL) 312 fatalerr("%s: Bad RES specification, \ 313 line %d of input file\n", basenm, linenum); 314 if (tokp[0] == '-') 315 fatalerr("%s: Bad RES specification, \ 316 line %d of input file\n", basenm, linenum); 317 res = strtoul(tokp, (char **)NULL, 10); 318 } 319 } else { 320 fatalerr("%s: Bad RES specification, line %d of input file\n", 321 basenm, linenum); 322 } 323 324 /* 325 * The remainder of the input file should contain exactly enough 326 * non-blank, non-comment lines to fill the table (ia_ndpents lines). 327 * We assume that any non-blank, non-comment line is data for the 328 * table and fail if we find more or less than we need. 329 */ 330 for (i = 0; i < iaadmin.ia_ndpents; i++) { 331 332 /* 333 * Get the next non-blank, non-comment line. 334 */ 335 do { 336 if (fgets(buf, sizeof (buf), fp) == NULL) 337 fatalerr("%s: Too few lines in input table\n", 338 basenm); 339 linenum++; 340 } while (buf[0] == '#' || buf[0] == '\0' || 341 (wslength = strspn(buf, " \t\n")) == strlen(buf) || 342 strchr(buf, '#') == buf + wslength); 343 344 if ((tokp = strtok(buf, " \t")) == NULL) 345 fatalerr("%s: Too few values, line %d of input file\n", 346 basenm, linenum); 347 348 if (res != HZ) { 349 hrtime.hrt_secs = 0; 350 hrtime.hrt_rem = atol(tokp); 351 hrtime.hrt_res = res; 352 if (_hrtnewres(&hrtime, HZ, HRT_RNDUP) == -1) 353 fatalerr("%s: Can't convert specified \ 354 resolution to ticks\n", basenm); 355 if ((ia_dptbl[i].ia_quantum = hrtconvert(&hrtime)) 356 == -1) 357 fatalerr("%s: ia_quantum value out of " 358 "valid range; line %d of input,\n" 359 "table not overwritten\n", 360 basenm, linenum); 361 } else { 362 ia_dptbl[i].ia_quantum = atol(tokp); 363 } 364 if (ia_dptbl[i].ia_quantum <= 0) 365 fatalerr("%s: ia_quantum value out of valid range; " 366 "line %d of input,\ntable not overwritten\n", 367 basenm, linenum); 368 369 if ((tokp = strtok(NULL, " \t")) == NULL || tokp[0] == '#') 370 fatalerr("%s: Too few values, line %d of input file\n", 371 basenm, linenum); 372 ia_dptbl[i].ia_tqexp = (short)atoi(tokp); 373 if (ia_dptbl[i].ia_tqexp < 0 || 374 ia_dptbl[i].ia_tqexp > iaadmin.ia_ndpents) 375 fatalerr("%s: ia_tqexp value out of valid range; " 376 "line %d of input,\ntable not overwritten\n", 377 basenm, linenum); 378 379 if ((tokp = strtok(NULL, " \t")) == NULL || tokp[0] == '#') 380 fatalerr("%s: Too few values, line %d of input file\n", 381 basenm, linenum); 382 ia_dptbl[i].ia_slpret = (short)atoi(tokp); 383 if (ia_dptbl[i].ia_slpret < 0 || 384 ia_dptbl[i].ia_slpret > iaadmin.ia_ndpents) 385 fatalerr("%s: ia_slpret value out of valid range; " 386 "line %d of input,\ntable not overwritten\n", 387 basenm, linenum); 388 389 if ((tokp = strtok(NULL, " \t")) == NULL || tokp[0] == '#') 390 fatalerr("%s: Too few values, line %d of input file\n", 391 basenm, linenum); 392 ia_dptbl[i].ia_maxwait = (short)atoi(tokp); 393 if (ia_dptbl[i].ia_maxwait < 0) 394 fatalerr("%s: ia_maxwait value out of valid range; " 395 "line %d of input,\ntable not overwritten\n", 396 basenm, linenum); 397 398 if ((tokp = strtok(NULL, " \t")) == NULL || tokp[0] == '#') 399 fatalerr("%s: Too few values, line %d of input file\n", 400 basenm, linenum); 401 ia_dptbl[i].ia_lwait = (short)atoi(tokp); 402 if (ia_dptbl[i].ia_lwait < 0 || 403 ia_dptbl[i].ia_lwait > iaadmin.ia_ndpents) 404 fatalerr("%s: ia_lwait value out of valid range; " 405 "line %d of input,\ntable not overwritten\n", 406 basenm, linenum); 407 408 if ((tokp = strtok(NULL, " \t")) != NULL && tokp[0] != '#') 409 fatalerr("%s: Too many values, line %d of input file\n", 410 basenm, linenum); 411 } 412 413 /* 414 * We've read enough lines to fill the table. We fail 415 * if the input file contains any more. 416 */ 417 while (fgets(buf, sizeof (buf), fp) != NULL) { 418 if (buf[0] != '#' && buf[0] != '\0' && 419 (wslength = strspn(buf, " \t\n")) != strlen(buf) && 420 strchr(buf, '#') != buf + wslength) 421 fatalerr("%s: Too many lines in input table\n", 422 basenm); 423 } 424 425 iaadmin.ia_dpents = ia_dptbl; 426 iaadmin.ia_cmd = IA_SETDPTBL; 427 if (priocntl(0, 0, PC_ADMIN, (caddr_t)&pcadmin) == -1) 428 fatalerr("%s: Can't set ia_dptbl, priocntl system call \ 429 failed with errno %d\n", basenm, errno); 430 } 431