mirror of
https://github.com/reactos/reactos.git
synced 2025-02-24 17:34:57 +00:00
[KERNEL32]:
Bug #47: CreateFiberEx should return ERROR_INVALID_PARAMETER for invalid flags. Bug #48: DeleteFiber should also check if HasFiberData is TRUE in TEB before calling ExitThread. Bug #49: DeleteFiber should only delete the FIBER data structure after cleanup is complete, not before. Also, enable the calls to RtlAllocateActivationContextStack since SxS kind-of exists now. However, we leak the context since RtlFreeActivationContextStack is not implemented. Also, add a call to BaseRundownFls so we don't forget to cleanup FLS data once FLS is implemented. svn path=/trunk/; revision=52805
This commit is contained in:
parent
84022a4625
commit
84a32acb78
1 changed files with 106 additions and 82 deletions
|
@ -26,6 +26,16 @@ typedef struct _FIBER /* Field offsets: */
|
|||
PVOID ActivationContextStack; /* 0x2E8 */
|
||||
} FIBER, *PFIBER;
|
||||
|
||||
/* PRIVATE FUNCTIONS **********************************************************/
|
||||
|
||||
VOID
|
||||
WINAPI
|
||||
BaseRundownFls(IN PVOID FlsData)
|
||||
{
|
||||
/* No FLS support yet */
|
||||
|
||||
}
|
||||
|
||||
__declspec(noreturn)
|
||||
VOID
|
||||
WINAPI
|
||||
|
@ -52,6 +62,8 @@ BaseFiberStartup(VOID)
|
|||
#endif
|
||||
}
|
||||
|
||||
/* PUBLIC FUNCTIONS ***********************************************************/
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
|
@ -93,58 +105,48 @@ WINAPI
|
|||
ConvertThreadToFiberEx(LPVOID lpParameter,
|
||||
DWORD dwFlags)
|
||||
{
|
||||
PTEB Teb;
|
||||
PFIBER Fiber;
|
||||
PTEB pTeb = NtCurrentTeb();
|
||||
PFIBER pfCurFiber;
|
||||
DPRINT1("Converting Thread to Fiber\n");
|
||||
|
||||
/* Check for invalid flags */
|
||||
if (dwFlags &~ FIBER_FLAG_FLOAT_SWITCH)
|
||||
{
|
||||
/* Fail */
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return NULL;
|
||||
}
|
||||
/* the current thread is already a fiber */
|
||||
if(pTeb->HasFiberData && pTeb->NtTib.FiberData) return pTeb->NtTib.FiberData;
|
||||
|
||||
/* Are we already a fiber? */
|
||||
Teb = NtCurrentTeb();
|
||||
if (Teb->HasFiberData)
|
||||
{
|
||||
/* Fail */
|
||||
SetLastError(ERROR_ALREADY_FIBER);
|
||||
return NULL;
|
||||
}
|
||||
/* allocate the fiber */
|
||||
pfCurFiber = (PFIBER)RtlAllocateHeap(GetProcessHeap(),
|
||||
0,
|
||||
sizeof(FIBER));
|
||||
|
||||
/* Allocate the fiber */
|
||||
Fiber = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(FIBER));
|
||||
if (!Fiber)
|
||||
/* failure */
|
||||
if (pfCurFiber == NULL)
|
||||
{
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Copy some contextual data from the thread to the fiber */
|
||||
Fiber->Parameter = lpParameter;
|
||||
Fiber->ExceptionList = Teb->NtTib.ExceptionList;
|
||||
Fiber->StackBase = Teb->NtTib.StackBase;
|
||||
Fiber->StackLimit = Teb->NtTib.StackLimit;
|
||||
Fiber->DeallocationStack = Teb->DeallocationStack;
|
||||
Fiber->FlsData = Teb->FlsData;
|
||||
Fiber->GuaranteedStackBytes = Teb->GuaranteedStackBytes;
|
||||
Fiber->ActivationContextStack = Teb->ActivationContextStackPointer;
|
||||
Fiber->Context.ContextFlags = CONTEXT_FULL;
|
||||
/* copy some contextual data from the thread to the fiber */
|
||||
pfCurFiber->Parameter = lpParameter;
|
||||
pfCurFiber->ExceptionList = pTeb->NtTib.ExceptionList;
|
||||
pfCurFiber->StackBase = pTeb->NtTib.StackBase;
|
||||
pfCurFiber->StackLimit = pTeb->NtTib.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 requested */
|
||||
/* Save FPU State if requsted */
|
||||
if (dwFlags & FIBER_FLAG_FLOAT_SWITCH)
|
||||
{
|
||||
Fiber->Context.ContextFlags |= CONTEXT_FLOATING_POINT;
|
||||
pfCurFiber->Context.ContextFlags |= CONTEXT_FLOATING_POINT;
|
||||
}
|
||||
|
||||
/* Associate the fiber to the current thread */
|
||||
Teb->NtTib.FiberData = Fiber;
|
||||
Teb->HasFiberData = TRUE;
|
||||
/* associate the fiber to the current thread */
|
||||
pTeb->NtTib.FiberData = pfCurFiber;
|
||||
pTeb->HasFiberData = TRUE;
|
||||
|
||||
/* Return opaque fiber data */
|
||||
return (LPVOID)Fiber;
|
||||
/* success */
|
||||
return (LPVOID)pfCurFiber;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -182,73 +184,86 @@ CreateFiberEx(SIZE_T dwStackCommitSize,
|
|||
LPFIBER_START_ROUTINE lpStartAddress,
|
||||
LPVOID lpParameter)
|
||||
{
|
||||
PFIBER pfCurFiber;
|
||||
NTSTATUS nErrCode;
|
||||
INITIAL_TEB usFiberInitialTeb;
|
||||
PFIBER Fiber;
|
||||
NTSTATUS Status;
|
||||
INITIAL_TEB InitialTeb;
|
||||
PVOID ActivationContextStack = NULL;
|
||||
DPRINT("Creating Fiber\n");
|
||||
|
||||
#ifdef SXS_SUPPORT_ENABLED
|
||||
/* Check for invalid flags */
|
||||
if (dwFlags &~ FIBER_FLAG_FLOAT_SWITCH)
|
||||
{
|
||||
/* Fail */
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Allocate the Activation Context Stack */
|
||||
nErrCode = RtlAllocateActivationContextStack(&ActivationContextStack);
|
||||
#endif
|
||||
Status = RtlAllocateActivationContextStack(&ActivationContextStack);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Fail */
|
||||
SetLastErrorByStatus(Status);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Allocate the fiber */
|
||||
pfCurFiber = (PFIBER)RtlAllocateHeap(GetProcessHeap(),
|
||||
0,
|
||||
sizeof(FIBER));
|
||||
/* Failure */
|
||||
if (pfCurFiber == NULL)
|
||||
Fiber = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(FIBER));
|
||||
if (!Fiber)
|
||||
{
|
||||
/* Fail */
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Create the stack for the fiber */
|
||||
nErrCode = BasepCreateStack(NtCurrentProcess(),
|
||||
dwStackCommitSize,
|
||||
dwStackReserveSize,
|
||||
&usFiberInitialTeb);
|
||||
/* Failure */
|
||||
if(!NT_SUCCESS(nErrCode))
|
||||
Status = BasepCreateStack(NtCurrentProcess(),
|
||||
dwStackCommitSize,
|
||||
dwStackReserveSize,
|
||||
&InitialTeb);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Free the fiber */
|
||||
RtlFreeHeap(GetProcessHeap(), 0, pfCurFiber);
|
||||
RtlFreeHeap(GetProcessHeap(), 0, Fiber);
|
||||
|
||||
/* Free the activation context */
|
||||
DPRINT1("Leaking activation stack because nobody implemented free");
|
||||
//RtlFreeActivationContextStack(&ActivationContextStack);
|
||||
|
||||
/* Failure */
|
||||
SetLastErrorByStatus(nErrCode);
|
||||
SetLastErrorByStatus(Status);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Clear the context */
|
||||
RtlZeroMemory(&pfCurFiber->Context, sizeof(CONTEXT));
|
||||
RtlZeroMemory(&Fiber->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;
|
||||
/* Copy the data into the fiber */
|
||||
Fiber->StackBase = InitialTeb.StackBase;
|
||||
Fiber->StackLimit = InitialTeb.StackLimit;
|
||||
Fiber->DeallocationStack = InitialTeb.AllocatedStackBase;
|
||||
Fiber->Parameter = lpParameter;
|
||||
Fiber->ExceptionList = EXCEPTION_CHAIN_END;
|
||||
Fiber->GuaranteedStackBytes = 0;
|
||||
Fiber->FlsData = NULL;
|
||||
Fiber->ActivationContextStack = ActivationContextStack;
|
||||
Fiber->Context.ContextFlags = CONTEXT_FULL;
|
||||
|
||||
/* Save FPU State if requsted */
|
||||
if (dwFlags & FIBER_FLAG_FLOAT_SWITCH)
|
||||
{
|
||||
pfCurFiber->Context.ContextFlags |= CONTEXT_FLOATING_POINT;
|
||||
Fiber->Context.ContextFlags |= CONTEXT_FLOATING_POINT;
|
||||
}
|
||||
|
||||
/* initialize the context for the fiber */
|
||||
BasepInitializeContext(&pfCurFiber->Context,
|
||||
BasepInitializeContext(&Fiber->Context,
|
||||
lpParameter,
|
||||
lpStartAddress,
|
||||
usFiberInitialTeb.StackBase,
|
||||
InitialTeb.StackBase,
|
||||
2);
|
||||
|
||||
/* Return the Fiber */
|
||||
return pfCurFiber;
|
||||
/* Return the Fiber */
|
||||
return Fiber;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -258,20 +273,29 @@ VOID
|
|||
WINAPI
|
||||
DeleteFiber(LPVOID lpFiber)
|
||||
{
|
||||
SIZE_T nSize = 0;
|
||||
PVOID pStackAllocBase = ((PFIBER)lpFiber)->DeallocationStack;
|
||||
SIZE_T Size = 0;
|
||||
PFIBER Fiber = (PFIBER)lpFiber;
|
||||
PTEB Teb;
|
||||
|
||||
/* free the fiber */
|
||||
RtlFreeHeap(GetProcessHeap(), 0, lpFiber);
|
||||
/* First, exit the thread */
|
||||
Teb = NtCurrentTeb();
|
||||
if ((Teb->HasFiberData) && (Teb->NtTib.FiberData == Fiber)) ExitThread(1);
|
||||
|
||||
/* the fiber is deleting itself: let the system deallocate the stack */
|
||||
if(NtCurrentTeb()->NtTib.FiberData == lpFiber) ExitThread(1);
|
||||
|
||||
/* deallocate the stack */
|
||||
/* Now de-allocate the stack */
|
||||
NtFreeVirtualMemory(NtCurrentProcess(),
|
||||
&pStackAllocBase,
|
||||
&nSize,
|
||||
&Fiber->DeallocationStack,
|
||||
&Size,
|
||||
MEM_RELEASE);
|
||||
|
||||
/* Get rid of FLS */
|
||||
if (Fiber->FlsData) BaseRundownFls(Fiber->FlsData);
|
||||
|
||||
/* Get rid of the activation stack */
|
||||
DPRINT1("Leaking activation stack because nobody implemented free");
|
||||
//RtlFreeActivationContextStack(Fiber->ActivationContextStack);
|
||||
|
||||
/* Free the fiber data */
|
||||
RtlFreeHeap(GetProcessHeap(), 0, lpFiber);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in a new issue