Author: ion
Date: Sun Feb 19 06:32:17 2012
New Revision: 55698

URL: http://svn.reactos.org/svn/reactos?rev=55698&view=rev
Log:
[CSRSRV]: Switch to the CSRSRV2 model of having a dynamic amount of threads 
handling CSRSS requests depending on how many are deadlocked, instead of 
creating a thread for every single client. CSRSRV now has about 2 API threads 
instead of 16.

Modified:
    trunk/reactos/subsystems/win32/csrss/csrsrv/api/wapi.c
    trunk/reactos/subsystems/win32/csrss/csrsrv/init.c
    trunk/reactos/subsystems/win32/csrss/csrsrv/session.c
    trunk/reactos/subsystems/win32/csrss/include/api.h

Modified: trunk/reactos/subsystems/win32/csrss/csrsrv/api/wapi.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/csrss/csrsrv/api/wapi.c?rev=55698&r1=55697&r2=55698&view=diff
==============================================================================
--- trunk/reactos/subsystems/win32/csrss/csrsrv/api/wapi.c [iso-8859-1] 
(original)
+++ trunk/reactos/subsystems/win32/csrss/csrsrv/api/wapi.c [iso-8859-1] Sun Feb 
19 06:32:17 2012
@@ -20,6 +20,9 @@
 static unsigned ApiDefinitionsCount = 0;
 static PCSRSS_API_DEFINITION ApiDefinitions = NULL;
 UNICODE_STRING CsrApiPortName;
+volatile LONG CsrpStaticThreadCount;
+volatile LONG CsrpDynamicThreadTotal;
+ULONG CsrMaxApiRequestThreads;
 
 /* FUNCTIONS *****************************************************************/
 
@@ -290,7 +293,7 @@
                                NULL /* FIXME*/);
 
     /* Create the Port Object */
-    Status = NtCreatePort(&hApiPort, //&CsrApiPort,
+    Status = NtCreatePort(&CsrApiPort,
                           &ObjectAttributes,
                           LPC_MAX_DATA_LENGTH, // hack
                           LPC_MAX_MESSAGE_LENGTH, // hack
@@ -741,10 +744,10 @@
 CsrpHandleConnectionRequest (PPORT_MESSAGE Request)
 {
     NTSTATUS Status;
-    HANDLE ServerPort = NULL, ServerThread = NULL;
+    HANDLE ServerPort = NULL;//, ServerThread = NULL;
     PCSR_PROCESS ProcessData = NULL;
     REMOTE_PORT_VIEW RemotePortView;
-    CLIENT_ID ClientId;
+//    CLIENT_ID ClientId;
     BOOLEAN AllowConnection = FALSE;
     PCSR_CONNECTION_INFO ConnectInfo;
     ServerPort = NULL;
@@ -836,7 +839,7 @@
                 Request->ClientId.UniqueProcess,
                 Request->ClientId.UniqueThread);
     }
-    
+#if 0
     if (!NT_SUCCESS(Status)) return Status;
 
     Status = RtlCreateUserThread(NtCurrentProcess(),
@@ -863,6 +866,7 @@
 
     Status = STATUS_SUCCESS;
     DPRINT("CSR: %s done\n", __FUNCTION__);
+#endif
     return Status;
 }
 
@@ -911,6 +915,83 @@
 
     /* Return it */
     return CsrThread;
+}
+
+/*++
+ * @name CsrpCheckRequestThreads
+ *
+ * The CsrpCheckRequestThreads routine checks if there are no more threads
+ * to handle CSR API Requests, and creates a new thread if possible, to
+ * avoid starvation.
+ *
+ * @param None.
+ *
+ * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
+ *         if a new thread couldn't be created.
+ *
+ * @remarks None.
+ *
+ *--*/
+NTSTATUS
+NTAPI
+CsrpCheckRequestThreads(VOID)
+{
+    HANDLE hThread;
+    CLIENT_ID ClientId;
+    NTSTATUS Status;
+
+    /* Decrease the count, and see if we're out */
+    if (!(_InterlockedDecrement(&CsrpStaticThreadCount)))
+    {
+        /* Check if we've still got space for a Dynamic Thread */
+        if (CsrpDynamicThreadTotal < CsrMaxApiRequestThreads)
+        {
+            /* Create a new dynamic thread */
+            Status = RtlCreateUserThread(NtCurrentProcess(),
+                                         NULL,
+                                         TRUE,
+                                         0,
+                                         0,
+                                         0,
+                                         
(PVOID)ClientConnectionThread,//CsrApiRequestThread,
+                                         NULL,
+                                         &hThread,
+                                         &ClientId);
+            /* Check success */
+            if (NT_SUCCESS(Status))
+            {
+                /* Increase the thread counts */
+                _InterlockedIncrement(&CsrpStaticThreadCount);
+                _InterlockedIncrement(&CsrpDynamicThreadTotal);
+
+                /* Add a new server thread */
+                if (CsrAddStaticServerThread(hThread,
+                                             &ClientId,
+                                             CsrThreadIsServerThread))
+                {
+                    /* Activate it */
+                    NtResumeThread(hThread, NULL);
+                }
+                else
+                {
+                    /* Failed to create a new static thread */
+                    _InterlockedDecrement(&CsrpStaticThreadCount);
+                    _InterlockedDecrement(&CsrpDynamicThreadTotal);
+
+                    /* Terminate it */
+                    DPRINT1("Failing\n");
+                    NtTerminateThread(hThread, 0);
+                    NtClose(hThread);
+
+                    /* Return */
+                    return STATUS_UNSUCCESSFUL;
+                }
+            }
+        }
+    }
+
+    /* Success */
+    return STATUS_SUCCESS;
 }
 
 VOID
@@ -926,12 +1007,13 @@
     PCSR_PROCESS ProcessData;
     PCSR_THREAD ServerThread;
     ULONG MessageType;
+    HANDLE ReplyPort;
 
     DPRINT("CSR: %s called\n", __FUNCTION__);
 
     /* Setup LPC loop port and message */
     Reply = NULL;
-//    ReplyPort = CsrApiPort;
+    ReplyPort = CsrApiPort;
 
     /* Connect to user32 */
     while (!CsrConnectToUser())
@@ -955,8 +1037,8 @@
         ASSERT(NT_SUCCESS(Status));
 
         /* Increase the Thread Counts */
-        //_InterlockedIncrement(&CsrpStaticThreadCount);
-        //_InterlockedIncrement(&CsrpDynamicThreadTotal);
+        _InterlockedIncrement(&CsrpStaticThreadCount);
+        _InterlockedIncrement(&CsrpDynamicThreadTotal);
     }
 
     /* Now start the loop */
@@ -976,7 +1058,8 @@
         }
 
         /* Send the reply and wait for a new request */
-        Status = NtReplyWaitReceivePort(hApiPort,
+        DPRINT("Replying to: %lx (%lx)\n", ReplyPort, CsrApiPort);
+        Status = NtReplyWaitReceivePort(ReplyPort,
                                         0,
                                         &Reply->Header,
                                         &Request->Header);
@@ -988,17 +1071,18 @@
             {
                 /* Check for specific status cases */
                 if ((Status != STATUS_INVALID_CID) &&
-                    (Status != STATUS_UNSUCCESSFUL))// &&
-//                    ((Status == STATUS_INVALID_HANDLE) || (ReplyPort == 
CsrApiPort)))
+                    (Status != STATUS_UNSUCCESSFUL) &&
+                    ((Status == STATUS_INVALID_HANDLE) || (ReplyPort == 
CsrApiPort)))
                 {
                     /* Notify the debugger */
                     DPRINT1("CSRSS: ReceivePort failed - Status == %X\n", 
Status);
-                    //DPRINT1("CSRSS: ReplyPortHandle %lx CsrApiPort %lx\n", 
ReplyPort, CsrApiPort);
+                    DPRINT1("CSRSS: ReplyPortHandle %lx CsrApiPort %lx\n", 
ReplyPort, CsrApiPort);
                 }
 
                 /* We failed big time, so start out fresh */
                 Reply = NULL;
-                //ReplyPort = CsrApiPort;
+                ReplyPort = CsrApiPort;
+                DPRINT1("failed: %lx\n", Status);
                 continue;
             }
             else
@@ -1020,13 +1104,17 @@
         {
             DPRINT("Port died, oh well\n");
             CsrFreeProcessData( Request->Header.ClientId.UniqueProcess );
-            break;
+            Reply = NULL;
+            ReplyPort = CsrApiPort;
+            continue;
         }
 
         if (MessageType == LPC_CONNECTION_REQUEST)
         {
+            DPRINT("Accepting new connection\n");
             CsrpHandleConnectionRequest((PPORT_MESSAGE)Request);
             Reply = NULL;
+            ReplyPort = CsrApiPort;
             continue;
         }
 
@@ -1034,6 +1122,7 @@
         {
             DPRINT("Client died, oh well\n");
             Reply = NULL;
+            ReplyPort = CsrApiPort;
             continue;
         }
 
@@ -1042,6 +1131,7 @@
         {
             DPRINT1("CSR: received message %d\n", Request->Header.u2.s2.Type);
             Reply = NULL;
+            ReplyPort = CsrApiPort;
             continue;
         }
 
@@ -1056,12 +1146,16 @@
             DPRINT1("Message %d: Unable to find data for process 0x%x\n",
                     MessageType,
                     Request->Header.ClientId.UniqueProcess);
-            break;
+            Reply = NULL;
+            ReplyPort = CsrApiPort;
+            continue;
         }
         if (ProcessData->Flags & CsrProcessTerminated)
         {
             DPRINT1("Message %d: process %d already terminated\n",
                     Request->Type, Request->Header.ClientId.UniqueProcess);
+            Reply = NULL;
+            ReplyPort = CsrApiPort;
             continue;
         }
 
@@ -1072,20 +1166,61 @@
             PCSR_THREAD Thread;
             Thread = CsrLocateThreadByClientId(NULL, 
&Request->Header.ClientId);
             CsrHandleHardError(Thread, (PHARDERROR_MSG)Request);
+            ReplyPort = CsrApiPort;
         }
         else
         {
             PCSR_THREAD Thread;
             PCSR_PROCESS Process = NULL;
 
-            //DPRINT1("locate thread %lx/%lx\n", 
Request->Header.ClientId.UniqueProcess, Request->Header.ClientId.UniqueThread);
-            Thread = CsrLocateThreadByClientId(&Process, 
&Request->Header.ClientId);
-            //DPRINT1("Thread found: %p %p\n", Thread, Process);
-
-            /* Call the Handler */
-            if (Thread) NtCurrentTeb()->CsrClientThread = Thread;
-            CsrApiCallHandler(ProcessData, Request);
-            if (Thread) NtCurrentTeb()->CsrClientThread = ServerThread;
+            /* Validation complete, start SEH */
+            _SEH2_TRY
+            {
+                /* Make sure we have enough threads */
+                CsrpCheckRequestThreads();
+                
+                //DPRINT1("locate thread %lx/%lx\n", 
Request->Header.ClientId.UniqueProcess, Request->Header.ClientId.UniqueThread);
+                Thread = CsrLocateThreadByClientId(&Process, 
&Request->Header.ClientId);
+                if (!Thread)
+                {
+                    DPRINT("No thread found for request %lx and clientID 
%lx.%lx\n",
+                            Request->Type & 0xFFFF,
+                            Request->Header.ClientId.UniqueProcess,
+                            Request->Header.ClientId.UniqueThread);
+                }
+                //DPRINT1("Thread found: %p %p\n", Thread, Process);
+
+                if (Thread) NtCurrentTeb()->CsrClientThread = Thread;
+            
+                /* Now we reply to a particular client */
+                if (Thread)
+                {
+                    ReplyPort = Thread->Process->ClientPort;
+                    ASSERT(Thread->Process == ProcessData);
+                }
+                else
+                {
+                    ReplyPort = ProcessData->ClientPort;
+                }
+
+                /* Call the Handler */
+                CsrApiCallHandler(ProcessData, Request);
+                
+                /* Increase the static thread count */
+                _InterlockedIncrement(&CsrpStaticThreadCount);
+            
+                if (Thread)
+                {
+                    NtCurrentTeb()->CsrClientThread = ServerThread;
+                    CsrDereferenceThread(Thread);
+                }
+            }
+            
_SEH2_EXCEPT(CsrUnhandledExceptionFilter(_SEH2_GetExceptionInformation()))
+            {
+                Reply = NULL;
+                ReplyPort = CsrApiPort;
+            }
+            _SEH2_END;
         }
 
         /* Send back the reply */
@@ -1095,7 +1230,7 @@
     /* Close the port and exit the thread */
     // NtClose(ServerPort);
 
-    DPRINT("CSR: %s done\n", __FUNCTION__);
+    DPRINT1("CSR: %s done\n", __FUNCTION__);
     /* We're out of the loop for some reason, terminate! */
     NtTerminateThread(NtCurrentThread(), Status);
     //return Status;

Modified: trunk/reactos/subsystems/win32/csrss/csrsrv/init.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/csrss/csrsrv/init.c?rev=55698&r1=55697&r2=55698&view=diff
==============================================================================
--- trunk/reactos/subsystems/win32/csrss/csrsrv/init.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/csrss/csrsrv/init.c [iso-8859-1] Sun Feb 19 
06:32:17 2012
@@ -22,7 +22,7 @@
 PCSR_THREAD CsrSbApiRequestThreadPtr;
 HANDLE CsrSmApiPort;
 HANDLE hSbApiPort = (HANDLE) 0;
-HANDLE hApiPort = (HANDLE) 0;
+HANDLE CsrApiPort = (HANDLE) 0;
 ULONG CsrDebug = 0xFFFFFFFF;
 ULONG CsrMaxApiRequestThreads;
 ULONG CsrTotalPerProcessDataLength;
@@ -1098,7 +1098,7 @@
     NtClose(CsrInitializationEvent);
 
     /* Have us handle Hard Errors */
-    Status = NtSetDefaultHardErrorPort(hApiPort);
+    Status = NtSetDefaultHardErrorPort(CsrApiPort);
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("CSRSRV:%s: NtSetDefaultHardErrorPort failed (Status=%08lx)\n",

Modified: trunk/reactos/subsystems/win32/csrss/csrsrv/session.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/csrss/csrsrv/session.c?rev=55698&r1=55697&r2=55698&view=diff
==============================================================================
--- trunk/reactos/subsystems/win32/csrss/csrsrv/session.c [iso-8859-1] 
(original)
+++ trunk/reactos/subsystems/win32/csrss/csrsrv/session.c [iso-8859-1] Sun Feb 
19 06:32:17 2012
@@ -231,7 +231,7 @@
     /* Set the exception port */
     Status = NtSetInformationProcess(hProcess,
                                      ProcessExceptionPort,
-                                     &hApiPort,//&CsrApiPort,
+                                     &CsrApiPort,
                                      sizeof(HANDLE));
 
     /* Check for success */

Modified: trunk/reactos/subsystems/win32/csrss/include/api.h
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/csrss/include/api.h?rev=55698&r1=55697&r2=55698&view=diff
==============================================================================
--- trunk/reactos/subsystems/win32/csrss/include/api.h [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/csrss/include/api.h [iso-8859-1] Sun Feb 19 
06:32:17 2012
@@ -299,7 +299,7 @@
 NTAPI
 CsrReleaseCapturedArguments(IN PCSR_API_MESSAGE ApiMessage);
 
-extern HANDLE hApiPort;
+extern HANDLE CsrApiPort;
 extern HANDLE CsrSmApiPort;
 extern HANDLE CsrSbApiPort;
 extern LIST_ENTRY CsrThreadHashTable[256];
@@ -313,6 +313,7 @@
 extern PVOID *CsrSrvSharedStaticServerData;
 extern HANDLE CsrInitializationEvent;
 extern PCSR_SERVER_DLL CsrLoadedServerDll[CSR_SERVER_DLL_MAX];
+extern ULONG CsrMaxApiRequestThreads;
 
 NTSTATUS
 NTAPI
@@ -386,6 +387,10 @@
     IN OUT PULONG Reply
 );
 
+LONG
+NTAPI
+CsrUnhandledExceptionFilter(IN PEXCEPTION_POINTERS ExceptionInfo);
+
 VOID
 NTAPI
 CsrLockedDereferenceProcess(PCSR_PROCESS CsrProcess);


Reply via email to