* scheme-io.texi: Removed obsolete section Binary IO. Added
[bpt/guile.git] / qt / meas.c
CommitLineData
44986d67
MD
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. */
25typedef 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
33extern void exit (int status);
34extern int atoi (char const *s);
35extern int fprintf (FILE *out, char const *fmt, ...);
36extern int fputs (char const *s, FILE *fp);
37extern void free (void *sto);
38extern void *malloc (unsigned nbytes);
39extern void perror (char const *s);
40
41void usage (void);
42void 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
47typedef 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 *
56t_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 *
81t_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
92t_free (thread_t *t)
93{
94 free (t->stk);
95 free (t);
96}
97
98
99 static void *
100t_null (qt_t *old, void *p1, void *p2)
101{
102 /* return (garbage); */
103}
104
105
106 static void *
107t_splat (qt_t *old, void *oldp, void *null)
108{
109 *(qt_t **)oldp = old;
110 /* return (garbage); */
111}
112
113
114static char const test01_msg[] =
115 "*QT_SP(sto,sz), QT_ARGS(top,p0,p1,userf,first)";
116
117static 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
126test01 (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
165static char const test02_msg[] = "QT_BLOCKI (0, 0, test02_aux, t->qt)";
166static qt_t *rootthread;
167
168 static void
169test02_aux1 (void *pu, void *pt, qt_userf_t *f)
170{
171 QT_ABORT (t_null, 0, 0, rootthread);
172}
173
174 static void *
175test02_aux2 (qt_t *old, void *farg1, void *farg2)
176{
177 rootthread = old;
178 /* return (garbage); */
179}
180
181 static void
182test02 (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
208static 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 *
215test03_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 *
227test03_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
237test03_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
245test03 (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
261static char const test04_msg[] = "stp_start w/ no threads.";
262
263 static void
264test04 (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
284static char const test05_msg[] = "stp w/ 2 yielding thread.";
285
286 static void
287test05_aux (void *null)
288{
289 stp_yield();
290 stp_yield();
291}
292
293 static void
294test05 (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
307static char const test06_msg[] = "*QT_ARGS(...), QT_BLOCKI one thread";
308
309static 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
321static qt_t *test06_sp;
322
323
324 static void
325test06_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 *
332test06_aux3 (qt_t *sp, void *null0c, void *null1c)
333{
334 test06_sp = sp;
335 /* return (garbage); */
336}
337
338
339 static void
340test06 (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
374static char test07_msg[] = "*cswap between threads";
375
376static 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
401static qt_t *test07_heavy;
402
403#define TEST07_N (4)
404
405
406 static void
407test07_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
421test07_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
437test07 (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
455static char test08_msg[] = "Floating-point cswap between threads";
456
457static char const *test08_descr[] = {
458 "Measure context switch times including floating-point, use QT_BLOCK.",
459 NULL
460};
461
462static qt_t *test08_heavy;
463
464#define TEST08_N (4)
465
466
467 static void
468test08_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
479test08_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
495test08 (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
515char const test09_msg[] = { "Start and run threads using varargs." };
516
517thread_t *test09_t0, *test09_t1, *test09_t2, *test09_main;
518
519 thread_t *
520test09_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
535test09_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
544test09_start (void *pt)
545{
546}
547
548
549 static void *
550test09_user0 (void)
551{
552 QT_BLOCKI (t_splat, &test09_t0->qt, 0, test09_t1->qt);
553 return ((void *)17);
554}
555
556 static void *
557test09_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 *
568test09_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
597test09 (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
629char const test10_msg[] = { "*Test varargs init & startup w/ 0 args." };
630
631char 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
654test10_startup (void *pt)
655{
656}
657
658
659/* User function for a varargs thread. */
660
661 static void *
662test10_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
673test10_cleanup (void *pt, void *vuserf_retval)
674{
675 QT_ABORT (t_null, 0, 0, ((thread_t *)pt)->qt);
676}
677
678
679 void
680test10_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
692test10 (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
708char const test11_msg[] = { "*Test varargs init & startup w/ 2 args." };
709
710char 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
718test11 (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
733char const test12_msg[] = { "*Test varargs init & startup w/ 4 args." };
734
735char 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
743test12 (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
759char const test13_msg[] = { "*Test varargs init & startup w/ 8 args." };
760
761char 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
768test13 (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
784char const test14_msg[] = { "*Test varargs initialization w/ 0 args." };
785
786char 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
794test14 (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
809char const test15_msg[] = { "*Test varargs initialization w/ 2 args." };
810
811char 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
819test15 (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
833char const test16_msg[] = { "*Test varargs initialization w/ 4 args." };
834
835char 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
844test16 (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
859char const test17_msg[] = { "*Test varargs initialization w/ 8 args." };
860
861char 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
870test17 (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
886char const test18_msg[] = { "*Call register indirect." };
887char const *test18_descr[] = { NULL };
888
889 void
890test18 (int n)
891{
892 b_call_reg (n);
893}
894
895
896char const test19_msg[] = { "*Call immediate." };
897char const *test19_descr[] = { NULL };
898
899 void
900test19 (int n)
901{
902 b_call_imm (n);
903}
904
905
906char const test20_msg[] = { "*Add register-to-register." };
907char const *test20_descr[] = { NULL };
908
909 void
910test20 (int n)
911{
912 b_add (n);
913}
914
915
916char const test21_msg[] = { "*Load memory to a register." };
917char const *test21_descr[] = { NULL };
918
919 void
920test21 (int n)
921{
922 b_load (n);
923}
924
925\f/* Driver. */
926
927typedef 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
934static 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
960static int tv = 0;
961
962 void
963tracer ()
964{
965
966 fprintf (stderr, "tracer\t%d\n", tv++);
967 fflush (stderr);
968}
969
970 void
971tracer2 (void *val)
972{
973 fprintf (stderr, "tracer2\t%d val=0x%p", tv++, val);
974 fflush (stderr);
975}
976
977
978 void
979describe()
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
1001usage()
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
1014args (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
1042main (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}