Thread improvements.
authorEric Kohl <eric.kohl@reactos.org>
Mon, 6 Sep 1999 21:32:57 +0000 (21:32 +0000)
committerEric Kohl <eric.kohl@reactos.org>
Mon, 6 Sep 1999 21:32:57 +0000 (21:32 +0000)
svn path=/trunk/; revision=646

reactos/apps/tests/bench/bench-thread.c
reactos/include/internal/id.h
reactos/lib/kernel32/thread/thread.c
reactos/lib/ntdll/rtl/thread.c
reactos/ntoskrnl/ke/wait.c
reactos/ntoskrnl/ps/kill.c
reactos/ntoskrnl/ps/thread.c

index 3164221..5bcaa38 100644 (file)
@@ -3,6 +3,7 @@
 
 #define NR_THREADS (0x5)
 
+
 DWORD WINAPI
 thread_main1(LPVOID param)
 {
@@ -11,6 +12,7 @@ thread_main1(LPVOID param)
    return 0;
 }
 
+
 DWORD WINAPI
 thread_main2(LPVOID param)
 {
@@ -19,33 +21,62 @@ thread_main2(LPVOID param)
    return 0;
 }
 
+
 int main (void)
 {
+   HANDLE hThread;
    DWORD i=0;
    DWORD id;
-   
-   printf("Creating %d threads...\n",NR_THREADS);
-//   for (i=0;i<NR_THREADS;i++)
-//     {
+
+#if 0
+   printf("Creating %d threads...\n",NR_THREADS*2);
+   for (i=0;i<NR_THREADS;i++)
+     {
        CreateThread(NULL,
                     0,
-                     thread_main1,
-                     (LPVOID)i,
+                    thread_main1,
+                    (LPVOID)i,
                     0,
                     &id);
-#if 0
+
        CreateThread(NULL,
                     0,
-                     thread_main2,
-                     (LPVOID)i,
+                    thread_main2,
+                    (LPVOID)i,
                     0,
                     &id);
      }
-#endif
-   printf("Threads created...\n");
 
-//     Sleep (5000);
-   SuspendThread (GetCurrentThread());
+   printf("All threads created...\n");
+
+   /*
+    * Waiting for threads is not implemented yet.
+    * If you want to see all threads running, uncomment the
+    * call to SuspendThread(). The test application will
+    * freeze after all threads are created.
+    */
+/*   SuspendThread (GetCurrentThread()); */
+
+#else
+
+   printf("Creating thread...\n");
+
+   hThread = CreateThread(NULL,
+                          0,
+                          thread_main1,
+                          (LPVOID)i,
+                          0,
+                          &id);
+
+   printf("Thread created. Waiting for termination...\n");
+
+   WaitForSingleObject (hThread,
+                        -1);
+
+   CloseHandle (hThread);
+
+   printf("Thread terminated...\n");
+#endif
 
    return 0;
 }
index 2addb17..412a557 100644 (file)
@@ -11,3 +11,4 @@
 #define ID_EVENT_OBJECT     (ID_BASE_OBJECT + 5)
 #define ID_TIMER_OBJECT     (ID_BASE_OBJECT + 6)
 #define ID_PROCESS_OBJECT   (ID_BASE_OBJECT + 7)
+#define ID_THREAD_OBJECT    (ID_BASE_OBJECT + 8) 
index 330b956..579391d 100644 (file)
 
 /* FUNCTIONS *****************************************************************/
 
+static VOID STDCALL
+ThreadStartup (LPTHREAD_START_ROUTINE lpStartAddress,
+               LPVOID lpParameter)
+{
+   UINT uExitCode;
+
+   uExitCode = (lpStartAddress)(lpParameter);
+
+   NtTerminateThread(NtCurrentThread(),
+                     uExitCode);
+}
+
+
 HANDLE STDCALL CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes,
                            DWORD dwStackSize,
                            LPTHREAD_START_ROUTINE lpStartAddress,
@@ -55,7 +68,6 @@ HANDLE STDCALL CreateRemoteThread(HANDLE hProcess,
    BOOLEAN CreateSuspended = FALSE;
    PVOID BaseAddress;
    DWORD StackSize;
-   ULONG BytesWritten;
    NTSTATUS Status;
    
    ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
@@ -94,18 +106,24 @@ HANDLE STDCALL CreateRemoteThread(HANDLE hProcess,
    DPRINT("Stack base address: %p\n", BaseAddress);
    
    memset(&ThreadContext,0,sizeof(CONTEXT));
-   ThreadContext.Eip = (LONG)lpStartAddress;
+//   ThreadContext.Eip = (LONG)lpStartAddress;
+   ThreadContext.Eip = (LONG)ThreadStartup;
    ThreadContext.SegGs = USER_DS;
    ThreadContext.SegFs = USER_DS;
    ThreadContext.SegEs = USER_DS;
    ThreadContext.SegDs = USER_DS;
    ThreadContext.SegCs = USER_CS;
    ThreadContext.SegSs = USER_DS;        
-   ThreadContext.Esp = (ULONG)(BaseAddress + StackSize - 8);
+   ThreadContext.Esp = (ULONG)(BaseAddress + StackSize - 12);
    ThreadContext.EFlags = (1<<1) + (1<<9);
 
-   /* write lpParameter to highest stack address */
-   *((PBYTE)(BaseAddress + StackSize - 4)) = lpParameter;
+   /* initialize call stack */
+   *((PULONG)(BaseAddress + StackSize - 4)) = (ULONG)lpParameter;
+   *((PULONG)(BaseAddress + StackSize - 8)) = (ULONG)lpStartAddress;
+   *((PULONG)(BaseAddress + StackSize - 12)) = 0xdeadbeef;
+
+   DPRINT("Esp: %p\n", ThreadContext.Esp);
+   DPRINT("Eip: %p\n", ThreadContext.Eip);
 
    Status = NtCreateThread(&ThreadHandle,
                            THREAD_ALL_ACCESS,
index eb4e0c6..5bca654 100644 (file)
@@ -132,8 +132,8 @@ RtlCreateUserThread(HANDLE ProcessHandle,
                     LONG StackZeroBits,
                     PULONG StackReserved,
                     PULONG StackCommit,
-                    PVOID StartAddress,
-                    HANDLE DebugPort,
+                    PTHREAD_START_ROUTINE StartAddress,
+                    PVOID   Parameter,
                     PHANDLE ThreadHandle,
                     PCLIENT_ID ClientId)
 {
@@ -214,6 +214,9 @@ DPRINT("Checkpoint\n");
    ObjectAttributes.SecurityQualityOfService = NULL;
 
 
+   if (*StackCommit < 4096)
+      *StackCommit = 4096;
+
    BaseAddress = 0;
    ZwAllocateVirtualMemory(ProcessHandle,
                           &BaseAddress,
@@ -271,8 +274,8 @@ DPRINT("Checkpoint\n");
 NTSTATUS STDCALL
 RtlInitializeContext(HANDLE ProcessHandle,
                      PCONTEXT Context,
-                     HANDLE DebugPort,
-                     PVOID StartAddress,
+                     PVOID Parameter,
+                     PTHREAD_START_ROUTINE StartAddress,
                      PINITIAL_TEB InitialTeb)
 {
     NTSTATUS Status;
@@ -289,8 +292,16 @@ RtlInitializeContext(HANDLE ProcessHandle,
     Context->SegDs  = USER_DS;
     Context->SegCs  = USER_CS;
     Context->SegSs  = USER_DS;
-    Context->Esp    = InitialTeb->StackBase - InitialTeb->StackCommit;
+    Context->Esp    = (ULONG)InitialTeb->StackBase +
+                      (DWORD)InitialTeb->StackCommit - 8;
     Context->EFlags = (1<<1)+(1<<9);
+
+
+    /* copy Parameter to thread stack */
+    *((PULONG)(InitialTeb->StackBase + (DWORD)InitialTeb->StackCommit - 4))
+        = (DWORD)Parameter;
+
+
 /* #endif */
 
     Status = STATUS_SUCCESS;
index 4f22865..baf06d8 100644 (file)
@@ -151,6 +151,9 @@ BOOLEAN KeDispatcherObjectWake(DISPATCHER_HEADER* hdr)
        
       case ID_PROCESS_OBJECT:
        return(KeDispatcherObjectWakeAll(hdr));
+
+      case ID_THREAD_OBJECT:
+       return(KeDispatcherObjectWakeAll(hdr));
      }
    DbgPrint("Dispatcher object %x has unknown type\n",hdr);
    KeBugCheck(0);
@@ -200,6 +203,9 @@ NTSTATUS KeWaitForSingleObject(PVOID Object,
           
         case ID_PROCESS_OBJECT:
           break;
+
+         case ID_THREAD_OBJECT:
+          break;
           
         case NotificationEvent:
           break;
@@ -222,7 +228,7 @@ NTSTATUS KeWaitForSingleObject(PVOID Object,
    blk.Object=Object;
    blk.Thread=KeGetCurrentThread();
    blk.WaitKey = WaitReason;     // Assumed
-   blk.WaitType = WaitMode;      // Assumed
+   blk.WaitType = WaitAll;
    blk.NextWaitBlock = NULL;
    InsertTailList(&(hdr->WaitListHead),&(blk.WaitListEntry));
 //   DPRINT("hdr->WaitListHead.Flink %x hdr->WaitListHead.Blink %x\n",
@@ -249,7 +255,91 @@ NTSTATUS KeWaitForMultipleObjects(ULONG Count,
                                  PLARGE_INTEGER Timeout,
                                  PKWAIT_BLOCK WaitBlockArray)
 {
+#if 0
+   DISPATCHER_HEADER* hdr;
+   PKWAIT_BLOCK blk;
+   ULONG Counter;
+
+   DPRINT("Entering KeWaitForSingleObject(Object %x) "
+   "PsGetCurrentThread() %x\n",Object,PsGetCurrentThread());
+
+   KeAcquireDispatcherDatabaseLock(FALSE);
+
+   for (Counter = 0; Counter < Count; Counter++)
+     {
+        hdr = (DISPATCHER_HEADER *)Object[Counter];
+
+        DPRINT("hdr->SignalState %d\n", hdr->SignalState);
+
+        if (hdr->SignalState > 0)
+          {
+             switch (hdr->Type)
+               {
+                  case SynchronizationEvent:
+                    hdr->SignalState = FALSE;
+                    break;
+
+                  case SemaphoreType:
+                    break;
+
+                  case ID_PROCESS_OBJECT:
+                    break;
+
+                  case ID_THREAD_OBJECT:
+                    break;
+
+                  case NotificationEvent:
+                    break;
+
+                  default:
+                    DbgPrint("(%s:%d) Dispatcher object %x has unknown type\n",
+                             __FILE__,__LINE__,hdr);
+                    KeBugCheck(0);
+
+               }
+             KeReleaseDispatcherDatabaseLock(FALSE);
+             return(STATUS_SUCCESS);
+          }
+     }
+
+   if (Timeout != NULL)
+     {
+       KeAddThreadTimeout(KeGetCurrentThread(),Timeout);
+     }
+
+   for (Counter = 0; Counter < Count; Counter++)
+     {
+        hdr = (DISPATCHER_HEADER *)Object[Counter];
+
+        blk = &WaitBlockArray[Counter];
+
+        blk->Object=Object[Counter];
+        blk->Thread=KeGetCurrentThread();
+        blk->WaitKey = WaitReason;     // Assumed
+        blk->WaitType = WaitType;
+        blk->NextWaitBlock = NULL;
+        InsertTailList(&(hdr->WaitListHead),&(blk.WaitListEntry));
+//        DPRINT("hdr->WaitListHead.Flink %x hdr->WaitListHead.Blink %x\n",
+//               hdr->WaitListHead.Flink,hdr->WaitListHead.Blink);
+     }
+
+   KeReleaseDispatcherDatabaseLock(FALSE);
+
+   DPRINT("Waiting at %s:%d with irql %d\n", __FILE__, __LINE__,
+   KeGetCurrentIrql());
+
+   PsSuspendThread(PsGetCurrentThread());
+
+   if (Timeout != NULL)
+     {
+       KeCancelTimer(&KeGetCurrentThread()->Timer);
+     }
+   DPRINT("Returning from KeWaitForMultipleObject()\n");
+
+   return(STATUS_SUCCESS);
+#else
    UNIMPLEMENTED;
+#endif
 }
 
 VOID KeInitializeDispatcher(VOID)
@@ -267,7 +357,59 @@ NtWaitForMultipleObjects (
        IN      PLARGE_INTEGER  Time
        )
 {
-       UNIMPLEMENTED;
+#if 0
+   KWAIT_BLOCK WaitBlockArray[MAXIMUM_WAIT_OBJECTS];
+   PVOID ObjectPtrArray[MAXIMUM_WAIT_OBJECTS];
+   NTSTATUS Status;
+   ULONG i, j;
+
+
+   DPRINT("NtWaitForMultipleObjects(Count %lu Object[] %x, Alertable %d, Time %x)\n",
+          Count,Object,Alertable,Time);
+
+   if (Count > MAXIMUM_WAIT_OBJECTS)
+        return ...; /* WAIT_FAIL */
+
+   /* reference all objects */
+   for (i = 0; i < Count; i++)
+     {
+        Status = ObReferenceObjectByHandle(Object[i],
+                                           SYNCHRONIZE,
+                                           NULL,
+                                           UserMode,
+                                           &ObjectPtrArray[i],
+                                           NULL);
+        if (Status != STATUS_SUCCESS)
+          {
+             /* dereference all referenced objects */
+             for (j = 0; j < i; i++)
+               {
+                  ObDereferenceObject(ObjectPtrArray[j]);
+               }
+
+             return(Status);
+          }
+     }
+
+   Status = KeWaitForMultipleObjects(Count,
+                                     ObjectPtrArray,
+                                     WaitType,
+                                     UserMode,
+                                     UserMode,
+                                     Alertable,
+                                     Time,
+                                     WaitBlockArray);
+
+   /* dereference all objects */
+   for (i = 0; i < Count; i++)
+     {
+        ObDereferenceObject(ObjectPtrArray[i]);
+     }
+
+   return(Status);
+#else
+   UNIMPLEMENTED;
+#endif
 }
 
 
index 9c92f24..04fd59d 100644 (file)
@@ -44,6 +44,7 @@ VOID PsTerminateCurrentThread(NTSTATUS ExitStatus)
    CurrentThread->ThreadsProcess = NULL;
    KeRaiseIrql(DISPATCH_LEVEL,&oldlvl);
    CurrentThread->Tcb.State = THREAD_STATE_TERMINATED;
+   KeDispatcherObjectWake(&CurrentThread->Tcb.DispatcherHeader);
    ZwYieldExecution();
    for(;;);
 }
@@ -58,6 +59,7 @@ VOID PsTerminateOtherThread(PETHREAD Thread, NTSTATUS ExitStatus)
    PiNrThreads--;
    KeRaiseIrql(DISPATCH_LEVEL, &oldlvl);
    Thread->Tcb.State = THREAD_STATE_TERMINATED;
+   KeDispatcherObjectWake(&Thread->Tcb.DispatcherHeader);
    ObDereferenceObject(Thread->ThreadsProcess);
    Thread->ThreadsProcess = NULL;
    KeLowerIrql(oldlvl);
index 4124367..dfe949f 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: thread.c,v 1.25 1999/08/29 06:59:11 ea Exp $
+/* $Id: thread.c,v 1.26 1999/09/06 21:28:33 ekohl Exp $
  *
  * COPYRIGHT:              See COPYING in the top level directory
  * PROJECT:                ReactOS kernel
@@ -259,7 +259,12 @@ PsInitializeThread (
    InitializeListHead(&Thread->Tcb.ApcState.ApcListHead[0]);
    InitializeListHead(&Thread->Tcb.ApcState.ApcListHead[1]);
    Thread->Tcb.KernelApcDisable = 1;
-   
+
+   KeInitializeDispatcherHeader(&Thread->Tcb.DispatcherHeader,
+                                ID_THREAD_OBJECT,
+                                sizeof(ETHREAD),
+                                FALSE);
+
    if (ProcessHandle != NULL)
      {
        Status = ObReferenceObjectByHandle(ProcessHandle,