internal static unsafe StackHead *GetStackSegmentRaw(UIntPtr size, ref ThreadContext context, bool kernelAllocation, bool initialStack) { // Allocate a new chunk, making room for StackHead at the top. // If you change these constants to add more data, see the // comment about InitialStackSize at the top of this file! #if DO_TRACE_STACKS Kernel.Waypoint(667); #endif if (size == UIntPtr.Zero) { size = InitialStackSize; } size = MemoryManager.PagePad(size + sizeof(StackHead) + SafetyBufferSize); UIntPtr chunk; Process owner = Process.GetProcessByID(context.processId); // //// NOTE: here's where we should be clever about //// whether to allocate a stack chunk in the user range //// or the kernel range. Except, if we switch contexts //// during an ABI call while using a user-range stack //// segment on a paging machine, we die. Gloss over //// this hackily by always getting stack segments //// from the kernel range. //if (kernelAllocation || (owner == Process.kernelProcess)) { // chunk = MemoryManager.KernelAllocate( // MemoryManager.PagesFromBytes(size), owner, 0, PageType.Stack); //} //else { // chunk = MemoryManager.UserAllocate( // MemoryManager.PagesFromBytes(size), owner, 0, PageType.Stack); //} // UIntPtr pageCount = MemoryManager.PagesFromBytes(size); #if DEBUG_STACK_VERBOSE fixed(ThreadContext *ptr = &context) { Tracing.Log(Tracing.Debug, "GetStackSegmentRaw(ctx={0:x8},size={1:d}) pages={2} [{3:x8}..{4:x8}]", (UIntPtr)ptr, size, pageCount, context.stackLimit, context.stackBegin); } #endif chunk = MemoryManager.StackAllocate(pageCount, owner, 0, kernelAllocation, initialStack); if (chunk != UIntPtr.Zero) { // NB: We do _not_ zero out stack memory! // We assume that Bartok prevents access to prev contents. StackHead *head = (StackHead *)(chunk + size - sizeof(StackHead)); context.stackBegin = chunk + size; context.stackLimit = chunk + SafetyBufferSize; #if DEBUG_STACK_VERBOSE Tracing.Log(Tracing.Debug, "GetStackSegmentRaw(size={0:d}) -> [{1:x8}..{2:x8}]", size, context.stackLimit, context.stackBegin); #endif return(head); } else { // Stack allocation failed. In the future, we should // trigger a kernel exception; for now, we break to the // debugger. #if DEBUG_STACK_VERBOSE Tracing.Log(Tracing.Debug, "GetStackSegmentRaw: KernelAllocate failed!(siz={0:d})", size); #endif //DebugStub.Break(); return(null); } }