lockt.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. /*
  2. * This file is part of Jehanne.
  3. *
  4. * Copyright (C) 2015 Giacomo Tesio <giacomo@tesio.it>
  5. *
  6. * Jehanne is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, version 2 of the License.
  9. *
  10. * Jehanne is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with Jehanne. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include <u.h>
  19. #include <lib9.h>
  20. QLock rl;
  21. Rendez rStart;
  22. Rendez rCompleted;
  23. int64_t elapsedInWaiter, resInWaiter;
  24. int verbose = 0;
  25. int
  26. failOnTimeout(void *v, char *s)
  27. {
  28. if(strncmp(s, "alarm", 4) == 0){
  29. if(verbose)
  30. print("%d: noted: %s\n", getpid(), s);
  31. print("FAIL: timeout\n");
  32. exits("FAIL");
  33. }
  34. return 0;
  35. }
  36. void
  37. spawnWaiter(Lock *l)
  38. {
  39. int pid;
  40. int64_t start;
  41. switch((pid = rfork(RFMEM|RFPROC|RFNOWAIT)))
  42. {
  43. case 0:
  44. /* wait for the alwaysLocked to be locked by the main process */
  45. qlock(&rl);
  46. while(resInWaiter == 0xff)
  47. rsleep(&rStart);
  48. start = nsec();
  49. resInWaiter = lockt(l, 6000);
  50. elapsedInWaiter = (nsec() - start) / (1000 * 1000);
  51. if(verbose)
  52. print("lockt returned %d, elapsed = %d ms\n", resInWaiter, elapsedInWaiter);
  53. rwakeup(&rCompleted);
  54. qunlock(&rl);
  55. exits(0);
  56. break;
  57. case -1:
  58. print("spawnWaiter: %r\n");
  59. exits("rfork fails");
  60. break;
  61. default:
  62. if(verbose)
  63. print("spawn waiter %d\n", pid);
  64. break;
  65. }
  66. }
  67. void
  68. main(void)
  69. {
  70. int64_t start, elapsed, res;
  71. static Lock l;
  72. rfork(RFNOTEG|RFREND);
  73. rStart.l = &rl;
  74. rCompleted.l = &rl;
  75. resInWaiter = 0xff;
  76. spawnWaiter(&l);
  77. jehanne_lock(&l);
  78. alarm(20000); /* global timeout, FAIL if reached */
  79. if (!atnotify(failOnTimeout, 1)){
  80. fprint(2, "%r\n");
  81. exits("atnotify fails");
  82. }
  83. /* verify that lockt returns 0 on timeout */
  84. start = nsec();
  85. res = lockt(&l, 1000);
  86. elapsed = (nsec() - start) / (1000 * 1000);
  87. if(verbose)
  88. print("lockt returned %d, elapsed = %d ms\n", res, elapsed);
  89. if(res != 0 || elapsed < 900 || elapsed > 1300){
  90. print("FAIL: lockt timeout\n");
  91. exits("FAIL");
  92. }
  93. /* verify that lockt returns 1 if the lock is released and
  94. * it can take it
  95. */
  96. resInWaiter = -1;
  97. qlock(&rl);
  98. rwakeupall(&rStart);
  99. qunlock(&rl);
  100. sleep(1200);
  101. jehanne_unlock(&l);
  102. qlock(&rl);
  103. while(elapsedInWaiter == 0)
  104. rsleep(&rCompleted);
  105. qunlock(&rl);
  106. if(resInWaiter != 1 || elapsedInWaiter < 1100 || elapsedInWaiter > 1500){
  107. print("FAIL: lockt delayed acquisition\n");
  108. exits("FAIL");
  109. }
  110. print("PASS\n");
  111. exits("PASS");
  112. }