]> git.donarmstrong.com Git - lilypond.git/blob - guile18/qt/meas.c
New upstream version 2.19.65
[lilypond.git] / guile18 / qt / meas.c
1 /* meas.c -- measure qt stuff. */
2
3 #include "copyright.h"
4
5 /* Need this to get assertions under Mach on the Sequent/i386: */
6 #ifdef __i386__
7 #define assert(ex) \
8   do { \
9     if (!(ex)) { \
10       fprintf (stderr, "[%s:%d] Assertion " #ex " failed\n", __FILE__, __LINE__); \
11       abort(); \
12     } \
13   } while (0)
14 #else
15 #include <assert.h>
16 #endif
17
18 /* This really ought to be defined in some ANSI include file (*I*
19    think...), but it's defined here instead, which leads us to another
20    machine dependency.
21
22    The `iaddr_t' type is an integer representation of a pointer,
23    suited for doing arithmetic on addresses, e.g. to round an address
24    to an alignment boundary. */
25 typedef unsigned long iaddr_t;
26
27 #include <stdarg.h>     /* For varargs tryout. */
28 #include <stdio.h>
29 #include "b.h"
30 #include "qt.h"
31 #include "stp.h"
32
33 extern void exit (int status);
34 extern int atoi (char const *s);
35 extern int fprintf (FILE *out, char const *fmt, ...);
36 extern int fputs (char const *s, FILE *fp);
37 extern void free (void *sto);
38 extern void *malloc (unsigned nbytes);
39 extern void perror (char const *s);
40
41 void usage (void);
42 void tracer(void);
43
44 /* Round `v' to be `a'-aligned, assuming `a' is a power of two. */
45 #define ROUND(v, a)     (((v) + (a) - 1) & ~((a)-1))
46
47 typedef struct thread_t {
48   qt_t *qt;             /* Pointer to thread of function... */
49   void *stk;
50   void *top;            /* Set top of stack if reuse. */
51   struct thread_t *next;
52 } thread_t;
53
54
55   static thread_t *
56 t_alloc (void)
57 {
58   thread_t *t;
59   int ssz = 0x1000;
60
61   t = malloc (sizeof(thread_t));
62   if (!t) {
63     perror ("malloc");
64     exit (1);
65   }
66   assert (ssz > QT_STKBASE);
67   t->stk = malloc (ssz);
68   t->stk = (void *)ROUND (((iaddr_t)t->stk), QT_STKALIGN);
69   if (!t->stk) {
70     perror ("malloc");
71     exit (1);
72   }
73   assert ((((iaddr_t)t->stk) & (QT_STKALIGN-1)) == 0);
74   t->top = QT_SP (t->stk, ssz - QT_STKBASE);
75
76   return (t);
77 }
78
79
80   static thread_t *
81 t_create (qt_only_t *starter, void *p0, qt_userf_t *f)
82 {
83   thread_t *t;
84
85   t = t_alloc();
86   t->qt = QT_ARGS (t->top, p0, t, f, starter);
87   return (t);
88 }
89
90
91   static void
92 t_free (thread_t *t)
93 {
94   free (t->stk);
95   free (t);
96 }
97
98
99   static void *
100 t_null (qt_t *old, void *p1, void *p2)
101 {
102   /* return (garbage); */
103 }
104
105
106   static void *
107 t_splat (qt_t *old, void *oldp, void *null)
108 {
109   *(qt_t **)oldp = old;
110   /* return (garbage); */
111 }
112
113
114 static char const test01_msg[] =
115   "*QT_SP(sto,sz), QT_ARGS(top,p0,p1,userf,first)";
116
117 static char const *test01_descr[] = {
118   "Performs 1 QT_SP and one QT_ARGS per iteration.",
119   NULL
120 };
121
122 /* This test gives a guess on how long it takes to initalize
123    a thread. */
124
125   static void
126 test01 (int n)
127 {
128   char stack[QT_STKBASE+QT_STKALIGN];
129   char *stk;
130   qt_t *top;
131
132   stk = (char *)ROUND (((iaddr_t)stack), QT_STKALIGN);
133
134   {
135     int i;
136
137     for (i=0; i<QT_STKBASE; ++i) {
138       stk[i] = 0;
139     }
140   }
141
142   while (n>0) {
143     /* RETVALUSED */
144     top = QT_SP (stk, QT_STKBASE);      QT_ARGS (top, 0, 0, 0, 0);
145 #ifdef NDEF
146     top = QT_SP (stk, QT_STKBASE);      QT_ARGS (top, 0, 0, 0, 0);
147     top = QT_SP (stk, QT_STKBASE);      QT_ARGS (top, 0, 0, 0, 0);
148     top = QT_SP (stk, QT_STKBASE);      QT_ARGS (top, 0, 0, 0, 0);
149     top = QT_SP (stk, QT_STKBASE);      QT_ARGS (top, 0, 0, 0, 0);
150
151     top = QT_SP (stk, QT_STKBASE);      QT_ARGS (top, 0, 0, 0, 0);
152     top = QT_SP (stk, QT_STKBASE);      QT_ARGS (top, 0, 0, 0, 0);
153     top = QT_SP (stk, QT_STKBASE);      QT_ARGS (top, 0, 0, 0, 0);
154     top = QT_SP (stk, QT_STKBASE);      QT_ARGS (top, 0, 0, 0, 0);
155     top = QT_SP (stk, QT_STKBASE);      QT_ARGS (top, 0, 0, 0, 0);
156
157     n -= 10;
158 #else
159     n -= 1;
160 #endif
161   }
162 }
163
164
165 static char const test02_msg[] = "QT_BLOCKI (0, 0, test02_aux, t->qt)";
166 static qt_t *rootthread;
167
168   static void
169 test02_aux1 (void *pu, void *pt, qt_userf_t *f)
170 {
171   QT_ABORT (t_null, 0, 0, rootthread);
172 }
173
174   static void *
175 test02_aux2 (qt_t *old, void *farg1, void *farg2)
176 {
177   rootthread = old;
178   /* return (garbage); */
179 }
180
181   static void
182 test02 (int n)
183 {
184   thread_t *t;
185
186   while (n>0) {
187   t = t_create (test02_aux1, 0, 0);
188     QT_BLOCKI (test02_aux2, 0, 0, t->qt);
189   t_free (t);
190   t = t_create (test02_aux1, 0, 0);
191     QT_BLOCKI (test02_aux2, 0, 0, t->qt);
192   t_free (t);
193   t = t_create (test02_aux1, 0, 0);
194     QT_BLOCKI (test02_aux2, 0, 0, t->qt);
195   t_free (t);
196   t = t_create (test02_aux1, 0, 0);
197     QT_BLOCKI (test02_aux2, 0, 0, t->qt);
198   t_free (t);
199   t = t_create (test02_aux1, 0, 0);
200     QT_BLOCKI (test02_aux2, 0, 0, t->qt);
201   t_free (t);
202
203     n -= 5;
204   }
205 }
206
207
208 static char const test03_msg[] = "QT_BLOCKI (...) test vals are right.";
209
210
211 /* Called by the thread function when it wants to shut down.
212    Return a value to the main thread. */
213
214   static void *
215 test03_aux0 (qt_t *old_is_garbage, void *farg1, void *farg2)
216 {
217   assert (farg1 == (void *)5);
218   assert (farg2 == (void *)6);
219   return ((void *)15);          /* Some unlikely value. */
220 }
221
222
223 /* Called during new thread startup by main thread.  Since the new
224    thread has never run before, return value is ignored. */
225
226   static void *
227 test03_aux1 (qt_t *old, void *farg1, void *farg2)
228 {
229   assert (old != NULL);
230   assert (farg1 == (void *)5);
231   assert (farg2 == (void *)6);
232   rootthread = old;
233   return ((void *)16);          /* Different than `15'. */
234 }
235
236   static void
237 test03_aux2 (void *pu, void *pt, qt_userf_t *f)
238 {
239   assert (pu == (void *)1);
240   assert (f == (qt_userf_t *)4);
241   QT_ABORT (test03_aux0, (void *)5, (void *)6, rootthread);
242 }
243
244   static void
245 test03 (int n)
246 {
247   thread_t *t;
248   void *rv;
249
250   while (n>0) {
251     t = t_create (test03_aux2, (void *)1, (qt_userf_t *)4);
252     rv = QT_BLOCKI (test03_aux1, (void *)5, (void *)6, t->qt);
253     assert (rv == (void *)15);
254     t_free (t);
255
256     --n;
257   }
258 }
259
260
261 static char const test04_msg[] = "stp_start w/ no threads.";
262
263   static void
264 test04 (int n)
265 {
266   while (n>0) {
267     stp_init(); stp_start();
268     stp_init(); stp_start();
269     stp_init(); stp_start();
270     stp_init(); stp_start();
271     stp_init(); stp_start();
272
273     stp_init(); stp_start();
274     stp_init(); stp_start();
275     stp_init(); stp_start();
276     stp_init(); stp_start();
277     stp_init(); stp_start();
278
279     n -= 10;
280   }
281 }
282
283
284 static char const test05_msg[] = "stp w/ 2 yielding thread.";
285
286   static void
287 test05_aux (void *null)
288 {
289   stp_yield();
290   stp_yield();
291 }
292
293   static void
294 test05 (int n)
295 {
296   while (n>0) {
297     stp_init();
298     stp_create (test05_aux, 0);
299     stp_create (test05_aux, 0);
300     stp_start();
301
302     --n;
303   }
304 }
305
306
307 static char const test06_msg[] = "*QT_ARGS(...), QT_BLOCKI one thread";
308
309 static char const *test06_descr[] = {
310   "Does a QT_ARGS, QT_BLOCKI to a helper function that saves the",
311   "stack pointer of the main thread, calls an `only' function that",
312   "saves aborts the thread, calling a null helper function.",
313   ":: start/stop = QT_ARGS + QT_BLOCKI + QT_ABORT + 3 procedure calls.",
314   NULL
315 };
316
317 /* This test initializes a thread, runs it, then returns to the main
318    program, which reinitializes the thread, runs it again, etc.  Each
319    iteration corresponds to 1 init, 1 abort, 1 block. */
320
321 static qt_t *test06_sp;
322
323
324   static void
325 test06_aux2 (void *null0a, void *null1b, void *null2b, qt_userf_t *null)
326 {
327   QT_ABORT (t_null, 0, 0, test06_sp);
328 }
329
330
331   static void *
332 test06_aux3 (qt_t *sp, void *null0c, void *null1c)
333 {
334   test06_sp = sp;
335   /* return (garbage); */
336 }
337
338
339   static void
340 test06 (int n)
341 {
342   thread_t *t;
343
344   t = t_create (0, 0, 0);
345
346   while (n>0) {
347     /* RETVALUSED */
348     QT_ARGS (t->top, 0, 0, 0, test06_aux2);
349     QT_BLOCKI (test06_aux3, 0, 0, t->qt);
350 #ifdef NDEF
351     /* RETVALUSED */
352     QT_ARGS (t->top, 0, 0, 0, test06_aux2);
353     QT_BLOCKI (test06_aux3, 0, 0, t->qt);
354
355     /* RETVALUSED */
356     QT_ARGS (t->top, 0, 0, 0, test06_aux2);
357     QT_BLOCKI (test06_aux3, 0, 0, t->qt);
358
359     /* RETVALUSED */
360     QT_ARGS (t->top, 0, 0, 0, test06_aux2);
361     QT_BLOCKI (test06_aux3, 0, 0, t->qt);
362
363     /* RETVALUSED */
364     QT_ARGS (t->top, 0, 0, 0, test06_aux2);
365     QT_BLOCKI (test06_aux3, 0, 0, t->qt);
366
367     n -= 5;
368 #else
369     --n;
370 #endif
371   }
372 }
373
374 static char test07_msg[] = "*cswap between threads";
375
376 static char const *test07_descr[] = {
377   "Build a chain of threads where each thread has a fixed successor.",
378   "There is no scheduling performed.  Each thread but one is a loop",
379   "that simply blocks with QT_BLOCKI, calling a helper that saves the",
380   "current stack pointer.  The last thread decrements a count, and,",
381   "if zero, aborts back to the main thread.  Else it continues with",
382   "the blocking chain.  The count is divided by the number of threads",
383   "in the chain, so `n' is the number of integer block operations.",
384   ":: integer cswap = QT_BLOCKI + a procedure call.",
385   NULL
386 };
387
388 /* This test repeatedly blocks a bunch of threads.
389    Each iteration corresponds to one block operation.
390
391    The threads are arranged so that there are TEST07_N-1 of them that
392    run `test07_aux2'.  Each one of those blocks saving it's sp to
393    storage owned by the preceding thread; a pointer to that storage is
394    passed in via `mep'.  Each thread has a handle on it's own storage
395    for the next thread, referenced by `nxtp', and it blocks by passing
396    control to `*nxtp', telling the helper function to save its state
397    in `*mep'.  The last thread in the chain decrements a count and, if
398    it's gone below zero, returns to `test07'; otherwise, it invokes
399    the first thread in the chain. */
400
401 static qt_t *test07_heavy;
402
403 #define TEST07_N (4)
404
405
406   static void
407 test07_aux2 (void *null0, void *mep, void *nxtp, qt_userf_t *null)
408 {
409   qt_t *nxt;
410
411   while (1) {
412     nxt = *(qt_t **)nxtp;
413 #ifdef NDEF
414     printf ("Helper 0x%p\n", nxtp);
415 #endif
416     QT_BLOCKI (t_splat, mep, 0, nxt);
417   }
418 }
419
420   static void
421 test07_aux3 (void *np, void *mep, void *nxtp, qt_userf_t *null)
422 {
423   int n;
424
425   n = *(int *)np;
426   while (1) {
427     n -= TEST07_N;
428     if (n<0) {
429       QT_ABORT (t_splat, mep, 0, test07_heavy);
430     }
431     QT_BLOCKI (t_splat, mep, 0, *(qt_t **)nxtp);
432   }
433 }
434
435
436   static void
437 test07 (int n)
438 {
439   int i;
440   thread_t *t[TEST07_N];
441
442   for (i=0; i<TEST07_N; ++i) {
443     t[i] = t_create (0, 0, 0);
444   }
445   for (i=0; i<TEST07_N-1; ++i) {
446     /* RETVALUSED */
447     QT_ARGS (t[i]->top, 0, &t[i]->qt, &t[i+1]->qt, test07_aux2);
448   }
449   /* RETVALUSED */
450   QT_ARGS (t[i]->top, &n, &t[TEST07_N-1]->qt, &t[0]->qt, test07_aux3);
451   QT_BLOCKI (t_splat, &test07_heavy, 0, t[0]->qt);
452 }
453
454
455 static char test08_msg[] = "Floating-point cswap between threads";
456
457 static char const *test08_descr[] = {
458   "Measure context switch times including floating-point, use QT_BLOCK.",
459   NULL
460 };
461
462 static qt_t *test08_heavy;
463
464 #define TEST08_N (4)
465
466
467   static void
468 test08_aux2 (void *null0, void *mep, void *nxtp, qt_userf_t *null)
469 {
470   qt_t *nxt;
471
472   while (1) {
473     nxt = *(qt_t **)nxtp;
474     QT_BLOCK (t_splat, mep, 0, nxt);
475   }
476 }
477
478   static void
479 test08_aux3 (void *np, void *mep, void *nxtp, qt_userf_t *null)
480 {
481   int n;
482
483   n = *(int *)np;
484   while (1) {
485     n -= TEST08_N;
486     if (n<0) {
487       QT_ABORT (t_splat, mep, 0, test08_heavy);
488     }
489     QT_BLOCK (t_splat, mep, 0, *(qt_t **)nxtp);
490   }
491 }
492
493
494   static void
495 test08 (int n)
496 {
497   int i;
498   thread_t *t[TEST08_N];
499
500   for (i=0; i<TEST08_N; ++i) {
501     t[i] = t_create (0, 0, 0);
502   }
503   for (i=0; i<TEST08_N-1; ++i) {
504     /* RETVALUSED */
505     QT_ARGS (t[i]->top, 0, &t[i]->qt, &t[i+1]->qt, test08_aux2);
506   }
507   /* RETVALUSED */
508   QT_ARGS (t[i]->top, &n, &t[TEST08_N-1]->qt, &t[0]->qt, test08_aux3);
509   QT_BLOCK (t_splat, &test08_heavy, 0, t[0]->qt);
510 }
511
512
513 /* Test the varargs procedure calling. */
514
515 char const test09_msg[] = { "Start and run threads using varargs." };
516
517 thread_t *test09_t0, *test09_t1, *test09_t2, *test09_main;
518
519   thread_t *
520 test09_create (qt_startup_t *start, qt_vuserf_t *f,
521                qt_cleanup_t *cleanup, int nbytes, ...)
522 {
523   va_list ap;
524   thread_t *t;
525
526   t = t_alloc();
527   va_start (ap, nbytes);
528   t->qt = QT_VARGS (t->top, nbytes, ap, t, start, f, cleanup);
529   va_end (ap);
530   return (t);
531 }
532
533
534   static void
535 test09_cleanup (void *pt, void *vuserf_retval)
536 {
537   assert (vuserf_retval == (void *)17);
538   QT_ABORT (t_splat, &((thread_t *)pt)->qt, 0,
539             ((thread_t *)pt)->next->qt);
540 }
541
542
543   static void
544 test09_start (void *pt)
545 {
546 }
547
548
549   static void *
550 test09_user0 (void)
551 {
552   QT_BLOCKI (t_splat, &test09_t0->qt, 0, test09_t1->qt);
553   return ((void *)17);
554 }
555
556   static void *
557 test09_user2 (int one, int two)
558 {
559   assert (one == 1);
560   assert (two == 2);
561   QT_BLOCKI (t_splat, &test09_t1->qt, 0, test09_t2->qt);
562   assert (one == 1);
563   assert (two == 2);
564   return ((void *)17);
565 }
566
567   static void *
568 test09_user10 (int one, int two, int three, int four, int five,
569               int six, int seven, int eight, int nine, int ten)
570 {
571   assert (one == 1);
572   assert (two == 2);
573   assert (three == 3);
574   assert (four == 4);
575   assert (five == 5);
576   assert (six == 6);
577   assert (seven == 7);
578   assert (eight == 8);
579   assert (nine == 9);
580   assert (ten == 10);
581   QT_BLOCKI (t_splat, &test09_t2->qt, 0, test09_main->qt);
582   assert (one == 1);
583   assert (two == 2);
584   assert (three == 3);
585   assert (four == 4);
586   assert (five == 5);
587   assert (six == 6);
588   assert (seven == 7);
589   assert (eight == 8);
590   assert (nine == 9);
591   assert (ten == 10);
592   return ((void *)17);
593 }
594
595
596   void
597 test09 (int n)
598 {
599   thread_t main;
600
601   test09_main = &main;
602
603   while (--n >= 0) {
604     test09_t0 = test09_create (test09_start, (qt_vuserf_t*)test09_user0,
605                                test09_cleanup, 0);
606     test09_t1 = test09_create (test09_start, (qt_vuserf_t*)test09_user2,
607                                test09_cleanup, 2 * sizeof(qt_word_t), 1, 2);
608     test09_t2 = test09_create (test09_start, (qt_vuserf_t*)test09_user10,
609                                test09_cleanup, 10 * sizeof(qt_word_t),
610                                1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
611
612     /* Chaining used by `test09_cleanup' to determine who is next. */
613     test09_t0->next = test09_t1;
614     test09_t1->next = test09_t2;
615     test09_t2->next = test09_main;
616
617     QT_BLOCKI (t_splat, &test09_main->qt, 0, test09_t0->qt);
618     QT_BLOCKI (t_splat, &test09_main->qt, 0, test09_t0->qt);
619
620     t_free (test09_t0);
621     t_free (test09_t1);
622     t_free (test09_t2);
623   }
624 }
625
626
627 \f/* Test 10/11/12: time the cost of various number of args. */
628
629 char const test10_msg[] = { "*Test varargs init & startup w/ 0 args." };
630
631 char const *test10_descr[] = {
632   "Start and stop threads that use variant argument lists (varargs).",
633   "Each thread is initialized by calling a routine that calls",
634   "QT_VARARGS.  Then runs the thread by calling QT_BLOCKI to hald the",
635   "main thread, a helper that saves the main thread's stack pointer,",
636   "a null startup function, a null user function, a cleanup function",
637   "that calls QT_ABORT and restarts the main thread.  Copies no user",
638   "parameters.",
639   ":: varargs start/stop = QT_BLOCKI + QT_ABORT + 6 function calls.",
640   NULL
641 };
642
643 /* Helper function to send control back to main.
644    Don't save anything. */
645
646
647 /* Helper function for starting the varargs thread.  Save the stack
648    pointer of the main thread so we can get back there eventually. */
649
650
651 /* Startup function for a varargs thread. */
652
653   static void
654 test10_startup (void *pt)
655 {
656 }
657
658
659 /* User function for a varargs thread. */
660
661   static void *
662 test10_run (int arg0, ...)
663 {
664   /* return (garbage); */
665 }
666
667
668 /* Cleanup function for a varargs thread.  Send control
669    back to the main thread.  Don't save any state from the thread that
670    is halting. */
671
672   void
673 test10_cleanup (void *pt, void *vuserf_retval)
674 {
675   QT_ABORT (t_null, 0, 0, ((thread_t *)pt)->qt);
676 }
677
678
679   void
680 test10_init (thread_t *new, thread_t *next, int nbytes, ...)
681 {
682   va_list ap;
683
684   va_start (ap, nbytes);
685   new->qt = QT_VARGS (new->top, nbytes, ap, next, test10_startup,
686                       test10_run, test10_cleanup);
687   va_end (ap);
688 }
689
690
691   void
692 test10 (int n)
693 {
694   thread_t main;
695   thread_t *t;
696
697   t = t_alloc();
698   t->next = &main;
699
700   while (--n >= 0) {
701     test10_init (t, &main, 0);
702     QT_BLOCKI (t_splat, &main.qt, 0, t->qt);
703   }
704   t_free (t);
705 }
706
707
708 char const test11_msg[] = { "*Test varargs init & startup w/ 2 args." };
709
710 char const *test11_descr[] = {
711   "Varargs initialization/run.  Copies 2 user arguments.",
712   ":: varargs 2 start/stop = QT_VARGS(2 args), QT_BLOCKI, QT_ABORT, 6 f() calls.",
713   NULL
714 };
715
716
717   void
718 test11 (int n)
719 {
720   thread_t main;
721   thread_t *t;
722
723   t = t_alloc();
724   t->next = &main;
725
726   while (--n >= 0) {
727     test10_init (t, &main, 2 * sizeof(int), 2, 1);
728     QT_BLOCKI (t_splat, &main.qt, 0, t->qt);
729   }
730   t_free (t);
731 }
732
733 char const test12_msg[] = { "*Test varargs init & startup w/ 4 args." };
734
735 char const *test12_descr[] = {
736   "Varargs initialization/run.  Copies 4 user arguments.",
737   ":: varargs 4 start/stop = QT_VARGS(4 args), QT_BLOCKI, QT_ABORT, 6 f() calls.",
738   NULL
739 };
740
741
742   void
743 test12 (int n)
744 {
745   thread_t main;
746   thread_t *t;
747
748   t = t_alloc();
749   t->next = &main;
750
751   while (--n >= 0) {
752     test10_init (t, &main, 4 * sizeof(int), 4, 3, 2, 1);
753     QT_BLOCKI (t_splat, &main.qt, 0, t->qt);
754   }
755   t_free (t);
756 }
757
758
759 char const test13_msg[] = { "*Test varargs init & startup w/ 8 args." };
760
761 char const *test13_descr[] = {
762   "Varargs initialization/run.  Copies 8 user arguments.",
763   ":: varargs 8 start/stop = QT_VARGS(8 args), QT_BLOCKI, QT_ABORT, 6 f() calls.",
764   NULL
765 };
766
767   void
768 test13 (int n)
769 {
770   thread_t main;
771   thread_t *t;
772
773   t = t_alloc();
774   t->next = &main;
775
776   while (--n >= 0) {
777     test10_init (t, &main, 8 * sizeof(int), 8, 7, 6, 5, 4, 3, 2, 1);
778     QT_BLOCKI (t_splat, &main.qt, 0, t->qt);
779   }
780   t_free (t);
781 }
782
783
784 char const test14_msg[] = { "*Test varargs initialization w/ 0 args." };
785
786 char const *test14_descr[] = {
787   "Varargs initialization without running the thread.  Just calls",
788   "QT_VARGS.",
789   ":: varargs 0 init = QT_VARGS()",
790   NULL
791 };
792
793   void
794 test14 (int n)
795 {
796   thread_t main;
797   thread_t *t;
798
799   t = t_alloc();
800   t->next = &main;
801
802   while (--n >= 0) {
803     test10_init (t, &main, 0 * sizeof(int));
804   }
805   t_free (t);
806 }
807
808
809 char const test15_msg[] = { "*Test varargs initialization w/ 2 args." };
810
811 char const *test15_descr[] = {
812   "Varargs initialization without running the thread.  Just calls",
813   "QT_VARGS.",
814   ":: varargs 2 init = QT_VARGS(2 args)",
815   NULL
816 };
817
818   void
819 test15 (int n)
820 {
821   thread_t main;
822   thread_t *t;
823
824   t = t_alloc();
825   t->next = &main;
826
827   while (--n >= 0) {
828     test10_init (t, &main, 2 * sizeof(int), 2, 1);
829   }
830   t_free (t);
831 }
832
833 char const test16_msg[] = { "*Test varargs initialization w/ 4 args." };
834
835 char const *test16_descr[] = {
836   "Varargs initialization without running the thread.  Just calls",
837   "QT_VARGS.",
838   ":: varargs 4 init = QT_VARGS(4 args)",
839   NULL
840 };
841
842
843   void
844 test16 (int n)
845 {
846   thread_t main;
847   thread_t *t;
848
849   t = t_alloc();
850   t->next = &main;
851
852   while (--n >= 0) {
853     test10_init (t, &main, 4 * sizeof(int), 4, 3, 2, 1);
854   }
855   t_free (t);
856 }
857
858
859 char const test17_msg[] = { "*Test varargs initialization w/ 8 args." };
860
861 char const *test17_descr[] = {
862   "Varargs initialization without running the thread.  Just calls",
863   "QT_VARGS.",
864   ":: varargs 8 init = QT_VARGS(8 args)",
865   NULL
866 };
867
868
869   void
870 test17 (int n)
871 {
872   thread_t main;
873   thread_t *t;
874
875   t = t_alloc();
876   t->next = &main;
877
878   while (--n >= 0) {
879     test10_init (t, &main, 8 * sizeof(int), 8, 7, 6, 5, 4, 3, 2, 1);
880   }
881   t_free (t);
882 }
883
884 \f/* Test times for basic machine operations. */
885
886 char const test18_msg[] = { "*Call register indirect." };
887 char const *test18_descr[] = { NULL };
888
889   void
890 test18 (int n)
891 {
892   b_call_reg (n);
893 }
894
895
896 char const test19_msg[] = { "*Call immediate." };
897 char const *test19_descr[] = { NULL };
898
899   void
900 test19 (int n)
901 {
902   b_call_imm (n);
903 }
904
905
906 char const test20_msg[] = { "*Add register-to-register." };
907 char const *test20_descr[] = { NULL };
908
909   void
910 test20 (int n)
911 {
912   b_add (n);
913 }
914
915
916 char const test21_msg[] = { "*Load memory to a register." };
917 char const *test21_descr[] = { NULL };
918
919   void
920 test21 (int n)
921 {
922   b_load (n);
923 }
924
925 \f/* Driver. */
926
927 typedef struct foo_t {
928     char const *msg;    /* Message to print for generic help. */
929     char const **descr; /* A description of what is done by the test. */
930     void (*f)(int n);
931 } foo_t;
932
933
934 static foo_t foo[] = {
935   { "Usage:\n", NULL, (void(*)(int n))usage },
936   { test01_msg, test01_descr, test01 },
937   { test02_msg, NULL, test02 },
938   { test03_msg, NULL, test03 },
939   { test04_msg, NULL, test04 },
940   { test05_msg, NULL, test05 },
941   { test06_msg, test06_descr, test06 },
942   { test07_msg, test07_descr, test07 },
943   { test08_msg, test08_descr, test08 },
944   { test09_msg, NULL, test09 },
945   { test10_msg, test10_descr, test10 },
946   { test11_msg, test11_descr, test11 },
947   { test12_msg, test12_descr, test12 },
948   { test13_msg, test13_descr, test13 },
949   { test14_msg, test14_descr, test14 },
950   { test15_msg, test15_descr, test15 },
951   { test16_msg, test16_descr, test16 },
952   { test17_msg, test17_descr, test17 },
953   { test18_msg, test18_descr, test18 },
954   { test19_msg, test19_descr, test19 },
955   { test20_msg, test20_descr, test20 },
956   { test21_msg, test21_descr, test21 },
957   { 0, 0 }
958 };
959
960 static int tv = 0;
961
962   void
963 tracer ()
964 {
965
966   fprintf (stderr, "tracer\t%d\n", tv++);
967   fflush (stderr);
968 }
969
970   void
971 tracer2 (void *val)
972 {
973   fprintf (stderr, "tracer2\t%d val=0x%p", tv++, val);
974   fflush (stderr);
975 }
976
977
978   void
979 describe()
980 {
981   int i;
982   FILE *out = stdout;
983
984   for (i=0; foo[i].msg; ++i) {
985     if (foo[i].descr) {
986       int j;
987
988       putc ('\n', out);
989       fprintf (out, "[%d]\n", i);
990       for (j=0; foo[i].descr[j]; ++j) {
991         fputs (foo[i].descr[j], out);
992         putc ('\n', out);
993       }
994     }
995   }
996   exit (0);
997 }
998
999
1000   void
1001 usage()
1002 {
1003   int i;
1004
1005   fputs (foo[0].msg, stderr);
1006   for (i=1; foo[i].msg; ++i) {
1007     fprintf (stderr, "%2d\t%s\n", i, foo[i].msg);
1008   }
1009   exit (1);
1010 }
1011
1012
1013   void
1014 args (int *which, int *n, int argc, char **argv)
1015 {
1016   static int nfuncs = 0;
1017
1018   if (argc == 2 && argv[1][0] == '-' && argv[1][1] == 'h') {
1019     describe();
1020   }
1021
1022   if (nfuncs == 0) {
1023     for (nfuncs=0; foo[nfuncs].msg; ++nfuncs)
1024       ;
1025   }
1026
1027   if (argc != 2 && argc != 3) {
1028     usage();
1029   }
1030
1031   *which = atoi (argv[1]);
1032   if (*which < 0 || *which >= nfuncs) {
1033     usage();
1034   }
1035   *n = (argc == 3)
1036     ? atoi (argv[2])
1037     : 1;
1038 }
1039
1040
1041   int
1042 main (int argc, char **argv)
1043 {
1044   int which, n;
1045   args (&which, &n, argc, argv);
1046   (*(foo[which].f))(n);
1047   exit (0);
1048   return (0);
1049 }