PageRenderTime 41ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/base/Kernel/Singularity/ThreadContext.cs

#
C# | 258 lines | 191 code | 24 blank | 43 comment | 9 complexity | 7fbe6e1b47f24b2e954dac99b2ba72d0 MD5 | raw file
  1. ////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Microsoft Research Singularity
  4. //
  5. // Copyright (c) Microsoft Corporation. All rights reserved.
  6. //
  7. // File: ThreadContext.cs
  8. //
  9. // Note:
  10. //
  11. namespace Microsoft.Singularity
  12. {
  13. using System;
  14. using System.Runtime.CompilerServices;
  15. using System.Runtime.InteropServices;
  16. using System.Threading;
  17. using Microsoft.Singularity.V1.Threads;
  18. using Microsoft.Singularity.Isal;
  19. [NoCCtor]
  20. [CLSCompliant(false)]
  21. [StructLayout(LayoutKind.Sequential)]
  22. [StructAlign(16)]
  23. [AccessedByRuntime("referenced from c++")]
  24. internal struct ThreadContext
  25. {
  26. [AccessedByRuntime("referenced from c++")]
  27. internal ThreadRecord threadRecord;
  28. [AccessedByRuntime("referenced from c++")]
  29. internal ushort num;
  30. [AccessedByRuntime("referenced from c++")]
  31. internal ushort regs;
  32. [AccessedByRuntime("referenced from c++")]
  33. internal unsafe ThreadContext * prev;
  34. [AccessedByRuntime("referenced from c++")]
  35. internal unsafe ThreadContext * next;
  36. [AccessedByRuntime("referenced from c++")]
  37. internal unsafe ThreadContext * prevInKern;
  38. [AccessedByRuntime("referenced from c++")]
  39. internal unsafe ThreadContext * nextInKern;
  40. [AccessedByRuntime("referenced from c++")]
  41. internal unsafe ThreadContext * prevInProc;
  42. [AccessedByRuntime("referenced from c++")]
  43. internal unsafe ThreadContext * nextInProc;
  44. [AccessedByRuntime("referenced from c++")]
  45. internal UIntPtr stackBegin;
  46. [AccessedByRuntime("referenced from c++")]
  47. internal UIntPtr stackLimit;
  48. [AccessedByRuntime("referenced from c++")]
  49. internal ushort processId;
  50. [AccessedByRuntime("referenced from c++")]
  51. internal bool uncaughtFlag; // true means "uncaught exception from process, so throw exception in kernel"
  52. [AccessedByRuntime("referenced from halforgc.asm")]
  53. internal bool suspendAlert; // true means "check whether thread should suspend"
  54. // Note: These two forks must be exactly the same size, but their
  55. // fields alias differently for kernel or process code.
  56. #if SINGULARITY_KERNEL
  57. [AccessedByRuntime("referenced from c++")]
  58. internal unsafe void *_thread;
  59. [AccessedByRuntime("referenced from c++")]
  60. internal UIntPtr processThread;
  61. [AccessedByRuntime("referenced from c++")]
  62. internal unsafe System.GCs.CallStack.TransitionRecord * stackMarkers;
  63. [AccessedByRuntime("referenced from c++")]
  64. internal unsafe System.GCs.CallStack.TransitionRecord * processMarkers;
  65. [AccessedByRuntime("referenced from c++")]
  66. internal ushort threadIndex;
  67. [AccessedByRuntime("referenced from c++")]
  68. internal ushort processThreadIndex;
  69. #elif SINGULARITY_PROCESS
  70. [AccessedByRuntime("referenced from c++")]
  71. internal UIntPtr kernelThread;
  72. [AccessedByRuntime("referenced from c++")]
  73. internal unsafe void *_thread;
  74. [AccessedByRuntime("referenced from c++")]
  75. internal unsafe System.GCs.CallStack.TransitionRecord * kernelMarkers;
  76. [AccessedByRuntime("referenced from c++")]
  77. internal unsafe System.GCs.CallStack.TransitionRecord * stackMarkers;
  78. [AccessedByRuntime("referenced from c++")]
  79. internal ushort kernelThreadIndex;
  80. [AccessedByRuntime("referenced from c++")]
  81. internal ushort threadIndex;
  82. #endif
  83. [AccessedByRuntime("referenced from halforgc.asm")]
  84. internal unsafe int gcStates;
  85. // See ThreadContext.IsInKernelMode
  86. private unsafe System.GCs.CallStack.TransitionRecord * modeMarker;
  87. #if PAGING
  88. [AccessedByRuntime("referenced from c++")]
  89. internal UIntPtr abiStackHead;
  90. [AccessedByRuntime("referenced from c++")]
  91. internal UIntPtr abiStackBegin;
  92. [AccessedByRuntime("referenced from c++")]
  93. internal UIntPtr abiStackLimit;
  94. #endif
  95. #if THREAD_TIME_ACCOUNTING
  96. [AccessedByRuntime("referenced from c++")]
  97. internal ulong lastExecutionTimeUpdate;
  98. [AccessedByRuntime("referenced from c++")]
  99. internal ulong executionTime;
  100. #endif
  101. //////////////////////////////////////////////// Methods & Properties.
  102. //
  103. internal Thread thread {
  104. [NoHeapAllocation]
  105. get { return GetThread(); }
  106. }
  107. [NoHeapAllocation]
  108. internal unsafe bool IsFirst()
  109. {
  110. return (((UIntPtr)prev) == UIntPtr.Zero);
  111. }
  112. [AccessedByRuntime("referenced from c++")]
  113. // Return true if the thread is in kernel mode, false if the
  114. // thread is in process mode.
  115. // Note that by the time this method returns, the thread might
  116. // have already switched to a different mode; in other words,
  117. // don't rely on this result of this method being up-to-date unless
  118. // the thread is suspended or blocked.
  119. [NoHeapAllocation]
  120. internal unsafe bool IsInKernelMode()
  121. {
  122. // When a thread enters process mode, RuntimeEntryPoint
  123. // sets modeMarker=processMarkers. Thus, in process mode:
  124. //
  125. // modeMarker == processMarkers
  126. //
  127. // When a thread in process mode calls the kernel, pushStackMark
  128. // pushes a child process marker onto the stack, so that
  129. // modeMarker is left pointing to the new processMarker's
  130. // parent (the old processMarker). Thus, in kernel mode:
  131. //
  132. // modeMarker == parent(processMarkers)
  133. //
  134. // This keeps the mode in sync with the process stack markers,
  135. // which is convenient though not essential. This assumes that
  136. // the only reason a process pushes a stack marker is to enter
  137. // kernel mode.
  138. //
  139. // Since processMarkers may be null, ThreadContext.ParentModeMarker
  140. // defines a special definition for parent(null).
  141. #if SINGULARITY_PROCESS
  142. System.GCs.CallStack.TransitionRecord * processMarkers =
  143. stackMarkers;
  144. #endif // SINGULARITY_PROCESS
  145. if (modeMarker == processMarkers) {
  146. return false;
  147. }
  148. else {
  149. VTable.Assert(modeMarker == ParentModeMarker(processMarkers));
  150. return true;
  151. }
  152. }
  153. [AccessedByRuntime("referenced from c++")]
  154. [NoHeapAllocation]
  155. internal unsafe void SetKernelMode()
  156. {
  157. #if SINGULARITY_PROCESS
  158. System.GCs.CallStack.TransitionRecord * processMarkers =
  159. stackMarkers;
  160. #endif // SINGULARITY_PROCESS
  161. modeMarker = ParentModeMarker(processMarkers);
  162. }
  163. [AccessedByRuntime("referenced from c++")]
  164. [NoHeapAllocation]
  165. internal unsafe void SetProcessMode()
  166. {
  167. #if SINGULARITY_PROCESS
  168. System.GCs.CallStack.TransitionRecord * processMarkers =
  169. stackMarkers;
  170. #endif // SINGULARITY_PROCESS
  171. modeMarker = processMarkers;
  172. }
  173. [NoHeapAllocation]
  174. internal bool IsRunning()
  175. {
  176. return !threadRecord.spill.IsSpilled;
  177. }
  178. [NoHeapAllocation]
  179. static private unsafe System.GCs.CallStack.TransitionRecord *
  180. ParentModeMarker(System.GCs.CallStack.TransitionRecord * child)
  181. {
  182. System.GCs.CallStack.TransitionRecord * bottom =
  183. (System.GCs.CallStack.TransitionRecord *) (-1);
  184. VTable.Assert(child != bottom);
  185. if (child == null) {
  186. return bottom;
  187. }
  188. else {
  189. return child->oldTransitionRecord;
  190. }
  191. }
  192. //////////////////////////////////////////////////// External Methods.
  193. //
  194. [AccessedByRuntime("output to header: defined in c++")]
  195. [MethodImpl(MethodImplOptions.InternalCall)]
  196. [StackBound(32)]
  197. [NoHeapAllocation]
  198. private extern Thread GetThread();
  199. [AccessedByRuntime("output to header: defined in c++")]
  200. [MethodImpl(MethodImplOptions.InternalCall)]
  201. [StackBound(32)]
  202. [NoHeapAllocation]
  203. internal extern void UpdateAfterGC(Thread thread);
  204. #if SINGULARITY_KERNEL
  205. [AccessedByRuntime("output to header: defined in c++")]
  206. [MethodImpl(MethodImplOptions.InternalCall)]
  207. [GCAnnotation(GCOption.NOGC)]
  208. [StackBound(32)]
  209. [NoHeapAllocation]
  210. internal extern void Initialize(int threadIndex, UIntPtr stackBegin, uint cr3);
  211. [AccessedByRuntime("output to header: defined in c++")]
  212. [MethodImpl(MethodImplOptions.InternalCall)]
  213. [GCAnnotation(GCOption.NOGC)]
  214. [StackBound(32)]
  215. [NoHeapAllocation]
  216. internal extern void InitializeIdle(int threadIndex, UIntPtr stackBegin, uint cr3);
  217. #endif
  218. }
  219. }
  220. // This is a temporary workaround to get around bartok assumptions
  221. namespace Microsoft.Singularity.X86
  222. {
  223. using System.Runtime.CompilerServices;
  224. struct ProcessorContext
  225. {
  226. [RequiredByBartok]
  227. Microsoft.Singularity.X86.ThreadContext threadContext;
  228. }
  229. struct ThreadContext
  230. {
  231. [RequiredByBartok]
  232. System.UIntPtr stackLimit;
  233. }
  234. }