mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 01:55:19 +00:00
- 4th out of 5 patch part of ROSRTL removal. This touches fibers:
* Support SxS when available (add new fiber member for this as well). * Support FLS when available. * Added new Fiber Members for new features in XP/2003 (GuaranteedStackBytes and FlsData) * Support FPU State Restore/Save in switch code. * Use new common stack/context initialization routines instead of ROSRTL. * Change Fiber structure to use CONTEXT directly in order to speed up and generalize context creation. * Fix BaseFiberStartup to send right parameters. Note: not yet fully tested with fibertest, I will do this later today and fix any bugs. svn path=/trunk/; revision=16650
This commit is contained in:
parent
22ef1b4558
commit
73e69c9d9e
3 changed files with 325 additions and 335 deletions
|
@ -1,297 +1,251 @@
|
|||
/* $Id$
|
||||
*
|
||||
* FILE: lib/kernel32/thread/fiber.c
|
||||
*
|
||||
* ReactOS Kernel32.dll
|
||||
*
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS System Libraries
|
||||
* FILE: lib/kernel32/thread/fiber.c
|
||||
* PURPOSE: Fiber Implementation
|
||||
* PROGRAMMERS:
|
||||
* Alex Ionescu (alex@relsoft.net)
|
||||
* KJK::Hyperion <noog@libero.it>
|
||||
*/
|
||||
#include <k32.h>
|
||||
|
||||
/* FIXME */
|
||||
#include <rosrtl/thread.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include "../include/debug.h"
|
||||
|
||||
struct _FIBER /* Field offsets: */
|
||||
{ /* 32 bit 64 bit */
|
||||
/* this must be the first field */
|
||||
LPVOID Parameter; /* 0x00 0x00 */
|
||||
|
||||
struct _EXCEPTION_REGISTRATION_RECORD * ExceptionList; /* 0x04 0x08 */
|
||||
LPVOID StackBase; /* 0x08 0x10 */
|
||||
LPVOID StackLimit; /* 0x0C 0x18 */
|
||||
LPVOID DeallocationStack; /* 0x10 0x20 */
|
||||
ULONG_PTR Flags; /* 0x14 0x28 */
|
||||
#if defined(_M_IX86)
|
||||
/* control flow registers */
|
||||
DWORD Eip; /* 0x18 ---- */
|
||||
DWORD Esp; /* 0x1C ---- */
|
||||
DWORD Ebp; /* 0x20 ---- */
|
||||
|
||||
/* general-purpose registers that must be preserved across calls */
|
||||
DWORD Ebx; /* 0x24 ---- */
|
||||
DWORD Esi; /* 0x28 ---- */
|
||||
DWORD Edi; /* 0x2C ---- */
|
||||
|
||||
/* floating point save area (optional) */
|
||||
FLOATING_SAVE_AREA FloatSave; /* 0x30 ---- */
|
||||
#else
|
||||
#error Unspecified or unsupported architecture.
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef struct _FIBER FIBER, * PFIBER;
|
||||
|
||||
__declspec(noreturn) void WINAPI FiberStartup(PVOID lpStartAddress);
|
||||
typedef struct _FIBER /* Field offsets: */
|
||||
{ /* 32 bit 64 bit */
|
||||
/* this must be the first field */
|
||||
LPVOID Parameter; /* 0x00 0x00 */
|
||||
struct _EXCEPTION_REGISTRATION_RECORD * ExceptionList; /* 0x04 0x08 */
|
||||
LPVOID StackBase; /* 0x08 0x10 */
|
||||
LPVOID StackLimit; /* 0x0C 0x18 */
|
||||
LPVOID DeallocationStack; /* 0x10 0x20 */
|
||||
CONTEXT Context; /* 0x14 0x28 */
|
||||
ULONG GuaranteedStackBytes; /* 0x2E0 */
|
||||
PVOID FlsData; /* 0x2E4 */
|
||||
PVOID ActivationContextStack; /* 0x2E8 */
|
||||
} FIBER, *PFIBER;
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
BOOL WINAPI ConvertFiberToThread(void)
|
||||
BOOL
|
||||
WINAPI
|
||||
ConvertFiberToThread(VOID)
|
||||
{
|
||||
PTEB pTeb = NtCurrentTeb();
|
||||
PTEB pTeb = NtCurrentTeb();
|
||||
DPRINT1("Converting Fiber to Thread\n");
|
||||
|
||||
/* the current thread isn't running a fiber: failure */
|
||||
if(!pTeb->HasFiberData)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
/* the current thread isn't running a fiber: failure */
|
||||
if(!pTeb->HasFiberData)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* this thread won't run a fiber anymore */
|
||||
pTeb->HasFiberData = FALSE;
|
||||
/* this thread won't run a fiber anymore */
|
||||
pTeb->HasFiberData = FALSE;
|
||||
|
||||
/* free the fiber */
|
||||
if(pTeb->Tib.FiberData != NULL)
|
||||
RtlFreeHeap(pTeb->ProcessEnvironmentBlock->ProcessHeap, 0, pTeb->Tib.FiberData);
|
||||
/* free the fiber */
|
||||
if(pTeb->Tib.FiberData != NULL)
|
||||
{
|
||||
RtlFreeHeap(GetProcessHeap(), 0, pTeb->Tib.FiberData);
|
||||
}
|
||||
|
||||
/* success */
|
||||
return TRUE;
|
||||
/* success */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
LPVOID WINAPI ConvertThreadToFiberEx(LPVOID lpParameter, DWORD dwFlags)
|
||||
LPVOID
|
||||
WINAPI
|
||||
ConvertThreadToFiberEx(LPVOID lpParameter,
|
||||
DWORD dwFlags)
|
||||
{
|
||||
PTEB pTeb = NtCurrentTeb();
|
||||
PFIBER pfCurFiber;
|
||||
PTEB pTeb = NtCurrentTeb();
|
||||
PFIBER pfCurFiber;
|
||||
DPRINT1("Converting Thread to Fiber\n");
|
||||
|
||||
/* the current thread is already a fiber */
|
||||
if(pTeb->HasFiberData && pTeb->Tib.FiberData) return pTeb->Tib.FiberData;
|
||||
/* the current thread is already a fiber */
|
||||
if(pTeb->HasFiberData && pTeb->Tib.FiberData) return pTeb->Tib.FiberData;
|
||||
|
||||
/* allocate the fiber */
|
||||
pfCurFiber = (PFIBER)RtlAllocateHeap(pTeb->ProcessEnvironmentBlock->ProcessHeap, 0, sizeof(FIBER));
|
||||
/* allocate the fiber */
|
||||
pfCurFiber = (PFIBER)RtlAllocateHeap(GetProcessHeap(),
|
||||
0,
|
||||
sizeof(FIBER));
|
||||
|
||||
/* failure */
|
||||
if(pfCurFiber == NULL)
|
||||
{
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
return NULL;
|
||||
}
|
||||
/* failure */
|
||||
if(pfCurFiber == NULL)
|
||||
{
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pfCurFiber->Parameter = lpParameter;
|
||||
pfCurFiber->Flags = dwFlags;
|
||||
/* copy some contextual data from the thread to the fiber */
|
||||
pfCurFiber->ExceptionList = pTeb->Tib.ExceptionList;
|
||||
pfCurFiber->StackBase = pTeb->Tib.StackBase;
|
||||
pfCurFiber->StackLimit = pTeb->Tib.StackLimit;
|
||||
pfCurFiber->DeallocationStack = pTeb->DeallocationStack;
|
||||
pfCurFiber->FlsData = pTeb->FlsData;
|
||||
pfCurFiber->GuaranteedStackBytes = pTeb->GuaranteedStackBytes;
|
||||
pfCurFiber->ActivationContextStack = pTeb->ActivationContextStackPointer;
|
||||
pfCurFiber->Context.ContextFlags = CONTEXT_FULL;
|
||||
|
||||
/* Save FPU State if requsted */
|
||||
if (dwFlags & FIBER_FLAG_FLOAT_SWITCH)
|
||||
{
|
||||
pfCurFiber->Context.ContextFlags |= CONTEXT_FLOATING_POINT;
|
||||
}
|
||||
|
||||
/* copy some contextual data from the thread to the fiber */
|
||||
pfCurFiber->ExceptionList = pTeb->Tib.ExceptionList;
|
||||
pfCurFiber->StackBase = pTeb->Tib.StackBase;
|
||||
pfCurFiber->StackLimit = pTeb->Tib.StackLimit;
|
||||
pfCurFiber->DeallocationStack = pTeb->DeallocationStack;
|
||||
/* associate the fiber to the current thread */
|
||||
pTeb->Tib.FiberData = pfCurFiber;
|
||||
pTeb->HasFiberData = TRUE;
|
||||
|
||||
/* associate the fiber to the current thread */
|
||||
pTeb->Tib.FiberData = pfCurFiber;
|
||||
pTeb->HasFiberData = TRUE;
|
||||
|
||||
/* success */
|
||||
return (LPVOID)pfCurFiber;
|
||||
/* success */
|
||||
return (LPVOID)pfCurFiber;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
LPVOID WINAPI ConvertThreadToFiber(LPVOID lpParameter)
|
||||
LPVOID
|
||||
WINAPI
|
||||
ConvertThreadToFiber(LPVOID lpParameter)
|
||||
{
|
||||
return ConvertThreadToFiberEx(lpParameter, 0);
|
||||
/* Call the newer function */
|
||||
return ConvertThreadToFiberEx(lpParameter, 0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
LPVOID WINAPI CreateFiber
|
||||
(
|
||||
SIZE_T dwStackSize,
|
||||
LPFIBER_START_ROUTINE lpStartAddress,
|
||||
LPVOID lpParameter
|
||||
)
|
||||
LPVOID
|
||||
WINAPI
|
||||
CreateFiber(SIZE_T dwStackSize,
|
||||
LPFIBER_START_ROUTINE lpStartAddress,
|
||||
LPVOID lpParameter)
|
||||
{
|
||||
return CreateFiberEx(dwStackSize, 0, 0, lpStartAddress, lpParameter);
|
||||
/* Call the Newer Function */
|
||||
return CreateFiberEx(dwStackSize, 0, 0, lpStartAddress, lpParameter);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
LPVOID WINAPI CreateFiberEx
|
||||
(
|
||||
SIZE_T dwStackCommitSize,
|
||||
SIZE_T dwStackReserveSize,
|
||||
DWORD dwFlags,
|
||||
LPFIBER_START_ROUTINE lpStartAddress,
|
||||
LPVOID lpParameter
|
||||
)
|
||||
LPVOID
|
||||
WINAPI
|
||||
CreateFiberEx(SIZE_T dwStackCommitSize,
|
||||
SIZE_T dwStackReserveSize,
|
||||
DWORD dwFlags,
|
||||
LPFIBER_START_ROUTINE lpStartAddress,
|
||||
LPVOID lpParameter)
|
||||
{
|
||||
PFIBER pfCurFiber;
|
||||
NTSTATUS nErrCode;
|
||||
PSIZE_T pnStackReserve = NULL;
|
||||
PSIZE_T pnStackCommit = NULL;
|
||||
INITIAL_TEB usFiberInitialTeb;
|
||||
CONTEXT ctxFiberContext;
|
||||
PTEB pTeb = NtCurrentTeb();
|
||||
PFIBER pfCurFiber;
|
||||
NTSTATUS nErrCode;
|
||||
INITIAL_TEB usFiberInitialTeb;
|
||||
CONTEXT ctxFiberContext;
|
||||
PVOID ActivationContextStack = NULL;
|
||||
DPRINT1("Creating Fiber\n");
|
||||
|
||||
/* allocate the fiber */
|
||||
pfCurFiber = (PFIBER)RtlAllocateHeap(pTeb->ProcessEnvironmentBlock->ProcessHeap, 0, sizeof(FIBER));
|
||||
#ifdef SXS_SUPPORT_ENABLED
|
||||
/* Allocate the Activation Context Stack */
|
||||
nErrCode = RtlAllocateActivationContextStack(&ActivationContextStack);
|
||||
#endif
|
||||
|
||||
/* Allocate the fiber */
|
||||
pfCurFiber = (PFIBER)RtlAllocateHeap(GetProcessHeap(),
|
||||
0,
|
||||
sizeof(FIBER));
|
||||
/* Failure */
|
||||
if(pfCurFiber == NULL)
|
||||
{
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* failure */
|
||||
if(pfCurFiber == NULL)
|
||||
{
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
return NULL;
|
||||
}
|
||||
/* Create the stack for the fiber */
|
||||
nErrCode = BasepCreateStack(NtCurrentProcess(),
|
||||
dwStackCommitSize,
|
||||
dwStackReserveSize,
|
||||
&usFiberInitialTeb);
|
||||
/* Failure */
|
||||
if(!NT_SUCCESS(nErrCode))
|
||||
{
|
||||
/* Free the fiber */
|
||||
RtlFreeHeap(GetProcessHeap(), 0, pfCurFiber);
|
||||
|
||||
/* if the stack reserve or commit size weren't specified, use defaults */
|
||||
if(dwStackReserveSize > 0) pnStackReserve = &dwStackReserveSize;
|
||||
if(dwStackCommitSize > 0) pnStackCommit = &dwStackCommitSize;
|
||||
|
||||
/* create the stack for the fiber */
|
||||
nErrCode = RtlRosCreateStack
|
||||
(
|
||||
NtCurrentProcess(),
|
||||
&usFiberInitialTeb,
|
||||
0,
|
||||
pnStackReserve,
|
||||
pnStackCommit
|
||||
);
|
||||
|
||||
/* failure */
|
||||
if(!NT_SUCCESS(nErrCode)) goto l_CleanupFiber;
|
||||
|
||||
/* initialize the context for the fiber */
|
||||
nErrCode = RtlRosInitializeContext
|
||||
(
|
||||
NtCurrentProcess(),
|
||||
&ctxFiberContext,
|
||||
FiberStartup,
|
||||
&usFiberInitialTeb,
|
||||
1,
|
||||
(ULONG_PTR *)&lpStartAddress
|
||||
);
|
||||
|
||||
/* failure */
|
||||
if(!NT_SUCCESS(nErrCode)) goto l_CleanupStack;
|
||||
|
||||
/* copy the data into the fiber */
|
||||
|
||||
/* fixed-size stack */
|
||||
if(usFiberInitialTeb.PreviousStackBase && usFiberInitialTeb.PreviousStackLimit)
|
||||
{
|
||||
pfCurFiber->StackBase = usFiberInitialTeb.PreviousStackBase;
|
||||
pfCurFiber->StackLimit = usFiberInitialTeb.PreviousStackLimit;
|
||||
pfCurFiber->DeallocationStack = usFiberInitialTeb.PreviousStackLimit;
|
||||
}
|
||||
/* expandable stack */
|
||||
else if
|
||||
(
|
||||
usFiberInitialTeb.StackBase &&
|
||||
usFiberInitialTeb.StackLimit &&
|
||||
usFiberInitialTeb.AllocatedStackBase
|
||||
)
|
||||
{
|
||||
pfCurFiber->StackBase = usFiberInitialTeb.StackBase;
|
||||
pfCurFiber->StackLimit = usFiberInitialTeb.StackLimit;
|
||||
pfCurFiber->DeallocationStack = usFiberInitialTeb.AllocatedStackBase;
|
||||
}
|
||||
/* bad initial stack */
|
||||
else goto l_CleanupStack;
|
||||
|
||||
pfCurFiber->Parameter = lpParameter;
|
||||
pfCurFiber->Flags = dwFlags;
|
||||
pfCurFiber->ExceptionList = (struct _EXCEPTION_REGISTRATION_RECORD *)-1;
|
||||
|
||||
#if defined(_M_IX86)
|
||||
|
||||
pfCurFiber->Eip = ctxFiberContext.Eip;
|
||||
pfCurFiber->Esp = ctxFiberContext.Esp;
|
||||
pfCurFiber->Ebp = ctxFiberContext.Ebp;
|
||||
pfCurFiber->Ebx = ctxFiberContext.Ebx;
|
||||
pfCurFiber->Esi = ctxFiberContext.Esi;
|
||||
pfCurFiber->Edi = ctxFiberContext.Edi;
|
||||
|
||||
if(dwFlags & FIBER_FLAG_FLOAT_SWITCH)
|
||||
pfCurFiber->FloatSave = ctxFiberContext.FloatSave;
|
||||
|
||||
#else
|
||||
#error Unspecified or unsupported architecture.
|
||||
#endif
|
||||
|
||||
return pfCurFiber;
|
||||
|
||||
l_CleanupStack:
|
||||
/* free the stack */
|
||||
RtlRosDeleteStack(NtCurrentProcess(), &usFiberInitialTeb);
|
||||
|
||||
l_CleanupFiber:
|
||||
/* free the fiber */
|
||||
RtlFreeHeap(pTeb->ProcessEnvironmentBlock->ProcessHeap, 0, pfCurFiber);
|
||||
|
||||
/* failure */
|
||||
ASSERT(!NT_SUCCESS(nErrCode));
|
||||
SetLastErrorByStatus(nErrCode);
|
||||
return NULL;
|
||||
/* Failure */
|
||||
SetLastErrorByStatus(nErrCode);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Clear the context */
|
||||
RtlZeroMemory(&pfCurFiber->Context, sizeof(CONTEXT));
|
||||
|
||||
/* copy the data into the fiber */
|
||||
pfCurFiber->StackBase = usFiberInitialTeb.StackBase;
|
||||
pfCurFiber->StackLimit = usFiberInitialTeb.StackLimit;
|
||||
pfCurFiber->DeallocationStack = usFiberInitialTeb.AllocatedStackBase;
|
||||
pfCurFiber->Parameter = lpParameter;
|
||||
pfCurFiber->ExceptionList = (struct _EXCEPTION_REGISTRATION_RECORD *)-1;
|
||||
pfCurFiber->GuaranteedStackBytes = 0;
|
||||
pfCurFiber->FlsData = NULL;
|
||||
pfCurFiber->ActivationContextStack = ActivationContextStack;
|
||||
pfCurFiber->Context.ContextFlags = CONTEXT_FULL;
|
||||
|
||||
/* Save FPU State if requsted */
|
||||
if (dwFlags & FIBER_FLAG_FLOAT_SWITCH)
|
||||
{
|
||||
pfCurFiber->Context.ContextFlags |= CONTEXT_FLOATING_POINT;
|
||||
}
|
||||
|
||||
/* initialize the context for the fiber */
|
||||
BasepInitializeContext(&ctxFiberContext,
|
||||
lpParameter,
|
||||
lpStartAddress,
|
||||
usFiberInitialTeb.StackBase,
|
||||
2);
|
||||
|
||||
/* Return the Fiber */
|
||||
return pfCurFiber;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
void WINAPI DeleteFiber(LPVOID lpFiber)
|
||||
VOID
|
||||
WINAPI
|
||||
DeleteFiber(LPVOID lpFiber)
|
||||
{
|
||||
SIZE_T nSize = 0;
|
||||
PVOID pStackAllocBase = ((PFIBER)lpFiber)->DeallocationStack;
|
||||
PTEB pTeb = NtCurrentTeb();
|
||||
SIZE_T nSize = 0;
|
||||
PVOID pStackAllocBase = ((PFIBER)lpFiber)->DeallocationStack;
|
||||
|
||||
/* free the fiber */
|
||||
RtlFreeHeap(pTeb->ProcessEnvironmentBlock->ProcessHeap, 0, lpFiber);
|
||||
/* free the fiber */
|
||||
RtlFreeHeap(GetProcessHeap(), 0, lpFiber);
|
||||
|
||||
/* the fiber is deleting itself: let the system deallocate the stack */
|
||||
if(pTeb->Tib.FiberData == lpFiber) ExitThread(1);
|
||||
/* the fiber is deleting itself: let the system deallocate the stack */
|
||||
if(NtCurrentTeb()->Tib.FiberData == lpFiber) ExitThread(1);
|
||||
|
||||
/* deallocate the stack */
|
||||
NtFreeVirtualMemory
|
||||
(
|
||||
NtCurrentProcess(),
|
||||
&pStackAllocBase,
|
||||
&nSize,
|
||||
MEM_RELEASE
|
||||
);
|
||||
/* deallocate the stack */
|
||||
NtFreeVirtualMemory(NtCurrentProcess(),
|
||||
&pStackAllocBase,
|
||||
&nSize,
|
||||
MEM_RELEASE);
|
||||
}
|
||||
|
||||
|
||||
__declspec(noreturn) extern void WINAPI ThreadStartup
|
||||
(
|
||||
LPTHREAD_START_ROUTINE lpStartAddress,
|
||||
LPVOID lpParameter
|
||||
);
|
||||
|
||||
|
||||
__declspec(noreturn) void WINAPI FiberStartup(PVOID lpStartAddress)
|
||||
__declspec(noreturn)
|
||||
VOID
|
||||
WINAPI
|
||||
BaseFiberStartup(VOID)
|
||||
{
|
||||
/* FIXME? this should be pretty accurate */
|
||||
ThreadStartup(lpStartAddress, GetFiberData());
|
||||
PFIBER Fiber = GetFiberData();
|
||||
|
||||
/* Call the Thread Startup Routine */
|
||||
DPRINT1("Starting Fiber\n");
|
||||
BaseThreadStartup((LPTHREAD_START_ROUTINE)Fiber->Context.Eax,
|
||||
(LPVOID)Fiber->Context.Ebx);
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -1,94 +1,128 @@
|
|||
/* $Id$
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS system libraries
|
||||
* FILE: lib/kernel32/thread/i386/fiber.S
|
||||
* PURPOSE: Fiber context switch code for the x86 architecture
|
||||
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
|
||||
*
|
||||
* UPDATE HISTORY:
|
||||
* 28/05/2003 - created
|
||||
*
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS system libraries
|
||||
* FILE: lib/kernel32/thread/i386/fiber.S
|
||||
* PURPOSE: Fiber context switch code for the x86 architecture
|
||||
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
|
||||
* KJK::Hyperion <noog@libero.it>
|
||||
*/
|
||||
|
||||
.extern _DbgPrint
|
||||
#include <ndk/i386/segment.h>
|
||||
|
||||
/*
|
||||
* FIXME: When ntoskrnl header changes are complete, move asm.h out of ntoskrnl
|
||||
* so that we can use it here as well
|
||||
*/
|
||||
//#include <ndk/asm.h>
|
||||
#include <../ntoskrnl/include/internal/asm.h>
|
||||
|
||||
.globl _SwitchToFiber@4
|
||||
|
||||
ErrStr:
|
||||
.ascii \
|
||||
"(KERNEL32:" __FILE__ ") Saving and restoring the floating point context \
|
||||
currently unimplemented\n\0"
|
||||
.intel_syntax noprefix
|
||||
|
||||
_SwitchToFiber@4:
|
||||
/* Get the TEB */
|
||||
mov edx, fs:[TEB_SELECTOR]
|
||||
|
||||
/* Get the Fiber */
|
||||
mov eax, [edx+TEB_FIBER_DATA]
|
||||
|
||||
/* Save the non-volatile registers */
|
||||
mov [eax+FIBER_CONTEXT_EBX], ebx
|
||||
mov [eax+FIBER_CONTEXT_ESI], esi
|
||||
mov [eax+FIBER_CONTEXT_EDI], edi
|
||||
mov [eax+FIBER_CONTEXT_EBP], ebp
|
||||
|
||||
/* Check if we're to save FPU State */
|
||||
cmp dword ptr [eax+FIBER_CONTEXT_FLAGS], CONTEXT_FULL + CONTEXT_FLOATING_POINT
|
||||
jnz NoFpuStateSave
|
||||
|
||||
/* Save the FPU State (Status and Control)*/
|
||||
fstsw [eax+FIBER_CONTEXT_FLOAT_SAVE_STATUS_WORD]
|
||||
fstcw [eax+FIBER_CONTEXT_FLOAT_SAVE_CONTROL_WORD]
|
||||
|
||||
/* Check if the CPU supports SIMD MXCSR State Save */
|
||||
cmp byte ptr [PROCESSOR_FEATURE_FXSR], 0
|
||||
jnz NoFpuStateSave
|
||||
stmxcsr [eax+FIBER_CONTEXT_DR6]
|
||||
|
||||
NoFpuStateSave:
|
||||
|
||||
movl %fs:0x18, %ecx /* Teb = NtCurrentTeb() */
|
||||
/* Save stack since we're not touching it anymore */
|
||||
mov [eax+FIBER_CONTEXT_ESP], esp
|
||||
|
||||
/* Transfer some data from the TEB */
|
||||
mov ecx, [edx+TEB_FLS_DATA]
|
||||
mov [eax+FIBER_FLS_DATA], ecx
|
||||
mov ecx, [edx+TEB_ACTIVATION_CONTEXT_STACK_POINTER]
|
||||
mov [eax+FIBER_ACTIVATION_CONTEXT_STACK], ecx
|
||||
|
||||
/* Transfer some data related to the Stack */
|
||||
mov ecx, [edx+TEB_EXCEPTION_LIST]
|
||||
mov [eax+FIBER_EXCEPTION_LIST], ecx
|
||||
mov ecx, [edx+TEB_STACK_LIMIT]
|
||||
mov [eax+FIBER_STACK_LIMIT], ecx
|
||||
mov ecx, [edx+TEB_GUARANTEED_STACK_BYTES]
|
||||
mov [eax+FIBER_GUARANTEED_STACK_BYTES], ecx
|
||||
|
||||
/* Switch to the new fiber */
|
||||
mov ecx, [esp+4]
|
||||
mov [edx+TEB_FIBER_DATA], ecx
|
||||
|
||||
/* Switch Fiber Data */
|
||||
mov esi, [ecx+FIBER_EXCEPTION_LIST]
|
||||
mov [edx+TEB_EXCEPTION_LIST], esi
|
||||
mov esi, [ecx+FIBER_STACK_BASE]
|
||||
mov [edx+TEB_STACK_BASE], esi
|
||||
mov esi, [ecx+FIBER_STACK_LIMIT]
|
||||
mov [edx+TEB_STACK_LIMIT], esi
|
||||
mov esi, [ecx+FIBER_DEALLOCATION_STACK]
|
||||
mov [edx+TEB_DEALLOCATION_STACK], esi
|
||||
mov esi, [ecx+FIBER_GUARANTEED_STACK_BYTES]
|
||||
mov [edx+TEB_GUARANTEED_STACK_BYTES], esi
|
||||
mov esi, [ecx+FIBER_ACTIVATION_CONTEXT_STACK]
|
||||
mov [edx+TEB_ACTIVATION_CONTEXT_STACK_POINTER], esi
|
||||
|
||||
/* Restore FPU State */
|
||||
cmp dword ptr [eax+FIBER_CONTEXT_FLAGS], CONTEXT_FULL + CONTEXT_FLOATING_POINT
|
||||
jnz NoFpuStateRestore
|
||||
|
||||
/* Check if the Status Word Changed */
|
||||
mov esi, [eax+FIBER_CONTEXT_FLOAT_SAVE_STATUS_WORD]
|
||||
cmp si, word ptr [ecx+FIBER_CONTEXT_FLOAT_SAVE_STATUS_WORD]
|
||||
jnz StatusWordChanged
|
||||
|
||||
/* Check if the Control Word Changed */
|
||||
mov esi, [eax+FIBER_CONTEXT_FLOAT_SAVE_CONTROL_WORD]
|
||||
cmp si, word ptr [ecx+FIBER_CONTEXT_FLOAT_SAVE_CONTROL_WORD]
|
||||
jz ControlWordEqual
|
||||
|
||||
StatusWordChanged:
|
||||
|
||||
/* get the current fiber */
|
||||
movl 0x10(%ecx), %eax /* Fiber = Teb->Tib.FiberData */
|
||||
/* Load the new one */
|
||||
mov word ptr [ecx+FIBER_CONTEXT_FLOAT_SAVE_TAG_WORD], 0xFFFF
|
||||
fldenv [ecx+FIBER_CONTEXT_FLOAT_SAVE_CONTROL_WORD]
|
||||
|
||||
ControlWordEqual:
|
||||
|
||||
/* store the volatile context of the current fiber */
|
||||
movl 0x0(%ecx), %edx
|
||||
movl %edx, 0x4(%eax) /* Fiber->ExceptionList = Teb->ExceptionList */
|
||||
movl 0x4(%ecx), %edx
|
||||
movl %edx, 0x8(%eax) /* Fiber->StackBase = Teb->StackBase */
|
||||
movl 0x8(%ecx), %edx
|
||||
movl %edx, 0xC(%eax) /* Fiber->StackLimit = Teb->StackLimit */
|
||||
movl 0xE0C(%ecx), %edx
|
||||
movl %edx, 0x10(%eax) /* Fiber->StackBottom = Teb->DeallocationStack */
|
||||
movl 0x0(%esp), %edx
|
||||
movl %edx, 0x18(%eax) /* Fiber->Eip = [esp + 0] */
|
||||
movl %esp, %edx
|
||||
addl $0x8, %edx
|
||||
movl %edx, 0x1C(%eax) /* Fiber->Esp = esp + 8 */
|
||||
movl %ebp, 0x20(%eax) /* Fiber->Ebp = ebp */
|
||||
movl %ebx, 0x24(%eax) /* Fiber->Ebx = ebx */
|
||||
movl %esi, 0x28(%eax) /* Fiber->Esi = edi */
|
||||
movl %edi, 0x2C(%eax) /* Fiber->Edi = esi */
|
||||
/* Load the new one */
|
||||
cmp byte ptr [PROCESSOR_FEATURE_FXSR], 0
|
||||
jnz NoFpuStateRestore
|
||||
ldmxcsr [ecx+FIBER_CONTEXT_DR6]
|
||||
|
||||
NoFpuStateRestore:
|
||||
|
||||
testl $1, 0x14(%eax)
|
||||
jz l_NoFloatSave
|
||||
|
||||
/* save the floating point context */
|
||||
/* TODO */
|
||||
pushl ErrStr
|
||||
call _DbgPrint
|
||||
popl %ecx
|
||||
|
||||
l_NoFloatSave:
|
||||
|
||||
/* switch to the specified fiber */
|
||||
movl 0x4(%esp), %eax /* Fiber = lpFiber */
|
||||
movl %eax, 0x10(%ecx) /* Teb->Tib.FiberData = Fiber */
|
||||
|
||||
/* restore the volatile context of the specified fiber */
|
||||
movl 0x4(%eax), %edx
|
||||
movl %edx, 0x0(%ecx) /* Teb->ExceptionList = Fiber->ExceptionList */
|
||||
movl 0x8(%eax), %edx
|
||||
movl %edx, 0x4(%ecx) /* Teb->StackBase = Fiber->StackBase */
|
||||
movl 0xC(%eax), %edx
|
||||
movl %edx, 0x8(%ecx) /* Teb->StackLimit = Fiber->StackLimit */
|
||||
movl 0x10(%eax), %edx
|
||||
movl %edx, 0xE0C(%ecx) /* Teb->StackBottom = Fiber->DeallocationStack */
|
||||
movl 0x18(%eax), %edx /* edx = Fiber->Eip */
|
||||
movl 0x1C(%eax), %esp /* esp = Fiber->Esp */
|
||||
movl 0x20(%eax), %ebp /* ebp = Fiber->Ebp */
|
||||
movl 0x24(%eax), %ebx /* ebx = Fiber->Ebx */
|
||||
movl 0x28(%eax), %esi /* esi = Fiber->Esi */
|
||||
movl 0x2C(%eax), %edi /* edi = Fiber->Edi */
|
||||
|
||||
testb $1, 0x14(%eax)
|
||||
jz l_NoFloatRestore
|
||||
|
||||
/* restore the floating point context */
|
||||
/* TODO */
|
||||
pushl ErrStr
|
||||
call _DbgPrint
|
||||
popl %ecx
|
||||
|
||||
l_NoFloatRestore:
|
||||
|
||||
/* jump to the saved program counter */
|
||||
jmp *%edx
|
||||
/* Restore non-volatile registers */
|
||||
mov esi, [ecx+FIBER_CONTEXT_ESI]
|
||||
mov edi, [ecx+FIBER_CONTEXT_EDI]
|
||||
mov ebx, [ecx+FIBER_CONTEXT_EBX]
|
||||
mov ebp, [ecx+FIBER_CONTEXT_EBP]
|
||||
mov esp, [ecx+FIBER_CONTEXT_ESP]
|
||||
|
||||
/* Restore FLS Data */
|
||||
mov eax, [ecx+FIBER_FLS_DATA]
|
||||
mov [edx+TEB_FLS_DATA], eax
|
||||
|
||||
/* Return */
|
||||
ret 4
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -44,26 +44,28 @@ _SEH_FILTER(BaseThreadExceptionFilter)
|
|||
return ExceptionDisposition;
|
||||
}
|
||||
|
||||
__declspec(noreturn) void STDCALL
|
||||
ThreadStartup
|
||||
(
|
||||
LPTHREAD_START_ROUTINE lpStartAddress,
|
||||
LPVOID lpParameter
|
||||
)
|
||||
__declspec(noreturn)
|
||||
VOID
|
||||
STDCALL
|
||||
BaseThreadStartup(LPTHREAD_START_ROUTINE lpStartAddress,
|
||||
LPVOID lpParameter)
|
||||
{
|
||||
volatile UINT uExitCode = 0;
|
||||
volatile UINT uExitCode = 0;
|
||||
|
||||
_SEH_TRY
|
||||
{
|
||||
uExitCode = (lpStartAddress)((PVOID)lpParameter);
|
||||
}
|
||||
_SEH_EXCEPT(BaseThreadExceptionFilter)
|
||||
{
|
||||
uExitCode = _SEH_GetExceptionCode();
|
||||
}
|
||||
_SEH_END;
|
||||
/* Attempt to call the Thread Start Address */
|
||||
_SEH_TRY
|
||||
{
|
||||
/* Get the exit code from the Thread Start */
|
||||
uExitCode = (lpStartAddress)((PVOID)lpParameter);
|
||||
}
|
||||
_SEH_EXCEPT(BaseThreadExceptionFilter)
|
||||
{
|
||||
/* Get the Exit code from the SEH Handler */
|
||||
uExitCode = _SEH_GetExceptionCode();
|
||||
} _SEH_END;
|
||||
|
||||
ExitThread(uExitCode);
|
||||
/* Exit the Thread */
|
||||
ExitThread(uExitCode);
|
||||
}
|
||||
|
||||
|
||||
|
@ -209,7 +211,7 @@ CreateRemoteThread
|
|||
0,
|
||||
nStackReserve,
|
||||
nStackCommit,
|
||||
ThreadStartup,
|
||||
BaseThreadStartup,
|
||||
&hThread,
|
||||
&cidClientId,
|
||||
2,
|
||||
|
@ -226,7 +228,7 @@ CreateRemoteThread
|
|||
0,
|
||||
&nStackReserve,
|
||||
&nStackCommit,
|
||||
(PTHREAD_START_ROUTINE)ThreadStartup,
|
||||
(PTHREAD_START_ROUTINE)BaseThreadStartup,
|
||||
&hThread,
|
||||
&cidClientId,
|
||||
2,
|
||||
|
|
Loading…
Reference in a new issue