- 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 */ /* FindNextPrinterNotification */
/* FlsAlloc */
#define FLS_OUT_OF_INDEXES (0xFFFFFFFF)
/* FMExtensionProc */ /* FMExtensionProc */
/* FoldString */ /* FoldString */

View file

@ -1515,6 +1515,7 @@ GetThreadTimes(
); );
__declspec(noreturn)
VOID VOID
STDCALL STDCALL
ExitThread( ExitThread(
@ -2796,6 +2797,16 @@ TlsFree(
DWORD dwTlsIndex 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 DWORD
STDCALL STDCALL
SleepEx( SleepEx(
@ -7569,45 +7580,38 @@ SHLoadInProc (REFCLSID);
/* Win32 Fibers */ /* Win32 Fibers */
typedef typedef VOID (WINAPI * PFIBER_START_ROUTINE) (IN LPVOID lpFiberArgument);
VOID (WINAPI *PFIBER_START_ROUTINE) (
IN LPVOID lpFiberArgument
);
typedef PFIBER_START_ROUTINE LPFIBER_START_ROUTINE; typedef PFIBER_START_ROUTINE LPFIBER_START_ROUTINE;
LPVOID #define FIBER_FLAG_FLOAT_SWITCH (1)
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
);
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 WINBOOL STDCALL
RegisterServicesProcess(DWORD ServicesProcessId); RegisterServicesProcess(DWORD ServicesProcessId);

View file

@ -179,7 +179,7 @@ typedef struct _TEB
ULONG LastErrorValue; // 34h ULONG LastErrorValue; // 34h
ULONG CountOfOwnedCriticalSections; // 38h ULONG CountOfOwnedCriticalSections; // 38h
PVOID CsrClientThread; // 3Ch PVOID CsrClientThread; // 3Ch
struct _W32THREAD* Win32ThreadInfo; // 40h struct _W32THREAD* Win32ThreadInfo; // 40h
ULONG Win32ClientInfo[0x1F]; // 44h ULONG Win32ClientInfo[0x1F]; // 44h
PVOID WOW32Reserved; // C0h PVOID WOW32Reserved; // C0h
ULONG CurrentLocale; // C4h ULONG CurrentLocale; // C4h
@ -220,9 +220,11 @@ typedef struct _TEB
PVOID Instrumentation[0x10]; // F2Ch PVOID Instrumentation[0x10]; // F2Ch
PVOID WinSockData; // F6Ch PVOID WinSockData; // F6Ch
ULONG GdiBatchCount; // F70h ULONG GdiBatchCount; // F70h
ULONG Spare2; // F74h // NOTE: RtlExitUserThread writes something here USHORT Spare2; // F74h
ULONG Spare3; // F78h BOOLEAN IsFiber; // F76h
ULONG Spare4; // F7Ch UCHAR Spare3; // F77h
ULONG Spare4; // F78h
ULONG Spare5; // F7Ch
PVOID ReservedForOle; // F80h PVOID ReservedForOle; // F80h
ULONG WaitingOnLoaderLock; // F84h ULONG WaitingOnLoaderLock; // F84h
PVOID WineDebugInfo; // Needed for WINE DLL's 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 #ifdef __cplusplus
@ -14,7 +14,7 @@ NTSTATUS STDCALL RtlRosCreateUserThreadEx
IN LONG StackZeroBits, IN LONG StackZeroBits,
IN OUT PULONG StackReserve OPTIONAL, IN OUT PULONG StackReserve OPTIONAL,
IN OUT PULONG StackCommit OPTIONAL, IN OUT PULONG StackCommit OPTIONAL,
IN PTHREAD_START_ROUTINE StartAddress, IN PVOID StartAddress,
OUT PHANDLE ThreadHandle OPTIONAL, OUT PHANDLE ThreadHandle OPTIONAL,
OUT PCLIENT_ID ClientId OPTIONAL, OUT PCLIENT_ID ClientId OPTIONAL,
IN ULONG ParameterCount, IN ULONG ParameterCount,
@ -29,7 +29,7 @@ NTSTATUS CDECL RtlRosCreateUserThreadVa
IN LONG StackZeroBits, IN LONG StackZeroBits,
IN OUT PULONG StackReserve OPTIONAL, IN OUT PULONG StackReserve OPTIONAL,
IN OUT PULONG StackCommit OPTIONAL, IN OUT PULONG StackCommit OPTIONAL,
IN PTHREAD_START_ROUTINE StartAddress, IN PVOID StartAddress,
OUT PHANDLE ThreadHandle OPTIONAL, OUT PHANDLE ThreadHandle OPTIONAL,
OUT PCLIENT_ID ClientId OPTIONAL, OUT PCLIENT_ID ClientId OPTIONAL,
IN ULONG ParameterCount, IN ULONG ParameterCount,
@ -39,13 +39,28 @@ NTSTATUS CDECL RtlRosCreateUserThreadVa
NTSTATUS NTAPI RtlRosInitializeContextEx NTSTATUS NTAPI RtlRosInitializeContextEx
( (
IN HANDLE ProcessHandle, IN HANDLE ProcessHandle,
IN PCONTEXT Context, OUT PCONTEXT Context,
IN PTHREAD_START_ROUTINE StartAddress, IN PVOID StartAddress,
IN PUSER_STACK UserStack, IN PUSER_STACK UserStack,
IN ULONG ParameterCount, IN ULONG ParameterCount,
IN ULONG_PTR * Parameters 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 #ifdef __cplusplus
} }
#endif #endif

View file

@ -171,6 +171,10 @@ FindResourceA@12
FindResourceExA@16 FindResourceExA@16
FindResourceExW@16 FindResourceExW@16
FindResourceW@12 FindResourceW@12
FlsAlloc@4
FlsFree@4
FlsGetValue@4
FlsSetValue@8
FlushConsoleInputBuffer@4 FlushConsoleInputBuffer@4
FlushFileBuffers@4 FlushFileBuffers@4
FlushInstructionCache@12 FlushInstructionCache@12
@ -239,7 +243,6 @@ GetCurrencyFormatW@24
GetCurrentConsoleFont@12 GetCurrentConsoleFont@12
GetCurrentDirectoryA@8 GetCurrentDirectoryA@8
GetCurrentDirectoryW@8 GetCurrentDirectoryW@8
GetCurrentFiber@0
GetCurrentProcess@0 GetCurrentProcess@0
GetCurrentProcessId@0 GetCurrentProcessId@0
GetCurrentThread@0 GetCurrentThread@0
@ -260,7 +263,6 @@ GetEnvironmentVariableA@12
GetEnvironmentVariableW@12 GetEnvironmentVariableW@12
GetExitCodeProcess@8 GetExitCodeProcess@8
GetExitCodeThread@8 GetExitCodeThread@8
GetFiberData@0
GetFileAttributesA@4 GetFileAttributesA@4
GetFileAttributesW@4 GetFileAttributesW@4
GetFileAttributesExA 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 ; kernel32.edf
; ;
@ -175,6 +175,10 @@ FindResourceA=FindResourceA@12
FindResourceExA=FindResourceExA@16 FindResourceExA=FindResourceExA@16
FindResourceExW=FindResourceExW@16 FindResourceExW=FindResourceExW@16
FindResourceW=FindResourceW@12 FindResourceW=FindResourceW@12
FlsAlloc=FlsAlloc@4
FlsFree=FlsFree@4
FlsGetValue=FlsGetValue@4
FlsSetValue=FlsSetValue@8
FlushConsoleInputBuffer=FlushConsoleInputBuffer@4 FlushConsoleInputBuffer=FlushConsoleInputBuffer@4
FlushFileBuffers=FlushFileBuffers@4 FlushFileBuffers=FlushFileBuffers@4
FlushInstructionCache=FlushInstructionCache@12 FlushInstructionCache=FlushInstructionCache@12
@ -243,7 +247,6 @@ GetCurrencyFormatW=GetCurrencyFormatW@24
GetCurrentConsoleFont=GetCurrentConsoleFont@12 GetCurrentConsoleFont=GetCurrentConsoleFont@12
GetCurrentDirectoryA=GetCurrentDirectoryA@8 GetCurrentDirectoryA=GetCurrentDirectoryA@8
GetCurrentDirectoryW=GetCurrentDirectoryW@8 GetCurrentDirectoryW=GetCurrentDirectoryW@8
GetCurrentFiber=GetCurrentFiber@0
GetCurrentProcess=GetCurrentProcess@0 GetCurrentProcess=GetCurrentProcess@0
GetCurrentProcessId=GetCurrentProcessId@0 GetCurrentProcessId=GetCurrentProcessId@0
GetCurrentThread=GetCurrentThread@0 GetCurrentThread=GetCurrentThread@0
@ -265,7 +268,6 @@ GetEnvironmentVariableA=GetEnvironmentVariableA@12
GetEnvironmentVariableW=GetEnvironmentVariableW@12 GetEnvironmentVariableW=GetEnvironmentVariableW@12
GetExitCodeProcess=GetExitCodeProcess@8 GetExitCodeProcess=GetExitCodeProcess@8
GetExitCodeThread=GetExitCodeThread@8 GetExitCodeThread=GetExitCodeThread@8
GetFiberData=GetFiberData@0
GetFileAttributesA=GetFileAttributesA@4 GetFileAttributesA=GetFileAttributesA@4
GetFileAttributesW=GetFileAttributesW@4 GetFileAttributesW=GetFileAttributesW@4
GetFileAttributesExA=GetFileAttributesExA@12 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 = ../.. PATH_TO_TOP = ../..
@ -44,7 +44,11 @@ NLS_OBJECTS =
THREAD_OBJECTS = \ THREAD_OBJECTS = \
thread/fiber.o \ thread/fiber.o \
thread/thread.o \ thread/thread.o \
thread/tls.o thread/tls.o \
thread/fls.o
THREAD_I386_OBJECTS = \
thread/i386/fiber.o
PROCESS_OBJECTS = \ PROCESS_OBJECTS = \
process/proc.o \ process/proc.o \
@ -58,9 +62,12 @@ EXCEPT_OBJECTS = except/except.o
DEBUG_OBJECTS = debug/debugger.o debug/output.o debug/break.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) \ TARGET_OBJECTS = $(MISC_OBJECTS) $(FILE_OBJECTS) $(THREAD_OBJECTS) \
$(PROCESS_OBJECTS) $(STRING_OBJECTS) $(MEM_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) 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 * FILE: lib/kernel32/thread/fiber.c
* *
@ -7,88 +7,264 @@
*/ */
#include <k32.h> #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 */
/********************************************************************** struct _EXCEPTION_REGISTRATION_RECORD * ExceptionList; /* 0x04 0x08 */
* ConvertThreadToFiber LPVOID StackBase; /* 0x08 0x10 */
*/ LPVOID StackLimit; /* 0x0C 0x18 */
LPVOID LPVOID DeallocationStack; /* 0x10 0x20 */
STDCALL ULONG_PTR Flags; /* 0x14 0x28 */
ConvertThreadToFiber( #if defined(_M_IX86)
LPVOID lpArgument /* 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); PTEB pTeb = NtCurrentTeb();
return NULL;
/* 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)
/**********************************************************************
* CreateFiber
*/
LPVOID
STDCALL
CreateFiber(
DWORD dwStackSize,
LPFIBER_START_ROUTINE lpStartAddress,
LPVOID lpArgument
)
{ {
SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return ConvertThreadToFiberEx(lpParameter, 0);
return NULL;
} }
LPVOID WINAPI ConvertThreadToFiberEx(LPVOID lpParameter, DWORD dwFlags)
/**********************************************************************
* DeleteFiber
*/
VOID
STDCALL
DeleteFiber(
LPVOID lpFiber
)
{ {
SetLastError(ERROR_CALL_NOT_IMPLEMENTED); PTEB pTeb = NtCurrentTeb();
return; 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
/********************************************************************** (
* GetCurrentFiber SIZE_T dwStackSize,
*/ LPFIBER_START_ROUTINE lpStartAddress,
PVOID LPVOID lpParameter
STDCALL )
GetCurrentFiber(VOID)
{ {
SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return CreateFiberEx(dwStackSize, 0, 0, lpStartAddress, lpParameter);
return NULL;
} }
LPVOID WINAPI CreateFiberEx
/********************************************************************** (
* GetFiberData SIZE_T dwStackCommitSize,
*/ SIZE_T dwStackReserveSize,
PVOID DWORD dwFlags,
STDCALL LPFIBER_START_ROUTINE lpStartAddress,
GetFiberData(VOID) LPVOID lpParameter
)
{ {
SetLastError(ERROR_CALL_NOT_IMPLEMENTED); PFIBER pfCurFiber;
return NULL; 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;
} }
void WINAPI DeleteFiber(LPVOID lpFiber)
/**********************************************************************
* SwitchToFiber
*/
VOID
STDCALL
SwitchToFiber(
LPVOID lpFiber
)
{ {
SetLastError(ERROR_CALL_NOT_IMPLEMENTED); SIZE_T nSize = 0;
return; 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 */ /* 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 * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries * PROJECT: ReactOS system libraries
@ -35,9 +35,11 @@ _except_handler(EXCEPTION_RECORD *ExceptionRecord,
} }
static VOID STDCALL __declspec(noreturn) void STDCALL ThreadStartup
ThreadStartup(LPTHREAD_START_ROUTINE lpStartAddress, (
LPVOID lpParameter) LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter
)
{ {
UINT uExitCode; 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 = ../.. PATH_TO_TOP = ../..
@ -8,7 +8,8 @@ TARGET_NAME = rosrtl
THREAD_OBJECTS = \ THREAD_OBJECTS = \
thread/context.o \ thread/context.o \
thread/create.o thread/create.o \
thread/stack.o
TARGET_OBJECTS = $(THREAD_OBJECTS) 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 NTSTATUS NTAPI RtlRosInitializeContextEx
( (
IN HANDLE ProcessHandle, IN HANDLE ProcessHandle,
IN PCONTEXT Context, OUT PCONTEXT Context,
IN PTHREAD_START_ROUTINE StartAddress, IN PVOID StartAddress,
IN PUSER_STACK UserStack, IN PUSER_STACK UserStack,
IN ULONG ParameterCount, IN ULONG ParameterCount,
IN ULONG_PTR * Parameters 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 LONG StackZeroBits,
IN OUT PULONG StackReserve OPTIONAL, IN OUT PULONG StackReserve OPTIONAL,
IN OUT PULONG StackCommit OPTIONAL, IN OUT PULONG StackCommit OPTIONAL,
IN PTHREAD_START_ROUTINE StartAddress, IN PVOID StartAddress,
OUT PHANDLE ThreadHandle OPTIONAL, OUT PHANDLE ThreadHandle OPTIONAL,
OUT PCLIENT_ID ClientId OPTIONAL, OUT PCLIENT_ID ClientId OPTIONAL,
IN ULONG ParameterCount, IN ULONG ParameterCount,
@ -27,13 +27,6 @@ NTSTATUS STDCALL RtlRosCreateUserThreadEx
{ {
USER_STACK usUserStack; USER_STACK usUserStack;
OBJECT_ATTRIBUTES oaThreadAttribs; 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; CONTEXT ctxInitialContext;
NTSTATUS nErrCode; NTSTATUS nErrCode;
HANDLE hThread; HANDLE hThread;
@ -41,130 +34,19 @@ NTSTATUS STDCALL RtlRosCreateUserThreadEx
if(ThreadHandle == NULL) ThreadHandle = &hThread; if(ThreadHandle == NULL) ThreadHandle = &hThread;
if(ClientId == NULL) ClientId = &cidClientId; if(ClientId == NULL) ClientId = &cidClientId;
/* allocate the stack for the thread */
nErrCode = RtlRosCreateStack
(
ProcessHandle,
&usUserStack,
StackZeroBits,
StackReserve,
StackCommit
);
if(StackReserve == NULL) StackReserve = &nStackReserve; /* failure */
else ROUNDUP(*StackReserve, PAGE_SIZE); if(!NT_SUCCESS(nErrCode)) goto l_Fail;
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);
}
/* initialize the registers and stack for the thread */ /* initialize the registers and stack for the thread */
nErrCode = RtlRosInitializeContextEx nErrCode = RtlRosInitializeContextEx
@ -178,7 +60,7 @@ NTSTATUS STDCALL RtlRosCreateUserThreadEx
); );
/* failure */ /* failure */
if(!NT_SUCCESS(nErrCode)) goto l_Cleanup; if(!NT_SUCCESS(nErrCode)) goto l_Fail;
/* create the thread object */ /* create the thread object */
nErrCode = NtCreateThread nErrCode = NtCreateThread
@ -194,25 +76,18 @@ NTSTATUS STDCALL RtlRosCreateUserThreadEx
); );
/* failure */ /* failure */
if(!NT_SUCCESS(nErrCode)) goto l_Cleanup; if(!NT_SUCCESS(nErrCode)) goto l_Fail;
/* success */ /* success */
return STATUS_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 */ /* failure */
l_Fail: l_Fail:
assert(!NT_SUCCESS(nErrCode)); assert(!NT_SUCCESS(nErrCode));
/* deallocate the stack */
RtlRosDeleteStack(ProcessHandle, &usUserStack);
return nErrCode; return nErrCode;
} }
@ -224,7 +99,7 @@ NTSTATUS CDECL RtlRosCreateUserThreadVa
IN LONG StackZeroBits, IN LONG StackZeroBits,
IN OUT PULONG StackReserve OPTIONAL, IN OUT PULONG StackReserve OPTIONAL,
IN OUT PULONG StackCommit OPTIONAL, IN OUT PULONG StackCommit OPTIONAL,
IN PTHREAD_START_ROUTINE StartAddress, IN PVOID StartAddress,
OUT PHANDLE ThreadHandle OPTIONAL, OUT PHANDLE ThreadHandle OPTIONAL,
OUT PCLIENT_ID ClientId OPTIONAL, OUT PCLIENT_ID ClientId OPTIONAL,
IN ULONG ParameterCount, 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 */