tm-syscall.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. /*
  2. * Copyright 2015, Sam Bobroff, IBM Corp.
  3. * Licensed under GPLv2.
  4. *
  5. * Test the kernel's system call code to ensure that a system call
  6. * made from within an active HTM transaction is aborted with the
  7. * correct failure code.
  8. * Conversely, ensure that a system call made from within a
  9. * suspended transaction can succeed.
  10. */
  11. #include <stdio.h>
  12. #include <unistd.h>
  13. #include <sys/syscall.h>
  14. #include <asm/tm.h>
  15. #include <asm/cputable.h>
  16. #include <linux/auxvec.h>
  17. #include <sys/time.h>
  18. #include <stdlib.h>
  19. #include "utils.h"
  20. extern int getppid_tm_active(void);
  21. extern int getppid_tm_suspended(void);
  22. unsigned retries = 0;
  23. #define TEST_DURATION 10 /* seconds */
  24. #define TM_RETRIES 100
  25. long failure_code(void)
  26. {
  27. return __builtin_get_texasru() >> 24;
  28. }
  29. bool failure_is_persistent(void)
  30. {
  31. return (failure_code() & TM_CAUSE_PERSISTENT) == TM_CAUSE_PERSISTENT;
  32. }
  33. bool failure_is_syscall(void)
  34. {
  35. return (failure_code() & TM_CAUSE_SYSCALL) == TM_CAUSE_SYSCALL;
  36. }
  37. pid_t getppid_tm(bool suspend)
  38. {
  39. int i;
  40. pid_t pid;
  41. for (i = 0; i < TM_RETRIES; i++) {
  42. if (suspend)
  43. pid = getppid_tm_suspended();
  44. else
  45. pid = getppid_tm_active();
  46. if (pid >= 0)
  47. return pid;
  48. if (failure_is_persistent()) {
  49. if (failure_is_syscall())
  50. return -1;
  51. printf("Unexpected persistent transaction failure.\n");
  52. printf("TEXASR 0x%016lx, TFIAR 0x%016lx.\n",
  53. __builtin_get_texasr(), __builtin_get_tfiar());
  54. exit(-1);
  55. }
  56. retries++;
  57. }
  58. printf("Exceeded limit of %d temporary transaction failures.\n", TM_RETRIES);
  59. printf("TEXASR 0x%016lx, TFIAR 0x%016lx.\n",
  60. __builtin_get_texasr(), __builtin_get_tfiar());
  61. exit(-1);
  62. }
  63. int tm_syscall(void)
  64. {
  65. unsigned count = 0;
  66. struct timeval end, now;
  67. SKIP_IF(!((long)get_auxv_entry(AT_HWCAP2)
  68. & PPC_FEATURE2_HTM_NOSC));
  69. setbuf(stdout, NULL);
  70. printf("Testing transactional syscalls for %d seconds...\n", TEST_DURATION);
  71. gettimeofday(&end, NULL);
  72. now.tv_sec = TEST_DURATION;
  73. now.tv_usec = 0;
  74. timeradd(&end, &now, &end);
  75. for (count = 0; timercmp(&now, &end, <); count++) {
  76. /*
  77. * Test a syscall within a suspended transaction and verify
  78. * that it succeeds.
  79. */
  80. FAIL_IF(getppid_tm(true) == -1); /* Should succeed. */
  81. /*
  82. * Test a syscall within an active transaction and verify that
  83. * it fails with the correct failure code.
  84. */
  85. FAIL_IF(getppid_tm(false) != -1); /* Should fail... */
  86. FAIL_IF(!failure_is_persistent()); /* ...persistently... */
  87. FAIL_IF(!failure_is_syscall()); /* ...with code syscall. */
  88. gettimeofday(&now, 0);
  89. }
  90. printf("%d active and suspended transactions behaved correctly.\n", count);
  91. printf("(There were %d transaction retries.)\n", retries);
  92. return 0;
  93. }
  94. int main(void)
  95. {
  96. return test_harness(tm_syscall, "tm_syscall");
  97. }