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