lock.c 2.3 KB

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