Ejemplo n.º 1
0
        internal static unsafe void ReturnStackSegmentRawCommon(ref ThreadContext context,
                                                                bool kernelAllocation,
                                                                bool initialStack)
        {
            UIntPtr begin = context.stackBegin;
            UIntPtr limit = context.stackLimit;

            StackHead *head = (StackHead *)(begin - sizeof(StackHead));

#if DO_TRACE_STACKS
            Kernel.Waypoint(669);
#endif

            UIntPtr addr = limit - SafetyBufferSize;
            UIntPtr size = begin - limit + SafetyBufferSize;

#if DEBUG_STACK_VERBOSE
            fixed(ThreadContext *ptr = &context)
            {
                Tracing.Log(Tracing.Debug,
                            "ReturnStackSegmentRaw(ctx={0:x8}) [{1:x8}..{2:x8}]\n",
                            (UIntPtr)ptr, context.stackLimit, context.stackBegin);
            }
#endif

#if !PAGING
            context.stackBegin = head->prevBegin;
            context.stackLimit = head->prevLimit;
#else
            //context.stackBegin = head->prevBegin;
            //context.stackLimit = head->prevLimit;
            // Moved below, because of the following scenario:
            //   - call UnlinkStack
            //   - UnlinkStack switches to the scheduler stack
            //   - UnlinkStack calls ReturnStackSegmentRaw, which calls
            //     various other methods
            //   - one of the other methods invokes write barrier code
            //   - the write barrier code performs a stack link check
            //   - If context.stackLimit is already set to head->prevLimit,
            //     then it may appear that we're out of stack space,
            //     even if we're really not, so we jump to LinkStack
            //   - LinkStack overwrites the scheduler stack
            // TODO: really fix this.
            UIntPtr stackBegin = head->prevBegin;
            UIntPtr stackLimit = head->prevLimit;
#endif

            Process owner = Process.GetProcessByID(context.processId);
            //
            //// See note above in GetStackSegmentRaw
            //if ((owner != Process.kernelProcess) &&
            //(addr >= BootInfo.KERNEL_BOUNDARY)) {
            //MemoryManager.UserFree(addr, MemoryManager.PagesFromBytes(size), owner);
            //}
            //else {
            //MemoryManager.KernelFree(addr, MemoryManager.PagesFromBytes(size), owner);
            //}
            //
            MemoryManager.StackFree(addr, MemoryManager.PagesFromBytes(size), owner, kernelAllocation, initialStack);

#if PAGING
            // See comments above.
            context.stackBegin = stackBegin;
            context.stackLimit = stackLimit;
#endif

#if DEBUG_STACK_VERBOSE
            Tracing.Log(Tracing.Debug,
                        "ReturnStackSegment({0:x8}, {1:x8}) [{2:x8}..{3:x8}]\n",
                        addr, size, context.stackLimit, context.stackBegin);
#endif
        }