Alexandre Julliard : ntdll: Allocate TEBs out of a larger memory block.

Alexandre Julliard julliard at winehq.org
Thu Apr 30 15:24:08 CDT 2020


Module: wine
Branch: master
Commit: dee934c0ff54851f049ab27b11d84c5a5810662c
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=dee934c0ff54851f049ab27b11d84c5a5810662c

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Thu Apr 30 10:05:56 2020 +0200

ntdll: Allocate TEBs out of a larger memory block.

Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/ntdll/ntdll_misc.h |   2 +-
 dlls/ntdll/thread.c     |  19 ++-------
 dlls/ntdll/virtual.c    | 103 ++++++++++++++++++++++++++++++++++++++----------
 3 files changed, 86 insertions(+), 38 deletions(-)

diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h
index 3e877593b6..a22b77b481 100644
--- a/dlls/ntdll/ntdll_misc.h
+++ b/dlls/ntdll/ntdll_misc.h
@@ -93,7 +93,6 @@ extern void debug_init(void) DECLSPEC_HIDDEN;
 extern TEB *thread_init(void) DECLSPEC_HIDDEN;
 extern void actctx_init(void) DECLSPEC_HIDDEN;
 extern void virtual_init(void) DECLSPEC_HIDDEN;
-extern void virtual_init_threading(void) DECLSPEC_HIDDEN;
 extern void fill_cpu_info(void) DECLSPEC_HIDDEN;
 extern void heap_set_debug_flags( HANDLE handle ) DECLSPEC_HIDDEN;
 extern void init_unix_codepage(void) DECLSPEC_HIDDEN;
@@ -200,6 +199,7 @@ extern NTSTATUS virtual_map_section( HANDLE handle, PVOID *addr_ptr, unsigned sh
                                      ULONG protect, pe_image_info_t *image_info ) DECLSPEC_HIDDEN;
 extern void virtual_get_system_info( SYSTEM_BASIC_INFORMATION *info ) DECLSPEC_HIDDEN;
 extern NTSTATUS virtual_create_builtin_view( void *base ) DECLSPEC_HIDDEN;
+extern TEB * virtual_alloc_first_teb(void) DECLSPEC_HIDDEN;
 extern NTSTATUS virtual_alloc_teb( TEB **teb ) DECLSPEC_HIDDEN;
 extern void virtual_free_teb( TEB *teb ) DECLSPEC_HIDDEN;
 extern NTSTATUS virtual_alloc_thread_stack( INITIAL_TEB *stack, SIZE_T reserve_size,
diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c
index 604fd20c84..d116c7bd57 100644
--- a/dlls/ntdll/thread.c
+++ b/dlls/ntdll/thread.c
@@ -246,13 +246,10 @@ TEB *thread_init(void)
     user_shared_data = addr;
     memcpy( user_shared_data->NtSystemRoot, default_windirW, sizeof(default_windirW) );
 
-    /* allocate and initialize the PEB */
-
-    addr = NULL;
-    size = sizeof(*peb);
-    virtual_alloc_aligned( &addr, 0, &size, MEM_COMMIT | MEM_TOP_DOWN, PAGE_READWRITE, 1 );
-    peb = addr;
+    /* allocate and initialize the PEB and initial TEB */
 
+    teb = virtual_alloc_first_teb();
+    peb = teb->Peb;
     peb->FastPebLock        = &peb_lock;
     peb->TlsBitmap          = &tls_bitmap;
     peb->TlsExpansionBitmap = &tls_expansion_bitmap;
@@ -282,21 +279,12 @@ TEB *thread_init(void)
      */
     peb->SessionId = 1;
 
-    /* allocate and initialize the initial TEB */
-
-    signal_init_threading();
-    virtual_alloc_teb( &teb );
-    teb->Peb = peb;
-    teb->Tib.StackBase = (void *)~0UL;
-
     thread_data = (struct ntdll_thread_data *)&teb->GdiTebBatch;
     thread_data->request_fd = -1;
     thread_data->reply_fd   = -1;
     thread_data->wait_fd[0] = -1;
     thread_data->wait_fd[1] = -1;
 
-    signal_init_thread( teb );
-    virtual_init_threading();
     debug_init();
     init_paths();
     set_process_name( __wine_main_argc, __wine_main_argv );
@@ -517,7 +505,6 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, SECURITY_DESCRIPTOR *descr,
 
     if ((status = virtual_alloc_teb( &teb ))) goto error;
 
-    teb->Peb = NtCurrentTeb()->Peb;
     teb->ClientId.UniqueProcess = ULongToHandle(GetCurrentProcessId());
     teb->ClientId.UniqueThread  = ULongToHandle(tid);
 
diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c
index 7be00a1ac2..5900616e0c 100644
--- a/dlls/ntdll/virtual.c
+++ b/dlls/ntdll/virtual.c
@@ -164,6 +164,11 @@ SIZE_T signal_stack_size = 0;
 SIZE_T signal_stack_mask = 0;
 static SIZE_T signal_stack_align;
 
+/* TEB allocation blocks */
+static TEB *teb_block;
+static TEB *next_free_teb;
+static int teb_block_pos;
+
 #define ROUND_ADDR(addr,mask) \
    ((void *)((UINT_PTR)(addr) & ~(UINT_PTR)(mask)))
 
@@ -2011,15 +2016,6 @@ void virtual_init(void)
 }
 
 
-/***********************************************************************
- *           virtual_init_threading
- */
-void virtual_init_threading(void)
-{
-    use_locks = TRUE;
-}
-
-
 /***********************************************************************
  *           virtual_get_system_info
  */
@@ -2093,29 +2089,90 @@ NTSTATUS virtual_create_builtin_view( void *module )
 }
 
 
+/***********************************************************************
+ *           virtual_alloc_first_teb
+ */
+TEB *virtual_alloc_first_teb(void)
+{
+    TEB *teb;
+    PEB *peb;
+    SIZE_T peb_size = page_size;
+    SIZE_T teb_size = signal_stack_mask + 1;
+    SIZE_T total = 32 * teb_size;
+
+    NtAllocateVirtualMemory( NtCurrentProcess(), (void **)&teb_block, 0, &total,
+                             MEM_RESERVE | MEM_TOP_DOWN, PAGE_READWRITE );
+    teb_block_pos = 30;
+    teb = (TEB *)((char *)teb_block + 30 * teb_size);
+    peb = (PEB *)((char *)teb_block + 32 * teb_size - peb_size);
+    NtAllocateVirtualMemory( NtCurrentProcess(), (void **)&teb, 0, &teb_size, MEM_COMMIT, PAGE_READWRITE );
+    NtAllocateVirtualMemory( NtCurrentProcess(), (void **)&peb, 0, &peb_size, MEM_COMMIT, PAGE_READWRITE );
+
+    teb->Peb = peb;
+    teb->Tib.Self = &teb->Tib;
+    teb->Tib.ExceptionList = (void *)~0ul;
+    teb->Tib.StackBase = (void *)~0ul;
+    teb->StaticUnicodeString.Buffer = teb->StaticUnicodeBuffer;
+    teb->StaticUnicodeString.MaximumLength = sizeof(teb->StaticUnicodeBuffer);
+    signal_init_threading();
+    signal_alloc_thread( teb );
+    signal_init_thread( teb );
+    use_locks = TRUE;
+    return teb;
+}
+
+
 /***********************************************************************
  *           virtual_alloc_teb
  */
 NTSTATUS virtual_alloc_teb( TEB **ret_teb )
 {
-    SIZE_T size = signal_stack_mask + 1;
-    void *addr = NULL;
-    TEB *teb;
-    NTSTATUS status;
+    sigset_t sigset;
+    TEB *teb = NULL;
+    NTSTATUS status = STATUS_SUCCESS;
+    SIZE_T teb_size = signal_stack_mask + 1;
 
-    if ((status = virtual_alloc_aligned( &addr, 0, &size, MEM_COMMIT | MEM_TOP_DOWN,
-                                         PAGE_READWRITE, signal_stack_align )))
-        return status;
+    server_enter_uninterrupted_section( &csVirtual, &sigset );
+    if (next_free_teb)
+    {
+        teb = next_free_teb;
+        next_free_teb = *(TEB **)teb;
+        memset( teb, 0, sizeof(*teb) );
+    }
+    else
+    {
+        if (!teb_block_pos)
+        {
+            void *addr = NULL;
+            SIZE_T total = 32 * teb_size;
 
-    *ret_teb = teb = addr;
+            if ((status = NtAllocateVirtualMemory( NtCurrentProcess(), &addr, 0, &total,
+                                                   MEM_RESERVE, PAGE_READWRITE )))
+            {
+                server_leave_uninterrupted_section( &csVirtual, &sigset );
+                return status;
+            }
+            teb_block = addr;
+            teb_block_pos = 32;
+        }
+        teb = (TEB *)((char *)teb_block + --teb_block_pos * teb_size);
+        NtAllocateVirtualMemory( NtCurrentProcess(), (void **)&teb, 0, &teb_size,
+                                 MEM_COMMIT, PAGE_READWRITE );
+    }
+    server_leave_uninterrupted_section( &csVirtual, &sigset );
+
+    *ret_teb = teb;
+    teb->Peb = NtCurrentTeb()->Peb;
     teb->Tib.Self = &teb->Tib;
     teb->Tib.ExceptionList = (void *)~0UL;
     teb->StaticUnicodeString.Buffer = teb->StaticUnicodeBuffer;
     teb->StaticUnicodeString.MaximumLength = sizeof(teb->StaticUnicodeBuffer);
     if ((status = signal_alloc_thread( teb )))
     {
-        size = 0;
-        NtFreeVirtualMemory( NtCurrentProcess(), &addr, &size, MEM_RELEASE );
+        server_enter_uninterrupted_section( &csVirtual, &sigset );
+        *(TEB **)teb = next_free_teb;
+        next_free_teb = teb;
+        server_leave_uninterrupted_section( &csVirtual, &sigset );
     }
     return status;
 }
@@ -2128,6 +2185,7 @@ void virtual_free_teb( TEB *teb )
 {
     struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)&teb->GdiTebBatch;
     SIZE_T size;
+    sigset_t sigset;
 
     signal_free_thread( teb );
     if (teb->DeallocationStack)
@@ -2140,8 +2198,11 @@ void virtual_free_teb( TEB *teb )
         size = 0;
         NtFreeVirtualMemory( GetCurrentProcess(), &thread_data->start_stack, &size, MEM_RELEASE );
     }
-    size = 0;
-    NtFreeVirtualMemory( NtCurrentProcess(), (void **)&teb, &size, MEM_RELEASE );
+
+    server_enter_uninterrupted_section( &csVirtual, &sigset );
+    *(TEB **)teb = next_free_teb;
+    next_free_teb = teb;
+    server_leave_uninterrupted_section( &csVirtual, &sigset );
 }
 
 




More information about the wine-cvs mailing list