meas.c

Go to the documentation of this file.
00001 /* meas.c -- measure qt stuff. */
00002 
00003 #include "copyright.h"
00004 
00005 /* Need this to get assertions under Mach on the Sequent/i386: */
00006 #ifdef __i386__
00007 #define assert(ex) \
00008   do { \
00009     if (!(ex)) { \
00010       fprintf (stderr, "[%s:%d] Assertion " #ex " failed\n", __FILE__, __LINE__); \
00011       abort(); \
00012     } \
00013   } while (0)
00014 #else
00015 #include <assert.h>
00016 #endif
00017 
00018 /* This really ought to be defined in some ANSI include file (*I*
00019    think...), but it's defined here instead, which leads us to another
00020    machine dependency.
00021 
00022    The `iaddr_t' type is an integer representation of a pointer,
00023    suited for doing arithmetic on addresses, e.g. to round an address
00024    to an alignment boundary. */
00025 typedef unsigned long iaddr_t;
00026 
00027 #include <stdarg.h> /* For varargs tryout. */
00028 #include <stdio.h>
00029 #include "b.h"
00030 #include "qt.h"
00031 #include "stp.h"
00032 
00033 extern void exit (int status);
00034 extern int atoi (char const *s);
00035 extern int fprintf (FILE *out, char const *fmt, ...);
00036 extern int fputs (char const *s, FILE *fp);
00037 extern void free (void *sto);
00038 extern void *malloc (unsigned nbytes);
00039 extern void perror (char const *s);
00040 
00041 void usage (void);
00042 void tracer(void);
00043 
00044 /* Round `v' to be `a'-aligned, assuming `a' is a power of two. */
00045 #define ROUND(v, a) (((v) + (a) - 1) & ~((a)-1))
00046 
00047 typedef struct thread_t {
00048   qt_t *qt;     /* Pointer to thread of function... */
00049   void *stk;
00050   void *top;        /* Set top of stack if reuse. */
00051   struct thread_t *next;
00052 } thread_t;
00053 
00054 
00055   static thread_t *
00056 t_alloc (void)
00057 {
00058   thread_t *t;
00059   int ssz = 0x1000;
00060 
00061   t = malloc (sizeof(thread_t));
00062   if (!t) {
00063     perror ("malloc");
00064     exit (1);
00065   }
00066   assert (ssz > QT_STKBASE);
00067   t->stk = malloc (ssz);
00068   t->stk = (void *)ROUND (((iaddr_t)t->stk), QT_STKALIGN);
00069   if (!t->stk) {
00070     perror ("malloc");
00071     exit (1);
00072   }
00073   assert ((((iaddr_t)t->stk) & (QT_STKALIGN-1)) == 0);
00074   t->top = QT_SP (t->stk, ssz - QT_STKBASE);
00075 
00076   return (t);
00077 }
00078 
00079 
00080   static thread_t *
00081 t_create (qt_only_t *starter, void *p0, qt_userf_t *f)
00082 {
00083   thread_t *t;
00084 
00085   t = t_alloc();
00086   t->qt = QT_ARGS (t->top, p0, t, f, starter);
00087   return (t);
00088 }
00089 
00090 
00091   static void
00092 t_free (thread_t *t)
00093 {
00094   free (t->stk);
00095   free (t);
00096 }
00097 
00098 
00099   static void *
00100 t_null (qt_t *old, void *p1, void *p2)
00101 {
00102   /* return (garbage); */
00103 }
00104 
00105 
00106   static void *
00107 t_splat (qt_t *old, void *oldp, void *null)
00108 {
00109   *(qt_t **)oldp = old;
00110   /* return (garbage); */
00111 }
00112 
00113 
00114 static char const test01_msg[] =
00115   "*QT_SP(sto,sz), QT_ARGS(top,p0,p1,userf,first)";
00116 
00117 static char const *test01_descr[] = {
00118   "Performs 1 QT_SP and one QT_ARGS per iteration.",
00119   NULL
00120 };
00121 
00122 /* This test gives a guess on how long it takes to initalize
00123    a thread. */
00124 
00125   static void
00126 test01 (int n)
00127 {
00128   char stack[QT_STKBASE+QT_STKALIGN];
00129   char *stk;
00130   qt_t *top;
00131 
00132   stk = (char *)ROUND (((iaddr_t)stack), QT_STKALIGN);
00133 
00134   {
00135     int i;
00136 
00137     for (i=0; i<QT_STKBASE; ++i) {
00138       stk[i] = 0;
00139     }
00140   }
00141 
00142   while (n>0) {
00143     /* RETVALUSED */
00144     top = QT_SP (stk, QT_STKBASE);  QT_ARGS (top, 0, 0, 0, 0);
00145 #ifdef NDEF
00146     top = QT_SP (stk, QT_STKBASE);  QT_ARGS (top, 0, 0, 0, 0);
00147     top = QT_SP (stk, QT_STKBASE);  QT_ARGS (top, 0, 0, 0, 0);
00148     top = QT_SP (stk, QT_STKBASE);  QT_ARGS (top, 0, 0, 0, 0);
00149     top = QT_SP (stk, QT_STKBASE);  QT_ARGS (top, 0, 0, 0, 0);
00150 
00151     top = QT_SP (stk, QT_STKBASE);  QT_ARGS (top, 0, 0, 0, 0);
00152     top = QT_SP (stk, QT_STKBASE);  QT_ARGS (top, 0, 0, 0, 0);
00153     top = QT_SP (stk, QT_STKBASE);  QT_ARGS (top, 0, 0, 0, 0);
00154     top = QT_SP (stk, QT_STKBASE);  QT_ARGS (top, 0, 0, 0, 0);
00155     top = QT_SP (stk, QT_STKBASE);  QT_ARGS (top, 0, 0, 0, 0);
00156 
00157     n -= 10;
00158 #else
00159     n -= 1;
00160 #endif
00161   }
00162 }
00163 
00164 
00165 static char const test02_msg[] = "QT_BLOCKI (0, 0, test02_aux, t->qt)";
00166 static qt_t *rootthread;
00167 
00168   static void
00169 test02_aux1 (void *pu, void *pt, qt_userf_t *f)
00170 {
00171   QT_ABORT (t_null, 0, 0, rootthread);
00172 }
00173 
00174   static void *
00175 test02_aux2 (qt_t *old, void *farg1, void *farg2)
00176 {
00177   rootthread = old;
00178   /* return (garbage); */
00179 }
00180 
00181   static void
00182 test02 (int n)
00183 {
00184   thread_t *t;
00185 
00186   while (n>0) {
00187   t = t_create (test02_aux1, 0, 0);
00188     QT_BLOCKI (test02_aux2, 0, 0, t->qt);
00189   t_free (t);
00190   t = t_create (test02_aux1, 0, 0);
00191     QT_BLOCKI (test02_aux2, 0, 0, t->qt);
00192   t_free (t);
00193   t = t_create (test02_aux1, 0, 0);
00194     QT_BLOCKI (test02_aux2, 0, 0, t->qt);
00195   t_free (t);
00196   t = t_create (test02_aux1, 0, 0);
00197     QT_BLOCKI (test02_aux2, 0, 0, t->qt);
00198   t_free (t);
00199   t = t_create (test02_aux1, 0, 0);
00200     QT_BLOCKI (test02_aux2, 0, 0, t->qt);
00201   t_free (t);
00202 
00203     n -= 5;
00204   }
00205 }
00206 
00207 
00208 static char const test03_msg[] = "QT_BLOCKI (...) test vals are right.";
00209 
00210 
00211 /* Called by the thread function when it wants to shut down.
00212    Return a value to the main thread. */
00213 
00214   static void *
00215 test03_aux0 (qt_t *old_is_garbage, void *farg1, void *farg2)
00216 {
00217   assert (farg1 == (void *)5);
00218   assert (farg2 == (void *)6);
00219   return ((void *)15);      /* Some unlikely value. */
00220 }
00221 
00222 
00223 /* Called during new thread startup by main thread.  Since the new
00224    thread has never run before, return value is ignored. */
00225 
00226   static void *
00227 test03_aux1 (qt_t *old, void *farg1, void *farg2)
00228 {
00229   assert (old != NULL);
00230   assert (farg1 == (void *)5);
00231   assert (farg2 == (void *)6);
00232   rootthread = old;
00233   return ((void *)16);      /* Different than `15'. */
00234 }
00235 
00236   static void
00237 test03_aux2 (void *pu, void *pt, qt_userf_t *f)
00238 {
00239   assert (pu == (void *)1);
00240   assert (f == (qt_userf_t *)4);
00241   QT_ABORT (test03_aux0, (void *)5, (void *)6, rootthread);
00242 }
00243 
00244   static void
00245 test03 (int n)
00246 {
00247   thread_t *t;
00248   void *rv;
00249 
00250   while (n>0) {
00251     t = t_create (test03_aux2, (void *)1, (qt_userf_t *)4);
00252     rv = QT_BLOCKI (test03_aux1, (void *)5, (void *)6, t->qt);
00253     assert (rv == (void *)15);
00254     t_free (t);
00255 
00256     --n;
00257   }
00258 }
00259 
00260 
00261 static char const test04_msg[] = "stp_start w/ no threads.";
00262 
00263   static void
00264 test04 (int n)
00265 {
00266   while (n>0) {
00267     stp_init(); stp_start();
00268     stp_init(); stp_start();
00269     stp_init(); stp_start();
00270     stp_init(); stp_start();
00271     stp_init(); stp_start();
00272 
00273     stp_init(); stp_start();
00274     stp_init(); stp_start();
00275     stp_init(); stp_start();
00276     stp_init(); stp_start();
00277     stp_init(); stp_start();
00278 
00279     n -= 10;
00280   }
00281 }
00282 
00283 
00284 static char const test05_msg[] = "stp w/ 2 yielding thread.";
00285 
00286   static void
00287 test05_aux (void *null)
00288 {
00289   stp_yield();
00290   stp_yield();
00291 }
00292 
00293   static void
00294 test05 (int n)
00295 {
00296   while (n>0) {
00297     stp_init();
00298     stp_create (test05_aux, 0);
00299     stp_create (test05_aux, 0);
00300     stp_start();
00301 
00302     --n;
00303   }
00304 }
00305 
00306 
00307 static char const test06_msg[] = "*QT_ARGS(...), QT_BLOCKI one thread";
00308 
00309 static char const *test06_descr[] = {
00310   "Does a QT_ARGS, QT_BLOCKI to a helper function that saves the",
00311   "stack pointer of the main thread, calls an `only' function that",
00312   "saves aborts the thread, calling a null helper function.",
00313   ":: start/stop = QT_ARGS + QT_BLOCKI + QT_ABORT + 3 procedure calls.",
00314   NULL
00315 };
00316 
00317 /* This test initializes a thread, runs it, then returns to the main
00318    program, which reinitializes the thread, runs it again, etc.  Each
00319    iteration corresponds to 1 init, 1 abort, 1 block. */
00320 
00321 static qt_t *test06_sp;
00322 
00323 
00324   static void
00325 test06_aux2 (void *null0a, void *null1b, void *null2b, qt_userf_t *null)
00326 {
00327   QT_ABORT (t_null, 0, 0, test06_sp);
00328 }
00329 
00330 
00331   static void *
00332 test06_aux3 (qt_t *sp, void *null0c, void *null1c)
00333 {
00334   test06_sp = sp;
00335   /* return (garbage); */
00336 }
00337 
00338 
00339   static void
00340 test06 (int n)
00341 {
00342   thread_t *t;
00343 
00344   t = t_create (0, 0, 0);
00345 
00346   while (n>0) {
00347     /* RETVALUSED */
00348     QT_ARGS (t->top, 0, 0, 0, test06_aux2);
00349     QT_BLOCKI (test06_aux3, 0, 0, t->qt);
00350 #ifdef NDEF
00351     /* RETVALUSED */
00352     QT_ARGS (t->top, 0, 0, 0, test06_aux2);
00353     QT_BLOCKI (test06_aux3, 0, 0, t->qt);
00354 
00355     /* RETVALUSED */
00356     QT_ARGS (t->top, 0, 0, 0, test06_aux2);
00357     QT_BLOCKI (test06_aux3, 0, 0, t->qt);
00358 
00359     /* RETVALUSED */
00360     QT_ARGS (t->top, 0, 0, 0, test06_aux2);
00361     QT_BLOCKI (test06_aux3, 0, 0, t->qt);
00362 
00363     /* RETVALUSED */
00364     QT_ARGS (t->top, 0, 0, 0, test06_aux2);
00365     QT_BLOCKI (test06_aux3, 0, 0, t->qt);
00366 
00367     n -= 5;
00368 #else
00369     --n;
00370 #endif
00371   }
00372 }
00373 
00374 static char test07_msg[] = "*cswap between threads";
00375 
00376 static char const *test07_descr[] = {
00377   "Build a chain of threads where each thread has a fixed successor.",
00378   "There is no scheduling performed.  Each thread but one is a loop",
00379   "that simply blocks with QT_BLOCKI, calling a helper that saves the",
00380   "current stack pointer.  The last thread decrements a count, and,",
00381   "if zero, aborts back to the main thread.  Else it continues with",
00382   "the blocking chain.  The count is divided by the number of threads",
00383   "in the chain, so `n' is the number of integer block operations.",
00384   ":: integer cswap = QT_BLOCKI + a procedure call.",
00385   NULL
00386 };
00387 
00388 /* This test repeatedly blocks a bunch of threads.
00389    Each iteration corresponds to one block operation.
00390 
00391    The threads are arranged so that there are TEST07_N-1 of them that
00392    run `test07_aux2'.  Each one of those blocks saving it's sp to
00393    storage owned by the preceding thread; a pointer to that storage is
00394    passed in via `mep'.  Each thread has a handle on it's own storage
00395    for the next thread, referenced by `nxtp', and it blocks by passing
00396    control to `*nxtp', telling the helper function to save its state
00397    in `*mep'.  The last thread in the chain decrements a count and, if
00398    it's gone below zero, returns to `test07'; otherwise, it invokes
00399    the first thread in the chain. */
00400 
00401 static qt_t *test07_heavy;
00402 
00403 #define TEST07_N (4)
00404 
00405 
00406   static void
00407 test07_aux2 (void *null0, void *mep, void *nxtp, qt_userf_t *null)
00408 {
00409   qt_t *nxt;
00410 
00411   while (1) {
00412     nxt = *(qt_t **)nxtp;
00413 #ifdef NDEF
00414     printf ("Helper 0x%p\n", nxtp);
00415 #endif
00416     QT_BLOCKI (t_splat, mep, 0, nxt);
00417   }
00418 }
00419 
00420   static void
00421 test07_aux3 (void *np, void *mep, void *nxtp, qt_userf_t *null)
00422 {
00423   int n;
00424 
00425   n = *(int *)np;
00426   while (1) {
00427     n -= TEST07_N;
00428     if (n<0) {
00429       QT_ABORT (t_splat, mep, 0, test07_heavy);
00430     }
00431     QT_BLOCKI (t_splat, mep, 0, *(qt_t **)nxtp);
00432   }
00433 }
00434 
00435 
00436   static void
00437 test07 (int n)
00438 {
00439   int i;
00440   thread_t *t[TEST07_N];
00441 
00442   for (i=0; i<TEST07_N; ++i) {
00443     t[i] = t_create (0, 0, 0);
00444   }
00445   for (i=0; i<TEST07_N-1; ++i) {
00446     /* RETVALUSED */
00447     QT_ARGS (t[i]->top, 0, &t[i]->qt, &t[i+1]->qt, test07_aux2);
00448   }
00449   /* RETVALUSED */
00450   QT_ARGS (t[i]->top, &n, &t[TEST07_N-1]->qt, &t[0]->qt, test07_aux3);
00451   QT_BLOCKI (t_splat, &test07_heavy, 0, t[0]->qt);
00452 }
00453 
00454 
00455 static char test08_msg[] = "Floating-point cswap between threads";
00456 
00457 static char const *test08_descr[] = {
00458   "Measure context switch times including floating-point, use QT_BLOCK.",
00459   NULL
00460 };
00461 
00462 static qt_t *test08_heavy;
00463 
00464 #define TEST08_N (4)
00465 
00466 
00467   static void
00468 test08_aux2 (void *null0, void *mep, void *nxtp, qt_userf_t *null)
00469 {
00470   qt_t *nxt;
00471 
00472   while (1) {
00473     nxt = *(qt_t **)nxtp;
00474     QT_BLOCK (t_splat, mep, 0, nxt);
00475   }
00476 }
00477 
00478   static void
00479 test08_aux3 (void *np, void *mep, void *nxtp, qt_userf_t *null)
00480 {
00481   int n;
00482 
00483   n = *(int *)np;
00484   while (1) {
00485     n -= TEST08_N;
00486     if (n<0) {
00487       QT_ABORT (t_splat, mep, 0, test08_heavy);
00488     }
00489     QT_BLOCK (t_splat, mep, 0, *(qt_t **)nxtp);
00490   }
00491 }
00492 
00493 
00494   static void
00495 test08 (int n)
00496 {
00497   int i;
00498   thread_t *t[TEST08_N];
00499 
00500   for (i=0; i<TEST08_N; ++i) {
00501     t[i] = t_create (0, 0, 0);
00502   }
00503   for (i=0; i<TEST08_N-1; ++i) {
00504     /* RETVALUSED */
00505     QT_ARGS (t[i]->top, 0, &t[i]->qt, &t[i+1]->qt, test08_aux2);
00506   }
00507   /* RETVALUSED */
00508   QT_ARGS (t[i]->top, &n, &t[TEST08_N-1]->qt, &t[0]->qt, test08_aux3);
00509   QT_BLOCK (t_splat, &test08_heavy, 0, t[0]->qt);
00510 }
00511 
00512 
00513 /* Test the varargs procedure calling. */
00514 
00515 char const test09_msg[] = { "Start and run threads using varargs." };
00516 
00517 thread_t *test09_t0, *test09_t1, *test09_t2, *test09_main;
00518 
00519   thread_t *
00520 test09_create (qt_startup_t *start, qt_vuserf_t *f,
00521            qt_cleanup_t *cleanup, int nbytes, ...)
00522 {
00523   va_list ap;
00524   thread_t *t;
00525 
00526   t = t_alloc();
00527   va_start (ap, nbytes);
00528   t->qt = QT_VARGS (t->top, nbytes, ap, t, start, f, cleanup);
00529   va_end (ap);
00530   return (t);
00531 }
00532 
00533 
00534   static void
00535 test09_cleanup (void *pt, void *vuserf_retval)
00536 {
00537   assert (vuserf_retval == (void *)17);
00538   QT_ABORT (t_splat, &((thread_t *)pt)->qt, 0,
00539         ((thread_t *)pt)->next->qt);
00540 }
00541 
00542 
00543   static void
00544 test09_start (void *pt)
00545 {
00546 }
00547 
00548 
00549   static void *
00550 test09_user0 (void)
00551 {
00552   QT_BLOCKI (t_splat, &test09_t0->qt, 0, test09_t1->qt);
00553   return ((void *)17);
00554 }
00555 
00556   static void *
00557 test09_user2 (int one, int two)
00558 {
00559   assert (one == 1);
00560   assert (two == 2);
00561   QT_BLOCKI (t_splat, &test09_t1->qt, 0, test09_t2->qt);
00562   assert (one == 1);
00563   assert (two == 2);
00564   return ((void *)17);
00565 }
00566 
00567   static void *
00568 test09_user10 (int one, int two, int three, int four, int five,
00569           int six, int seven, int eight, int nine, int ten)
00570 {
00571   assert (one == 1);
00572   assert (two == 2);
00573   assert (three == 3);
00574   assert (four == 4);
00575   assert (five == 5);
00576   assert (six == 6);
00577   assert (seven == 7);
00578   assert (eight == 8);
00579   assert (nine == 9);
00580   assert (ten == 10);
00581   QT_BLOCKI (t_splat, &test09_t2->qt, 0, test09_main->qt);
00582   assert (one == 1);
00583   assert (two == 2);
00584   assert (three == 3);
00585   assert (four == 4);
00586   assert (five == 5);
00587   assert (six == 6);
00588   assert (seven == 7);
00589   assert (eight == 8);
00590   assert (nine == 9);
00591   assert (ten == 10);
00592   return ((void *)17);
00593 }
00594 
00595 
00596   void
00597 test09 (int n)
00598 {
00599   thread_t main;
00600 
00601   test09_main = &main;
00602 
00603   while (--n >= 0) {
00604     test09_t0 = test09_create (test09_start, (qt_vuserf_t*)test09_user0,
00605                    test09_cleanup, 0);
00606     test09_t1 = test09_create (test09_start, (qt_vuserf_t*)test09_user2,
00607                    test09_cleanup, 2 * sizeof(qt_word_t), 1, 2);
00608     test09_t2 = test09_create (test09_start, (qt_vuserf_t*)test09_user10,
00609                    test09_cleanup, 10 * sizeof(qt_word_t),
00610                    1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
00611 
00612     /* Chaining used by `test09_cleanup' to determine who is next. */
00613     test09_t0->next = test09_t1;
00614     test09_t1->next = test09_t2;
00615     test09_t2->next = test09_main;
00616 
00617     QT_BLOCKI (t_splat, &test09_main->qt, 0, test09_t0->qt);
00618     QT_BLOCKI (t_splat, &test09_main->qt, 0, test09_t0->qt);
00619 
00620     t_free (test09_t0);
00621     t_free (test09_t1);
00622     t_free (test09_t2);
00623   }
00624 }
00625 
00626 
00627 /* Test 10/11/12: time the cost of various number of args. */
00628 
00629 char const test10_msg[] = { "*Test varargs init & startup w/ 0 args." };
00630 
00631 char const *test10_descr[] = {
00632   "Start and stop threads that use variant argument lists (varargs).",
00633   "Each thread is initialized by calling a routine that calls",
00634   "QT_VARARGS.  Then runs the thread by calling QT_BLOCKI to hald the",
00635   "main thread, a helper that saves the main thread's stack pointer,",
00636   "a null startup function, a null user function, a cleanup function",
00637   "that calls QT_ABORT and restarts the main thread.  Copies no user",
00638   "parameters.",
00639   ":: varargs start/stop = QT_BLOCKI + QT_ABORT + 6 function calls.",
00640   NULL
00641 };
00642 
00643 /* Helper function to send control back to main.
00644    Don't save anything. */
00645 
00646 
00647 /* Helper function for starting the varargs thread.  Save the stack
00648    pointer of the main thread so we can get back there eventually. */
00649 
00650 
00651 /* Startup function for a varargs thread. */
00652 
00653   static void
00654 test10_startup (void *pt)
00655 {
00656 }
00657 
00658 
00659 /* User function for a varargs thread. */
00660 
00661   static void *
00662 test10_run (int arg0, ...)
00663 {
00664   /* return (garbage); */
00665 }
00666 
00667 
00668 /* Cleanup function for a varargs thread.  Send control
00669    back to the main thread.  Don't save any state from the thread that
00670    is halting. */
00671 
00672   void
00673 test10_cleanup (void *pt, void *vuserf_retval)
00674 {
00675   QT_ABORT (t_null, 0, 0, ((thread_t *)pt)->qt);
00676 }
00677 
00678 
00679   void
00680 test10_init (thread_t *new, thread_t *next, int nbytes, ...)
00681 {
00682   va_list ap;
00683 
00684   va_start (ap, nbytes);
00685   new->qt = QT_VARGS (new->top, nbytes, ap, next, test10_startup,
00686               test10_run, test10_cleanup);
00687   va_end (ap);
00688 }
00689 
00690 
00691   void
00692 test10 (int n)
00693 {
00694   thread_t main;
00695   thread_t *t;
00696 
00697   t = t_alloc();
00698   t->next = &main;
00699 
00700   while (--n >= 0) {
00701     test10_init (t, &main, 0);
00702     QT_BLOCKI (t_splat, &main.qt, 0, t->qt);
00703   }
00704   t_free (t);
00705 }
00706 
00707 
00708 char const test11_msg[] = { "*Test varargs init & startup w/ 2 args." };
00709 
00710 char const *test11_descr[] = {
00711   "Varargs initialization/run.  Copies 2 user arguments.",
00712   ":: varargs 2 start/stop = QT_VARGS(2 args), QT_BLOCKI, QT_ABORT, 6 f() calls.",
00713   NULL
00714 };
00715 
00716 
00717   void
00718 test11 (int n)
00719 {
00720   thread_t main;
00721   thread_t *t;
00722 
00723   t = t_alloc();
00724   t->next = &main;
00725 
00726   while (--n >= 0) {
00727     test10_init (t, &main, 2 * sizeof(int), 2, 1);
00728     QT_BLOCKI (t_splat, &main.qt, 0, t->qt);
00729   }
00730   t_free (t);
00731 }
00732 
00733 char const test12_msg[] = { "*Test varargs init & startup w/ 4 args." };
00734 
00735 char const *test12_descr[] = {
00736   "Varargs initialization/run.  Copies 4 user arguments.",
00737   ":: varargs 4 start/stop = QT_VARGS(4 args), QT_BLOCKI, QT_ABORT, 6 f() calls.",
00738   NULL
00739 };
00740 
00741 
00742   void
00743 test12 (int n)
00744 {
00745   thread_t main;
00746   thread_t *t;
00747 
00748   t = t_alloc();
00749   t->next = &main;
00750 
00751   while (--n >= 0) {
00752     test10_init (t, &main, 4 * sizeof(int), 4, 3, 2, 1);
00753     QT_BLOCKI (t_splat, &main.qt, 0, t->qt);
00754   }
00755   t_free (t);
00756 }
00757 
00758 
00759 char const test13_msg[] = { "*Test varargs init & startup w/ 8 args." };
00760 
00761 char const *test13_descr[] = {
00762   "Varargs initialization/run.  Copies 8 user arguments.",
00763   ":: varargs 8 start/stop = QT_VARGS(8 args), QT_BLOCKI, QT_ABORT, 6 f() calls.",
00764   NULL
00765 };
00766 
00767   void
00768 test13 (int n)
00769 {
00770   thread_t main;
00771   thread_t *t;
00772 
00773   t = t_alloc();
00774   t->next = &main;
00775 
00776   while (--n >= 0) {
00777     test10_init (t, &main, 8 * sizeof(int), 8, 7, 6, 5, 4, 3, 2, 1);
00778     QT_BLOCKI (t_splat, &main.qt, 0, t->qt);
00779   }
00780   t_free (t);
00781 }
00782 
00783 
00784 char const test14_msg[] = { "*Test varargs initialization w/ 0 args." };
00785 
00786 char const *test14_descr[] = {
00787   "Varargs initialization without running the thread.  Just calls",
00788   "QT_VARGS.",
00789   ":: varargs 0 init = QT_VARGS()",
00790   NULL
00791 };
00792 
00793   void
00794 test14 (int n)
00795 {
00796   thread_t main;
00797   thread_t *t;
00798 
00799   t = t_alloc();
00800   t->next = &main;
00801 
00802   while (--n >= 0) {
00803     test10_init (t, &main, 0 * sizeof(int));
00804   }
00805   t_free (t);
00806 }
00807 
00808 
00809 char const test15_msg[] = { "*Test varargs initialization w/ 2 args." };
00810 
00811 char const *test15_descr[] = {
00812   "Varargs initialization without running the thread.  Just calls",
00813   "QT_VARGS.",
00814   ":: varargs 2 init = QT_VARGS(2 args)",
00815   NULL
00816 };
00817 
00818   void
00819 test15 (int n)
00820 {
00821   thread_t main;
00822   thread_t *t;
00823 
00824   t = t_alloc();
00825   t->next = &main;
00826 
00827   while (--n >= 0) {
00828     test10_init (t, &main, 2 * sizeof(int), 2, 1);
00829   }
00830   t_free (t);
00831 }
00832 
00833 char const test16_msg[] = { "*Test varargs initialization w/ 4 args." };
00834 
00835 char const *test16_descr[] = {
00836   "Varargs initialization without running the thread.  Just calls",
00837   "QT_VARGS.",
00838   ":: varargs 4 init = QT_VARGS(4 args)",
00839   NULL
00840 };
00841 
00842 
00843   void
00844 test16 (int n)
00845 {
00846   thread_t main;
00847   thread_t *t;
00848 
00849   t = t_alloc();
00850   t->next = &main;
00851 
00852   while (--n >= 0) {
00853     test10_init (t, &main, 4 * sizeof(int), 4, 3, 2, 1);
00854   }
00855   t_free (t);
00856 }
00857 
00858 
00859 char const test17_msg[] = { "*Test varargs initialization w/ 8 args." };
00860 
00861 char const *test17_descr[] = {
00862   "Varargs initialization without running the thread.  Just calls",
00863   "QT_VARGS.",
00864   ":: varargs 8 init = QT_VARGS(8 args)",
00865   NULL
00866 };
00867 
00868 
00869   void
00870 test17 (int n)
00871 {
00872   thread_t main;
00873   thread_t *t;
00874 
00875   t = t_alloc();
00876   t->next = &main;
00877 
00878   while (--n >= 0) {
00879     test10_init (t, &main, 8 * sizeof(int), 8, 7, 6, 5, 4, 3, 2, 1);
00880   }
00881   t_free (t);
00882 }
00883 
00884 /* Test times for basic machine operations. */
00885 
00886 char const test18_msg[] = { "*Call register indirect." };
00887 char const *test18_descr[] = { NULL };
00888 
00889   void
00890 test18 (int n)
00891 {
00892   b_call_reg (n);
00893 }
00894 
00895 
00896 char const test19_msg[] = { "*Call immediate." };
00897 char const *test19_descr[] = { NULL };
00898 
00899   void
00900 test19 (int n)
00901 {
00902   b_call_imm (n);
00903 }
00904 
00905 
00906 char const test20_msg[] = { "*Add register-to-register." };
00907 char const *test20_descr[] = { NULL };
00908 
00909   void
00910 test20 (int n)
00911 {
00912   b_add (n);
00913 }
00914 
00915 
00916 char const test21_msg[] = { "*Load memory to a register." };
00917 char const *test21_descr[] = { NULL };
00918 
00919   void
00920 test21 (int n)
00921 {
00922   b_load (n);
00923 }
00924 
00925 /* Driver. */
00926 
00927 typedef struct foo_t {
00928     char const *msg;    /* Message to print for generic help. */
00929     char const **descr; /* A description of what is done by the test. */
00930     void (*f)(int n);
00931 } foo_t;
00932 
00933 
00934 static foo_t foo[] = {
00935   { "Usage:\n", NULL, (void(*)(int n))usage },
00936   { test01_msg, test01_descr, test01 },
00937   { test02_msg, NULL, test02 },
00938   { test03_msg, NULL, test03 },
00939   { test04_msg, NULL, test04 },
00940   { test05_msg, NULL, test05 },
00941   { test06_msg, test06_descr, test06 },
00942   { test07_msg, test07_descr, test07 },
00943   { test08_msg, test08_descr, test08 },
00944   { test09_msg, NULL, test09 },
00945   { test10_msg, test10_descr, test10 },
00946   { test11_msg, test11_descr, test11 },
00947   { test12_msg, test12_descr, test12 },
00948   { test13_msg, test13_descr, test13 },
00949   { test14_msg, test14_descr, test14 },
00950   { test15_msg, test15_descr, test15 },
00951   { test16_msg, test16_descr, test16 },
00952   { test17_msg, test17_descr, test17 },
00953   { test18_msg, test18_descr, test18 },
00954   { test19_msg, test19_descr, test19 },
00955   { test20_msg, test20_descr, test20 },
00956   { test21_msg, test21_descr, test21 },
00957   { 0, 0 }
00958 };
00959 
00960 static int tv = 0;
00961 
00962   void
00963 tracer ()
00964 {
00965 
00966   fprintf (stderr, "tracer\t%d\n", tv++);
00967   fflush (stderr);
00968 }
00969 
00970   void
00971 tracer2 (void *val)
00972 {
00973   fprintf (stderr, "tracer2\t%d val=0x%p", tv++, val);
00974   fflush (stderr);
00975 }
00976 
00977 
00978   void
00979 describe()
00980 {
00981   int i;
00982   FILE *out = stdout;
00983 
00984   for (i=0; foo[i].msg; ++i) {
00985     if (foo[i].descr) {
00986       int j;
00987 
00988       putc ('\n', out);
00989       fprintf (out, "[%d]\n", i);
00990       for (j=0; foo[i].descr[j]; ++j) {
00991     fputs (foo[i].descr[j], out);
00992     putc ('\n', out);
00993       }
00994     }
00995   }
00996   exit (0);
00997 }
00998 
00999 
01000   void
01001 usage()
01002 {
01003   int i;
01004 
01005   fputs (foo[0].msg, stderr);
01006   for (i=1; foo[i].msg; ++i) {
01007     fprintf (stderr, "%2d\t%s\n", i, foo[i].msg);
01008   }
01009   exit (1);
01010 }
01011 
01012 
01013   void
01014 args (int *which, int *n, int argc, char **argv)
01015 {
01016   static int nfuncs = 0;
01017 
01018   if (argc == 2 && argv[1][0] == '-' && argv[1][1] == 'h') {
01019     describe();
01020   }
01021 
01022   if (nfuncs == 0) {
01023     for (nfuncs=0; foo[nfuncs].msg; ++nfuncs)
01024       ;
01025   }
01026 
01027   if (argc != 2 && argc != 3) {
01028     usage();
01029   }
01030 
01031   *which = atoi (argv[1]);
01032   if (*which < 0 || *which >= nfuncs) {
01033     usage();
01034   }
01035   *n = (argc == 3)
01036     ? atoi (argv[2])
01037     : 1;
01038 }
01039 
01040 
01041   int
01042 main (int argc, char **argv)
01043 {
01044   int which, n;
01045   args (&which, &n, argc, argv);
01046   (*(foo[which].f))(n);
01047   exit (0);
01048   return (0);
01049 }

Generated on Wed Jan 21 15:32:10 2009 for SystemC by  doxygen 1.5.5