You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by st...@apache.org on 2001/11/17 08:54:34 UTC

cvs commit: httpd-2.0/server/mpm/winnt mpm_winnt.c mpm_winnt.h

stoddard    01/11/16 23:54:34

  Modified:    server/mpm/winnt mpm_winnt.c mpm_winnt.h
  Log:
  Externalize the functions to manage the mpm's queue of completion_contexts.
  Now a module can produce to the queue of contexts that the worker threads
  consume from.
  
  Insomnia tonight in Cary NC...
  
  Revision  Changes    Path
  1.195     +101 -99   httpd-2.0/server/mpm/winnt/mpm_winnt.c
  
  Index: mpm_winnt.c
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/server/mpm/winnt/mpm_winnt.c,v
  retrieving revision 1.194
  retrieving revision 1.195
  diff -u -r1.194 -r1.195
  --- mpm_winnt.c	2001/11/15 20:49:54	1.194
  +++ mpm_winnt.c	2001/11/17 07:54:34	1.195
  @@ -75,45 +75,8 @@
   #include "mpm_common.h"
   #include <malloc.h>
   
  -typedef HANDLE thread;
  -#ifdef CONTAINING_RECORD
  -#undef CONTAINING_RECORD
  -#endif
  -#define CONTAINING_RECORD(address, type, field) ((type *)( \
  -                                                  (PCHAR)(address) - \
  -                                                  (PCHAR)(&((type *)0)->field)))
  -#define PADDED_ADDR_SIZE sizeof(SOCKADDR_IN)+16
  -
  -typedef struct CompContext {
  -    struct CompContext *next;
  -    OVERLAPPED Overlapped;
  -    apr_socket_t *sock;
  -    SOCKET accept_socket;
  -    char buff[2*PADDED_ADDR_SIZE];
  -    struct sockaddr *sa_server;
  -    int sa_server_len;
  -    struct sockaddr *sa_client;
  -    int sa_client_len;
  -    apr_pool_t *ptrans;
  -} COMP_CONTEXT, *PCOMP_CONTEXT;
  -
  -typedef enum {
  -    IOCP_CONNECTION_ACCEPTED = 1,
  -    IOCP_WAIT_FOR_RECEIVE = 2,
  -    IOCP_WAIT_FOR_TRANSMITFILE = 3,
  -    IOCP_SHUTDOWN = 4
  -} io_state_e;
  -
  -/* Queue for managing the passing of COMP_CONTEXTs from 
  - * the accept thread to the worker threads and back again
  - */
  -apr_lock_t  *qlock;
  -COMP_CONTEXT *qhead = NULL;
  -COMP_CONTEXT *qtail = NULL;
  -
  -static HANDLE ThreadDispatchIOCP = NULL;
  -
   server_rec *ap_server_conf;
  +typedef HANDLE thread;
   
   /* Definitions of WINNT MPM specific config globals */
   static apr_pool_t *pconf;
  @@ -139,11 +102,96 @@
   static DWORD parent_pid;
   
   int ap_threads_per_child = 0;
  +
  +/* ap_my_generation are used by the scoreboard code */
  +ap_generation_t volatile ap_my_generation=0;
   
  -/* ap_get_max_daemons and ap_my_generation are used by the scoreboard
  - * code
  +/* Queue for managing the passing of COMP_CONTEXTs between
  + * the accept and worker threads.
    */
  -ap_generation_t volatile ap_my_generation=0; /* Used by the scoreboard */
  +static apr_lock_t  *qlock;
  +static PCOMP_CONTEXT qhead = NULL;
  +static PCOMP_CONTEXT qtail = NULL;
  +static int num_completion_contexts = 0;
  +static HANDLE ThreadDispatchIOCP = NULL;
  +AP_DECLARE(void) mpm_recycle_completion_context(PCOMP_CONTEXT pCompContext)
  +{
  +    /* Recycle the completion context.
  +     * - destroy the ptrans pool
  +     * - put the context on the queue to be consumed by the accept thread
  +     * Note: 
  +     * pCompContext->accept_socket may be in a disconnected but reusable 
  +     * state so -don't- close it.
  +     */
  +    if (pCompContext) {
  +        apr_pool_clear(pCompContext->ptrans);
  +        apr_pool_destroy(pCompContext->ptrans);
  +        pCompContext->ptrans = NULL;
  +        pCompContext->next = NULL;
  +        apr_lock_acquire(qlock);
  +        if (qtail)
  +            qtail->next = pCompContext;
  +        else
  +            qhead = pCompContext;
  +        qtail = pCompContext;
  +        apr_lock_release(qlock);
  +    }
  +}
  +AP_DECLARE(PCOMP_CONTEXT) mpm_get_completion_context(void)
  +{
  +    PCOMP_CONTEXT pCompContext = NULL;
  +
  +    /* Grab a context off the queue */
  +    apr_lock_acquire(qlock);
  +    if (qhead) {
  +        pCompContext = qhead;
  +        qhead = qhead->next;
  +        if (!qhead)
  +            qtail = NULL;
  +    }
  +    apr_lock_release(qlock);
  +
  +    /* If we failed to grab a context off the queue, alloc one out of 
  +     * the child pool. There may be up to ap_threads_per_child contexts
  +     * in the system at once.
  +     */
  +    if (!pCompContext) {
  +        if (num_completion_contexts >= ap_threads_per_child) {
  +            static int reported = 0;
  +            if (!reported) {
  +                ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, ap_server_conf,
  +                             "Server ran out of threads to serve requests. Consider "
  +                             "raising the ThreadsPerChild setting");
  +                reported = 1;
  +            }
  +            return NULL;
  +        }
  +        pCompContext = (PCOMP_CONTEXT) apr_pcalloc(pchild, sizeof(COMP_CONTEXT));
  +
  +        pCompContext->Overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 
  +        if (pCompContext->Overlapped.hEvent == NULL) {
  +            /* Hopefully this is a temporary condition ... */
  +            ap_log_error(APLOG_MARK,APLOG_WARNING, apr_get_os_error(), ap_server_conf,
  +                         "mpm_get_completion_context: CreateEvent failed.");
  +            return NULL;
  +        }
  +        pCompContext->accept_socket = INVALID_SOCKET;
  +        num_completion_contexts++;
  +    }
  +    return pCompContext;
  +}
  +AP_DECLARE(apr_status_t) mpm_post_completion_context(PCOMP_CONTEXT pCompContext, 
  +                                                     io_state_e state)
  +{
  +    LPOVERLAPPED pOverlapped;
  +    if (pCompContext)
  +        pOverlapped = &pCompContext->Overlapped;
  +    else
  +        pOverlapped = NULL;
  +
  +    PostQueuedCompletionStatus(ThreadDispatchIOCP, 0, state, pOverlapped);
  +    return APR_SUCCESS;
  +}
   
   /* This is the helper code to resolve late bound entry points 
    * missing from one or more releases of the Win32 API...
  @@ -652,7 +700,7 @@
    */
   static void winnt_accept(void *listen_socket) 
   {
  -    static int num_completion_contexts = 0;
  +
       PCOMP_CONTEXT pCompContext;
       DWORD BytesRead;
       SOCKET nlsd;
  @@ -661,46 +709,17 @@
       nlsd = (SOCKET) listen_socket;
   
       while (!shutdown_in_progress) {
  -
  -        pCompContext = NULL;
  -        /* Grab a context off the queue */
  -        apr_lock_acquire(qlock);
  -        if (qhead) {
  -            pCompContext = qhead;
  -            qhead = qhead->next;
  -            if (!qhead)
  -                qtail = NULL;
  -        }
  -        apr_lock_release(qlock);
  -
  -        /* If we failed to grab a context off the queue, alloc one out of 
  -         * the child pool. There may be up to ap_threads_per_child contexts
  -         * in the system at once.
  -         */
  +        pCompContext = mpm_get_completion_context();
           if (!pCompContext) {
  -            if (num_completion_contexts >= ap_threads_per_child) {
  -                static int reported = 0;
  -                if (!reported) {
  -                    ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, ap_server_conf,
  -                                 "Server ran out of threads to serve requests. Consider "
  -                                 "raising the ThreadsPerChild setting");
  -                    reported = 1;
  -                }
  -                Sleep(500);
  -                continue;
  -            }
  -            pCompContext = (PCOMP_CONTEXT) apr_pcalloc(pchild, sizeof(COMP_CONTEXT));
  -
  -            pCompContext->Overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 
  -            if (pCompContext->Overlapped.hEvent == NULL) {
  -                ap_log_error(APLOG_MARK,APLOG_ERR, apr_get_os_error(), ap_server_conf,
  -                             "winnt_accept: CreateEvent failed. Process will exit.");
  -                // return -1;
  -            }
  -            pCompContext->accept_socket = INVALID_SOCKET;
  -            num_completion_contexts++;
  +            /* Hopefully whatever is preventing us from getting a 
  +             * completion context is a temporary condition. Give other 
  +             * threads a chance to run before trying again. 
  +             */
  +            Sleep(750);
  +            continue;
           }
   
  +
       again:            
           /* Create and initialize the accept socket */
           if (pCompContext->accept_socket == INVALID_SOCKET) {
  @@ -757,7 +776,8 @@
           }
   
           /* When a connection is received, send an io completion notification to
  -         * the ThreadDispatchIOCP
  +         * the ThreadDispatchIOCP. This function could be replaced by
  +         * mpm_post_completion_context(), but why do an extra function call...
            */
           PostQueuedCompletionStatus(ThreadDispatchIOCP, 0, IOCP_CONNECTION_ACCEPTED,
                                      &pCompContext->Overlapped);
  @@ -776,25 +796,7 @@
       DWORD CompKey;
       LPOVERLAPPED pol;
   
  -    /* Recycle the completion context.
  -     * - destroy the ptrans pool
  -     * - put the context on the queue to be consumed by the accept thread
  -     * Note: pCompContext->accept_socket may be in a disconnected
  -     * but reusable state so -don't- close it.
  -     */
  -    if (pCompContext) {
  -        apr_pool_clear(pCompContext->ptrans);
  -        apr_pool_destroy(pCompContext->ptrans);
  -        pCompContext->ptrans = NULL;
  -        pCompContext->next = NULL;
  -        apr_lock_acquire(qlock);
  -        if (qtail)
  -            qtail->next = pCompContext;
  -        else
  -            qhead = pCompContext;
  -        qtail = pCompContext;
  -        apr_lock_release(qlock);
  -    }
  +    mpm_recycle_completion_context(pCompContext);
   
       g_blocked_threads++;        
       while (1) {
  
  
  
  1.30      +37 -0     httpd-2.0/server/mpm/winnt/mpm_winnt.h
  
  Index: mpm_winnt.h
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/server/mpm/winnt/mpm_winnt.h,v
  retrieving revision 1.29
  retrieving revision 1.30
  diff -u -r1.29 -r1.30
  --- mpm_winnt.h	2001/10/17 15:51:22	1.29
  +++ mpm_winnt.h	2001/11/17 07:54:34	1.30
  @@ -160,4 +160,41 @@
       (dwProcessId, dwType));
   #define RegisterServiceProcess ap_winapi_RegisterServiceProcess
   
  +/*
  + * The Windoes MPM uses a queue of completion contexts that it passes
  + * between the accept threads and the worker threads. Declare the
  + * functions to access the queue and the structures passed on the
  + * queue in the header file to enable modules to access them
  + * if necessary. The queue resides in the MPM.
  + */
  +#ifdef CONTAINING_RECORD
  +#undef CONTAINING_RECORD
  +#endif
  +#define CONTAINING_RECORD(address, type, field) ((type *)( \
  +                                                  (PCHAR)(address) - \
  +                                                  (PCHAR)(&((type *)0)->field)))
  +#define PADDED_ADDR_SIZE sizeof(SOCKADDR_IN)+16
  +typedef struct CompContext {
  +    struct CompContext *next;
  +    OVERLAPPED Overlapped;
  +    apr_socket_t *sock;
  +    SOCKET accept_socket;
  +    char buff[2*PADDED_ADDR_SIZE];
  +    struct sockaddr *sa_server;
  +    int sa_server_len;
  +    struct sockaddr *sa_client;
  +    int sa_client_len;
  +    apr_pool_t *ptrans;
  +} COMP_CONTEXT, *PCOMP_CONTEXT;
  +
  +typedef enum {
  +    IOCP_CONNECTION_ACCEPTED = 1,
  +    IOCP_WAIT_FOR_RECEIVE = 2,
  +    IOCP_WAIT_FOR_TRANSMITFILE = 3,
  +    IOCP_SHUTDOWN = 4
  +} io_state_e;
  +
  +AP_DECLARE(PCOMP_CONTEXT) mpm_get_completion_context(void);
  +AP_DECLARE(void)          mpm_recycle_completion_context(PCOMP_CONTEXT pCompContext);
  +AP_DECLARE(apr_status_t)  mpm_post_completion_context(PCOMP_CONTEXT pCompContext, io_state_e state);
   #endif /* APACHE_MPM_WINNT_H */