lock.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. #define _LOCK_EXTENSION
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include "../plan9/sys9.h"
  5. #include <lock.h>
  6. enum
  7. {
  8. Pagesize = 4096,
  9. Semperpg = Pagesize/(16*sizeof(unsigned int)),
  10. Lockaddr = 0x60000000,
  11. POWER = 0x320,
  12. MAGNUM = 0x330,
  13. MAGNUMII = 0x340,
  14. R4K = 0x500,
  15. };
  16. static int arch;
  17. extern int C_3ktas(int*);
  18. extern int C_4ktas(int*);
  19. extern int C_fcr0(void);
  20. static void
  21. lockinit(void)
  22. {
  23. int n;
  24. if(arch != 0)
  25. return; /* allow multiple calls */
  26. arch = C_fcr0();
  27. switch(arch) {
  28. case POWER:
  29. n = _SEGATTACH(0, "lock", (void*)Lockaddr, Pagesize);
  30. if(n < 0) {
  31. arch = MAGNUM;
  32. break;
  33. }
  34. memset((void*)Lockaddr, 0, Pagesize);
  35. break;
  36. case MAGNUM:
  37. case MAGNUMII:
  38. case R4K:
  39. break;
  40. default:
  41. abort();
  42. }
  43. }
  44. void
  45. lock(Lock *lk)
  46. {
  47. int *hwsem;
  48. int hash;
  49. retry:
  50. switch(arch) {
  51. case 0:
  52. lockinit();
  53. goto retry;
  54. case MAGNUM:
  55. case MAGNUMII:
  56. while(C_3ktas(&lk->val))
  57. _SLEEP(0);
  58. return;
  59. case R4K:
  60. for(;;){
  61. while(lk->val)
  62. ;
  63. if(C_4ktas(&lk->val) == 0)
  64. return;
  65. }
  66. break;
  67. case POWER:
  68. /* Use low order lock bits to generate hash */
  69. hash = ((int)lk/sizeof(int)) & (Semperpg-1);
  70. hwsem = (int*)Lockaddr+hash;
  71. for(;;) {
  72. if((*hwsem & 1) == 0) {
  73. if(lk->val)
  74. *hwsem = 0;
  75. else {
  76. lk->val = 1;
  77. *hwsem = 0;
  78. return;
  79. }
  80. }
  81. while(lk->val)
  82. ;
  83. }
  84. }
  85. }
  86. int
  87. canlock(Lock *lk)
  88. {
  89. int *hwsem;
  90. int hash;
  91. retry:
  92. switch(arch) {
  93. case 0:
  94. lockinit();
  95. goto retry;
  96. case MAGNUM:
  97. case MAGNUMII:
  98. if(C_3ktas(&lk->val))
  99. return 0;
  100. return 1;
  101. case R4K:
  102. if(C_4ktas(&lk->val))
  103. return 0;
  104. return 1;
  105. case POWER:
  106. /* Use low order lock bits to generate hash */
  107. hash = ((int)lk/sizeof(int)) & (Semperpg-1);
  108. hwsem = (int*)Lockaddr+hash;
  109. if((*hwsem & 1) == 0) {
  110. if(lk->val)
  111. *hwsem = 0;
  112. else {
  113. lk->val = 1;
  114. *hwsem = 0;
  115. return 1;
  116. }
  117. }
  118. return 0;
  119. }
  120. }
  121. void
  122. unlock(Lock *lk)
  123. {
  124. lk->val = 0;
  125. }
  126. int
  127. tas(int *p)
  128. {
  129. int *hwsem;
  130. int hash;
  131. retry:
  132. switch(arch) {
  133. case 0:
  134. lockinit();
  135. goto retry;
  136. case MAGNUM:
  137. case MAGNUMII:
  138. return C_3ktas(p);
  139. case R4K:
  140. return C_4ktas(p);
  141. case POWER:
  142. /* Use low order lock bits to generate hash */
  143. hash = ((int)p/sizeof(int)) & (Semperpg-1);
  144. hwsem = (int*)Lockaddr+hash;
  145. if((*hwsem & 1) == 0) {
  146. if(*p)
  147. *hwsem = 0;
  148. else {
  149. *p = 1;
  150. *hwsem = 0;
  151. return 0;
  152. }
  153. }
  154. return 1;
  155. }
  156. }