- 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:
Alex Ionescu 2005-07-19 21:04:19 +00:00
parent 22ef1b4558
commit 73e69c9d9e
3 changed files with 325 additions and 335 deletions

View file

@ -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 */

View file

@ -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 */

View file

@ -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,