1/* Functional tests of the htm __builtin_... macros.  */
2
3/* { dg-do run } */
4/* { dg-require-effective-target htm } */
5/* { dg-options "-O3 -march=zEC12 -mzarch" } */
6
7/* ---------------------------- included header files ---------------------- */
8
9#include <stdio.h>
10#include <string.h>
11#include <stdint.h>
12#include <htmintrin.h>
13
14/* ---------------------------- local definitions -------------------------- */
15
16#define DEFAULT_MAX_REPETITIONS 5
17#define DEFAULT_REQUIRED_QUORUM ((DEFAULT_MAX_REPETITIONS) - 1)
18#define NUM_WARMUP_RUNS 10
19
20/* ---------------------------- local macros ------------------------------- */
21
22#define TEST_DF_REP(name) \
23  { #name, name, DEFAULT_MAX_REPETITIONS, DEFAULT_REQUIRED_QUORUM }
24#define TEST_NO_REP(name) { #name, name, 1, 1 }
25
26/* ---------------------------- local types -------------------------------- */
27
28typedef int (*test_func_t)(void);
29
30typedef struct
31{
32  const char *name;
33  test_func_t test_func;
34  int max_repetitions;
35  int required_quorum;
36} test_table_entry_t;
37
38/* ---------------------------- local variables ---------------------------- */
39
40__attribute__ ((aligned(256))) static struct __htm_tdb local_tdb256;
41static struct __htm_tdb local_tdb;
42static int do_dump_tdb = 0;
43
44/* ---------------------------- exported variables (globals) --------------- */
45
46__attribute__ ((aligned(256))) struct
47{
48  float float_1;
49  float float_2;
50  float float_3;
51} global = { 1.0, 2.5, 0.0 };
52
53__attribute__ ((aligned(256))) struct
54{
55  volatile uint64_t c1;
56  volatile uint64_t c2;
57  volatile uint64_t c3;
58} counters = { 0, 0, 0 };
59
60/* ---------------------------- local helper functions --------------------- */
61
62static void dump_tdb (struct __htm_tdb *tdb)
63{
64  unsigned char *p;
65  int i;
66  int j;
67
68  if (do_dump_tdb == 0)
69    {
70      return;
71    }
72  p = (unsigned char *)tdb;
73  for (i = 0; i < 16; i++)
74    {
75      fprintf (stderr, "0x%02x  ", i * 16);
76      for (j = 0; j < 16; j++)
77	{
78	  fprintf (stderr, "%02x", (int)p[i * 16 + j]);
79	  if (j < 15)
80	    {
81	      fprintf (stderr, " ");
82	    }
83	  if (j == 7)
84	    {
85	      fprintf (stderr, " ");
86	    }
87	}
88      fprintf (stderr, "\n");
89    }
90
91  return;
92}
93
94/* ---------------------------- local test functions ----------------------- */
95
96/* Check values of the constants defined in htmintrin.h.  */
97static int test_constants (void)
98{
99  if (_HTM_TBEGIN_STARTED != 0)
100    {
101      return 100 * _HTM_TBEGIN_STARTED + 1;
102    }
103  if (_HTM_TBEGIN_INDETERMINATE != 1)
104    {
105      return 100 * _HTM_TBEGIN_INDETERMINATE + 2;
106    }
107  if (_HTM_TBEGIN_TRANSIENT != 2)
108    {
109      return 100 * _HTM_TBEGIN_TRANSIENT + 3;
110    }
111  if (_HTM_TBEGIN_PERSISTENT != 3)
112    {
113      return 100 * _HTM_TBEGIN_PERSISTENT + 4;
114    }
115
116  return 0;
117}
118
119static int test_tbegin_ntstg_tend (void)
120{
121  int rc;
122
123  counters.c1 = 0;
124  counters.c2 = 0;
125  if ((rc = __builtin_tbegin ((void *)0)) == 0)
126    {
127      __builtin_non_tx_store ((uint64_t *)&counters.c1, 1);
128      counters.c2 = 2;
129      rc = __builtin_tend ();
130      if (rc != 0)
131	{
132	  return 100 * rc + 5;
133	}
134      if (counters.c1 != 1)
135	{
136	  return 100 * counters.c1 + 2;
137	}
138      if (counters.c2 != 2)
139	{
140	  return 100 * counters.c2 + 3;
141	}
142    }
143  else
144    {
145      return 100 * rc + 4;
146    }
147
148  return 0;
149}
150
151static int test_tbegin_ntstg_tabort (void)
152{
153  float f;
154
155  counters.c1 = 0;
156  counters.c2 = 0;
157  f = 0;
158  if (__builtin_tbegin ((void *)0) == 0)
159    {
160      __builtin_non_tx_store ((uint64_t *)&counters.c1, 1);
161      counters.c2 = 2;
162      f = 1;
163      __builtin_tabort (256);
164      return 1;
165    }
166  if (counters.c1 != 1)
167    {
168      return 100 * counters.c1 + 2;
169    }
170  if (counters.c2 != 0)
171    {
172      return 100 * counters.c2 + 3;
173    }
174  if (f != 0)
175    {
176      return 100 * f + 4;
177    }
178
179  return 0;
180}
181
182static int test_tbegin_nofloat (void)
183{
184  int rc;
185
186  counters.c1 = 0;
187  counters.c2 = 0;
188  if ((rc = __builtin_tbegin_nofloat ((void *)0)) == 0)
189    {
190      __builtin_non_tx_store ((uint64_t *)&counters.c1, 1);
191      counters.c2 = 2;
192      rc = __builtin_tend ();
193      if (rc != 0)
194	{
195	  return 100 * rc + 5;
196	}
197      if (counters.c1 != 1)
198	{
199	  return 100 * counters.c1 + 2;
200	}
201      if (counters.c2 != 2)
202	{
203	  return 100 * counters.c2 + 3;
204	}
205    }
206  else
207    {
208      return 100 * rc + 4;
209    }
210
211  return 0;
212}
213
214static int test_tbegin_retry (void)
215{
216  int rc;
217
218  counters.c1 = 0;
219  counters.c2 = 0;
220  counters.c3 = 0;
221  if ((rc = __builtin_tbegin_retry ((void *)0, 5)) == 0)
222    {
223      int do_abort;
224
225      do_abort = (counters.c1 == 0) ? 1 : 0;
226      __builtin_non_tx_store (
227			     (uint64_t *)&counters.c1, counters.c1 + 1);
228      if (do_abort == 1)
229	{
230	  __builtin_tabort (256);
231	}
232      counters.c2 = counters.c2 + 10;
233      __builtin_non_tx_store ((uint64_t *)&counters.c3, 3);
234      rc = __builtin_tend ();
235      if (rc != 0)
236	{
237	  return 100 * rc + 5;
238	}
239      if (counters.c1 != 2)
240	{
241	  return 100 * counters.c1 + 2;
242	}
243      if (counters.c2 != 10)
244	{
245	  return 100 * counters.c2 + 3;
246	}
247      if (counters.c3 != 3)
248	{
249	  return 100 * counters.c3 + 6;
250	}
251    }
252  else
253    {
254      return 100 * rc + 4;
255    }
256
257  return 0;
258}
259
260static int test_tbegin_retry_nofloat (void)
261{
262  int rc;
263
264  counters.c1 = 0;
265  counters.c2 = 0;
266  counters.c3 = 0;
267  if ((rc = __builtin_tbegin_retry_nofloat ((void *)0, 5)) == 0)
268    {
269      int do_abort;
270
271      do_abort = (counters.c1 == 0) ? 1 : 0;
272      __builtin_non_tx_store (
273			     (uint64_t *)&counters.c1, counters.c1 + 1);
274      if (do_abort == 1)
275	{
276	  __builtin_tabort (256);
277	}
278      counters.c2 = counters.c2 + 10;
279      __builtin_non_tx_store ((uint64_t *)&counters.c3, 3);
280      rc = __builtin_tend ();
281      if (rc != 0)
282	{
283	  return 100 * rc + 5;
284	}
285      if (counters.c1 != 2)
286	{
287	  return 100 * counters.c1 + 2;
288	}
289      if (counters.c2 != 10)
290	{
291	  return 100 * counters.c2 + 3;
292	}
293      if (counters.c3 != 3)
294	{
295	  return 100 * counters.c3 + 6;
296	}
297    }
298  else
299    {
300      return 100 * rc + 4;
301    }
302
303  return 0;
304}
305
306static int test_tbegin_aborts (void)
307{
308  float f;
309  int rc;
310
311  f = 77;
312  if ((rc = __builtin_tbegin ((void *)0)) == 0)
313    {
314      f = 88;
315      __builtin_tabort (256);
316      return 2;
317    }
318  else if (rc != 2)
319    {
320      return 3;
321    }
322  if (f != 77)
323    {
324      return 4;
325    }
326  f = 66;
327  if ((rc = __builtin_tbegin ((void *)0)) == 0)
328    {
329      f = 99;
330      __builtin_tabort (257);
331      return 5;
332    }
333  else if (rc != 3)
334    {
335      return 100 * rc + 6;
336    }
337  if (f != 66)
338    {
339      return 100 * f + 7;
340    }
341  if ((rc = __builtin_tbegin ((void *)0)) == 0)
342    {
343      global.float_3 = global.float_1 + global.float_2;
344      rc = __builtin_tend ();
345      if (rc != 0)
346	{
347	  return 100 * rc + 8;
348	}
349    }
350  else
351    {
352      return 100 * rc + 9;
353    }
354  if (global.float_3 != global.float_1 + global.float_2)
355    {
356      return 100 * rc + 10;
357    }
358
359  return 0;
360}
361
362static __attribute__((noinline)) void indirect_abort(int abort_code)
363{
364  __builtin_tabort (abort_code);
365
366  return;
367}
368
369static int test_tbegin_indirect_aborts (void)
370{
371  float f;
372  int rc;
373
374  f = 77;
375  if ((rc = __builtin_tbegin ((void *)0)) == 0)
376    {
377      f = 88;
378      indirect_abort(256);
379      return 2;
380    }
381  else if (rc != 2)
382    {
383      return 100 * rc + 3;
384    }
385  if (f != 77)
386    {
387      return 100 * rc + 4;
388    }
389  f = 66;
390  if ((rc = __builtin_tbegin ((void *)0)) == 0)
391    {
392      f = 99;
393      indirect_abort(257);
394      return 5;
395    }
396  else if (rc != 3)
397    {
398      return 100 * rc + 6;
399    }
400  if (f != 66)
401    {
402      return 100 * f + 7;
403    }
404
405  return 0;
406}
407
408static int test_tbegin_nofloat_aborts (void)
409{
410  int rc;
411
412  if ((rc = __builtin_tbegin_nofloat ((void *)0)) == 0)
413    {
414      __builtin_tabort (256);
415      return 2;
416    }
417  if ((rc = __builtin_tbegin_nofloat ((void *)0)) == 0)
418    {
419      __builtin_tabort (257);
420      return 1005;
421    }
422  else if (rc != 3)
423    {
424      return 1000 * rc + 6;
425    }
426
427  return 0;
428}
429
430static int test_tbegin_nofloat_indirect_aborts (void)
431{
432  int rc;
433
434  if ((rc = __builtin_tbegin_nofloat ((void *)0)) == 0)
435    {
436      indirect_abort (256);
437      return 2;
438    }
439  if ((rc = __builtin_tbegin_nofloat ((void *)0)) == 0)
440    {
441      indirect_abort (257);
442      return 1005;
443    }
444  else if (rc != 3)
445    {
446      return 1000 * rc + 6;
447    }
448
449  return 0;
450}
451
452static
453int _test_tbegin_retry_aborts (int retries, uint64_t abort_code)
454{
455  int rc;
456
457  counters.c1 = 0;
458  if ((rc = __builtin_tbegin_retry ((void *)0, retries)) == 0)
459    {
460      __builtin_non_tx_store ((uint64_t *)&counters.c1, counters.c1 + 1);
461      __builtin_tabort (abort_code);
462      return 2;
463    }
464  else
465    {
466      if ((abort_code & 1) == 0)
467	{
468	  if (rc != 2)
469	    {
470	      return 100 * rc + 2003;
471	    }
472	  else if (counters.c1 != (uint64_t)retries + 1)
473	    {
474	      return 1000 * counters.c1 + 100 * retries + 4;
475	    }
476	}
477      else
478	{
479	  if (rc != 3)
480	    {
481	      return 100 * rc + 3005;
482	    }
483	  else if (counters.c1 != 1)
484	    {
485	      return 1000 * counters.c1 + 100 * retries + 6;
486	    }
487	}
488    }
489
490  return 0;
491}
492
493static int test_tbegin_retry_aborts (void)
494{
495  int rc;
496  int retries;
497
498  for (retries = 1; retries <= 3; retries++)
499    {
500      rc = _test_tbegin_retry_aborts (retries, 256);
501      if (rc != 0)
502	{
503	  return 10000 + rc;
504	}
505    }
506  for (retries = 1; retries <= 3; retries++)
507    {
508      rc = _test_tbegin_retry_aborts (retries, 257);
509      if (rc != 0)
510	{
511	  return 20000 + rc;
512	}
513    }
514  if ((rc = __builtin_tbegin_retry ((void *)0, 5)) == 0)
515    {
516      global.float_3 = global.float_1 + global.float_2;
517      rc = __builtin_tend ();
518      if (rc != 0)
519	{
520	  return 30000 + 100 * rc + 6;
521	}
522    }
523  else
524    {
525      return 30000 + 100 * rc + 7;
526    }
527
528  return 0;
529}
530
531static int _test_tbegin_retry_nofloat_aborts (int retries, uint64_t abort_code)
532{
533  int rc;
534
535  counters.c1 = 0;
536  if ((rc = __builtin_tbegin_retry_nofloat ((void *)0, retries)) == 0)
537    {
538      __builtin_non_tx_store ((uint64_t *)&counters.c1, counters.c1 + 1);
539      __builtin_tabort (abort_code);
540      return 2;
541    }
542  else
543    {
544      if ((abort_code & 1) == 0)
545	{
546	  if (rc != 2)
547	    {
548	      return 100 * rc + 2003;
549	    }
550	  else if (counters.c1 != (uint64_t)retries + 1)
551	    {
552	      return 1000 * counters.c1 + 100 * retries + 4;
553	    }
554	}
555      else
556	{
557	  if (rc != 3)
558	    {
559	      return 100 * rc + 3005;
560	    }
561	  else if (counters.c1 != 1)
562	    {
563	      return 1000 * counters.c1 + 100 * retries + 6;
564	    }
565	}
566    }
567
568  return 0;
569}
570
571static int test_tbegin_retry_nofloat_aborts (void)
572{
573  int rc;
574  int retries;
575
576  for (retries = 1; retries <= 3; retries++)
577    {
578      rc = _test_tbegin_retry_nofloat_aborts (retries, 256);
579      if (rc != 0)
580	{
581	  return 10 * retries + rc;
582	}
583    }
584  for (retries = 1; retries <= 3; retries++)
585    {
586      rc = _test_tbegin_retry_nofloat_aborts (retries, 257);
587      if (rc != 0)
588	{
589	  return 10000 + 10 * retries + rc;
590	}
591    }
592
593  return 0;
594}
595
596static int test_tbegin_tdb (void)
597{
598  int rc;
599
600  local_tdb.format = 0;
601  if ((rc = __builtin_tbegin (&local_tdb)) == 0)
602    {
603      rc = __builtin_tend ();
604      if (rc != 0)
605	{
606	  return 100 * rc + 1;
607	}
608      if (local_tdb.format != 0)
609	{
610	  dump_tdb (&local_tdb);
611	  return 100 * local_tdb.format + 2;
612	}
613    }
614  else
615    {
616      return 100 * rc + 3;
617    }
618  local_tdb.format = 0;
619  if ((rc = __builtin_tbegin (&local_tdb)) == 0)
620    {
621      __builtin_tabort (257);
622      return 4;
623    }
624  else
625    {
626      if (rc != 3)
627	{
628	  return 100 * rc + 5;
629	}
630      if (local_tdb.format != 1)
631	{
632	  dump_tdb (&local_tdb);
633	  return 100 * local_tdb.format + 6;
634	}
635    }
636  local_tdb256.format = 0;
637  if ((rc = __builtin_tbegin (&local_tdb256)) == 0)
638    {
639      rc = __builtin_tend ();
640      if (rc != 0)
641	{
642	  return 1100 * rc + 1;
643	}
644      if (local_tdb256.format != 0)
645	{
646	  dump_tdb (&local_tdb256);
647	  return 1100 * local_tdb256.format + 2;
648	}
649    }
650  else
651    {
652      return 1100 * rc + 3;
653    }
654  local_tdb256.format = 0;
655  if ((rc = __builtin_tbegin (&local_tdb256)) == 0)
656    {
657      __builtin_tabort (257);
658      return 2004;
659    }
660  else
661    {
662      if (rc != 3)
663	{
664	  return 2100 * rc + 5;
665	}
666      if (local_tdb256.format != 1)
667	{
668	  dump_tdb (&local_tdb256);
669	  return 2100 * local_tdb256.format + 6;
670	}
671    }
672
673  return 0;
674}
675
676static int test_tbegin_nofloat_tdb (void)
677{
678  int rc;
679
680  local_tdb.format = 0;
681  if ((rc = __builtin_tbegin_nofloat (&local_tdb)) == 0)
682    {
683      rc = __builtin_tend ();
684      if (rc != 0)
685	{
686	  return 100 * rc + 1;
687	}
688      if (local_tdb.format != 0)
689	{
690	  dump_tdb (&local_tdb);
691	  return 100 * local_tdb.format + 2;
692	}
693    }
694  else
695    {
696      return 3;
697    }
698  local_tdb.format = 0;
699  if ((rc = __builtin_tbegin_nofloat (&local_tdb)) == 0)
700    {
701      __builtin_tabort (257);
702      return 4;
703    }
704  else
705    {
706      if (rc != 3)
707	{
708	  return 100 * rc + 5;
709	}
710      if (local_tdb.format != 1)
711	{
712	  dump_tdb (&local_tdb);
713	  return 100 * local_tdb.format + 6;
714	}
715    }
716  local_tdb256.format = 0;
717  if ((rc = __builtin_tbegin_nofloat (&local_tdb256)) == 0)
718    {
719      rc = __builtin_tend ();
720      if (rc != 0)
721	{
722	  return 1100 * rc + 1;
723	}
724      if (local_tdb256.format != 0)
725	{
726	  dump_tdb (&local_tdb256);
727	  return 1100 * local_tdb256.format + 2;
728	}
729    }
730  else
731    {
732      return 1003;
733    }
734  local_tdb256.format = 0;
735  if ((rc = __builtin_tbegin_nofloat (&local_tdb256)) == 0)
736    {
737      __builtin_tabort (257);
738      return 2004;
739    }
740  else
741    {
742      if (rc != 3)
743	{
744	  return 2100 * rc + 5;
745	}
746      if (local_tdb256.format != 1)
747	{
748	  dump_tdb (&local_tdb256);
749	  return 2100 * local_tdb256.format + 6;
750	}
751    }
752
753  return 0;
754}
755
756static int test_tbegin_retry_tdb (void)
757{
758  int rc;
759
760  local_tdb256.format = 0;
761  if ((rc = __builtin_tbegin_retry (&local_tdb256, 2)) == 0)
762    {
763      rc = __builtin_tend ();
764      if (rc != 0)
765	{
766	  return 1100 * rc + 1;
767	}
768      if (local_tdb256.format != 0)
769	{
770	  dump_tdb (&local_tdb256);
771	  return 1100 * local_tdb256.format + 2;
772	}
773    }
774  else
775    {
776      return 1003;
777    }
778  local_tdb256.format = 0;
779  if ((rc = __builtin_tbegin_retry (&local_tdb256, 2)) == 0)
780    {
781      __builtin_tabort (257);
782      return 2004;
783    }
784  else
785    {
786      if (rc != 3)
787	{
788	  return 2100 * rc + 5;
789	}
790      if (local_tdb256.format != 1)
791	{
792	  dump_tdb (&local_tdb256);
793	  return 2100 * local_tdb256.format + 6;
794	}
795    }
796
797  return 0;
798}
799
800static int test_tbegin_retry_nofloat_tdb (void)
801{
802  int rc;
803
804  local_tdb.format = 0;
805  if ((rc = __builtin_tbegin_retry_nofloat (&local_tdb, 2)) == 0)
806    {
807      rc = __builtin_tend ();
808      if (rc != 0)
809	{
810	  return 100 * rc + 1;
811	}
812      if (local_tdb.format != 0)
813	{
814	  dump_tdb (&local_tdb);
815	  return 100 * local_tdb.format + 2;
816	}
817    }
818  else
819    {
820      return 100 * rc + 3;
821    }
822  local_tdb.format = 0;
823  if ((rc = __builtin_tbegin_retry_nofloat (&local_tdb, 2)) == 0)
824    {
825      __builtin_tabort (257);
826      return 4;
827    }
828  else
829    {
830      if (rc != 3)
831	{
832	  return 100 * rc + 5;
833	}
834      if (local_tdb.format != 1)
835	{
836	  dump_tdb (&local_tdb);
837	  return 100 * local_tdb.format + 6;
838	}
839    }
840  local_tdb256.format = 0;
841  if ((rc = __builtin_tbegin_retry_nofloat (&local_tdb256, 2)) == 0)
842    {
843      rc = __builtin_tend ();
844      if (rc != 0)
845	{
846	  return 1100 * rc + 1;
847	}
848      if (local_tdb256.format != 0)
849	{
850	  dump_tdb (&local_tdb256);
851	  return 1100 * local_tdb256.format + 2;
852	}
853    }
854  else
855    {
856      return 1100 * rc + 3;
857    }
858  local_tdb256.format = 0;
859  if ((rc = __builtin_tbegin_retry_nofloat (&local_tdb256, 2)) == 0)
860    {
861      __builtin_tabort (257);
862      return 2004;
863    }
864  else
865    {
866      if (rc != 3)
867	{
868	  return 2100 * rc + 5;
869	}
870      if (local_tdb256.format != 1)
871	{
872	  dump_tdb (&local_tdb256);
873	  return 2100 * local_tdb256.format + 6;
874	}
875    }
876
877  return 0;
878}
879
880static int test_etnd (void)
881{
882  int rc;
883
884  counters.c1 = 0;
885  counters.c2 = 0;
886  counters.c3 = 0;
887  if ((rc = __builtin_tbegin ((void *)0)) == 0)
888    {
889      counters.c1 = __builtin_tx_nesting_depth ();
890      if (__builtin_tbegin ((void *)0) == 0)
891	{
892	  counters.c2 = __builtin_tx_nesting_depth ();
893	  if (__builtin_tbegin ((void *)0) == 0)
894	    {
895	      counters.c3 = __builtin_tx_nesting_depth ();
896	      __builtin_tend ();
897	    }
898	  __builtin_tend ();
899	}
900      __builtin_tend ();
901    }
902  else
903    {
904      return 100 * rc + 1;
905    }
906  if (counters.c1 != 1)
907    {
908      return 100 * counters.c1 + 2;
909    }
910  if (counters.c2 != 2)
911    {
912      return 100 * counters.c2 + 3;
913    }
914  if (counters.c3 != 3)
915    {
916      return 100 * counters.c3 + 4;
917    }
918
919  return 0;
920}
921
922static int test_tbeginc (void)
923{
924  int rc;
925
926  counters.c1 = 0;
927  __builtin_tbeginc ();
928  counters.c1 = 1;
929  rc = __builtin_tend ();
930  if (rc != 0)
931    {
932      return 10000 * rc + 1;
933    }
934  if (counters.c1 != 1)
935    {
936      return 100000 * counters.c1 + 3;
937    }
938
939  return 0;
940}
941
942/* ---------------------------- local testing framework functions ---------- */
943
944static int run_one_test (const test_table_entry_t *test_entry)
945{
946  int do_print_passes;
947  int succeeded;
948  int rc;
949  int i;
950
951  /* Warmup run to get all necessary data and instruction pages into the page
952   * tables.  */
953  {
954    int run;
955
956    do_dump_tdb = 0;
957    for (run = 0; run < NUM_WARMUP_RUNS; run++)
958      {
959	test_entry->test_func ();
960      }
961    do_dump_tdb = 1;
962  }
963  do_print_passes = (
964		     test_entry->required_quorum != 1 ||
965		     test_entry->max_repetitions != 1);
966  printf ("RRR RUN  %s\n", test_entry->name);
967  if (do_print_passes == 1)
968    {
969      printf (
970	     "         (requires %d successful out of %d runs)\n",
971	     test_entry->required_quorum,
972	     test_entry->max_repetitions);
973    }
974  succeeded = 0;
975  rc = 0;
976  for (rc = 0, i = 0; i < test_entry->max_repetitions; i++)
977    {
978      if (do_print_passes == 1)
979	{
980	  if (i == 0)
981	    {
982	      printf ("        ");
983	    }
984	  else
985	    {
986	      printf (",");
987	    }
988	}
989      rc = test_entry->test_func ();
990      if (rc == 0)
991	{
992	  if (do_print_passes == 1)
993	    {
994	      printf (" success");
995	    }
996	  succeeded++;
997	  if (succeeded >= test_entry->required_quorum)
998	    {
999	      break;
1000	    }
1001	}
1002      else
1003	{
1004	  printf (" failed (rc = %d)", rc);
1005	}
1006    }
1007  if (do_print_passes == 1 || rc != 0)
1008    {
1009      printf ("\n");
1010    }
1011  if (succeeded >= test_entry->required_quorum)
1012    {
1013      printf ("+++ OK   %s\n", test_entry->name);
1014
1015      return 0;
1016    }
1017  else
1018    {
1019      printf ("--- FAIL %s\n", test_entry->name);
1020
1021      return (rc != 0) ? rc : -1;
1022    }
1023}
1024
1025static int run_all_tests (const test_table_entry_t *test_table)
1026{
1027  const test_table_entry_t *test;
1028  int rc;
1029
1030  for (
1031       rc = 0, test = &test_table[0];
1032       test->test_func != NULL && rc == 0; test++)
1033    {
1034      rc = run_one_test (test);
1035    }
1036
1037  return rc;
1038}
1039
1040/* ---------------------------- interface functions ------------------------ */
1041
1042int main (void)
1043{
1044  const test_table_entry_t test_table[] = {
1045    TEST_NO_REP (test_constants),
1046    TEST_DF_REP (test_tbegin_ntstg_tend),
1047    TEST_DF_REP (test_tbegin_ntstg_tabort),
1048    TEST_DF_REP (test_tbegin_nofloat),
1049    TEST_NO_REP (test_tbegin_retry),
1050    TEST_NO_REP (test_tbegin_retry_nofloat),
1051    TEST_DF_REP (test_tbegin_aborts),
1052    TEST_DF_REP (test_tbegin_indirect_aborts),
1053    TEST_DF_REP (test_tbegin_nofloat_aborts),
1054    TEST_DF_REP (test_tbegin_nofloat_indirect_aborts),
1055    TEST_NO_REP (test_tbegin_retry_aborts),
1056    TEST_NO_REP (test_tbegin_retry_nofloat_aborts),
1057    TEST_DF_REP (test_tbegin_tdb),
1058    TEST_DF_REP (test_tbegin_nofloat_tdb),
1059    TEST_NO_REP (test_tbegin_retry_tdb),
1060    TEST_NO_REP (test_tbegin_retry_nofloat_tdb),
1061    TEST_DF_REP (test_etnd),
1062    TEST_DF_REP (test_tbeginc),
1063    { (void *)0, 0, 0 }
1064  };
1065
1066  {
1067    int rc;
1068
1069    rc = run_all_tests (test_table);
1070
1071    return rc;
1072  }
1073}
1074