00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include <types.h>
00031 #include <kern/errno.h>
00032 #include <kern/reboot.h>
00033 #include <kern/unistd.h>
00034 #include <limits.h>
00035 #include <lib.h>
00036 #include <uio.h>
00037 #include <clock.h>
00038 #include <thread.h>
00039 #include <proc.h>
00040 #include <synch.h>
00041 #include <vfs.h>
00042 #include <sfs.h>
00043 #include <syscall.h>
00044 #include <test.h>
00045 #include "opt-synchprobs.h"
00046 #include "opt-sfs.h"
00047 #include "opt-net.h"
00048
00049
00050
00051
00052
00053 #define _PATH_SHELL "/bin/sh"
00054
00055 #define MAXMENUARGS 16
00056
00057
00058 void
00059 getinterval(time_t s1, uint32_t ns1, time_t s2, uint32_t ns2,
00060 time_t *rs, uint32_t *rns)
00061 {
00062 if (ns2 < ns1) {
00063 ns2 += 1000000000;
00064 s2--;
00065 }
00066
00067 *rns = ns2 - ns1;
00068 *rs = s2 - s1;
00069 }
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086 static
00087 void
00088 cmd_progthread(void *ptr, unsigned long nargs)
00089 {
00090 char **args = ptr;
00091 char progname[128];
00092 int result;
00093
00094 KASSERT(nargs >= 1);
00095
00096 if (nargs > 2) {
00097 kprintf("Warning: argument passing from menu not supported\n");
00098 }
00099
00100
00101 KASSERT(strlen(args[0]) < sizeof(progname));
00102
00103 strcpy(progname, args[0]);
00104
00105 result = runprogram(progname);
00106 if (result) {
00107 kprintf("Running program %s failed: %s\n", args[0],
00108 strerror(result));
00109 return;
00110 }
00111
00112
00113 }
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127 static
00128 int
00129 common_prog(int nargs, char **args)
00130 {
00131 struct proc *proc;
00132 int result;
00133
00134 #if OPT_SYNCHPROBS
00135 kprintf("Warning: this probably won't work with a "
00136 "synchronization-problems kernel.\n");
00137 #endif
00138
00139
00140 proc = proc_create_runprogram(args[0] );
00141 if (proc == NULL) {
00142 return ENOMEM;
00143 }
00144
00145 result = thread_fork(args[0] ,
00146 proc ,
00147 cmd_progthread ,
00148 args , nargs );
00149 if (result) {
00150 kprintf("thread_fork failed: %s\n", strerror(result));
00151 proc_destroy(proc);
00152 return result;
00153 }
00154
00155 #ifdef UW
00156
00157
00158 P(no_proc_sem);
00159 #endif // UW
00160
00161 return 0;
00162 }
00163
00164
00165
00166
00167 static
00168 int
00169 cmd_prog(int nargs, char **args)
00170 {
00171 if (nargs < 2) {
00172 kprintf("Usage: p program [arguments]\n");
00173 return EINVAL;
00174 }
00175
00176
00177 args++;
00178 nargs--;
00179
00180 return common_prog(nargs, args);
00181 }
00182
00183
00184
00185
00186 static
00187 int
00188 cmd_shell(int nargs, char **args)
00189 {
00190 (void)args;
00191 if (nargs != 1) {
00192 kprintf("Usage: s\n");
00193 return EINVAL;
00194 }
00195
00196 args[0] = (char *)_PATH_SHELL;
00197
00198 return common_prog(nargs, args);
00199 }
00200
00201
00202
00203
00204 static
00205 int
00206 cmd_chdir(int nargs, char **args)
00207 {
00208 if (nargs != 2) {
00209 kprintf("Usage: cd directory\n");
00210 return EINVAL;
00211 }
00212
00213 return vfs_chdir(args[1]);
00214 }
00215
00216
00217
00218
00219 static
00220 int
00221 cmd_pwd(int nargs, char **args)
00222 {
00223 char buf[PATH_MAX+1];
00224 int result;
00225 struct iovec iov;
00226 struct uio ku;
00227
00228 (void)nargs;
00229 (void)args;
00230
00231 uio_kinit(&iov, &ku, buf, sizeof(buf)-1, 0, UIO_READ);
00232 result = vfs_getcwd(&ku);
00233 if (result) {
00234 kprintf("vfs_getcwd failed (%s)\n", strerror(result));
00235 return result;
00236 }
00237
00238
00239 buf[sizeof(buf)-1-ku.uio_resid] = 0;
00240
00241
00242 kprintf("%s\n", buf);
00243
00244 return 0;
00245 }
00246
00247
00248
00249
00250 static
00251 int
00252 cmd_sync(int nargs, char **args)
00253 {
00254 (void)nargs;
00255 (void)args;
00256
00257 vfs_sync();
00258
00259 return 0;
00260 }
00261
00262
00263
00264
00265 static
00266 int
00267 cmd_panic(int nargs, char **args)
00268 {
00269 (void)nargs;
00270 (void)args;
00271
00272 panic("User requested panic\n");
00273 return 0;
00274 }
00275
00276
00277
00278
00279 static
00280 int
00281 cmd_quit(int nargs, char **args)
00282 {
00283 (void)nargs;
00284 (void)args;
00285
00286 vfs_sync();
00287 sys_reboot(RB_POWEROFF);
00288 thread_exit();
00289 return 0;
00290 }
00291
00292
00293
00294
00295
00296
00297 static const struct {
00298 const char *name;
00299 int (*func)(const char *device);
00300 } mounttable[] = {
00301 #if OPT_SFS
00302 { "sfs", sfs_mount },
00303 #endif
00304 { NULL, NULL }
00305 };
00306
00307 static
00308 int
00309 cmd_mount(int nargs, char **args)
00310 {
00311 char *fstype;
00312 char *device;
00313 int i;
00314
00315 if (nargs != 3) {
00316 kprintf("Usage: mount fstype device:\n");
00317 return EINVAL;
00318 }
00319
00320 fstype = args[1];
00321 device = args[2];
00322
00323
00324 if (device[strlen(device)-1]==':') {
00325 device[strlen(device)-1] = 0;
00326 }
00327
00328 for (i=0; mounttable[i].name; i++) {
00329 if (!strcmp(mounttable[i].name, fstype)) {
00330 return mounttable[i].func(device);
00331 }
00332 }
00333 kprintf("Unknown filesystem type %s\n", fstype);
00334 return EINVAL;
00335 }
00336
00337 static
00338 int
00339 cmd_unmount(int nargs, char **args)
00340 {
00341 char *device;
00342
00343 if (nargs != 2) {
00344 kprintf("Usage: unmount device:\n");
00345 return EINVAL;
00346 }
00347
00348 device = args[1];
00349
00350
00351 if (device[strlen(device)-1]==':') {
00352 device[strlen(device)-1] = 0;
00353 }
00354
00355 return vfs_unmount(device);
00356 }
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366 static
00367 int
00368 cmd_bootfs(int nargs, char **args)
00369 {
00370 char *device;
00371
00372 if (nargs != 2) {
00373 kprintf("Usage: bootfs device\n");
00374 return EINVAL;
00375 }
00376
00377 device = args[1];
00378
00379
00380 if (device[strlen(device)-1]==':') {
00381 device[strlen(device)-1] = 0;
00382 }
00383
00384 return vfs_setbootfs(device);
00385 }
00386
00387 static
00388 int
00389 cmd_kheapstats(int nargs, char **args)
00390 {
00391 (void)nargs;
00392 (void)args;
00393
00394 kheap_printstats();
00395
00396 return 0;
00397 }
00398
00399
00400
00401
00402
00403 static
00404 void
00405 showmenu(const char *name, const char *x[])
00406 {
00407 int ct, half, i;
00408
00409 kprintf("\n");
00410 kprintf("%s\n", name);
00411
00412 for (i=ct=0; x[i]; i++) {
00413 ct++;
00414 }
00415 half = (ct+1)/2;
00416
00417 for (i=0; i<half; i++) {
00418 kprintf(" %-36s", x[i]);
00419 if (i+half < ct) {
00420 kprintf("%s", x[i+half]);
00421 }
00422 kprintf("\n");
00423 }
00424
00425 kprintf("\n");
00426 }
00427
00428 static const char *opsmenu[] = {
00429 "[s] Shell ",
00430 "[p] Other program ",
00431 "[mount] Mount a filesystem ",
00432 "[unmount] Unmount a filesystem ",
00433 "[bootfs] Set \"boot\" filesystem ",
00434 "[pf] Print a file ",
00435 "[cd] Change directory ",
00436 "[pwd] Print current directory ",
00437 "[sync] Sync filesystems ",
00438 "[panic] Intentional panic ",
00439 "[q] Quit and shut down ",
00440 NULL
00441 };
00442
00443 static
00444 int
00445 cmd_opsmenu(int n, char **a)
00446 {
00447 (void)n;
00448 (void)a;
00449
00450 showmenu("OS/161 operations menu", opsmenu);
00451 return 0;
00452 }
00453
00454 static const char *testmenu[] = {
00455 "[at] Array test ",
00456 "[bt] Bitmap test ",
00457 "[km1] Kernel malloc test ",
00458 "[km2] kmalloc stress test ",
00459 "[tt1] Thread test 1 ",
00460 "[tt2] Thread test 2 ",
00461 "[tt3] Thread test 3 ",
00462 #if OPT_NET
00463 "[net] Network test ",
00464 #endif
00465 "[sy1] Semaphore test ",
00466 "[sy2] Lock test (1) ",
00467 "[sy3] CV test (1) ",
00468 #ifdef UW
00469 "[uw1] UW lock test (1) ",
00470 "[uw2] UW vmstats test (3) ",
00471 #endif // UW
00472 "[fs1] Filesystem test ",
00473 "[fs2] FS read stress (4) ",
00474 "[fs3] FS write stress (4) ",
00475 "[fs4] FS write stress 2 (4) ",
00476 "[fs5] FS create stress (4) ",
00477 NULL
00478 };
00479
00480 static
00481 int
00482 cmd_testmenu(int n, char **a)
00483 {
00484 (void)n;
00485 (void)a;
00486
00487 showmenu("OS/161 tests menu", testmenu);
00488 kprintf(" (1) These tests will fail until you finish the "
00489 "synch assignment.\n");
00490 kprintf(" (4) These tests may fail until you finish the "
00491 "file system assignment.\n");
00492 kprintf("\n");
00493
00494 return 0;
00495 }
00496
00497 static const char *mainmenu[] = {
00498 "[?o] Operations menu ",
00499 "[?t] Tests menu ",
00500 #if OPT_SYNCHPROBS
00501 "[sp1] Whale Mating ",
00502 #ifdef UW
00503 "[sp2] Cat/mouse ",
00504 #endif
00505 #endif
00506 "[kh] Kernel heap stats ",
00507 "[q] Quit and shut down ",
00508 NULL
00509 };
00510
00511 static
00512 int
00513 cmd_mainmenu(int n, char **a)
00514 {
00515 (void)n;
00516 (void)a;
00517
00518 showmenu("OS/161 kernel menu", mainmenu);
00519 return 0;
00520 }
00521
00522
00523
00524
00525
00526 static struct {
00527 const char *name;
00528 int (*func)(int nargs, char **args);
00529 } cmdtable[] = {
00530
00531 { "?", cmd_mainmenu },
00532 { "h", cmd_mainmenu },
00533 { "help", cmd_mainmenu },
00534 { "?o", cmd_opsmenu },
00535 { "?t", cmd_testmenu },
00536
00537
00538 { "s", cmd_shell },
00539 { "p", cmd_prog },
00540 { "mount", cmd_mount },
00541 { "unmount", cmd_unmount },
00542 { "bootfs", cmd_bootfs },
00543 { "pf", printfile },
00544 { "cd", cmd_chdir },
00545 { "pwd", cmd_pwd },
00546 { "sync", cmd_sync },
00547 { "panic", cmd_panic },
00548 { "q", cmd_quit },
00549 { "exit", cmd_quit },
00550 { "halt", cmd_quit },
00551
00552 #if OPT_SYNCHPROBS
00553
00554 { "sp1", whalemating },
00555 #ifdef UW
00556 { "sp2", catmouse },
00557 #endif
00558 #endif
00559
00560
00561 { "kh", cmd_kheapstats },
00562
00563
00564 { "at", arraytest },
00565 { "bt", bitmaptest },
00566 { "km1", malloctest },
00567 { "km2", mallocstress },
00568 #if OPT_NET
00569 { "net", nettest },
00570 #endif
00571 { "tt1", threadtest },
00572 { "tt2", threadtest2 },
00573 { "tt3", threadtest3 },
00574 { "sy1", semtest },
00575
00576
00577 { "sy2", locktest },
00578 { "sy3", cvtest },
00579 #ifdef UW
00580 { "uw1", uwlocktest1 },
00581 { "uw2", uwvmstatstest },
00582 #endif
00583
00584
00585 { "fs1", fstest },
00586 { "fs2", readstress },
00587 { "fs3", writestress },
00588 { "fs4", writestress2 },
00589 { "fs5", createstress },
00590
00591 { NULL, NULL }
00592 };
00593
00594
00595
00596
00597 static
00598 int
00599 cmd_dispatch(char *cmd)
00600 {
00601 time_t beforesecs, aftersecs, secs;
00602 uint32_t beforensecs, afternsecs, nsecs;
00603 char *args[MAXMENUARGS];
00604 int nargs=0;
00605 char *word;
00606 char *context;
00607 int i, result;
00608
00609 for (word = strtok_r(cmd, " \t", &context);
00610 word != NULL;
00611 word = strtok_r(NULL, " \t", &context)) {
00612
00613 if (nargs >= MAXMENUARGS) {
00614 kprintf("Command line has too many words\n");
00615 return E2BIG;
00616 }
00617 args[nargs++] = word;
00618 }
00619
00620 if (nargs==0) {
00621 return 0;
00622 }
00623
00624 for (i=0; cmdtable[i].name; i++) {
00625 if (*cmdtable[i].name && !strcmp(args[0], cmdtable[i].name)) {
00626 KASSERT(cmdtable[i].func!=NULL);
00627
00628 gettime(&beforesecs, &beforensecs);
00629
00630 result = cmdtable[i].func(nargs, args);
00631
00632 gettime(&aftersecs, &afternsecs);
00633 getinterval(beforesecs, beforensecs,
00634 aftersecs, afternsecs,
00635 &secs, &nsecs);
00636
00637 kprintf("Operation took %lu.%09lu seconds\n",
00638 (unsigned long) secs,
00639 (unsigned long) nsecs);
00640
00641 return result;
00642 }
00643 }
00644
00645 kprintf("%s: Command not found\n", args[0]);
00646 return EINVAL;
00647 }
00648
00649
00650
00651
00652
00653
00654
00655
00656 static
00657 void
00658 menu_execute(char *line, int isargs)
00659 {
00660 char *command;
00661 char *context;
00662 int result;
00663
00664 for (command = strtok_r(line, ";", &context);
00665 command != NULL;
00666 command = strtok_r(NULL, ";", &context)) {
00667
00668 if (isargs) {
00669 kprintf("OS/161 kernel: %s\n", command);
00670 }
00671
00672 result = cmd_dispatch(command);
00673 if (result) {
00674 kprintf("Menu command failed: %s\n", strerror(result));
00675 if (isargs) {
00676 panic("Failure processing kernel arguments\n");
00677 }
00678 }
00679 }
00680 }
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699 void
00700 menu(char *args)
00701 {
00702 char buf[64];
00703
00704 menu_execute(args, 1);
00705
00706 while (1) {
00707 kprintf("OS/161 kernel [? for menu]: ");
00708 kgets(buf, sizeof(buf));
00709 menu_execute(buf, 0);
00710 }
00711 }