159 lines
3.4 KiB
C
159 lines
3.4 KiB
C
/*++
|
||
|
||
Copyright (c) 1990 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
context.c
|
||
|
||
Abstract:
|
||
|
||
This module contains the context management routines for
|
||
Win32
|
||
|
||
Author:
|
||
|
||
Mark Lucovsky (markl) 28-Sep-1990
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include "basedll.h"
|
||
#pragma hdrstop
|
||
|
||
#define _KXPPC_C_HEADER_
|
||
#include "kxppc.h"
|
||
|
||
|
||
VOID
|
||
BaseInitializeContext(
|
||
OUT PCONTEXT Context,
|
||
IN PVOID Parameter OPTIONAL,
|
||
IN PVOID InitialPc OPTIONAL,
|
||
IN PVOID InitialSp OPTIONAL,
|
||
IN BASE_CONTEXT_TYPE ContextType
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function initializes a context structure so that it can
|
||
be used in a subsequent call to NtCreateThread.
|
||
|
||
Arguments:
|
||
|
||
Context - Supplies a context buffer to be initialized by this routine.
|
||
|
||
Parameter - Supplies the thread's parameter.
|
||
|
||
InitialPc - Supplies an initial program counter value.
|
||
|
||
InitialSp - Supplies an initial stack pointer value.
|
||
|
||
NewThread - Supplies a flag that specifies that this is a new
|
||
thread, or a new process.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
//
|
||
// Initialize the control registers.
|
||
// So that the thread begins at BaseThreadStart
|
||
//
|
||
|
||
RtlZeroMemory((PVOID)Context, sizeof(CONTEXT));
|
||
|
||
//
|
||
// Initialize the control registers.
|
||
//
|
||
Context->Gpr1 = (ULONG)InitialSp - STK_MIN_FRAME;
|
||
|
||
//
|
||
// While we may not NEED to set the ILE bit in the context's
|
||
// MSR, it is always safest to do so ...
|
||
//
|
||
Context->Msr =
|
||
MASK_SPR(MSR_ILE,1) |
|
||
MASK_SPR(MSR_FP,1) |
|
||
MASK_SPR(MSR_FE0,1) |
|
||
MASK_SPR(MSR_FE1,1) |
|
||
MASK_SPR(MSR_ME,1) |
|
||
MASK_SPR(MSR_IR,1) |
|
||
MASK_SPR(MSR_DR,1) |
|
||
MASK_SPR(MSR_PR,1) |
|
||
MASK_SPR(MSR_LE,1);
|
||
|
||
//
|
||
// Set the initial context of the thread in a machine specific way.
|
||
//
|
||
// For threads, we put in Iar the function descriptor address for
|
||
// BaseProcessStart or BaseThreadStart, not the function entry point
|
||
// address. This works because LdrInitializeThunk translates the
|
||
// descriptor into an entry point address and a TOC pointer before
|
||
// allowing the thread to run.
|
||
//
|
||
// For fibers, we put in Iar the actual entry point address for
|
||
// BaseFiberStart. This is because the fiber will first run via
|
||
// SwitchToFiber, which needs an entry point, because subsequent
|
||
// switches to the fiber only have a return address.
|
||
//
|
||
// (Note that we don't need to worry about the TOC pointer for
|
||
// BaseFiberStart because it's entered from SwitchToFiber, and
|
||
// SwitchToFiber and BaseThreadStart use the same TOC.)
|
||
//
|
||
|
||
Context->ContextFlags = CONTEXT_FULL;
|
||
|
||
Context->Gpr3 = (ULONG)InitialPc;
|
||
|
||
if ( ContextType == BaseContextTypeProcess ) {
|
||
Context->Iar = (ULONG)BaseProcessStart;
|
||
} else {
|
||
if ( ContextType == BaseContextTypeThread ) {
|
||
Context->Iar = (ULONG)BaseThreadStart;
|
||
} else {
|
||
Context->Iar = *(ULONG *)BaseFiberStart;
|
||
}
|
||
Context->Gpr4 = (ULONG)Parameter;
|
||
}
|
||
}
|
||
|
||
VOID
|
||
BaseFiberStart(
|
||
VOID
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function is called to start a Win32 fiber. Its purpose
|
||
is to call BaseThreadStart, getting the necessary arguments
|
||
from the fiber context record.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
PFIBER Fiber;
|
||
|
||
Fiber = GetCurrentFiber();
|
||
BaseThreadStart( (LPTHREAD_START_ROUTINE)Fiber->FiberContext.Gpr3,
|
||
(LPVOID)Fiber->FiberContext.Gpr4 );
|
||
}
|
||
|