2002-08-09 David Welch <welch@computer2.darkstar.org>
authorDavid Welch <welch@cwcom.net>
Fri, 9 Aug 2002 17:23:57 +0000 (17:23 +0000)
committerDavid Welch <welch@cwcom.net>
Fri, 9 Aug 2002 17:23:57 +0000 (17:23 +0000)
* ntoskrnl/ps/create.c (NtCreateThread): Call PsSuspendThread
if NtCreateThread has CreateSuspended as TRUE.
* ntoskrnl/ps/suspend.c (PsSuspendThread, PsResumeThread,
PiSuspendThreadKernelRoutine): Fixed suspend functionality.

2002-08-09  David Welch  <welch@computer2.darkstar.org>

* ntoskrnl/ke/i386/usertrap.c (print_user_address): Copy
the LDR variable from the right address.

2002-08-09  David Welch  <welch@computer2.darkstar.org>

* ntoskrnl/ke/apc.c (KiDeliverNormalApc): Check for
kernel APCs pending on exit from the kernel.
* ntoskrnl/ke/apc.c (KiDeliverNormalApc, KiDeliverUserApc,
KiDeliverApc): Set the APC's inserted flag to FALSE after
removing it from the thread's queue.

2002-08-09  David Welch  <welch@computer2.darkstar.org>

* lib/kernel32/thread/thread.c (ThreadStartup): Don't
call DLL entrypoints; this is done by LdrInitializeThunk.
* lib/ntdll/ldr/startup.c (LdrInitializeThunk): Call
DLLs in initialization order; take the loader lock before
calling.

2002-08-09  David Welch  <welch@computer2.darkstar.org>

* apps/tests/thread/thread.c (main): Test suspend and
resume functionality.

svn path=/trunk/; revision=3324

12 files changed:
reactos/ChangeLog
reactos/apps/tests/thread/thread.c
reactos/lib/kernel32/thread/thread.c
reactos/lib/ntdll/ldr/startup.c
reactos/ntoskrnl/include/internal/ps.h
reactos/ntoskrnl/ke/apc.c
reactos/ntoskrnl/ke/i386/usertrap.c
reactos/ntoskrnl/ke/kthread.c
reactos/ntoskrnl/ke/sem.c
reactos/ntoskrnl/ps/create.c
reactos/ntoskrnl/ps/psmgr.c
reactos/ntoskrnl/ps/suspend.c

index baffcc0..2fab6fc 100644 (file)
@@ -1,3 +1,36 @@
+2002-08-09  David Welch  <welch@computer2.darkstar.org>
+
+       * ntoskrnl/ps/create.c (NtCreateThread): Call PsSuspendThread
+       if NtCreateThread has CreateSuspended as TRUE.
+       * ntoskrnl/ps/suspend.c (PsSuspendThread, PsResumeThread,
+       PiSuspendThreadKernelRoutine): Fixed suspend functionality.
+
+2002-08-09  David Welch  <welch@computer2.darkstar.org>
+
+       * ntoskrnl/ke/i386/usertrap.c (print_user_address): Copy
+       the LDR variable from the right address.
+
+2002-08-09  David Welch  <welch@computer2.darkstar.org>
+
+       * ntoskrnl/ke/apc.c (KiDeliverNormalApc): Check for
+       kernel APCs pending on exit from the kernel.
+       * ntoskrnl/ke/apc.c (KiDeliverNormalApc, KiDeliverUserApc,
+       KiDeliverApc): Set the APC's inserted flag to FALSE after
+       removing it from the thread's queue.
+
+2002-08-09  David Welch  <welch@computer2.darkstar.org>
+
+       * lib/kernel32/thread/thread.c (ThreadStartup): Don't
+       call DLL entrypoints; this is done by LdrInitializeThunk.
+       * lib/ntdll/ldr/startup.c (LdrInitializeThunk): Call
+       DLLs in initialization order; take the loader lock before
+       calling.
+
+2002-08-09  David Welch  <welch@computer2.darkstar.org>
+
+       * apps/tests/thread/thread.c (main): Test suspend and
+       resume functionality.
+
 2002-08-08  David Welch  <welch@computer2.darkstar.org>
 
        * ntoskrnl/mm/section (NtQuerySection): Return the
index edb17e7..e781951 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: thread.c,v 1.7 2001/02/06 00:11:17 dwelch Exp $
+/* $Id: thread.c,v 1.8 2002/08/09 17:23:56 dwelch Exp $
  *
  *
  *
@@ -44,7 +44,7 @@ int main (int argc, char* argv[])
    DWORD i=0;
    DWORD id;
    ULONG nr;
-   
+   HANDLE ThreadHandle[NR_THREADS];
 
    // The user must supply one argument (the seed). if he/she doesn't
    // then we show the help.
@@ -60,16 +60,30 @@ int main (int argc, char* argv[])
    printf("Creating %d threads...\n",NR_THREADS*2);
    for (i=0;i<NR_THREADS;i++)
      {
-       CreateThread(NULL,
-                    0,
-                    thread_main1,
-                    (LPVOID)i,
-                    0,
-                    &id);
+       ThreadHandle[i] = CreateThread(NULL,
+                                     0,
+                                     thread_main1,
+                                     (LPVOID)i,
+                                     CREATE_SUSPENDED,
+                                     &id);
+
+     }
+
+   for (i=0;i<NR_THREADS;i++)
+     {
+       ResumeThread(ThreadHandle[i]);
+     }
 
+   for (i=0;i<NR_THREADS;i++)
+     {
+       SuspendThread(ThreadHandle[i]);
+     }
+
+   for (i=0;i<NR_THREADS;i++)
+     {
+       ResumeThread(ThreadHandle[i]);
      }
 
    printf("All threads created...\n");
-   for(;;);
    return 0;
 }
index 6f9aa24..0718f5f 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: thread.c,v 1.26 2001/08/15 20:35:39 ea Exp $
+/* $Id: thread.c,v 1.27 2002/08/09 17:23:56 dwelch Exp $
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS system libraries
 
 static VOID ThreadAttachDlls (VOID);
 
-/* Type for a DLL's entry point */
-typedef
-WINBOOL
-STDCALL
-(* PDLLMAIN_FUNC) (
-       HANDLE  hInst,
-       ULONG   ul_reason_for_call,
-       LPVOID  lpReserved
-       );
-
 /* FUNCTIONS *****************************************************************/
 
 static VOID STDCALL
@@ -44,8 +34,6 @@ ThreadStartup (LPTHREAD_START_ROUTINE lpStartAddress,
 {
    UINT uExitCode;
 
-   ThreadAttachDlls ();
-
    /* FIXME: notify csrss of thread creation ?? */
 
    uExitCode = (lpStartAddress)(lpParameter);
@@ -53,42 +41,6 @@ ThreadStartup (LPTHREAD_START_ROUTINE lpStartAddress,
    ExitThread(uExitCode);
 }
 
-static VOID
-ThreadAttachDlls (VOID)
-{
-   PLIST_ENTRY ModuleListHead;
-   PLIST_ENTRY Entry;
-   PLDR_MODULE Module;
-
-   DPRINT("ThreadAttachDlls() called\n");
-
-   RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock);
-
-   ModuleListHead = &NtCurrentPeb()->Ldr->InInitializationOrderModuleList;
-   Entry = ModuleListHead->Blink;
-
-   while (Entry != ModuleListHead)
-     {
-       Module = CONTAINING_RECORD(Entry, LDR_MODULE, InInitializationOrderModuleList);
-
-       if (Module->EntryPoint != 0)
-         {
-            PDLLMAIN_FUNC Entrypoint = (PDLLMAIN_FUNC)Module->EntryPoint;
-
-            DPRINT("Calling entry point at 0x%08x\n", Entrypoint);
-            Entrypoint (Module->BaseAddress,
-                        DLL_THREAD_ATTACH,
-                        NULL);
-         }
-
-       Entry = Entry->Blink;
-     }
-
-   RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock);
-
-   DPRINT("ThreadAttachDlls() done\n");
-}
-
 HANDLE STDCALL CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes,
                            DWORD dwStackSize,
                            LPTHREAD_START_ROUTINE lpStartAddress,
index c0b50cb..bf77cb0 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: startup.c,v 1.39 2002/08/08 17:54:13 dwelch Exp $
+/* $Id: startup.c,v 1.40 2002/08/09 17:23:56 dwelch Exp $
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
@@ -62,11 +62,14 @@ LdrInitializeThunk (ULONG Unknown1,
        PDLLMAIN_FUNC Entrypoint;
        PLDR_MODULE current;
 
-       current_entry = NtCurrentPeb()->Ldr->InLoadOrderModuleList.Flink;
-       while (current_entry != &NtCurrentPeb()->Ldr->InLoadOrderModuleList)
+       RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock);
+       current_entry = 
+        NtCurrentPeb()->Ldr->InInitializationOrderModuleList.Flink;
+       while (current_entry != 
+             &NtCurrentPeb()->Ldr->InInitializationOrderModuleList)
         {
           current = CONTAINING_RECORD(current_entry, LDR_MODULE, 
-                                      InLoadOrderModuleList);
+                                      InInitializationOrderModuleList);
           Entrypoint = (PDLLMAIN_FUNC)current->EntryPoint;
           if (Entrypoint != NULL &&
               current->BaseAddress != NtCurrentPeb()->ImageBaseAddress)
@@ -75,6 +78,7 @@ LdrInitializeThunk (ULONG Unknown1,
             }
           current_entry = current_entry->Flink;
         }
+       RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock);
        return;
      }
 
index 5cc5550..5ee14e0 100644 (file)
@@ -16,7 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: ps.h,v 1.37 2002/08/08 17:54:14 dwelch Exp $
+/* $Id: ps.h,v 1.38 2002/08/09 17:23:56 dwelch Exp $
  *
  * FILE:            ntoskrnl/ke/kthread.c
  * PURPOSE:         Process manager definitions
@@ -580,6 +580,8 @@ PiTimeoutThread(struct _KDPC *dpc,
 
 VOID STDCALL
 PsDispatchThread(ULONG NewThreadStatus);
+VOID
+PsInitialiseSuspendImplementation(VOID);
 
 #endif /* ASSEMBLER */
 
index 0db4dbb..8a8a633 100644 (file)
@@ -90,32 +90,35 @@ KiDeliverNormalApc(VOID)
 
    KeAcquireSpinLock(&PiApcLock, &oldlvl);
    while(!IsListEmpty(&(Thread->Tcb.ApcState.ApcListHead[0])))
-   {
-     current = Thread->Tcb.ApcState.ApcListHead[0].Blink;
-     Apc = CONTAINING_RECORD(current, KAPC, ApcListEntry);
-     if (Apc->NormalRoutine != NULL)
-       {
-        (VOID)RemoveTailList(&Thread->Tcb.ApcState.ApcListHead[0]);
-        Thread->Tcb.ApcState.KernelApcInProgress++;
-        Thread->Tcb.ApcState.KernelApcPending--;
-
-        KeReleaseSpinLock(&PiApcLock, oldlvl);
-        
-        NormalRoutine = Apc->NormalRoutine;
-        NormalContext = Apc->NormalContext;
-        SystemArgument1 = Apc->SystemArgument1;
-        SystemArgument2 = Apc->SystemArgument2;
-        Apc->KernelRoutine(Apc,
-                           &NormalRoutine,
-                           &NormalContext,
-                           &SystemArgument1,
-                           &SystemArgument2);
-        NormalRoutine(NormalContext, SystemArgument1, SystemArgument2);
-
-        KeAcquireSpinLock(&PiApcLock, &oldlvl);
-        Thread->Tcb.ApcState.KernelApcInProgress--;
-       }
-   }
+     {
+       current = Thread->Tcb.ApcState.ApcListHead[0].Blink;
+       Apc = CONTAINING_RECORD(current, KAPC, ApcListEntry);
+       if (Apc->NormalRoutine == NULL)
+        {
+          DbgPrint("Exiting kernel with kernel APCs pending.\n");
+          KeBugCheck(0);
+        }
+       (VOID)RemoveTailList(&Thread->Tcb.ApcState.ApcListHead[0]);
+       Apc->Inserted = FALSE;
+       Thread->Tcb.ApcState.KernelApcInProgress++;
+       Thread->Tcb.ApcState.KernelApcPending--;
+       
+       KeReleaseSpinLock(&PiApcLock, oldlvl);
+       
+       NormalRoutine = Apc->NormalRoutine;
+       NormalContext = Apc->NormalContext;
+       SystemArgument1 = Apc->SystemArgument1;
+       SystemArgument2 = Apc->SystemArgument2;
+       Apc->KernelRoutine(Apc,
+                         &NormalRoutine,
+                         &NormalContext,
+                         &SystemArgument1,
+                         &SystemArgument2);
+       NormalRoutine(NormalContext, SystemArgument1, SystemArgument2);
+       
+       KeAcquireSpinLock(&PiApcLock, &oldlvl);
+       Thread->Tcb.ApcState.KernelApcInProgress--;
+     }
    KeReleaseSpinLock(&PiApcLock, oldlvl);
 }
 
@@ -161,8 +164,9 @@ KiDeliverUserApc(PKTRAP_FRAME TrapFrame)
    while (!IsListEmpty(&Thread->ApcState.ApcListHead[1]))
      {
        current_entry = RemoveHeadList(&Thread->ApcState.ApcListHead[1]);
-       KeReleaseSpinLock(&PiApcLock, oldlvl);
        Apc = CONTAINING_RECORD(current_entry, KAPC, ApcListEntry);
+       Apc->Inserted = FALSE;
+       KeReleaseSpinLock(&PiApcLock, oldlvl);       
        
        /*
        * Save the thread's current context (in other words the registers
@@ -259,6 +263,7 @@ KiDeliverApc(ULONG Unknown1,
        if (Apc->NormalRoutine == NULL)
         {
           current_entry = current_entry->Flink;
+          Apc->Inserted = FALSE;
           RemoveEntryList(&Apc->ApcListEntry);
           Thread->Tcb.ApcState.KernelApcInProgress++;
           Thread->Tcb.ApcState.KernelApcPending--;
index d1fb32f..27e245f 100644 (file)
@@ -92,7 +92,7 @@ print_user_address(PVOID address)
        return(TRUE);
      }
 
-   Status = MmSafeCopyFromUser(&Ldr, Peb->Ldr, sizeof(PPEB_LDR_DATA));
+   Status = MmSafeCopyFromUser(&Ldr, &Peb->Ldr, sizeof(PPEB_LDR_DATA));
    if (!NT_SUCCESS(Status))
      {
        DbgPrint("<%x>", address);
index 45e737d..ab10ef4 100644 (file)
@@ -16,7 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: kthread.c,v 1.30 2002/08/08 17:54:14 dwelch Exp $
+/* $Id: kthread.c,v 1.31 2002/08/09 17:23:57 dwelch Exp $
  *
  * FILE:            ntoskrnl/ke/kthread.c
  * PURPOSE:         Microkernel thread support
@@ -224,7 +224,7 @@ KeInitializeThread(PKPROCESS Process, PKTHREAD Thread, BOOLEAN First)
                  PiSuspendThreadNormalRoutine,
                  KernelMode,
                  NULL);
-  KeInitializeSemaphore(&Thread->SuspendSemaphore, 0, 255);
+  KeInitializeSemaphore(&Thread->SuspendSemaphore, 0, 128);
   Thread->ThreadListEntry.Flink = NULL;
   Thread->ThreadListEntry.Blink = NULL;
   Thread->FreezeCount = 0;
index 99f7b94..8b1defa 100644 (file)
@@ -16,7 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: sem.c,v 1.8 2001/03/16 23:04:59 dwelch Exp $
+/* $Id: sem.c,v 1.9 2002/08/09 17:23:57 dwelch Exp $
  *
  * PROJECT:         ReactOS kernel
  * FILE:            ntoskrnl/ke/sem.c
@@ -81,30 +81,28 @@ KeReleaseSemaphore (PKSEMAPHORE     Semaphore,
  *          object is Not-Signaled.
  */
 {
-   ULONG initState = Semaphore->Header.SignalState;
+   ULONG InitialState;
   
    DPRINT("KeReleaseSemaphore(Semaphore %x, Increment %d, Adjustment %d, "
          "Wait %d)\n", Semaphore, Increment, Adjustment, Wait);
    
    KeAcquireDispatcherDatabaseLock(Wait);
    
-   if (Semaphore->Limit < initState+Adjustment
-       || initState > initState+Adjustment)
+   InitialState = Semaphore->Header.SignalState;
+   if (Semaphore->Limit < InitialState + Adjustment ||
+       InitialState > InitialState + Adjustment)
      {
        ExRaiseStatus(STATUS_SEMAPHORE_LIMIT_EXCEEDED);
      }
    
-   Semaphore->Header.SignalState+=Adjustment;
-   DPRINT("initState %d\n", initState);
-   if(initState == 0)
+   Semaphore->Header.SignalState += Adjustment;
+   if (InitialState == 0)
      {
-       //  wake up SignalState waiters
-       DPRINT("Waking waiters\n");
-       KeDispatcherObjectWake(&Semaphore->Header);
+       KeDispatcherObjectWake(&Semaphore->Header);
      }
    
   KeReleaseDispatcherDatabaseLock(Wait);
-  return initState;
+  return(InitialState);
 }
 
 /* EOF */
index 20136dd..c2d21d2 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: create.c,v 1.48 2002/08/08 17:54:16 dwelch Exp $
+/* $Id: create.c,v 1.49 2002/08/09 17:23:57 dwelch Exp $
  *
  * COPYRIGHT:              See COPYING in the top level directory
  * PROJECT:                ReactOS kernel
@@ -590,15 +590,13 @@ NtCreateThread(PHANDLE ThreadHandle,
     {
       return(Status);
     }
-
-  /* Attention: TebBase is in user memory space */
   Thread->Tcb.Teb = TebBase;
 
-  Thread->StartAddress=NULL;
+  Thread->StartAddress = NULL;
 
   if (Client != NULL)
     {
-      *Client=Thread->Cid;
+      *Client = Thread->Cid;
     }
 
   /*
@@ -615,6 +613,10 @@ NtCreateThread(PHANDLE ThreadHandle,
    * If the thread is to be created suspended then queue an APC to
    * do the suspend before we run any userspace code.
    */
+  if (CreateSuspended)
+    {
+      PsSuspendThread(Thread, NULL);
+    }
 
   /*
    * Queue an APC to the thread that will execute the ntdll startup
@@ -680,7 +682,7 @@ PsCreateSystemThread(PHANDLE ThreadHandle,
        return(Status);
      }
    
-   Thread->StartAddress=StartRoutine;
+   Thread->StartAddress = StartRoutine;
    Status = Ke386InitThread(&Thread->Tcb,
                            StartRoutine,
                            StartContext);
@@ -689,7 +691,7 @@ PsCreateSystemThread(PHANDLE ThreadHandle,
        return(Status);
      }
 
-   if (ClientId!=NULL)
+   if (ClientId != NULL)
      {
        *ClientId=Thread->Cid;
      }
index 9189c77..9832a2d 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: psmgr.c,v 1.11 2001/07/12 17:21:06 ekohl Exp $
+/* $Id: psmgr.c,v 1.12 2002/08/09 17:23:57 dwelch Exp $
  *
  * COPYRIGHT:               See COPYING in the top level directory
  * PROJECT:                 ReactOS kernel
@@ -32,6 +32,7 @@ VOID PiInitProcessManager(VOID)
    PsInitThreadManagment();
    PsInitIdleThread();
    PiInitApcManagement();
+   PsInitialiseSuspendImplementation();
 }
 
 
index 86effe3..ae74467 100644 (file)
@@ -16,7 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: suspend.c,v 1.7 2002/07/10 15:17:35 ekohl Exp $
+/* $Id: suspend.c,v 1.8 2002/08/09 17:23:57 dwelch Exp $
  *
  * PROJECT:                ReactOS kernel
  * FILE:                   ntoskrnl/ps/suspend.c
  *
  */
 
+/* GLOBALS *******************************************************************/
+
+static FAST_MUTEX SuspendMutex;
+
 /* FUNCTIONS *****************************************************************/
 
 VOID STDCALL
@@ -62,20 +66,36 @@ PiSuspendThreadNormalRoutine(PVOID NormalContext,
                             PVOID SystemArgument1,
                             PVOID SystemArgument2)
 {
-  KeWaitForSingleObject(&PsGetCurrentThread()->Tcb.SuspendSemaphore,
-                       0,
-                       UserMode,
-                       TRUE,
-                       NULL);
+  PETHREAD CurrentThread = PsGetCurrentThread();
+  while (CurrentThread->Tcb.SuspendCount > 0)
+    {
+      KeWaitForSingleObject(&CurrentThread->Tcb.SuspendSemaphore,
+                           0,
+                           UserMode,
+                           TRUE,
+                           NULL);
+    }
 }
 
 
 NTSTATUS
 PsResumeThread(PETHREAD Thread, PULONG SuspendCount)
 {
-  *SuspendCount = InterlockedDecrement((PULONG)&Thread->Tcb.SuspendCount);
-  KeReleaseSemaphore(&Thread->Tcb.SuspendSemaphore, IO_NO_INCREMENT, 1, FALSE);
-
+  ExAcquireFastMutex(&SuspendMutex);
+  if (SuspendCount != NULL)
+    {
+      *SuspendCount = Thread->Tcb.SuspendCount;
+    }
+  if (Thread->Tcb.SuspendCount > 0)
+    {
+      Thread->Tcb.SuspendCount--;
+      if (Thread->Tcb.SuspendCount == 0)
+       {
+         KeReleaseSemaphore(&Thread->Tcb.SuspendSemaphore, IO_NO_INCREMENT, 
+                            1, FALSE);
+       }      
+    }
+  ExReleaseFastMutex(&SuspendMutex);
   return(STATUS_SUCCESS);
 }
 
@@ -85,19 +105,21 @@ PsSuspendThread(PETHREAD Thread, PULONG PreviousSuspendCount)
 {
   ULONG OldValue;
 
-  OldValue = InterlockedIncrement((PULONG)&Thread->Tcb.SuspendCount);
-  if (OldValue == 0)
+  ExAcquireFastMutex(&SuspendMutex);
+  OldValue = Thread->Tcb.SuspendCount;
+  Thread->Tcb.SuspendCount++;
+  if (!Thread->Tcb.SuspendApc.Inserted)
     {
       KeInsertQueueApc(&Thread->Tcb.SuspendApc,
                       NULL,
                       NULL,
                       0);
     }
-  else
+  ExReleaseFastMutex(&SuspendMutex);
+  if (PreviousSuspendCount != NULL)
     {
-      InterlockedDecrement(&Thread->Tcb.SuspendSemaphore.Header.SignalState);
+      *PreviousSuspendCount = OldValue;
     }
-
   return(STATUS_SUCCESS);
 }
 
@@ -186,4 +208,10 @@ NtSuspendThread(IN HANDLE ThreadHandle,
   return(STATUS_SUCCESS);
 }
 
+VOID
+PsInitialiseSuspendImplementation(VOID)
+{
+  ExInitializeFastMutex(&SuspendMutex);
+}
+
 /* EOF */