Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

291 lines
17 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. icecap.c
  5. Abstract:
  6. Macro definitions for manually-inserted icecap probes
  7. Author:
  8. Rick Vicik (rickv) 10-Aug-2001
  9. Revision History:
  10. --*/
  11. #ifdef _CAPKERN
  12. PublicFunction(_CAP_Start_Profiling2)
  13. PublicFunction(_CAP_End_Profiling2)
  14. #define CAPSTART(parent,child) \
  15. movl out0 = @fptr(parent) ;\
  16. movl out1 = @fptr(child) ;\
  17. br.call.sptk.few b0=_CAP_Start_Profiling2;;
  18. #define CAPEND(parent) \
  19. movl out0 = @fptr(parent) ;\
  20. br.call.sptk.few b0=_CAP_End_Profiling2;;
  21. #ifdef CAPKERN_SYNCH_POINTS
  22. #define REC1INTSIZE 32
  23. #define REC2INTSIZE 40
  24. .global BBTBuffer
  25. //
  26. // Kernel Icecap logs to Perfmem (BBTBuffer) using the following format:
  27. //
  28. // BBTBuffer[0] contains the length in pages (4k or 8k)
  29. // BBTBuffer[1] is a flagword: 1 = trace
  30. // 2 = RDPMD4
  31. // 4 = user stack dump
  32. // BBTBuffer[2] is ptr to beginning of cpu0 buffer
  33. // BBTBuffer[3] is ptr to beginning of cpu1 buffer (also end of cpu0 buffer)
  34. // BBTBuffer[4] is ptr to beginning of cpu2 buffer (also end of cpu1 buffer)
  35. // ...
  36. // BBTBuffer[n+2] is ptr to beginning of cpu 'n' buffer (also end of cpu 'n-1' buffer)
  37. // BBTBuffer[n+3] is ptr the end of cpu 'n' buffer
  38. //
  39. // The area starting with &BBTBuffer[n+4] is divided into private buffers
  40. // for each cpu. The first dword in each cpu-private buffer points to the
  41. // beginning of freespace in that buffer. Each one is initialized to point
  42. // just after itself. Space is claimed using lock xadd on that dword.
  43. // If the resulting value points beyond the beginning of the next cpu's
  44. // buffer, this buffer is considered full and nothing further is logged.
  45. // Each cpu's freespace pointer is in a separate cacheline.
  46. // both of these macros mutate the tmp? register arguments and the ar.ccv register
  47. #define CAPSPINLOG1INT(data, spare, tmp1, tmp2, tmp3, tmp4, tmpp) \
  48. ;; \
  49. movl tmp1 = BBTBuffer ;\
  50. ;; \
  51. ld8 tmp1 = [tmp1] /* tmp1 = ptr to BBTBuffer*/ ;\
  52. ;; \
  53. cmp.eq tmpp = r0, tmp1 ;\
  54. (tmpp) br.cond.dpnt.few ENDCAPSPINLOG1INT@__LINE__ ;\
  55. adds tmp2 = 8, tmp1 ;\
  56. ;; \
  57. ld8 tmp2 = [tmp2] /* tmp2 = BBTBuffer[1] */ ;\
  58. ;; \
  59. tbit.z tmpp = tmp2, 0 ;\
  60. (tmpp) br.cond.dpnt.few ENDCAPSPINLOG1INT@__LINE__ ;\
  61. movl tmp3 = KiPcr + PcNumber ;\
  62. ;; \
  63. ld1 tmp3 = [tmp3] /* tmp3 = 1 byte cpu# */ ;\
  64. ;; \
  65. add tmp3 = 2, tmp3 ;\
  66. ;; \
  67. shladd tmp3 = tmp3, 3, tmp1 /* tmp3 = &BBTBuffer[cpu# + 2] */ ;\
  68. ;; \
  69. ld8 tmp1 = [tmp3] /* tmp1 = BBTBuffer[cpu# + 2] (&freeptr) */ ;\
  70. add tmp2 = 8, tmp3 ;\
  71. ;; \
  72. cmp.eq tmpp = r0, tmp1 ;\
  73. ld8 tmp3 = [tmp1] /* tmp3 = BBTBuffer[cpu#+2][0] (freeptr) */ ;\
  74. ld8 tmp2 = [tmp2] /* tmp2 = BBTBuffer[(cpu#+1)+2] (beginnextbuf) */ ;\
  75. (tmpp) br.cond.dpnt.few ENDCAPSPINLOG1INT@__LINE__ ;\
  76. ;; \
  77. cmp.gtu tmpp = tmp3, tmp2 ;\
  78. (tmpp) br.cond.dpnt.few ENDCAPSPINLOG1INT@__LINE__ ;\
  79. ;; \
  80. RETRYCAPSPINLOG1INT@__LINE__: \
  81. ld8 tmp3 = [tmp1] /* tmp3 = reloaded freeptr */ ;\
  82. ;; \
  83. mov.m ar.ccv = tmp3 /* only exchange on our loaded freeptr */ ;\
  84. add tmp4 = REC1INTSIZE, tmp3 /* new freeptr val */ ;\
  85. ;; \
  86. cmpxchg8.acq tmp4=[tmp1], tmp4, ar.ccv /* tmp4 = freeptr before xchng */ ;\
  87. ;; \
  88. cmp.ne tmpp = tmp4, tmp3 /* if cmpxchg failed, retry */ ;\
  89. (tmpp) br.cond.dpnt.few RETRYCAPSPINLOG1INT@__LINE__ ;\
  90. add tmp1 = REC1INTSIZE, tmp4 /* tmp1 = end of record */ ;\
  91. add tmp3 = 8, tmp4 /* tmp3 = 8 bytes into record */ ;\
  92. ;; \
  93. cmp.geu tmpp = tmp1, tmp2 /* check if end of record is within buf */ ;\
  94. (tmpp) br.cond.dpnt.few ENDCAPSPINLOG1INT@__LINE__ ;\
  95. movl tmp2 = (REC1INTSIZE - 4)<<16 ;\
  96. ;; \
  97. add tmp2 = 16|(spare<<8), tmp2 ;\
  98. ;; \
  99. st8 [tmp4] = tmp2, 16 /* store type(16),spare,size */ ;\
  100. mov.m tmp1 = ar.itc ;\
  101. ;; \
  102. st8 [tmp3] = tmp1 /* store TS */ ;\
  103. st8 [tmp4] = data, 8 /* store data */ ;\
  104. mov tmp3 = brp ;\
  105. ;; \
  106. st8 [tmp4] = tmp3 ;\
  107. ;; \
  108. ENDCAPSPINLOG1INT@__LINE__:
  109. #define CAPSPINLOG2INT(data1, data2, spare, tmp1, tmp2, tmp3, tmp4, tmpp) \
  110. ;; \
  111. movl tmp1 = BBTBuffer ;\
  112. ;; \
  113. ld8 tmp1 = [tmp1] ;\
  114. ;; \
  115. cmp.eq tmpp = r0, tmp1 ;\
  116. (tmpp) br.cond.dpnt.few ENDCAPSPINLOG2INT@__LINE__ ;\
  117. adds tmp2 = 8, tmp1 ;\
  118. ;; \
  119. ld8 tmp2 = [tmp2] ;\
  120. ;; \
  121. tbit.z tmpp = tmp2, 0 ;\
  122. (tmpp) br.cond.dpnt.few ENDCAPSPINLOG2INT@__LINE__ ;\
  123. movl tmp3 = KiPcr + PcNumber ;\
  124. ;; \
  125. ld1 tmp3 = [tmp3] ;\
  126. ;; \
  127. add tmp3 = 2, tmp3 ;\
  128. ;; \
  129. shladd tmp3 = tmp3, 3, tmp1 ;\
  130. ;; \
  131. ld8 tmp1 = [tmp3] ;\
  132. add tmp2 = 8, tmp3 ;\
  133. ;; \
  134. cmp.eq tmpp = r0, tmp1 ;\
  135. ld8 tmp3 = [tmp1] ;\
  136. ld8 tmp2 = [tmp2] ;\
  137. (tmpp) br.cond.dpnt.few ENDCAPSPINLOG2INT@__LINE__ ;\
  138. ;; \
  139. cmp.gtu tmpp = tmp3, tmp2 ;\
  140. (tmpp) br.cond.dpnt.few ENDCAPSPINLOG2INT@__LINE__ ;\
  141. ;; \
  142. RETRYCAPSPINLOG2INT@__LINE__: \
  143. ld8 tmp3 = [tmp1] ;\
  144. ;; \
  145. mov.m ar.ccv = tmp3 ;\
  146. add tmp4 = REC2INTSIZE, tmp3 ;\
  147. ;; \
  148. cmpxchg8.acq tmp4=[tmp1], tmp4, ar.ccv ;\
  149. ;; \
  150. cmp.ne tmpp = tmp4, tmp3 ;\
  151. (tmpp) br.cond.dpnt.few RETRYCAPSPINLOG2INT@__LINE__ ;\
  152. add tmp1 = REC2INTSIZE, tmp4 ;\
  153. ;; \
  154. cmp.geu tmpp = tmp1, tmp2 ;\
  155. (tmpp) br.cond.dpnt.few ENDCAPSPINLOG2INT@__LINE__ ;\
  156. movl tmp2 = (REC2INTSIZE - 4)<<16 ;\
  157. ;; \
  158. add tmp2 = 16|(spare<<8), tmp2 ;\
  159. add tmp3 = 16, tmp4 ;\
  160. ;; \
  161. st8 [tmp4] = tmp2, 8 ;\
  162. st8 [tmp3] = data1, 8 ;\
  163. mov.m tmp1 = ar.itc ;\
  164. ;; \
  165. st8 [tmp4] = tmp1 ;\
  166. st8 [tmp3] = data2, 8 ;\
  167. mov tmp4 = brp ;\
  168. ;; \
  169. st8 [tmp3] = tmp4 ;\
  170. ;; \
  171. ENDCAPSPINLOG2INT@__LINE__:
  172. //++
  173. // Routine:
  174. //
  175. // CAP_ACQUIRE_SPINLOCK(rpLock, rOwn, Loop)
  176. //
  177. // Routine Description:
  178. //
  179. // Acquire a spinlock. Waits for lock to become free
  180. // by spinning on the cached lock value.
  181. //
  182. // Agruments:
  183. //
  184. // rpLock: pointer to the spinlock (64-bit)
  185. // rOwn: value to store in lock to indicate owner
  186. // Depending on call location, it could be:
  187. // - rpLock
  188. // - pointer to process
  189. // - pointer to thread
  190. // - pointer to PRCB
  191. // Loop: unique name for loop label
  192. //
  193. // Return Value:
  194. //
  195. // None
  196. //
  197. // Notes:
  198. //
  199. // Uses temporaries: predicates pt0, pt1, pt2, and GR t22.
  200. //--
  201. #define CAP_ACQUIRE_SPINLOCK(rpLock, rOwn, Loop, rCounter, temp1, temp2, temp3) \
  202. cmp##.##eq pt0, pt1 = zero, zero ;\
  203. cmp##.##eq pt2 = zero, zero ;\
  204. mov rCounter = -1 ;\
  205. ;; ;\
  206. Loop: ;\
  207. .pred.rel "mutex",pt0,pt1 ;\
  208. (pt1) YIELD ;\
  209. (pt0) xchg8 t22 = [rpLock], rOwn ;\
  210. (pt1) ld8##.##nt1 t22 = [rpLock] ;\
  211. ;; ;\
  212. (pt0) cmp##.##ne pt2 = zero, t22 ;\
  213. cmp##.##eq pt0, pt1 = zero, t22 ;\
  214. add rCounter = 1, rCounter ;\
  215. (pt2) br##.##dpnt Loop ;\
  216. ;; ;\
  217. CAPSPINLOG1INT(rpLock, 1, t22, temp1, temp2, temp3, pt2) ;\
  218. cmp##.##eq pt2 = zero, rCounter ;\
  219. (pt2) br##.##cond##.##sptk CAP_SKIP_COLL_LOG@__LINE__ ;\
  220. CAPSPINLOG2INT(rCounter, rpLock, 2, t22, temp1, temp2, temp3, pt2) ;\
  221. CAP_SKIP_COLL_LOG@__LINE__:
  222. //++
  223. // Routine:
  224. //
  225. // CAP_RELEASE_SPINLOCK(rpLock)
  226. //
  227. // Routine Description:
  228. //
  229. // Release a spinlock by setting lock to zero.
  230. //
  231. // Agruments:
  232. //
  233. // rpLock: pointer to the spinlock.
  234. //
  235. // Return Value:
  236. //
  237. // None
  238. //
  239. // Notes:
  240. //
  241. // Uses an ordered store to ensure previous memory accesses in
  242. // critical section complete.
  243. //--
  244. #define CAP_RELEASE_SPINLOCK(rpLock, temp1, temp2, temp3, temp4, tempp) \
  245. st8##.##rel [rpLock] = zero ;\
  246. CAPSPINLOG1INT(rpLock, 7, temp1, temp2, temp3, temp4, tempp)
  247. #endif //CAPKERN_SYNCH_POINTS
  248. #else //!defined(_CAPKERN)
  249. #define CAPSTART(parent,child)
  250. #define CAPEND(parent)
  251. #endif