mirror of
https://github.com/reactos/reactos.git
synced 2024-08-28 22:28:36 +00:00
- Kernel32: implemented fibers. Almost complete - only lacks some Windows 2003 Server features (switching the floating point context and Fiber Local Storage functions)
- Kernel32: GetCurrentFiber and GetFiberData are macros, not functions - Kernel32: ExitThread now is declared as __declspec(noreturn) - RosRtl: two new functions to allocate and free stacks - RosRtl: corrected a couple of prototypes svn path=/trunk/; revision=4794
This commit is contained in:
parent
2382d9e48e
commit
66080da575
|
@ -1136,6 +1136,9 @@ extern "C" {
|
|||
|
||||
/* FindNextPrinterNotification */
|
||||
|
||||
/* FlsAlloc */
|
||||
#define FLS_OUT_OF_INDEXES (0xFFFFFFFF)
|
||||
|
||||
/* FMExtensionProc */
|
||||
|
||||
/* FoldString */
|
||||
|
|
|
@ -1515,6 +1515,7 @@ GetThreadTimes(
|
|||
);
|
||||
|
||||
|
||||
__declspec(noreturn)
|
||||
VOID
|
||||
STDCALL
|
||||
ExitThread(
|
||||
|
@ -2796,6 +2797,16 @@ TlsFree(
|
|||
DWORD dwTlsIndex
|
||||
);
|
||||
|
||||
typedef VOID WINAPI (*PFLS_CALLBACK_FUNCTION)(PVOID lpFlsData);
|
||||
|
||||
DWORD WINAPI FlsAlloc(PFLS_CALLBACK_FUNCTION lpCallback);
|
||||
|
||||
BOOL WINAPI FlsFree(DWORD dwFlsIndex);
|
||||
|
||||
PVOID WINAPI FlsGetValue(DWORD dwFlsIndex);
|
||||
|
||||
BOOL WINAPI FlsSetValue(DWORD dwFlsIndex, PVOID lpFlsData);
|
||||
|
||||
DWORD
|
||||
STDCALL
|
||||
SleepEx(
|
||||
|
@ -7569,45 +7580,38 @@ SHLoadInProc (REFCLSID);
|
|||
|
||||
/* Win32 Fibers */
|
||||
|
||||
typedef
|
||||
VOID (WINAPI *PFIBER_START_ROUTINE) (
|
||||
IN LPVOID lpFiberArgument
|
||||
);
|
||||
typedef VOID (WINAPI * PFIBER_START_ROUTINE) (IN LPVOID lpFiberArgument);
|
||||
typedef PFIBER_START_ROUTINE LPFIBER_START_ROUTINE;
|
||||
|
||||
LPVOID
|
||||
STDCALL
|
||||
ConvertThreadToFiber (
|
||||
LPVOID lpArgument
|
||||
);
|
||||
LPVOID
|
||||
STDCALL
|
||||
CreateFiber (
|
||||
DWORD dwStackSize,
|
||||
LPFIBER_START_ROUTINE lpStartAddress,
|
||||
LPVOID lpArgument
|
||||
);
|
||||
VOID
|
||||
STDCALL
|
||||
DeleteFiber(
|
||||
LPVOID lpFiber
|
||||
);
|
||||
PVOID
|
||||
STDCALL
|
||||
GetCurrentFiber (
|
||||
VOID
|
||||
);
|
||||
PVOID
|
||||
STDCALL
|
||||
GetFiberData (
|
||||
VOID
|
||||
);
|
||||
VOID
|
||||
STDCALL
|
||||
SwitchToFiber (
|
||||
LPVOID lpFiber
|
||||
);
|
||||
#define FIBER_FLAG_FLOAT_SWITCH (1)
|
||||
|
||||
BOOL WINAPI ConvertFiberToThread(void);
|
||||
|
||||
LPVOID WINAPI ConvertThreadToFiber(LPVOID lpParameter);
|
||||
|
||||
LPVOID WINAPI ConvertThreadToFiberEx(LPVOID lpParameter, DWORD dwFlags);
|
||||
|
||||
LPVOID WINAPI CreateFiber
|
||||
(
|
||||
SIZE_T dwStackSize,
|
||||
LPFIBER_START_ROUTINE lpStartAddress,
|
||||
LPVOID lpParameter
|
||||
);
|
||||
|
||||
LPVOID WINAPI CreateFiberEx
|
||||
(
|
||||
SIZE_T dwStackCommitSize,
|
||||
SIZE_T dwStackReserveSize,
|
||||
DWORD dwFlags,
|
||||
LPFIBER_START_ROUTINE lpStartAddress,
|
||||
LPVOID lpParameter
|
||||
);
|
||||
|
||||
void WINAPI DeleteFiber(LPVOID lpFiber);
|
||||
|
||||
void WINAPI SwitchToFiber(LPVOID lpFiber);
|
||||
|
||||
#define GetFiberData() *(LPVOID *)(((PNT_TIB)NtCurrentTeb())->Fib.FiberData)
|
||||
|
||||
WINBOOL STDCALL
|
||||
RegisterServicesProcess(DWORD ServicesProcessId);
|
||||
|
|
|
@ -179,7 +179,7 @@ typedef struct _TEB
|
|||
ULONG LastErrorValue; // 34h
|
||||
ULONG CountOfOwnedCriticalSections; // 38h
|
||||
PVOID CsrClientThread; // 3Ch
|
||||
struct _W32THREAD* Win32ThreadInfo; // 40h
|
||||
struct _W32THREAD* Win32ThreadInfo; // 40h
|
||||
ULONG Win32ClientInfo[0x1F]; // 44h
|
||||
PVOID WOW32Reserved; // C0h
|
||||
ULONG CurrentLocale; // C4h
|
||||
|
@ -220,9 +220,11 @@ typedef struct _TEB
|
|||
PVOID Instrumentation[0x10]; // F2Ch
|
||||
PVOID WinSockData; // F6Ch
|
||||
ULONG GdiBatchCount; // F70h
|
||||
ULONG Spare2; // F74h // NOTE: RtlExitUserThread writes something here
|
||||
ULONG Spare3; // F78h
|
||||
ULONG Spare4; // F7Ch
|
||||
USHORT Spare2; // F74h
|
||||
BOOLEAN IsFiber; // F76h
|
||||
UCHAR Spare3; // F77h
|
||||
ULONG Spare4; // F78h
|
||||
ULONG Spare5; // F7Ch
|
||||
PVOID ReservedForOle; // F80h
|
||||
ULONG WaitingOnLoaderLock; // F84h
|
||||
PVOID WineDebugInfo; // Needed for WINE DLL's
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: thread.h,v 1.1 2003/04/29 02:17:00 hyperion Exp $
|
||||
/* $Id: thread.h,v 1.2 2003/05/29 00:36:41 hyperion Exp $
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -14,7 +14,7 @@ NTSTATUS STDCALL RtlRosCreateUserThreadEx
|
|||
IN LONG StackZeroBits,
|
||||
IN OUT PULONG StackReserve OPTIONAL,
|
||||
IN OUT PULONG StackCommit OPTIONAL,
|
||||
IN PTHREAD_START_ROUTINE StartAddress,
|
||||
IN PVOID StartAddress,
|
||||
OUT PHANDLE ThreadHandle OPTIONAL,
|
||||
OUT PCLIENT_ID ClientId OPTIONAL,
|
||||
IN ULONG ParameterCount,
|
||||
|
@ -29,7 +29,7 @@ NTSTATUS CDECL RtlRosCreateUserThreadVa
|
|||
IN LONG StackZeroBits,
|
||||
IN OUT PULONG StackReserve OPTIONAL,
|
||||
IN OUT PULONG StackCommit OPTIONAL,
|
||||
IN PTHREAD_START_ROUTINE StartAddress,
|
||||
IN PVOID StartAddress,
|
||||
OUT PHANDLE ThreadHandle OPTIONAL,
|
||||
OUT PCLIENT_ID ClientId OPTIONAL,
|
||||
IN ULONG ParameterCount,
|
||||
|
@ -39,13 +39,28 @@ NTSTATUS CDECL RtlRosCreateUserThreadVa
|
|||
NTSTATUS NTAPI RtlRosInitializeContextEx
|
||||
(
|
||||
IN HANDLE ProcessHandle,
|
||||
IN PCONTEXT Context,
|
||||
IN PTHREAD_START_ROUTINE StartAddress,
|
||||
OUT PCONTEXT Context,
|
||||
IN PVOID StartAddress,
|
||||
IN PUSER_STACK UserStack,
|
||||
IN ULONG ParameterCount,
|
||||
IN ULONG_PTR * Parameters
|
||||
);
|
||||
|
||||
NTSTATUS NTAPI RtlRosCreateStack
|
||||
(
|
||||
IN HANDLE ProcessHandle,
|
||||
OUT PUSER_STACK UserStack,
|
||||
IN LONG StackZeroBits,
|
||||
IN OUT PULONG StackReserve OPTIONAL,
|
||||
IN OUT PULONG StackCommit OPTIONAL
|
||||
);
|
||||
|
||||
NTSTATUS NTAPI RtlRosDeleteStack
|
||||
(
|
||||
IN HANDLE ProcessHandle,
|
||||
IN PUSER_STACK UserStack
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -171,6 +171,10 @@ FindResourceA@12
|
|||
FindResourceExA@16
|
||||
FindResourceExW@16
|
||||
FindResourceW@12
|
||||
FlsAlloc@4
|
||||
FlsFree@4
|
||||
FlsGetValue@4
|
||||
FlsSetValue@8
|
||||
FlushConsoleInputBuffer@4
|
||||
FlushFileBuffers@4
|
||||
FlushInstructionCache@12
|
||||
|
@ -239,7 +243,6 @@ GetCurrencyFormatW@24
|
|||
GetCurrentConsoleFont@12
|
||||
GetCurrentDirectoryA@8
|
||||
GetCurrentDirectoryW@8
|
||||
GetCurrentFiber@0
|
||||
GetCurrentProcess@0
|
||||
GetCurrentProcessId@0
|
||||
GetCurrentThread@0
|
||||
|
@ -260,7 +263,6 @@ GetEnvironmentVariableA@12
|
|||
GetEnvironmentVariableW@12
|
||||
GetExitCodeProcess@8
|
||||
GetExitCodeThread@8
|
||||
GetFiberData@0
|
||||
GetFileAttributesA@4
|
||||
GetFileAttributesW@4
|
||||
GetFileAttributesExA
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
; $Id: kernel32.edf,v 1.23 2003/04/26 00:25:01 hyperion Exp $
|
||||
; $Id: kernel32.edf,v 1.24 2003/05/29 00:36:41 hyperion Exp $
|
||||
;
|
||||
; kernel32.edf
|
||||
;
|
||||
|
@ -175,6 +175,10 @@ FindResourceA=FindResourceA@12
|
|||
FindResourceExA=FindResourceExA@16
|
||||
FindResourceExW=FindResourceExW@16
|
||||
FindResourceW=FindResourceW@12
|
||||
FlsAlloc=FlsAlloc@4
|
||||
FlsFree=FlsFree@4
|
||||
FlsGetValue=FlsGetValue@4
|
||||
FlsSetValue=FlsSetValue@8
|
||||
FlushConsoleInputBuffer=FlushConsoleInputBuffer@4
|
||||
FlushFileBuffers=FlushFileBuffers@4
|
||||
FlushInstructionCache=FlushInstructionCache@12
|
||||
|
@ -243,7 +247,6 @@ GetCurrencyFormatW=GetCurrencyFormatW@24
|
|||
GetCurrentConsoleFont=GetCurrentConsoleFont@12
|
||||
GetCurrentDirectoryA=GetCurrentDirectoryA@8
|
||||
GetCurrentDirectoryW=GetCurrentDirectoryW@8
|
||||
GetCurrentFiber=GetCurrentFiber@0
|
||||
GetCurrentProcess=GetCurrentProcess@0
|
||||
GetCurrentProcessId=GetCurrentProcessId@0
|
||||
GetCurrentThread=GetCurrentThread@0
|
||||
|
@ -265,7 +268,6 @@ GetEnvironmentVariableA=GetEnvironmentVariableA@12
|
|||
GetEnvironmentVariableW=GetEnvironmentVariableW@12
|
||||
GetExitCodeProcess=GetExitCodeProcess@8
|
||||
GetExitCodeThread=GetExitCodeThread@8
|
||||
GetFiberData=GetFiberData@0
|
||||
GetFileAttributesA=GetFileAttributesA@4
|
||||
GetFileAttributesW=GetFileAttributesW@4
|
||||
GetFileAttributesExA=GetFileAttributesExA@12
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# $Id: makefile,v 1.65 2003/05/25 17:17:03 ekohl Exp $
|
||||
# $Id: makefile,v 1.66 2003/05/29 00:36:41 hyperion Exp $
|
||||
|
||||
PATH_TO_TOP = ../..
|
||||
|
||||
|
@ -44,7 +44,11 @@ NLS_OBJECTS =
|
|||
THREAD_OBJECTS = \
|
||||
thread/fiber.o \
|
||||
thread/thread.o \
|
||||
thread/tls.o
|
||||
thread/tls.o \
|
||||
thread/fls.o
|
||||
|
||||
THREAD_I386_OBJECTS = \
|
||||
thread/i386/fiber.o
|
||||
|
||||
PROCESS_OBJECTS = \
|
||||
process/proc.o \
|
||||
|
@ -58,9 +62,12 @@ EXCEPT_OBJECTS = except/except.o
|
|||
|
||||
DEBUG_OBJECTS = debug/debugger.o debug/output.o debug/break.o
|
||||
|
||||
ARCH_OBJECTS = $(THREAD_I386_OBJECTS)
|
||||
|
||||
TARGET_OBJECTS = $(MISC_OBJECTS) $(FILE_OBJECTS) $(THREAD_OBJECTS) \
|
||||
$(PROCESS_OBJECTS) $(STRING_OBJECTS) $(MEM_OBJECTS) \
|
||||
$(SYNCH_OBJECTS) $(EXCEPT_OBJECTS) $(DEBUG_OBJECTS)
|
||||
$(SYNCH_OBJECTS) $(EXCEPT_OBJECTS) $(DEBUG_OBJECTS) \
|
||||
$(ARCH_OBJECTS)
|
||||
|
||||
|
||||
DEP_OBJECTS = $(TARGET_OBJECTS)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: fiber.c,v 1.4 2003/01/15 21:24:36 chorns Exp $
|
||||
/* $Id: fiber.c,v 1.5 2003/05/29 00:36:41 hyperion Exp $
|
||||
*
|
||||
* FILE: lib/kernel32/thread/fiber.c
|
||||
*
|
||||
|
@ -7,88 +7,264 @@
|
|||
*/
|
||||
#include <k32.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include <kernel32/kernel32.h>
|
||||
|
||||
struct _FIBER /* Field offsets: */
|
||||
{ /* 32 bit 64 bit */
|
||||
/* this must be the first field */
|
||||
LPVOID Parameter; /* 0x00 0x00 */
|
||||
|
||||
/**********************************************************************
|
||||
* ConvertThreadToFiber
|
||||
*/
|
||||
LPVOID
|
||||
STDCALL
|
||||
ConvertThreadToFiber(
|
||||
LPVOID lpArgument
|
||||
)
|
||||
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);
|
||||
|
||||
BOOL WINAPI ConvertFiberToThread(void)
|
||||
{
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
return NULL;
|
||||
PTEB pTeb = NtCurrentTeb();
|
||||
|
||||
/* the current thread isn't running a fiber: failure */
|
||||
if(!pTeb->IsFiber)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* this thread won't run a fiber anymore */
|
||||
pTeb->IsFiber = FALSE;
|
||||
|
||||
/* free the fiber */
|
||||
if(pTeb->Tib.Fib.FiberData != NULL)
|
||||
RtlFreeHeap(pTeb->Peb->ProcessHeap, 0, pTeb->Tib.Fib.FiberData);
|
||||
|
||||
/* success */
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* CreateFiber
|
||||
*/
|
||||
LPVOID
|
||||
STDCALL
|
||||
CreateFiber(
|
||||
DWORD dwStackSize,
|
||||
LPFIBER_START_ROUTINE lpStartAddress,
|
||||
LPVOID lpArgument
|
||||
)
|
||||
LPVOID WINAPI ConvertThreadToFiber(LPVOID lpParameter)
|
||||
{
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
return NULL;
|
||||
return ConvertThreadToFiberEx(lpParameter, 0);
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* DeleteFiber
|
||||
*/
|
||||
VOID
|
||||
STDCALL
|
||||
DeleteFiber(
|
||||
LPVOID lpFiber
|
||||
)
|
||||
LPVOID WINAPI ConvertThreadToFiberEx(LPVOID lpParameter, DWORD dwFlags)
|
||||
{
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
return;
|
||||
PTEB pTeb = NtCurrentTeb();
|
||||
PFIBER pfCurFiber;
|
||||
|
||||
/* the current thread is already a fiber */
|
||||
if(pTeb->IsFiber && pTeb->Tib.Fib.FiberData) return pTeb->Tib.Fib.FiberData;
|
||||
|
||||
/* allocate the fiber */
|
||||
pfCurFiber = (PFIBER)RtlAllocateHeap(pTeb->Peb->ProcessHeap, 0, sizeof(FIBER));
|
||||
|
||||
/* 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;
|
||||
|
||||
/* associate the fiber to the current thread */
|
||||
pTeb->Tib.Fib.FiberData = pfCurFiber;
|
||||
pTeb->IsFiber = TRUE;
|
||||
|
||||
/* success */
|
||||
return (LPVOID)pfCurFiber;
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* GetCurrentFiber
|
||||
*/
|
||||
PVOID
|
||||
STDCALL
|
||||
GetCurrentFiber(VOID)
|
||||
LPVOID WINAPI CreateFiber
|
||||
(
|
||||
SIZE_T dwStackSize,
|
||||
LPFIBER_START_ROUTINE lpStartAddress,
|
||||
LPVOID lpParameter
|
||||
)
|
||||
{
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
return NULL;
|
||||
return CreateFiberEx(dwStackSize, 0, 0, lpStartAddress, lpParameter);
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* GetFiberData
|
||||
*/
|
||||
PVOID
|
||||
STDCALL
|
||||
GetFiberData(VOID)
|
||||
LPVOID WINAPI CreateFiberEx
|
||||
(
|
||||
SIZE_T dwStackCommitSize,
|
||||
SIZE_T dwStackReserveSize,
|
||||
DWORD dwFlags,
|
||||
LPFIBER_START_ROUTINE lpStartAddress,
|
||||
LPVOID lpParameter
|
||||
)
|
||||
{
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
return NULL;
|
||||
PFIBER pfCurFiber;
|
||||
NTSTATUS nErrCode;
|
||||
PSIZE_T pnStackReserve = NULL;
|
||||
PSIZE_T pnStackCommit = NULL;
|
||||
USER_STACK usFiberStack;
|
||||
CONTEXT ctxFiberContext;
|
||||
PCHAR pStackBase;
|
||||
PCHAR pStackLimit;
|
||||
PTEB pTeb = NtCurrentTeb();
|
||||
|
||||
/* allocate the fiber */
|
||||
pfCurFiber = (PFIBER)RtlAllocateHeap(pTeb->Peb->ProcessHeap, 0, sizeof(FIBER));
|
||||
|
||||
/* failure */
|
||||
if(pfCurFiber == NULL)
|
||||
{
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* 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(),
|
||||
&usFiberStack,
|
||||
0,
|
||||
pnStackReserve,
|
||||
pnStackCommit
|
||||
);
|
||||
|
||||
/* failure */
|
||||
if(!NT_SUCCESS(nErrCode)) goto l_CleanupFiber;
|
||||
|
||||
/* initialize the context for the fiber */
|
||||
nErrCode = RtlRosInitializeContextEx
|
||||
(
|
||||
NtCurrentProcess(),
|
||||
&ctxFiberContext,
|
||||
FiberStartup,
|
||||
&usFiberStack,
|
||||
1,
|
||||
(ULONG_PTR *)&lpStartAddress
|
||||
);
|
||||
|
||||
/* failure */
|
||||
if(!NT_SUCCESS(nErrCode)) goto l_CleanupStack;
|
||||
|
||||
/* copy the data into the fiber */
|
||||
|
||||
/* fixed-size stack */
|
||||
if(usFiberStack.FixedStackBase && usFiberStack.FixedStackLimit)
|
||||
{
|
||||
pfCurFiber->StackBase = usFiberStack.FixedStackBase;
|
||||
pfCurFiber->StackLimit = usFiberStack.FixedStackLimit;
|
||||
pfCurFiber->DeallocationStack = usFiberStack.FixedStackLimit;
|
||||
}
|
||||
/* expandable stack */
|
||||
else if
|
||||
(
|
||||
usFiberStack.ExpandableStackBase &&
|
||||
usFiberStack.ExpandableStackLimit &&
|
||||
usFiberStack.ExpandableStackBottom
|
||||
)
|
||||
{
|
||||
pfCurFiber->StackBase = usFiberStack.ExpandableStackBase;
|
||||
pfCurFiber->StackLimit = usFiberStack.ExpandableStackLimit;
|
||||
pfCurFiber->DeallocationStack = usFiberStack.ExpandableStackBottom;
|
||||
}
|
||||
/* 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(), &usFiberStack);
|
||||
|
||||
l_CleanupFiber:
|
||||
/* free the fiber */
|
||||
RtlFreeHeap(pTeb->Peb->ProcessHeap, 0, pfCurFiber);
|
||||
|
||||
/* failure */
|
||||
assert(!NT_SUCCESS(nErrCode));
|
||||
SetLastErrorByStatus(nErrCode);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* SwitchToFiber
|
||||
*/
|
||||
VOID
|
||||
STDCALL
|
||||
SwitchToFiber(
|
||||
LPVOID lpFiber
|
||||
)
|
||||
void WINAPI DeleteFiber(LPVOID lpFiber)
|
||||
{
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
return;
|
||||
SIZE_T nSize = 0;
|
||||
PVOID pStackAllocBase = ((PFIBER)lpFiber)->DeallocationStack;
|
||||
PTEB pTeb = NtCurrentTeb();
|
||||
|
||||
/* free the fiber */
|
||||
RtlFreeHeap(pTeb->Peb->ProcessHeap, 0, lpFiber);
|
||||
|
||||
/* the fiber is deleting itself: let the system deallocate the stack */
|
||||
if(pTeb->Tib.Fib.FiberData == lpFiber) ExitThread(1);
|
||||
|
||||
/* 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)
|
||||
{
|
||||
/* FIXME? this should be pretty accurate */
|
||||
ThreadStartup(lpStartAddress, NtCurrentTeb()->Tib.Fib.FiberData);
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
55
reactos/lib/kernel32/thread/fls.c
Normal file
55
reactos/lib/kernel32/thread/fls.c
Normal file
|
@ -0,0 +1,55 @@
|
|||
/* $Id: fls.c,v 1.1 2003/05/29 00:36:41 hyperion Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS system libraries
|
||||
* FILE: lib/kernel32/thread/fls.c
|
||||
* PURPOSE: Fiber local storage functions
|
||||
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
|
||||
*
|
||||
* UPDATE HISTORY:
|
||||
* 28/05/2003 - created. Stubs only
|
||||
*
|
||||
*/
|
||||
|
||||
#include <k32.h>
|
||||
|
||||
#include <kernel32/kernel32.h>
|
||||
|
||||
DWORD WINAPI FlsAlloc(PFLS_CALLBACK_FUNCTION lpCallback)
|
||||
{
|
||||
(void)lpCallback;
|
||||
|
||||
UNIMPLEMENTED;
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
return FLS_OUT_OF_INDEXES;
|
||||
}
|
||||
|
||||
BOOL WINAPI FlsFree(DWORD dwFlsIndex)
|
||||
{
|
||||
(void)dwFlsIndex;
|
||||
|
||||
UNIMPLEMENTED;
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
PVOID WINAPI FlsGetValue(DWORD dwFlsIndex)
|
||||
{
|
||||
(void)dwFlsIndex;
|
||||
|
||||
UNIMPLEMENTED;
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BOOL WINAPI FlsSetValue(DWORD dwFlsIndex, PVOID lpFlsData)
|
||||
{
|
||||
(void)dwFlsIndex;
|
||||
(void)lpFlsData;
|
||||
|
||||
UNIMPLEMENTED;
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* EOF */
|
94
reactos/lib/kernel32/thread/i386/fiber.S
Normal file
94
reactos/lib/kernel32/thread/i386/fiber.S
Normal file
|
@ -0,0 +1,94 @@
|
|||
/* $Id: fiber.S,v 1.1 2003/05/29 00:36:41 hyperion Exp $
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
.extern _DbgPrint
|
||||
|
||||
.globl _SwitchToFiber@4
|
||||
|
||||
_SwitchToFiber@4:
|
||||
|
||||
ErrStr:
|
||||
.ascii \
|
||||
"(KERNEL32:" __FILE__ ") Saving and restoring the floating point context \
|
||||
currently unimplemented\n\0"
|
||||
|
||||
movl %fs:0x18, %ecx /* Teb = NtCurrentTeb() */
|
||||
|
||||
/* get the current fiber */
|
||||
movl 0x10(%ecx), %eax /* Fiber = Teb->Tib.Fib.FiberData */
|
||||
|
||||
/* 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->StackBottom */
|
||||
movl 0x0(%esp), %edx
|
||||
movl %edx, 0x18(%eax) /* Fiber->Eip = [esp] */
|
||||
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 */
|
||||
|
||||
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->StackBottom */
|
||||
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_NoFloatSave
|
||||
|
||||
/* restore the floating point context */
|
||||
/* TODO */
|
||||
pushl ErrStr
|
||||
call _DbgPrint
|
||||
popl %ecx
|
||||
|
||||
l_NoFloatRestore:
|
||||
|
||||
/* jump to the saved program counter */
|
||||
jmp *%edx
|
||||
|
||||
/* EOF */
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: thread.c,v 1.39 2003/04/30 22:00:41 gvg Exp $
|
||||
/* $Id: thread.c,v 1.40 2003/05/29 00:36:41 hyperion Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS system libraries
|
||||
|
@ -35,9 +35,11 @@ _except_handler(EXCEPTION_RECORD *ExceptionRecord,
|
|||
}
|
||||
|
||||
|
||||
static VOID STDCALL
|
||||
ThreadStartup(LPTHREAD_START_ROUTINE lpStartAddress,
|
||||
LPVOID lpParameter)
|
||||
__declspec(noreturn) void STDCALL ThreadStartup
|
||||
(
|
||||
LPTHREAD_START_ROUTINE lpStartAddress,
|
||||
LPVOID lpParameter
|
||||
)
|
||||
{
|
||||
UINT uExitCode;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# $Id: makefile,v 1.1 2003/04/29 02:17:01 hyperion Exp $
|
||||
# $Id: makefile,v 1.2 2003/05/29 00:36:41 hyperion Exp $
|
||||
|
||||
PATH_TO_TOP = ../..
|
||||
|
||||
|
@ -8,7 +8,8 @@ TARGET_NAME = rosrtl
|
|||
|
||||
THREAD_OBJECTS = \
|
||||
thread/context.o \
|
||||
thread/create.o
|
||||
thread/create.o \
|
||||
thread/stack.o
|
||||
|
||||
TARGET_OBJECTS = $(THREAD_OBJECTS)
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: context.c,v 1.1 2003/04/29 02:17:01 hyperion Exp $
|
||||
/* $Id: context.c,v 1.2 2003/05/29 00:36:41 hyperion Exp $
|
||||
*/
|
||||
/*
|
||||
*/
|
||||
|
@ -16,8 +16,8 @@
|
|||
NTSTATUS NTAPI RtlRosInitializeContextEx
|
||||
(
|
||||
IN HANDLE ProcessHandle,
|
||||
IN PCONTEXT Context,
|
||||
IN PTHREAD_START_ROUTINE StartAddress,
|
||||
OUT PCONTEXT Context,
|
||||
IN PVOID StartAddress,
|
||||
IN PUSER_STACK UserStack,
|
||||
IN ULONG ParameterCount,
|
||||
IN ULONG_PTR * Parameters
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: create.c,v 1.1 2003/04/29 02:17:01 hyperion Exp $
|
||||
/* $Id: create.c,v 1.2 2003/05/29 00:36:41 hyperion Exp $
|
||||
*/
|
||||
/*
|
||||
*/
|
||||
|
@ -18,7 +18,7 @@ NTSTATUS STDCALL RtlRosCreateUserThreadEx
|
|||
IN LONG StackZeroBits,
|
||||
IN OUT PULONG StackReserve OPTIONAL,
|
||||
IN OUT PULONG StackCommit OPTIONAL,
|
||||
IN PTHREAD_START_ROUTINE StartAddress,
|
||||
IN PVOID StartAddress,
|
||||
OUT PHANDLE ThreadHandle OPTIONAL,
|
||||
OUT PCLIENT_ID ClientId OPTIONAL,
|
||||
IN ULONG ParameterCount,
|
||||
|
@ -27,13 +27,6 @@ NTSTATUS STDCALL RtlRosCreateUserThreadEx
|
|||
{
|
||||
USER_STACK usUserStack;
|
||||
OBJECT_ATTRIBUTES oaThreadAttribs;
|
||||
/* FIXME: read the defaults from the executable image */
|
||||
ULONG_PTR nStackReserve = 0x100000;
|
||||
/* FIXME: when we finally have exception handling, make this PAGE_SIZE */
|
||||
ULONG_PTR nStackCommit = 0x100000;
|
||||
ULONG_PTR nSize = 0;
|
||||
PVOID pStackLowest = NULL;
|
||||
ULONG nDummy;
|
||||
CONTEXT ctxInitialContext;
|
||||
NTSTATUS nErrCode;
|
||||
HANDLE hThread;
|
||||
|
@ -41,130 +34,19 @@ NTSTATUS STDCALL RtlRosCreateUserThreadEx
|
|||
|
||||
if(ThreadHandle == NULL) ThreadHandle = &hThread;
|
||||
if(ClientId == NULL) ClientId = &cidClientId;
|
||||
|
||||
/* allocate the stack for the thread */
|
||||
nErrCode = RtlRosCreateStack
|
||||
(
|
||||
ProcessHandle,
|
||||
&usUserStack,
|
||||
StackZeroBits,
|
||||
StackReserve,
|
||||
StackCommit
|
||||
);
|
||||
|
||||
if(StackReserve == NULL) StackReserve = &nStackReserve;
|
||||
else ROUNDUP(*StackReserve, PAGE_SIZE);
|
||||
|
||||
if(StackCommit == NULL) StackCommit = &nStackCommit;
|
||||
else ROUNDUP(*StackCommit, PAGE_SIZE);
|
||||
|
||||
#if 0
|
||||
/* the stack commit size must be equal to or less than the reserve size */
|
||||
if(*StackCommit > *StackReserve) *StackCommit = *StackReserve;
|
||||
#else
|
||||
/* FIXME: no SEH, no guard pages */
|
||||
*StackCommit = *StackReserve;
|
||||
#endif
|
||||
|
||||
usUserStack.FixedStackBase = NULL;
|
||||
usUserStack.FixedStackLimit = NULL;
|
||||
usUserStack.ExpandableStackBase = NULL;
|
||||
usUserStack.ExpandableStackLimit = NULL;
|
||||
usUserStack.ExpandableStackBottom = NULL;
|
||||
|
||||
/* FIXME: this code assumes a stack growing downwards */
|
||||
/* fixed stack */
|
||||
if(*StackCommit == *StackReserve)
|
||||
{
|
||||
usUserStack.FixedStackLimit = NULL;
|
||||
|
||||
/* allocate the stack */
|
||||
nErrCode = NtAllocateVirtualMemory
|
||||
(
|
||||
ProcessHandle,
|
||||
&(usUserStack.FixedStackLimit),
|
||||
StackZeroBits,
|
||||
StackReserve,
|
||||
MEM_RESERVE | MEM_COMMIT,
|
||||
PAGE_READWRITE
|
||||
);
|
||||
|
||||
/* failure */
|
||||
if(!NT_SUCCESS(nErrCode)) goto l_Fail;
|
||||
|
||||
/* store the highest (first) address of the stack */
|
||||
usUserStack.FixedStackBase =
|
||||
(PUCHAR)(usUserStack.FixedStackLimit) + *StackReserve;
|
||||
|
||||
*StackCommit = *StackReserve;
|
||||
}
|
||||
/* expandable stack */
|
||||
else
|
||||
{
|
||||
ULONG_PTR nGuardSize = PAGE_SIZE;
|
||||
PVOID pGuardBase;
|
||||
|
||||
DPRINT("Expandable stack\n");
|
||||
|
||||
usUserStack.FixedStackLimit = NULL;
|
||||
usUserStack.FixedStackBase = NULL;
|
||||
usUserStack.ExpandableStackBottom = NULL;
|
||||
|
||||
/* reserve the stack */
|
||||
nErrCode = NtAllocateVirtualMemory
|
||||
(
|
||||
ProcessHandle,
|
||||
&(usUserStack.ExpandableStackBottom),
|
||||
StackZeroBits,
|
||||
StackReserve,
|
||||
MEM_RESERVE,
|
||||
PAGE_READWRITE
|
||||
);
|
||||
|
||||
/* failure */
|
||||
if(!NT_SUCCESS(nErrCode)) goto l_Fail;
|
||||
|
||||
DPRINT("Reserved %08X bytes\n", *StackReserve);
|
||||
|
||||
/* expandable stack base - the highest address of the stack */
|
||||
usUserStack.ExpandableStackBase =
|
||||
(PUCHAR)(usUserStack.ExpandableStackBottom) + *StackReserve;
|
||||
|
||||
/* expandable stack limit - the lowest committed address of the stack */
|
||||
usUserStack.ExpandableStackLimit =
|
||||
(PUCHAR)(usUserStack.ExpandableStackBase) - *StackCommit;
|
||||
|
||||
DPRINT("Stack base %p\n", usUserStack.ExpandableStackBase);
|
||||
DPRINT("Stack limit %p\n", usUserStack.ExpandableStackLimit);
|
||||
DPRINT("Stack bottom %p\n", usUserStack.ExpandableStackBottom);
|
||||
|
||||
/* commit as much stack as requested */
|
||||
nErrCode = NtAllocateVirtualMemory
|
||||
(
|
||||
ProcessHandle,
|
||||
&(usUserStack.ExpandableStackLimit),
|
||||
0,
|
||||
StackCommit,
|
||||
MEM_COMMIT,
|
||||
PAGE_READWRITE
|
||||
);
|
||||
|
||||
/* failure */
|
||||
if(!NT_SUCCESS(nErrCode)) goto l_Fail;
|
||||
|
||||
assert((*StackReserve - *StackCommit) >= PAGE_SIZE);
|
||||
assert((*StackReserve - *StackCommit) % PAGE_SIZE == 0);
|
||||
|
||||
pGuardBase = (PUCHAR)(usUserStack.ExpandableStackLimit) - PAGE_SIZE;
|
||||
|
||||
DPRINT("Guard base %p\n", usUserStack.ExpandableStackBase);
|
||||
|
||||
/* set up the guard page */
|
||||
nErrCode = NtAllocateVirtualMemory
|
||||
(
|
||||
ProcessHandle,
|
||||
&pGuardBase,
|
||||
0,
|
||||
&nGuardSize,
|
||||
MEM_COMMIT,
|
||||
PAGE_READWRITE | PAGE_GUARD
|
||||
);
|
||||
|
||||
/* failure */
|
||||
if(!NT_SUCCESS(nErrCode)) goto l_Fail;
|
||||
|
||||
DPRINT("Guard base %p\n", usUserStack.ExpandableStackBase);
|
||||
}
|
||||
/* failure */
|
||||
if(!NT_SUCCESS(nErrCode)) goto l_Fail;
|
||||
|
||||
/* initialize the registers and stack for the thread */
|
||||
nErrCode = RtlRosInitializeContextEx
|
||||
|
@ -178,7 +60,7 @@ NTSTATUS STDCALL RtlRosCreateUserThreadEx
|
|||
);
|
||||
|
||||
/* failure */
|
||||
if(!NT_SUCCESS(nErrCode)) goto l_Cleanup;
|
||||
if(!NT_SUCCESS(nErrCode)) goto l_Fail;
|
||||
|
||||
/* create the thread object */
|
||||
nErrCode = NtCreateThread
|
||||
|
@ -194,25 +76,18 @@ NTSTATUS STDCALL RtlRosCreateUserThreadEx
|
|||
);
|
||||
|
||||
/* failure */
|
||||
if(!NT_SUCCESS(nErrCode)) goto l_Cleanup;
|
||||
if(!NT_SUCCESS(nErrCode)) goto l_Fail;
|
||||
|
||||
/* success */
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
/* deallocate the stack */
|
||||
l_Cleanup:
|
||||
if(usUserStack.FixedStackLimit)
|
||||
pStackLowest = usUserStack.FixedStackLimit;
|
||||
else if(usUserStack.ExpandableStackBottom)
|
||||
pStackLowest = usUserStack.ExpandableStackBottom;
|
||||
|
||||
/* free the stack, if it was allocated */
|
||||
if(pStackLowest != NULL)
|
||||
NtFreeVirtualMemory(ProcessHandle, &pStackLowest, &nSize, MEM_RELEASE);
|
||||
|
||||
/* failure */
|
||||
l_Fail:
|
||||
assert(!NT_SUCCESS(nErrCode));
|
||||
|
||||
/* deallocate the stack */
|
||||
RtlRosDeleteStack(ProcessHandle, &usUserStack);
|
||||
|
||||
return nErrCode;
|
||||
}
|
||||
|
||||
|
@ -224,7 +99,7 @@ NTSTATUS CDECL RtlRosCreateUserThreadVa
|
|||
IN LONG StackZeroBits,
|
||||
IN OUT PULONG StackReserve OPTIONAL,
|
||||
IN OUT PULONG StackCommit OPTIONAL,
|
||||
IN PTHREAD_START_ROUTINE StartAddress,
|
||||
IN PVOID StartAddress,
|
||||
OUT PHANDLE ThreadHandle OPTIONAL,
|
||||
OUT PCLIENT_ID ClientId OPTIONAL,
|
||||
IN ULONG ParameterCount,
|
||||
|
|
187
reactos/lib/rosrtl/thread/stack.c
Normal file
187
reactos/lib/rosrtl/thread/stack.c
Normal file
|
@ -0,0 +1,187 @@
|
|||
/* $Id: stack.c,v 1.1 2003/05/29 00:36:41 hyperion Exp $
|
||||
*/
|
||||
/*
|
||||
*/
|
||||
|
||||
#include <ddk/ntddk.h>
|
||||
#include <rosrtl/thread.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include <ntdll/ntdll.h>
|
||||
|
||||
NTSTATUS NTAPI RtlRosCreateStack
|
||||
(
|
||||
IN HANDLE ProcessHandle,
|
||||
OUT PUSER_STACK UserStack,
|
||||
IN LONG StackZeroBits,
|
||||
IN OUT PULONG StackReserve OPTIONAL,
|
||||
IN OUT PULONG StackCommit OPTIONAL
|
||||
)
|
||||
{
|
||||
/* FIXME: read the defaults from the executable image */
|
||||
ULONG_PTR nStackReserve = 0x100000;
|
||||
/* FIXME: when we finally have exception handling, make this PAGE_SIZE */
|
||||
ULONG_PTR nStackCommit = 0x100000;
|
||||
PVOID pStackLowest;
|
||||
ULONG_PTR nSize = 0;
|
||||
NTSTATUS nErrCode;
|
||||
|
||||
if(StackReserve == NULL) StackReserve = &nStackReserve;
|
||||
else ROUNDUP(*StackReserve, PAGE_SIZE);
|
||||
|
||||
if(StackCommit == NULL) StackCommit = &nStackCommit;
|
||||
else ROUNDUP(*StackCommit, PAGE_SIZE);
|
||||
|
||||
#if 0
|
||||
/* the stack commit size must be equal to or less than the reserve size */
|
||||
if(*StackCommit > *StackReserve) *StackCommit = *StackReserve;
|
||||
#else
|
||||
/* FIXME: no SEH, no guard pages */
|
||||
*StackCommit = *StackReserve;
|
||||
#endif
|
||||
|
||||
/* FIXME: this code assumes a stack growing downwards */
|
||||
/* fixed stack */
|
||||
if(*StackCommit == *StackReserve)
|
||||
{
|
||||
UserStack->ExpandableStackBase = NULL;
|
||||
UserStack->ExpandableStackLimit = NULL;
|
||||
UserStack->ExpandableStackBottom = NULL;
|
||||
|
||||
UserStack->FixedStackLimit = NULL;
|
||||
|
||||
/* allocate the stack */
|
||||
nErrCode = NtAllocateVirtualMemory
|
||||
(
|
||||
ProcessHandle,
|
||||
&(UserStack->FixedStackLimit),
|
||||
StackZeroBits,
|
||||
StackReserve,
|
||||
MEM_RESERVE | MEM_COMMIT,
|
||||
PAGE_READWRITE
|
||||
);
|
||||
|
||||
/* failure */
|
||||
if(!NT_SUCCESS(nErrCode)) goto l_Fail;
|
||||
|
||||
/* store the highest (first) address of the stack */
|
||||
UserStack->FixedStackBase =
|
||||
(PUCHAR)(UserStack->FixedStackLimit) + *StackReserve;
|
||||
|
||||
*StackCommit = *StackReserve;
|
||||
}
|
||||
/* expandable stack */
|
||||
else
|
||||
{
|
||||
ULONG_PTR nGuardSize = PAGE_SIZE;
|
||||
PVOID pGuardBase;
|
||||
|
||||
DPRINT("Expandable stack\n");
|
||||
|
||||
UserStack->FixedStackBase = NULL;
|
||||
UserStack->FixedStackLimit = NULL;
|
||||
|
||||
UserStack->ExpandableStackBottom = NULL;
|
||||
|
||||
/* reserve the stack */
|
||||
nErrCode = NtAllocateVirtualMemory
|
||||
(
|
||||
ProcessHandle,
|
||||
&(UserStack->ExpandableStackBottom),
|
||||
StackZeroBits,
|
||||
StackReserve,
|
||||
MEM_RESERVE,
|
||||
PAGE_READWRITE
|
||||
);
|
||||
|
||||
/* failure */
|
||||
if(!NT_SUCCESS(nErrCode)) goto l_Fail;
|
||||
|
||||
DPRINT("Reserved %08X bytes\n", *StackReserve);
|
||||
|
||||
/* expandable stack base - the highest address of the stack */
|
||||
UserStack->ExpandableStackBase =
|
||||
(PUCHAR)(UserStack->ExpandableStackBottom) + *StackReserve;
|
||||
|
||||
/* expandable stack limit - the lowest committed address of the stack */
|
||||
UserStack->ExpandableStackLimit =
|
||||
(PUCHAR)(UserStack->ExpandableStackBase) - *StackCommit;
|
||||
|
||||
DPRINT("Stack base %p\n", UserStack->ExpandableStackBase);
|
||||
DPRINT("Stack limit %p\n", UserStack->ExpandableStackLimit);
|
||||
DPRINT("Stack bottom %p\n", UserStack->ExpandableStackBottom);
|
||||
|
||||
/* commit as much stack as requested */
|
||||
nErrCode = NtAllocateVirtualMemory
|
||||
(
|
||||
ProcessHandle,
|
||||
&(UserStack->ExpandableStackLimit),
|
||||
0,
|
||||
StackCommit,
|
||||
MEM_COMMIT,
|
||||
PAGE_READWRITE
|
||||
);
|
||||
|
||||
/* failure */
|
||||
if(!NT_SUCCESS(nErrCode)) goto l_Cleanup;
|
||||
|
||||
assert((*StackReserve - *StackCommit) >= PAGE_SIZE);
|
||||
assert((*StackReserve - *StackCommit) % PAGE_SIZE == 0);
|
||||
|
||||
pGuardBase = (PUCHAR)(UserStack->ExpandableStackLimit) - PAGE_SIZE;
|
||||
|
||||
DPRINT("Guard base %p\n", UserStack->ExpandableStackBase);
|
||||
|
||||
/* set up the guard page */
|
||||
nErrCode = NtAllocateVirtualMemory
|
||||
(
|
||||
ProcessHandle,
|
||||
&pGuardBase,
|
||||
0,
|
||||
&nGuardSize,
|
||||
MEM_COMMIT,
|
||||
PAGE_READWRITE | PAGE_GUARD
|
||||
);
|
||||
|
||||
/* failure */
|
||||
if(!NT_SUCCESS(nErrCode)) goto l_Cleanup;
|
||||
|
||||
DPRINT("Guard base %p\n", UserStack->ExpandableStackBase);
|
||||
}
|
||||
|
||||
|
||||
/* success */
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
/* deallocate the stack */
|
||||
l_Cleanup:
|
||||
RtlRosDeleteStack(ProcessHandle, UserStack);
|
||||
|
||||
/* failure */
|
||||
l_Fail:
|
||||
assert(!NT_SUCCESS(nErrCode));
|
||||
return nErrCode;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI RtlRosDeleteStack
|
||||
(
|
||||
IN HANDLE ProcessHandle,
|
||||
IN PUSER_STACK UserStack
|
||||
)
|
||||
{
|
||||
PVOID pStackLowest = NULL;
|
||||
ULONG_PTR nSize;
|
||||
|
||||
if(UserStack->FixedStackLimit)
|
||||
pStackLowest = UserStack->FixedStackLimit;
|
||||
else if(UserStack->ExpandableStackBottom)
|
||||
pStackLowest = UserStack->ExpandableStackBottom;
|
||||
|
||||
/* free the stack, if it was allocated */
|
||||
if(pStackLowest != NULL)
|
||||
return NtFreeVirtualMemory(ProcessHandle, &pStackLowest, &nSize, MEM_RELEASE);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* EOF */
|
Loading…
Reference in a new issue