tm-syscall.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  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 <sys/time.h>
  16. #include <stdlib.h>
  17. #include "utils.h"
  18. #include "tm.h"
  19. extern int getppid_tm_active(void);
  20. extern int getppid_tm_suspended(void);
  21. unsigned retries = 0;
  22. #define TEST_DURATION 10 /* seconds */
  23. #define TM_RETRIES 100
  24. long failure_code(void)
  25. {
  26. return __builtin_get_texasru() >> 24;
  27. }
  28. bool failure_is_persistent(void)
  29. {
  30. return (failure_code() & TM_CAUSE_PERSISTENT) == TM_CAUSE_PERSISTENT;
  31. }
  32. bool failure_is_syscall(void)
  33. {
  34. return (failure_code() & TM_CAUSE_SYSCALL) == TM_CAUSE_SYSCALL;
  35. }
  36. pid_t getppid_tm(bool suspend)
  37. {
  38. int i;
  39. pid_t pid;
  40. for (i = 0; i < TM_RETRIES; i++) {
  41. if (suspend)
  42. pid = getppid_tm_suspended();
  43. else
  44. pid = getppid_tm_active();
  45. if (pid >= 0)
  46. return pid;
  47. if (failure_is_persistent()) {
  48. if (failure_is_syscall())
  49. return -1;
  50. printf("Unexpected persistent transaction failure.\n");
  51. printf("TEXASR 0x%016lx, TFIAR 0x%016lx.\n",
  52. __builtin_get_texasr(), __builtin_get_tfiar());
  53. exit(-1);
  54. }
  55. retries++;
  56. }
  57. printf("Exceeded limit of %d temporary transaction failures.\n", TM_RETRIES);
  58. printf("TEXASR 0x%016lx, TFIAR 0x%016lx.\n",
  59. __builtin_get_texasr(), __builtin_get_tfiar());
  60. exit(-1);
  61. }
  62. int tm_syscall(void)
  63. {
  64. unsigned count = 0;
  65. struct timeval end, now;
  66. SKIP_IF(!have_htm_nosc());
  67. setbuf(stdout, NULL);
  68. printf("Testing transactional syscalls for %d seconds...\n", TEST_DURATION);
  69. gettimeofday(&end, NULL);
  70. now.tv_sec = TEST_DURATION;
  71. now.tv_usec = 0;
  72. timeradd(&end, &now, &end);
  73. for (count = 0; timercmp(&now, &end, <); count++) {
  74. /*
  75. * Test a syscall within a suspended transaction and verify
  76. * that it succeeds.
  77. */
  78. FAIL_IF(getppid_tm(true) == -1); /* Should succeed. */
  79. /*
  80. * Test a syscall within an active transaction and verify that
  81. * it fails with the correct failure code.
  82. */
  83. FAIL_IF(getppid_tm(false) != -1); /* Should fail... */
  84. FAIL_IF(!failure_is_persistent()); /* ...persistently... */
  85. FAIL_IF(!failure_is_syscall()); /* ...with code syscall. */
  86. gettimeofday(&now, 0);
  87. }
  88. printf("%d active and suspended transactions behaved correctly.\n", count);
  89. printf("(There were %d transaction retries.)\n", retries);
  90. return 0;
  91. }
  92. int main(void)
  93. {
  94. return test_harness(tm_syscall, "tm_syscall");
  95. }