/* FindNextPrinterNotification */
+/* FlsAlloc */
+#define FLS_OUT_OF_INDEXES (0xFFFFFFFF)
+
/* FMExtensionProc */
/* FoldString */
);
+__declspec(noreturn)
VOID
STDCALL
ExitThread(
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(
/* 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);
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
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
-/* $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
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,
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,
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
FindResourceExA@16
FindResourceExW@16
FindResourceW@12
+FlsAlloc@4
+FlsFree@4
+FlsGetValue@4
+FlsSetValue@8
FlushConsoleInputBuffer@4
FlushFileBuffers@4
FlushInstructionCache@12
GetCurrentConsoleFont@12
GetCurrentDirectoryA@8
GetCurrentDirectoryW@8
-GetCurrentFiber@0
GetCurrentProcess@0
GetCurrentProcessId@0
GetCurrentThread@0
GetEnvironmentVariableW@12
GetExitCodeProcess@8
GetExitCodeThread@8
-GetFiberData@0
GetFileAttributesA@4
GetFileAttributesW@4
GetFileAttributesExA
-; $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
;
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
GetCurrentConsoleFont=GetCurrentConsoleFont@12
GetCurrentDirectoryA=GetCurrentDirectoryA@8
GetCurrentDirectoryW=GetCurrentDirectoryW@8
-GetCurrentFiber=GetCurrentFiber@0
GetCurrentProcess=GetCurrentProcess@0
GetCurrentProcessId=GetCurrentProcessId@0
GetCurrentThread=GetCurrentThread@0
GetEnvironmentVariableW=GetEnvironmentVariableW@12
GetExitCodeProcess=GetExitCodeProcess@8
GetExitCodeThread=GetExitCodeThread@8
-GetFiberData=GetFiberData@0
GetFileAttributesA=GetFileAttributesA@4
GetFileAttributesW=GetFileAttributesW@4
GetFileAttributesExA=GetFileAttributesExA@12
-# $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 = ../..
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 \
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)
-/* $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
*
*/
#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
- )
-{
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return NULL;
-}
+ 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 ---- */
-/**********************************************************************
- * CreateFiber
- */
-LPVOID
-STDCALL
-CreateFiber(
- DWORD dwStackSize,
- LPFIBER_START_ROUTINE lpStartAddress,
- LPVOID lpArgument
- )
+ /* 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;
+ }
-/**********************************************************************
- * DeleteFiber
- */
-VOID
-STDCALL
-DeleteFiber(
- LPVOID lpFiber
- )
+ /* 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)
{
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return;
+ return ConvertThreadToFiberEx(lpParameter, 0);
}
+LPVOID WINAPI ConvertThreadToFiberEx(LPVOID lpParameter, DWORD dwFlags)
+{
+ PTEB pTeb = NtCurrentTeb();
+ PFIBER pfCurFiber;
-/**********************************************************************
- * GetCurrentFiber
- */
-PVOID
-STDCALL
-GetCurrentFiber(VOID)
+ /* 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 lpParameter
+)
{
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return NULL;
+ 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();
-/**********************************************************************
- * GetFiberData
- */
-PVOID
-STDCALL
-GetFiberData(VOID)
+ /* 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)
{
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return NULL;
+ 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
+);
-/**********************************************************************
- * SwitchToFiber
- */
-VOID
-STDCALL
-SwitchToFiber(
- LPVOID lpFiber
- )
+__declspec(noreturn) void WINAPI FiberStartup(PVOID lpStartAddress)
{
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return;
+ /* FIXME? this should be pretty accurate */
+ ThreadStartup(lpStartAddress, NtCurrentTeb()->Tib.Fib.FiberData);
}
-
/* EOF */
--- /dev/null
+/* $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 */
--- /dev/null
+/* $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 */
-/* $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
}
-static VOID STDCALL
-ThreadStartup(LPTHREAD_START_ROUTINE lpStartAddress,
- LPVOID lpParameter)
+__declspec(noreturn) void STDCALL ThreadStartup
+(
+ LPTHREAD_START_ROUTINE lpStartAddress,
+ LPVOID lpParameter
+)
{
UINT uExitCode;
-# $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 = ../..
THREAD_OBJECTS = \
thread/context.o \
- thread/create.o
+ thread/create.o \
+ thread/stack.o
TARGET_OBJECTS = $(THREAD_OBJECTS)
-/* $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 $
*/
/*
*/
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
-/* $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 $
*/
/*
*/
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,
{
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;
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
- (
- 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);
- }
+ /* allocate the stack for the thread */
+ nErrCode = RtlRosCreateStack
+ (
+ ProcessHandle,
+ &usUserStack,
+ StackZeroBits,
+ StackReserve,
+ StackCommit
+ );
+
+ /* failure */
+ if(!NT_SUCCESS(nErrCode)) goto l_Fail;
/* initialize the registers and stack for the thread */
nErrCode = RtlRosInitializeContextEx
);
/* failure */
- if(!NT_SUCCESS(nErrCode)) goto l_Cleanup;
+ if(!NT_SUCCESS(nErrCode)) goto l_Fail;
/* create the thread object */
nErrCode = NtCreateThread
);
/* 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;
}
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,
--- /dev/null
+/* $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 */