/* * Copyright (c) 2000, Amnon BARAK (amnon@cs.huji.ac.il). All rights reserved. * * OpenMosix $Id: mosctl.c,v 1.11 2003/05/14 22:27:14 demichel Exp $ * * Permission to use, copy and distribute this software is hereby granted * under the terms of version 2 or any later version of the GNU General Public * License, as published by the Free Software Foundation. * * THIS SOFTWARE IS PROVIDED IN ITS "AS IS" CONDITION, WITH NO WARRANTY * WHATSOEVER. NO LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING * FROM THE USE OF THIS SOFTWARE WILL BE ACCEPTED. */ /* * Author(s): Amnon Shiloh, Oren Laadan, Ariel Rosenblatt */ /* Adapted to OpenMosix from Mosix and bugfixing by David Santo Orcero */ /* irbis@orcero.org http://www.orcero.org/irbis */ /* Mosix is (c) of prof. Amnon Barak http://www.mosix.org */ /* Original code is (c) of prof. Amnon Barak http://www.mosix.org */ /* OpenMosix is (c) of Moshe Bar http://www.openmosix.com */ /* Each respective trademark is of its own owner */ /* All rights reserved. */ /* This software is distributed under GPL 2 */ /* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTY IS ASSUMED. */ /* NO LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING */ /* FROM THE USE OF THIS SOFTWARE WILL BE ACCEPTED. IT CAN BURN */ /* YOUR HARD DISK, ERASE ALL YOUR DATA AND BROKE DOWN YOUR */ /* MICROWAVE OVEN. YOU ARE ADVISED. */ #include #include #include #include #include #include #include #include #include /* Updated by Moshe Bar */ #define STD_SPD 14000 /* standard CPU speed = 14000 */ struct coms { const char *com; char no; } coms[] = { {"stay", D_STAY}, {"nostay", D_NOSTAY}, {"-stay", D_NOSTAY}, {"lstay", D_LSTAY}, {"nolstay", D_NOLSTAY}, {"-lstay", D_NOLSTAY}, {"block", D_BLOCK}, {"noblock", D_NOBLOCK}, {"-block", D_NOBLOCK}, {"quiet", D_QUIET}, {"noquiet", D_NOQUIET}, {"-quiet", D_NOQUIET}, {"nomfs", D_NOMFS}, {"mfs", D_MFS}, {"-mfs", D_NOMFS}, {"-nomfs", D_MFS}, {"nonomfs", D_MFS}, {"expel", D_EXPEL}, {"bring", D_BRING}, {"getload", D_GETLOAD}, {"getyard", D_GETSSPEED}, {"setyard", D_SETSSPEED}, {"speedof", D_GETSPEED}, {"getspeed", D_GETSPEED}, {"getmem", D_GETMEM}, {"memory", D_GETMEM}, {"mem", D_GETMEM}, {"getrawmem", D_GETRMEM}, {"getfree", D_GETRMEM}, {"getrawfree", D_GETRMEM}, {"rawfree", D_GETRMEM}, {"getutil", D_GETUTIL}, {"util", D_GETUTIL}, {"getutilizability", D_GETUTIL}, {"utilizability", D_GETUTIL}, {"setspeed", D_SETSPEED}, {"whois", D_MOSIX_TO_IP}, {"gettune", D_GETTUNE}, {"status", D_GETSTAT}, {"stat", D_GETSTAT}, {"isup", D_GETSTAT}, {"decay", D_GETDECAY}, {"getdecay", D_GETDECAY}, {"setdecay", D_SETDECAY}, {"sdecay", D_SETDECAY}, {(char *)0, 0}, }; #define s386 "i386" #define s486 "i486" #define s586 "i586" #define s686 "i686" #define s786 "i786" #define s886 "i886" #define MAXNICK 5 struct speeds { const char *model; const char *mach[MAXNICK]; int spd; } speeds[] = { {s386, {"386/8", "80386/8", NULL, NULL, NULL}, 11}, {s386, {"386/16", "80386/16", NULL, NULL, NULL}, 16}, {s386, {"386/20", "80386/20", NULL, NULL, NULL}, 23}, {s386, {"386/25", "80386/25", NULL, NULL, NULL}, 36}, {s386, {"386/33", "80386/33", NULL, NULL, NULL}, 47}, {s386, {"386/40", "80386/40", NULL, NULL, NULL}, 60}, {s386, {"486/8", "80486/8", NULL, NULL, NULL}, 74}, {s486, {"486/25", "80486/25", NULL, NULL, NULL}, 113}, {s486, {"486/40", "80486/40", NULL, NULL, NULL}, 175}, {s486, {"486/50", "80486/50", NULL, NULL, NULL}, 215}, {s486, {"486/66", "80486/66", NULL, NULL, NULL}, 270}, {s486, {"486/75", "80486/75", NULL, NULL, NULL}, 323}, {s486, {"486/100", "80486/100", NULL, NULL, NULL}, 422}, {s586, {"PENTIUM/8", "P/8", "80586/8", "P5/8", "586/8"}, 338}, {s586, {"PENTIUM/60", "P/60", "80586/60", "P5/60", "586/60"}, 597}, {s586, {"PENTIUM/66", "P/66", "80586/66", "P5/66", "586/66"}, 657}, {s586, {"PENTIUM/75", "P/75", "80586/75", "P5/75", "586/75"}, 746}, {s586, {"PENTIUM/90", "P/90", "80586/90", "P5/90", "586/90"}, 895}, {s586, {"PENTIUM/100", "P/100", "80586/100", "P5/100", "586/100"}, 995}, {s586, {"PENTIUM/120", "P/120", "80586/120", "P5/120", "586/120"}, 1194}, {s586, {"PENTIUM/133", "P/133", "80586/133", "P5/133", "586/133"}, 1323}, {s586, {"PENTIUM/150", "P/150", "80586/150", "P5/150", "586/150"}, 1492}, {s586, {"PENTIUM/166", "P/166", "80586/166", "P5/166", "586/166"}, 1652}, {s586, {"PENTIUM/180", "P/180", "80586/180", "P5/180", "586/180"}, 1791}, {s686, {"PPRO/8", "PP/8", "PENTIUMPRO/8", "PENTIUM/PRO/8", "P6/8"}, 458}, {s686, {"PPRO/133", "PP/133", "PENTIUMPRO/133", "PENTIUM/PRO/133", "P6/133"}, 1328}, {s686, {"PPRO/150", "PP/150", "PENTIUMPRO/150", "PENTIUM/PRO/150", "P6/150"}, 1498}, {s686, {"PPRO/166", "PP/166", "PENTIUMPRO/166", "PENTIUM/PRO/166", "P6/166"}, 1658}, {s686, {"PPRO/180", "PP/180", "PENTIUMPRO/180", "PENTIUM/PRO/180", "P6/180"}, 1798}, {s686, {"PPRO/200", "PP/200", "PENTIUMPRO/200", "PENTIUM/PRO/200", "P6/200"}, 1997}, {s686, {"PII/233", "P2/233", "PENTIUM2/233", "PENTIUM/2/233", "P6/233"}, 2327}, {s686, {"PII/266", "P2/266", "PENTIUM2/266", "PENTIUM/2/266", "P6/266"}, 2657}, {s686, {"PII/300", "P2/300", "PENTIUM2/300", "PENTIUM/2/300", "P6/300"}, 2996}, {s686, {"PII/350", "P2/350", "PENTIUM2/350", "PENTIUM/2/350", "P6/350"}, 3495}, {s686, {"PII/400", "P2/400", "PENTIUM2/400", "PENTIUM/2/400", "P6/400"}, 3995}, {s686, {"PII/450", "P2/450", "PENTIUM2/450", "PENTIUM/2/450", "P6/450"}, 4494}, {s686, {"PII/500", "P2/500", "PENTIUM2/500", "PENTIUM/2/500", "P6/500"}, 5994}, {s786, {"PIII/450", "P3/450", "PENTIUM3/450", "PENTIUM/3/050", "P7/450"},4500}, {s786, {"PIII/500", "P3/500", "PENTIUM3/500", "PENTIUM/3/500", "P7/500"},5000}, {s786, {"PIII/550", "P3/550", "PENTIUM3/550", "PENTIUM/3/550", "P7/550"},5500}, {s786, {"PIII/600", "P3/600", "PENTIUM3/600", "PENTIUM/3/600", "P7/600"},6000}, {s786, {"PIII/650", "P3/650", "PENTIUM3/650", "PENTIUM/3/650", "P7/650"},6500}, {s786, {"PIII/667", "P3/667", "PENTIUM3/667", "PENTIUM/3/667", "P7/667"},6667}, {s786, {"PIII/700", "P3/700", "PENTIUM3/700", "PENTIUM/3/700", "P7/700"},7000}, {s786, {"PIII/733", "P3/733", "PENTIUM3/733", "PENTIUM/3/733", "P7/733"},7333}, {s786, {"PIII/750", "P3/750", "PENTIUM3/750", "PENTIUM/3/750", "P7/750"},7500}, {s786, {"PIII/800", "P3/800", "PENTIUM3/800", "PENTIUM/3/800", "P7/800"},8000}, {s786, {"PIII/866", "P3/866", "PENTIUM3/866", "PENTIUM/3/866", "P7/866"},8667}, {s786, {"PIII/933", "P3/933", "PENTIUM3/933", "PENTIUM/3/933", "P7/933"},9333}, {s786, {"PIII/1000", "P3/1000", "PENTIUM3/1000", "PENTIUM/3/1000", "P7/1000"},10000}, {s886, {"PIV/1300", "P4/1300", "PENTIUM4/1300", "PENTIUM/4/1300", "P8/1300"},13000}, {s886, {"PIV/1400", "P4/1400", "PENTIUM4/1400", "PENTIUM/4/1400", "P8/1400"},14000}, {s886, {"PIV/1500", "P4/1500", "PENTIUM4/1500", "PENTIUM/4/1500", "P8/1500"},15000}, {NULL, {NULL, NULL, NULL, NULL}, 0} }; #define MOSIX_STANDARD "Pentium-III at 1GHz" const char *cdesc[] = { "Home-node overhead in processing a demand-page", "Remote overhead in processing a demand-page", "Home-node overhead in processing a system call", "Remote overhead in processing a system call", "Basic home-node overhead for reading data", "Home-node overhead per 1KB read", "Basic remote overhead for reading data", "Remote overhead per 1KB read", "Basic home-node overhead for writing data", "Home-node overhead per 1KB written", "Basic remote overhead for writing data", "Remote overhead per 1KB written", "Migration time of an empty process", "Extra migration time per dirty page", }; #define iabs(x) ((x) >= 0 ? (x) : -(x)) int main(int na, char **argv) { register struct coms *c; int64_t ans; register char *x; register int64_t n; int64_t arg = 0; register struct speeds *sp, *bestsp=0; register char *u; unsigned long i1, i2, i3, i4; char stop; struct hostent *he; unsigned long addr; size_t length = 0; void *resp = NULL; static int *costs; int64_t overheads_num; int64_t tot; struct decay_params dec; char address[20]; if (!msx_is_mosix()) { fprintf(stderr, "This is NOT a OpenMosix system!\n"); exit(1); } if(na < 2 || na > 5) { Usage: fprintf(stderr, "Usage: %s command\n", argv[0]); fprintf(stderr, "Available commands: stay/nostay, lstay/nolstay, block/noblock, quiet/noquiet,\n"); fprintf(stderr, " mfs/nomfs, expel, bring, gettune, getdecay,\n"); fprintf(stderr, " whois [mosix_no|IP-address|hostname],\n"); fprintf(stderr, " getload [node-number], getspeed [node-number],\n"); fprintf(stderr, " status [node-number], getmem [node-number],\n"); fprintf(stderr, " getfree [node-number], getutil [node-number],\n"); fprintf(stderr, " getyard, setyard [node-type], setspeed speed,\n"); fprintf(stderr, " setdecay interval(seconds) slow(/%d) fast(/%d),\n", DECAY_QUOTIENT, DECAY_QUOTIENT); /* fprintf(stderr, " isup [node-number], settune [file_name].\n"); */ fprintf(stderr, " isup [node-number]\n"); exit(1); } for(x = argv[1] ; *x ; x++) if(*x >= 'A' && *x <= 'Z') *x += 'a' - 'A'; for(c = coms ; c->com ; c++) if(!strcmp(c->com, argv[1])) break; if(!c->com) { printf("%s: No such option.\n", argv[0]); exit(1); } if(c->no == D_SETDECAY) { if(na != 5) goto Usage; arg = (int)&dec; if(sscanf(argv[2], "%d", &dec.interval) != 1 || sscanf(argv[3], "%d", &dec.slow) != 1 || sscanf(argv[4], "%d", &dec.fast) != 1) goto Usage; } else if(c->no == D_GETLOAD || c->no == D_GETSPEED || c->no == D_GETSTAT || c->no == D_GETMEM || c->no == D_GETRMEM || c->no == D_GETUTIL) { if(na > 3) goto Usage; if(na == 3) arg = atoi(argv[2]); } else if(c->no == D_SETSPEED) { if(na != 3) goto Usage; for(u = argv[2] ; *u ; u++) if(*u < '0' || *u > '9') goto Usage; arg = atoi(argv[2]); } else if(c->no == D_SETSSPEED) { if(na > 3) goto Usage; if(na == 2) { Usage2: fprintf(stderr, "Recognised Processor Types:\n\n"); for(arg = 0, sp = speeds; sp->mach[0]; sp++, arg++){ if(arg) { fprintf(stderr, ", "); if(arg % 6 == 0) fprintf(stderr, "\n"); } fprintf(stderr, "%s", sp->mach[0]); } fprintf(stderr, "\n\nInstead, you may also specify a number, where %d represents OpenMosix's standard\n", STD_SPD); fprintf(stderr, "processor speed (eg. %s).\n", MOSIX_STANDARD); fprintf(stderr, "You may also set the local processor's speed as the standard using 'this'.\n"); exit(1); } arg = 0; for(u = argv[2] ; *u ; u++) { if(*u >= 'a' && *u <= 'z') *u += 'A' - 'a'; if(*u == '-' || *u == '_') *u = '/'; if(*u < '0' || *u > '9') arg = 1; } if(arg == 0) { arg = atoi(argv[2]); } else if(!strcasecmp(argv[2], "THIS")) { arg = msxctl(D_GETSPEED, 0, NULL, 0); if(arg == -1) { perror("Failed to get local speed"); exit(1); } } else { for(sp = speeds ; sp->mach[0] ; sp++) for(n = 0 ; n < MAXNICK && sp->mach[n] ; n++) if(!strcmp(argv[2], sp->mach[n])) goto fnd; fnd: if(!sp->mach[0]) goto Usage2; arg = sp->spd; } } else if(na == 3 && c->no == D_MOSIX_TO_IP) { for(u = argv[2] ; *u ; u++) if(*u < '0' || *u > '9') break; if(*u) { if(sscanf(argv[2], "%lui.%lui.%lui.%lui%c", &i1, &i2, &i3, &i4, &stop) != 4) { if(!(he = gethostbyname(argv[2]))) { fprintf(stderr, "%s: No Such Host-Name\n", argv[2]); exit(1); } bcopy(he->h_addr, &addr, sizeof(addr)); arg = ntohl(addr); } else { arg = (i1 << 24) | (i2 << 16) | (i3 << 8) | i4; } c->no = D_IP_TO_MOSIX; } else { resp = address; arg = atoi(argv[2]); } } else if(na == 2 && c->no == D_MOSIX_TO_IP) c->no = D_IP_TO_MOSIX; else if (na != 2) goto Usage; if(c->no == D_GETTUNE) { overheads_num = msxctl(D_GETNTUNE, 0, NULL, 0); if (overheads_num <= 0 || (costs = malloc(overheads_num * sizeof(int))) == NULL) { perror("Getting tune values"); exit(1); } resp = costs; length = overheads_num * sizeof(int); } else if (c->no == D_GETDECAY) resp = &dec; else if (c->no == D_GETMEM || c->no == D_GETRMEM) resp = &tot; ans = msxctl(c->no, arg, resp, (int) length); if(ans == -1) { if(c->no == D_GETLOAD || c->no == D_GETSPEED || c->no == D_GETMEM || c->no == D_GETSTAT || c->no == D_GETRMEM || c->no == D_GETUTIL) switch(errno) { case EINVAL: fprintf(stderr, "Error: Improper node number\n"); break; case EWOULDBLOCK: case EHOSTDOWN: if(!strcmp(c->com, "isup")) fprintf(stderr, "no (it seems)\n"); else fprintf(stderr, "Error: no response\n"); break; case ENOENT: fprintf(stderr,"Node #%s is not configured\n",argv[2]); break; default: perror("Error"); } else if(c->no == D_SETDECAY && errno == EINVAL) fprintf(stderr, "Error: Improper value\n"); else if (errno == ENOENT && c->no == D_IP_TO_MOSIX) fprintf(stderr, "Node at %s is not configured\n",argv[2]); else if (errno == ENOENT && c->no == D_MOSIX_TO_IP) fprintf(stderr, "Node #%s is not configured\n",argv[2]); else perror("Error"); } else switch(c->no) { case D_GETLOAD: printf("load=%lld\n", ans); break; case D_GETSPEED: { struct utsname un; printf("speed=%lld", ans); if(!arg && uname(&un) == 0) { n = 1000000; for(sp = &speeds[0] ; sp->mach[0] ; sp++) if(!strcmp(un.machine, sp->model) && n >= iabs(sp->spd - ans)) { n = iabs(sp->spd - ans); bestsp = sp; } if(n <= bestsp->spd * 0.06) printf(" (%s%s)", n ? "close to " : "", bestsp->mach[0]); } printf(".\n"); break; } case D_MOSIX_TO_IP: printf("%s\n", (char*)resp); break; case D_IP_TO_MOSIX: printf("%s is openMosix #%lld\n", na == 3 ? argv[2] : "This", ans); break; case D_SETSSPEED: ans = arg; case D_GETSSPEED: { struct utsname un; printf("Yardstick speed %sset to %lld", c->no == D_GETSSPEED ? "currently " : "", ans); if (uname(&un) != 0) goto anything; bestsp = speeds; n = 1000000; for(sp = &speeds[0] ; sp->mach[0] ; sp++) if(!strcmp(un.machine, sp->model) && n >= iabs(sp->spd - ans)) { n = iabs(sp->spd - ans); bestsp = sp; } if(n <= bestsp->spd * 0.06) printf(" (%s a %s processor)", n ? "probably" : "matching", bestsp->mach[0]); else { anything: n = iabs(speeds[0].spd - ans); for(sp = &speeds[1] ; sp->mach[0] ; sp++) if(n >= iabs(sp->spd - ans)) { n = iabs(sp->spd - ans); bestsp = sp; } if(n <= bestsp->spd * 0.06) printf(" (%s a %s processor)", n ? "probably" : "matching", bestsp->mach[0]); } printf(".\n"); break; } case D_EXPEL: printf("All remote processes were expelled and no further remote processes accepted.\n"); break; case D_BRING: printf("All local processes were brought back and will stay here.\n"); break; case D_STAY: printf(ans ? "Automatic load-balancing already disabled.\n" : "Automatic load-balancing disabled: no processes will leave This node\n(except by an explicit request)\n"); break; case D_NOSTAY: printf(ans ? "automatic load-balancing re-enabled.\n" : "automatic load-balancing already enabled.\n"); break; case D_LSTAY: printf(ans ? "Local processes already not leaving the node automatically.\n" : "No local processes will leave the node automatically.\n"); break; case D_NOLSTAY: printf(ans ? "Local processes may now leave the node automatically.\n" : "Local processes already allowed to leave automatically.\n"); break; case D_BLOCK: printf(ans ? "Remote processes already not allowed here.\n" : "Remote processes will not be allowed in here.\n"); break; case D_NOBLOCK: printf(ans ? "Remote processes now allowed in.\n" : "Remote processes already allowed in.\n"); break; case D_QUIET: printf(ans ? "Load-balancing activity already shut-down.\n" : "Load-balancing activity is now shut-down (for fine-timing measurements)\n"); break; case D_NOQUIET: printf(ans ? "Load balancing activity now resumed.\n" : "Load balancing already active.\n"); break; case D_NOMFS: printf(ans ? "MFS access already disallowed to this node.\n" : "MFS access to this node now disallowed.\n"); break; case D_MFS: printf(ans ? "MFS access to this node now allowed.\n" : "MFS access already enabled.\n"); break; case D_GETTUNE: { int group, last = 0; printf("\nOpenMosix Kernel Tuning Parameters (microseconds):\n\n\n"); n = (msxctl(D_GETNTUNE, 0, NULL, 0) + 2 ) / 16; for (group = 0 ; group < n ; group++) { if (costs[group * 16 + 14] == 0) { if (group) printf("The following parameters apply to all the remainning OpenMosix nodes:\n\n"); last = 1; } else if (costs[group * 16 + 14] <= costs[group * 16 + 15]) printf("The following parameters apply to all OpenMosix nodes between %d and %d:\n\n", costs[group * 16 + 14], costs[group * 16 + 15]); else if (costs[group * 16 + 14] != 0 && costs[group * 16 + 15] == 0) printf("The following parameters apply to all OpenMosix nodes except %d:\n\n", costs[group * 16 + 14]); else if (costs[group * 16 + 14] > costs[group * 16 + 15]) printf("The following parameters apply to all OpenMosix nodes NOT between %d and %d:\n\n", costs[group * 16 + 15], costs[group * 16 + 14]); for (n = group * 16 ; n < group * 16 + 14; n++) printf("\t%-47s = %d\n", cdesc[n % 16], costs[n]); printf("\n\n"); if (last) { break; } } printf("\n"); break; } case D_GETMEM: printf("free memory = %lld of %lld\n", ans, tot); break; case D_GETRMEM: printf("raw free memory = %lld of %lld\n", ans, tot); break; case D_GETUTIL: n = msxctl(D_GETCPUS, arg, NULL, 0); printf("Utilizability = %lld%%", ans); if(n > 1) printf(" (of %lld%%)", 100 * n); printf("\n"); break; case D_GETSTAT: if(!strcmp(c->com, "isup")) { printf((ans & DS_MOSIX_UP) ? "yes\n" : "no\n"); break; } printf((ans & DS_MOSIX_UP) ? "up" : "down"); if(ans & DS_STAY) printf(",stay"); if(ans & DS_LSTAY) printf(",lstay"); if(ans & DS_BLOCK) printf(",block"); if(ans & DS_QUIET) printf(",quiet"); if(ans & DS_NOMFS) printf(",nomfs"); printf(".\n"); break; case D_GETDECAY: printf("Decaying statistics of active processes occurs every %d second%s.\n", dec.interval, dec.interval > 1 ? "s" : ""); printf("Slow decay leaves %d/%d.\n", dec.slow, DECAY_QUOTIENT); printf("Fast decay leaves %d/%d.\n", dec.fast, DECAY_QUOTIENT); break; } exit(0); }