- Kernel32: implemented fibers. Almost complete - only lacks some Windows 2003 Serve...
authorKJK::Hyperion <hackbunny@reactos.org>
Thu, 29 May 2003 00:36:41 +0000 (00:36 +0000)
committerKJK::Hyperion <hackbunny@reactos.org>
Thu, 29 May 2003 00:36:41 +0000 (00:36 +0000)
 - 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

15 files changed:
reactos/include/defines.h
reactos/include/funcs.h
reactos/include/napi/teb.h
reactos/include/rosrtl/thread.h
reactos/lib/kernel32/kernel32.def
reactos/lib/kernel32/kernel32.edf
reactos/lib/kernel32/makefile
reactos/lib/kernel32/thread/fiber.c
reactos/lib/kernel32/thread/fls.c [new file with mode: 0644]
reactos/lib/kernel32/thread/i386/fiber.S [new file with mode: 0644]
reactos/lib/kernel32/thread/thread.c
reactos/lib/rosrtl/makefile
reactos/lib/rosrtl/thread/context.c
reactos/lib/rosrtl/thread/create.c
reactos/lib/rosrtl/thread/stack.c [new file with mode: 0644]

index e191776..1569a4b 100644 (file)
@@ -1136,6 +1136,9 @@ extern "C" {
 
 /* FindNextPrinterNotification */
 
+/* FlsAlloc */
+#define FLS_OUT_OF_INDEXES (0xFFFFFFFF)
+
 /* FMExtensionProc */
 
 /* FoldString */
index d4ce50b..f81c4e1 100644 (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);
index 0cf8beb..fa062d2 100644 (file)
@@ -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
index 3cca46a..023b54d 100644 (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
index 60deca5..33109d7 100644 (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
index 20121c5..3b4b1d2 100644 (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
index c68a56c..b4ba6bd 100644 (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)
index a460ec3..c7d89db 100644 (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
  *
  */
 #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 */
diff --git a/reactos/lib/kernel32/thread/fls.c b/reactos/lib/kernel32/thread/fls.c
new file mode 100644 (file)
index 0000000..bc2ee10
--- /dev/null
@@ -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 */
diff --git a/reactos/lib/kernel32/thread/i386/fiber.S b/reactos/lib/kernel32/thread/i386/fiber.S
new file mode 100644 (file)
index 0000000..b8ff836
--- /dev/null
@@ -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 */
index e87b725..a989bbd 100644 (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;
 
index 26ccb6a..f5f8055 100644 (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)
  
index fff8569..66b9d92 100644 (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
index af428c7..b0a68dd 100644 (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;
@@ -41,130 +34,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
-  (
-   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
@@ -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,
diff --git a/reactos/lib/rosrtl/thread/stack.c b/reactos/lib/rosrtl/thread/stack.c
new file mode 100644 (file)
index 0000000..d0a7eb1
--- /dev/null
@@ -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 */