meas.c 21 KB

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