- 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:
KJK::Hyperion 2003-05-29 00:36:41 +00:00
parent 2382d9e48e
commit 66080da575
15 changed files with 697 additions and 272 deletions

View file

@ -1136,6 +1136,9 @@ extern "C" {
/* FindNextPrinterNotification */
/* FlsAlloc */
#define FLS_OUT_OF_INDEXES (0xFFFFFFFF)
/* FMExtensionProc */
/* FoldString */

View file

@ -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);

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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 */
}
LPVOID WINAPI ConvertThreadToFiber(LPVOID lpParameter)
{
return ConvertThreadToFiberEx(lpParameter, 0);
}
/**********************************************************************
* CreateFiber
*/
LPVOID
STDCALL
CreateFiber(
DWORD dwStackSize,
LPVOID WINAPI ConvertThreadToFiberEx(LPVOID lpParameter, DWORD dwFlags)
{
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;
}
LPVOID WINAPI CreateFiber
(
SIZE_T dwStackSize,
LPFIBER_START_ROUTINE lpStartAddress,
LPVOID lpArgument
)
LPVOID lpParameter
)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return CreateFiberEx(dwStackSize, 0, 0, lpStartAddress, 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;
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;
}
/**********************************************************************
* DeleteFiber
*/
VOID
STDCALL
DeleteFiber(
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
);
/**********************************************************************
* GetCurrentFiber
*/
PVOID
STDCALL
GetCurrentFiber(VOID)
__declspec(noreturn) void WINAPI FiberStartup(PVOID lpStartAddress)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return NULL;
/* FIXME? this should be pretty accurate */
ThreadStartup(lpStartAddress, NtCurrentTeb()->Tib.Fib.FiberData);
}
/**********************************************************************
* GetFiberData
*/
PVOID
STDCALL
GetFiberData(VOID)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return NULL;
}
/**********************************************************************
* SwitchToFiber
*/
VOID
STDCALL
SwitchToFiber(
LPVOID lpFiber
)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return;
}
/* EOF */

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

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

View file

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

View file

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

View file

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

View file

@ -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;
@ -42,130 +35,19 @@ NTSTATUS STDCALL RtlRosCreateUserThreadEx
if(ThreadHandle == NULL) ThreadHandle = &hThread;
if(ClientId == NULL) ClientId = &cidClientId;
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
/* allocate the stack for the thread */
nErrCode = RtlRosCreateStack
(
ProcessHandle,
&(usUserStack.FixedStackLimit),
&usUserStack,
StackZeroBits,
StackReserve,
MEM_RESERVE | MEM_COMMIT,
PAGE_READWRITE
StackCommit
);
/* 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);
}
/* 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,

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