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
99 } counters
= { 0, 0, 0 };
101 /* ---------------------------- local helper functions --------------------- */
103 static void dump_tdb(struct __htm_tdb
*tdb
)
109 p
= (unsigned char *)tdb
;
110 for (i
= 0; i
< 16; i
++)
112 fprintf(stderr
, "0x%02x ", i
* 16);
113 for (j
= 0; j
< 16; j
++)
115 fprintf(stderr
, "%02x", (int)p
[i
* 16 + j
]);
118 fprintf(stderr
, " ");
122 fprintf(stderr
, " ");
125 fprintf(stderr
, "\n");
131 static void make_fake_tdb(struct __htm_tdb
*tdb
)
133 memset(tdb
, 0, sizeof(*tdb
));
135 tdb
->nesting_depth
= 1;
136 tdb
->atia
= DEFAULT_ABORT_ADDRESS
;
137 tdb
->abort_code
= 11;
142 static int check_abort_code_in_tdb(struct __htm_tdb
*tdb
, uint64_t abort_code
)
151 addr
= __TM_failure_address(&local_tdb
);
152 if (addr
!= DEFAULT_ABORT_ADDRESS
)
158 long long tdb_abort_code
;
160 tdb_abort_code
= __TM_failure_code(tdb
);
161 if ((uint64_t)tdb_abort_code
!= abort_code
)
164 stderr
, "tm_ac %" PRIu64
", ac %" PRIu64
165 ", tdb_ac %" PRIu64
"\n",
166 (uint64_t)tdb_abort_code
, abort_code
,
167 (uint64_t)tdb
->abort_code
);
171 expect_rc
= (abort_code
>= 256) ? 1 : 0;
172 rc
= __TM_is_user_abort(tdb
);
175 fprintf(stderr
, "rc %ld, expect_rc %ld\n", rc
, expect_rc
);
182 rc
= __TM_is_named_user_abort(tdb
, &code
);
186 stderr
, "rc %ld, expect_rc %ld\n", rc
,
190 if (expect_rc
== 1 && code
!= abort_code
- 256)
195 if (abort_code
> (uint64_t)num_abort_classes
)
197 abort_code
= (uint64_t)num_abort_classes
;
199 expect_rc
= (abort_classes
[abort_code
] == ABORT_T_ILLEGAL
) ? 1 : 0;
200 rc
= __TM_is_illegal(tdb
);
204 fprintf(stderr
, "rc %ld, expect_rc %ld\n", rc
, expect_rc
);
208 (abort_classes
[abort_code
] == ABORT_T_FOOTPRINT_EXCEEDED
) ?
210 rc
= __TM_is_footprint_exceeded(tdb
);
214 fprintf(stderr
, "rc %ld, expect_rc %ld\n", rc
, expect_rc
);
218 (abort_classes
[abort_code
] == ABORT_T_NESTED_TOO_DEEP
) ? 1 : 0;
219 rc
= __TM_is_nested_too_deep(tdb
);
223 fprintf(stderr
, "rc %ld, expect_rc %ld\n", rc
, expect_rc
);
226 expect_rc
= (abort_classes
[abort_code
] == ABORT_T_CONFLICT
) ? 1 : 0;
227 rc
= __TM_is_conflict(tdb
);
231 fprintf(stderr
, "rc %ld, expect_rc %ld\n", rc
, expect_rc
);
238 /* ---------------------------- local test functions ----------------------- */
240 /* Not a test; make sure that the involved global cachelines are reserved for
242 static int init_cache(void)
244 make_fake_tdb(&local_tdb
);
245 make_fake_tdb(&local_tdb256
);
248 global_float_1
= 1.0;
249 global_float_2
= 2.5;
250 global_float_3
= 0.0;
258 static int test_abort_classification(void)
262 make_fake_tdb(&local_tdb
);
263 for (i
= 0; i
<= 256; i
++)
267 local_tdb
.abort_code
= (uint64_t)i
;
268 rc
= check_abort_code_in_tdb(&local_tdb
, (uint64_t)i
);
278 static int test_cc_classification(void)
282 rc
= __TM_is_failure_persistent(0);
287 rc
= __TM_is_failure_persistent(1);
292 rc
= __TM_is_failure_persistent(2);
297 rc
= __TM_is_failure_persistent(3);
306 static int test_tbegin_ntstg_tend(void)
312 if ((rc
= __TM_simple_begin()) == 0)
314 __TM_non_transactional_store((uint64_t *)&counters
.c1
, 1);
321 if (counters
.c1
!= 1)
323 return 100 * counters
.c1
+ 2;
325 if (counters
.c2
!= 2)
327 return 100 * counters
.c2
+ 3;
338 static int test_tbegin_ntstg_tabort(void)
345 if (__TM_simple_begin() == 0)
347 __TM_non_transactional_store((uint64_t *)&counters
.c1
, 1);
353 if (counters
.c1
!= 1)
355 return 100 * counters
.c1
+ 2;
357 if (counters
.c2
!= 0)
359 return 100 * counters
.c2
+ 3;
369 static int test_tbegin_aborts(void)
375 if ((rc
= __TM_simple_begin()) == 0)
390 if ((rc
= __TM_simple_begin()) == 0)
404 if ((rc
= __TM_simple_begin()) == 0)
406 global_float_3
= global_float_1
+ global_float_2
;
417 if (global_float_3
!= global_float_1
+ global_float_2
)
419 return 100 * rc
+ 10;
425 static int test_tbegin_tdb(void)
429 local_tdb
.format
= 0;
430 if ((rc
= __TM_begin(&local_tdb
)) == 0)
437 if (local_tdb
.format
!= 0)
439 dump_tdb(&local_tdb
);
440 return 100 * local_tdb
.format
+ 2;
447 local_tdb
.format
= 0;
448 if ((rc
= __TM_begin(&local_tdb
)) == 0)
459 if (local_tdb
.format
!= 1)
461 dump_tdb(&local_tdb
);
462 return 100 * local_tdb
.format
+ 6;
465 local_tdb256
.format
= 0;
466 if ((rc
= __TM_begin(&local_tdb256
)) == 0)
471 return 1100 * rc
+ 1;
473 if (local_tdb256
.format
!= 0)
475 dump_tdb(&local_tdb256
);
476 return 1100 * local_tdb256
.format
+ 2;
481 return 1100 * rc
+ 3;
483 #if 1 /*!!!does not work*/
484 local_tdb256
.format
= 0;
485 if ((rc
= __TM_begin(&local_tdb256
)) == 0)
494 return 2100 * rc
+ 5;
496 if (local_tdb256
.format
!= 1)
498 dump_tdb(&local_tdb256
);
499 return 2100 * local_tdb256
.format
+ 6;
507 static int test_etnd(void)
514 make_fake_tdb(&local_tdb
);
515 local_tdb
.nesting_depth
= 0;
516 nd
= __TM_nesting_depth(&local_tdb
);
521 local_tdb
.nesting_depth
= 7;
522 nd
= __TM_nesting_depth(&local_tdb
);
527 local_tdb
.format
= 0;
528 nd
= __TM_nesting_depth(&local_tdb
);
538 if ((rc
= __TM_simple_begin()) == 0)
540 counters
.c1
= __TM_nesting_depth(0);
541 if (__TM_simple_begin() == 0)
543 counters
.c2
= __TM_nesting_depth(0);
544 if (__TM_simple_begin() == 0)
546 counters
.c3
= __TM_nesting_depth(0);
557 if (counters
.c1
!= 1)
559 return 100 * counters
.c1
+ 2;
561 if (counters
.c2
!= 2)
563 return 100 * counters
.c2
+ 3;
565 if (counters
.c3
!= 3)
567 return 100 * counters
.c3
+ 4;
573 /* ---------------------------- local testing framework functions ---------- */
575 static int run_one_test(const test_table_entry_t
*test_entry
)
583 test_entry
->required_quorum
!= 1 ||
584 test_entry
->max_repetitions
!= 1);
585 printf("RRR RUN %s\n", test_entry
->name
);
586 if (do_print_passes
== 1)
589 " (requires %d successful out of %d runs)\n",
590 test_entry
->required_quorum
,
591 test_entry
->max_repetitions
);
595 for (rc
= 0, i
= 0; i
< test_entry
->max_repetitions
; i
++)
597 if (do_print_passes
== 1)
608 rc
= test_entry
->test_func();
611 if (do_print_passes
== 1)
616 if (succeeded
>= test_entry
->required_quorum
)
623 printf(" failed (rc = %d)", rc
);
626 if (do_print_passes
== 1 || rc
!= 0)
630 if (succeeded
>= test_entry
->required_quorum
)
632 printf("+++ OK %s\n", test_entry
->name
);
638 printf("--- FAIL %s\n", test_entry
->name
);
640 return (rc
!= 0) ? rc
: -1;
644 static int run_all_tests(const test_table_entry_t
*test_table
)
646 const test_table_entry_t
*test
;
650 rc
= 0, test
= &test_table
[0];
651 test
->test_func
!= NULL
&& rc
== 0; test
++)
653 rc
= run_one_test(test
);
659 /* ---------------------------- interface functions ------------------------ */
663 const test_table_entry_t test_table
[] = {
664 TEST_NO_REP(init_cache
),
665 TEST_NO_REP(test_abort_classification
),
666 TEST_NO_REP(test_cc_classification
),
667 TEST_DF_REP(test_tbegin_ntstg_tend
),
668 TEST_DF_REP(test_tbegin_ntstg_tabort
),
669 TEST_DF_REP(test_tbegin_aborts
),
670 TEST_DF_REP(test_tbegin_tdb
),
671 TEST_DF_REP(test_etnd
),
678 rc
= run_all_tests(test_table
);