1 /* Functional tests of the htm __TM_... macros. */
4 /* { dg-require-effective-target htm } */
5 /* { dg-options "-O3 -march=zEC12 -mzarch" } */
7 /* ---------------------------- included header files ---------------------- */
12 #include <htmxlintrin.h>
14 /* ---------------------------- local definitions -------------------------- */
16 #define DEFAULT_MAX_REPETITIONS 7
17 #define DEFAULT_REQUIRED_QUORUM 4
18 #define DEFAULT_ABORT_ADDRESS (0x12345678u)
20 /* ---------------------------- local macros ------------------------------- */
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 }
26 /* ---------------------------- local types -------------------------------- */
28 typedef int (*test_func_t
)(void);
33 test_func_t test_func
;
48 ABORT_T_FOOTPRINT_EXCEEDED
,
49 ABORT_T_NESTED_TOO_DEEP
,
52 ABORT_T_INVALID_ABORT_CODE
55 /* ---------------------------- local variables ---------------------------- */
57 __attribute__ ((aligned(256))) static struct __htm_tdb local_tdb256
;
58 static struct __htm_tdb local_tdb
;
60 static abort_t
const abort_classes
[] =
62 ABORT_T_INVALID_ABORT_CODE
,
70 ABORT_T_FOOTPRINT_EXCEEDED
,
72 ABORT_T_FOOTPRINT_EXCEEDED
,
78 ABORT_T_NESTED_TOO_DEEP
,
85 static size_t num_abort_classes
= sizeof(abort_classes
) / sizeof(abort_t
);
87 /* ---------------------------- exported variables (globals) --------------- */
90 uint64_t global_u64
= 0;
91 float global_float_1
= 1.0;
92 float global_float_2
= 2.5;
93 float global_float_3
= 0.0;
94 __attribute__ ((aligned(256))) struct
97 char pad1
[256 - sizeof(uint64_t)];
99 char pad2
[256 - sizeof(uint64_t)];
100 volatile uint64_t c3
;
103 /* ---------------------------- local helper functions --------------------- */
105 static void dump_tdb(struct __htm_tdb
*tdb
)
111 p
= (unsigned char *)tdb
;
112 for (i
= 0; i
< 16; i
++)
114 fprintf(stderr
, "0x%02x ", i
* 16);
115 for (j
= 0; j
< 16; j
++)
117 fprintf(stderr
, "%02x", (int)p
[i
* 16 + j
]);
120 fprintf(stderr
, " ");
124 fprintf(stderr
, " ");
127 fprintf(stderr
, "\n");
133 static void make_fake_tdb(struct __htm_tdb
*tdb
)
135 memset(tdb
, 0, sizeof(*tdb
));
137 tdb
->nesting_depth
= 1;
138 tdb
->atia
= DEFAULT_ABORT_ADDRESS
;
139 tdb
->abort_code
= 11;
144 static int check_abort_code_in_tdb(struct __htm_tdb
*tdb
, uint64_t abort_code
)
153 addr
= __TM_failure_address(&local_tdb
);
154 if (addr
!= DEFAULT_ABORT_ADDRESS
)
160 long long tdb_abort_code
;
162 tdb_abort_code
= __TM_failure_code(tdb
);
163 if ((uint64_t)tdb_abort_code
!= abort_code
)
166 stderr
, "tm_ac %" PRIu64
", ac %" PRIu64
167 ", tdb_ac %" PRIu64
"\n",
168 (uint64_t)tdb_abort_code
, abort_code
,
169 (uint64_t)tdb
->abort_code
);
173 expect_rc
= (abort_code
>= 256) ? 1 : 0;
174 rc
= __TM_is_user_abort(tdb
);
177 fprintf(stderr
, "rc %ld, expect_rc %ld\n", rc
, expect_rc
);
184 rc
= __TM_is_named_user_abort(tdb
, &code
);
188 stderr
, "rc %ld, expect_rc %ld\n", rc
,
192 if (expect_rc
== 1 && code
!= abort_code
- 256)
197 if (abort_code
> (uint64_t)num_abort_classes
)
199 abort_code
= (uint64_t)num_abort_classes
;
201 expect_rc
= (abort_classes
[abort_code
] == ABORT_T_ILLEGAL
) ? 1 : 0;
202 rc
= __TM_is_illegal(tdb
);
206 fprintf(stderr
, "rc %ld, expect_rc %ld\n", rc
, expect_rc
);
210 (abort_classes
[abort_code
] == ABORT_T_FOOTPRINT_EXCEEDED
) ?
212 rc
= __TM_is_footprint_exceeded(tdb
);
216 fprintf(stderr
, "rc %ld, expect_rc %ld\n", rc
, expect_rc
);
220 (abort_classes
[abort_code
] == ABORT_T_NESTED_TOO_DEEP
) ? 1 : 0;
221 rc
= __TM_is_nested_too_deep(tdb
);
225 fprintf(stderr
, "rc %ld, expect_rc %ld\n", rc
, expect_rc
);
228 expect_rc
= (abort_classes
[abort_code
] == ABORT_T_CONFLICT
) ? 1 : 0;
229 rc
= __TM_is_conflict(tdb
);
233 fprintf(stderr
, "rc %ld, expect_rc %ld\n", rc
, expect_rc
);
240 /* ---------------------------- local test functions ----------------------- */
242 /* Not a test; make sure that the involved global cachelines are reserved for
244 static int init_cache(void)
246 make_fake_tdb(&local_tdb
);
247 make_fake_tdb(&local_tdb256
);
250 global_float_1
= 1.0;
251 global_float_2
= 2.5;
252 global_float_3
= 0.0;
260 static int test_abort_classification(void)
264 make_fake_tdb(&local_tdb
);
265 for (i
= 0; i
<= 256; i
++)
269 local_tdb
.abort_code
= (uint64_t)i
;
270 rc
= check_abort_code_in_tdb(&local_tdb
, (uint64_t)i
);
280 static int test_cc_classification(void)
284 rc
= __TM_is_failure_persistent(0);
289 rc
= __TM_is_failure_persistent(1);
294 rc
= __TM_is_failure_persistent(2);
299 rc
= __TM_is_failure_persistent(3);
308 static int test_tbegin_ntstg_tend(void)
314 if ((rc
= __TM_simple_begin()) == 0)
316 __TM_non_transactional_store((uint64_t *)&counters
.c1
, 1);
323 if (counters
.c1
!= 1)
325 return 100 * counters
.c1
+ 2;
327 if (counters
.c2
!= 2)
329 return 100 * counters
.c2
+ 3;
340 static int test_tbegin_ntstg_tabort(void)
347 if (__TM_simple_begin() == 0)
349 __TM_non_transactional_store((uint64_t *)&counters
.c1
, 1);
355 if (counters
.c1
!= 1)
357 return 100 * counters
.c1
+ 2;
359 if (counters
.c2
!= 0)
361 return 100 * counters
.c2
+ 3;
371 static int test_tbegin_aborts(void)
377 if ((rc
= __TM_simple_begin()) == 0)
392 if ((rc
= __TM_simple_begin()) == 0)
406 if ((rc
= __TM_simple_begin()) == 0)
408 global_float_3
= global_float_1
+ global_float_2
;
419 if (global_float_3
!= global_float_1
+ global_float_2
)
421 return 100 * rc
+ 10;
427 static int test_tbegin_tdb(void)
431 local_tdb
.format
= 0;
432 if ((rc
= __TM_begin(&local_tdb
)) == 0)
439 if (local_tdb
.format
!= 0)
441 dump_tdb(&local_tdb
);
442 return 100 * local_tdb
.format
+ 2;
449 local_tdb
.format
= 0;
450 if ((rc
= __TM_begin(&local_tdb
)) == 0)
461 if (local_tdb
.format
!= 1)
463 dump_tdb(&local_tdb
);
464 return 100 * local_tdb
.format
+ 6;
467 local_tdb256
.format
= 0;
468 if ((rc
= __TM_begin(&local_tdb256
)) == 0)
473 return 1100 * rc
+ 1;
475 if (local_tdb256
.format
!= 0)
477 dump_tdb(&local_tdb256
);
478 return 1100 * local_tdb256
.format
+ 2;
483 return 1100 * rc
+ 3;
485 #if 1 /*!!!does not work*/
486 local_tdb256
.format
= 0;
487 if ((rc
= __TM_begin(&local_tdb256
)) == 0)
496 return 2100 * rc
+ 5;
498 if (local_tdb256
.format
!= 1)
500 dump_tdb(&local_tdb256
);
501 return 2100 * local_tdb256
.format
+ 6;
509 static int test_etnd(void)
516 make_fake_tdb(&local_tdb
);
517 local_tdb
.nesting_depth
= 0;
518 nd
= __TM_nesting_depth(&local_tdb
);
523 local_tdb
.nesting_depth
= 7;
524 nd
= __TM_nesting_depth(&local_tdb
);
529 local_tdb
.format
= 0;
530 nd
= __TM_nesting_depth(&local_tdb
);
540 if ((rc
= __TM_simple_begin()) == 0)
542 counters
.c1
= __TM_nesting_depth(0);
543 if (__TM_simple_begin() == 0)
545 counters
.c2
= __TM_nesting_depth(0);
546 if (__TM_simple_begin() == 0)
548 counters
.c3
= __TM_nesting_depth(0);
559 if (counters
.c1
!= 1)
561 return 100 * counters
.c1
+ 2;
563 if (counters
.c2
!= 2)
565 return 100 * counters
.c2
+ 3;
567 if (counters
.c3
!= 3)
569 return 100 * counters
.c3
+ 4;
575 /* ---------------------------- local testing framework functions ---------- */
577 static int run_one_test(const test_table_entry_t
*test_entry
)
585 test_entry
->required_quorum
!= 1 ||
586 test_entry
->max_repetitions
!= 1);
587 printf("RRR RUN %s\n", test_entry
->name
);
588 if (do_print_passes
== 1)
591 " (requires %d successful out of %d runs)\n",
592 test_entry
->required_quorum
,
593 test_entry
->max_repetitions
);
597 for (rc
= 0, i
= 0; i
< test_entry
->max_repetitions
; i
++)
599 if (do_print_passes
== 1)
610 rc
= test_entry
->test_func();
613 if (do_print_passes
== 1)
618 if (succeeded
>= test_entry
->required_quorum
)
625 printf(" failed (rc = %d)", rc
);
628 if (do_print_passes
== 1 || rc
!= 0)
632 if (succeeded
>= test_entry
->required_quorum
)
634 printf("+++ OK %s\n", test_entry
->name
);
640 printf("--- FAIL %s\n", test_entry
->name
);
642 return (rc
!= 0) ? rc
: -1;
646 static int run_all_tests(const test_table_entry_t
*test_table
)
648 const test_table_entry_t
*test
;
652 rc
= 0, test
= &test_table
[0];
653 test
->test_func
!= NULL
&& rc
== 0; test
++)
655 rc
= run_one_test(test
);
661 /* ---------------------------- interface functions ------------------------ */
665 const test_table_entry_t test_table
[] = {
666 TEST_NO_REP(init_cache
),
667 TEST_NO_REP(test_abort_classification
),
668 TEST_NO_REP(test_cc_classification
),
669 TEST_DF_REP(test_tbegin_ntstg_tend
),
670 TEST_DF_REP(test_tbegin_ntstg_tabort
),
671 TEST_DF_REP(test_tbegin_aborts
),
672 TEST_DF_REP(test_tbegin_tdb
),
673 TEST_DF_REP(test_etnd
),
680 rc
= run_all_tests(test_table
);