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...@hyperreal.org on 1999/10/08 21:07:20 UTC

cvs commit: apache-2.0/src/os/win32 iol_socket.c iol_socket.h

stoddard    99/10/08 12:07:19

  Modified:    src/include ap_listen.h
               src/modules/mpm/winnt winnt.c winnt.h
               src/os/win32 iol_socket.c iol_socket.h
  Log:
  Use AcceptEx with an async completion port. What we are gaining here is
  LIFO dispatching out of the worker thread pool.
  
  Revision  Changes    Path
  1.9       +3 -0      apache-2.0/src/include/ap_listen.h
  
  Index: ap_listen.h
  ===================================================================
  RCS file: /home/cvs/apache-2.0/src/include/ap_listen.h,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- ap_listen.h	1999/10/07 21:47:36	1.8
  +++ ap_listen.h	1999/10/08 19:06:55	1.9
  @@ -65,6 +65,9 @@
       ap_listen_rec *next;
       ap_socket_t *sd;
       int active;
  +#ifdef WIN32
  +    int count;
  +#endif
   /* more stuff here, like which protocol is bound to the port */
   };
   
  
  
  
  1.17      +183 -135  apache-2.0/src/modules/mpm/winnt/winnt.c
  
  Index: winnt.c
  ===================================================================
  RCS file: /home/cvs/apache-2.0/src/modules/mpm/winnt/winnt.c,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -u -r1.16 -r1.17
  --- winnt.c	1999/10/07 20:48:26	1.16
  +++ winnt.c	1999/10/08 19:06:58	1.17
  @@ -90,6 +90,7 @@
   static char ap_coredump_dir[MAX_STRING_LEN];
   
   static server_rec *server_conf;
  +HANDLE AcceptExCompPort = NULL;
   
   static int one_process = 0;
   
  @@ -363,7 +364,7 @@
       }
       return NULL;
   }
  -static int setup_listeners(server_rec *s)
  +static int setup_listeners(ap_context_t *pconf, server_rec *s)
   {
       ap_listen_rec *lr;
       int num_listeners = 0;
  @@ -372,7 +373,7 @@
       /* Setup the listeners */
       FD_ZERO(&listenfds);
   
  -    if (ap_listen_open(s->process, s->port)) {
  +    if (ap_listen_open(pconf, s->port)) {
          return 0;
       }
       for (lr = ap_listeners; lr; lr = lr->next) {
  @@ -384,6 +385,7 @@
                   listenmaxfd = nsd;
               }
           }
  +        lr->count = 0;
       }
   
       head_listener = ap_listeners;
  @@ -445,6 +447,7 @@
           }
   //        ap_register_cleanup(p, (void *)lr->sd, socket_cleanup, NULL);
           ap_put_os_sock(&lr->sd, &nsd, pconf);
  +        lr->count = 0;
       }
       CloseHandle(pipe);
   
  @@ -724,106 +727,126 @@
       }
   }
   #endif
  -static PCOMP_CONTEXT winnt_get_connection(PCOMP_CONTEXT context)
  +/* 
  + * Windows NT specific code...
  + */
  +static int create_and_queue_completion_context(ap_context_t *p, ap_listen_rec *lr) 
   {
  -    int requests_this_child = 0;
  -    int count_select_errors = 0;
  -    struct timeval tv;
  -    fd_set main_fds;
  -    int wait_time = 1;
  +    PCOMP_CONTEXT context;
  +    DWORD BytesRead;
       SOCKET nsd;
  -    int rc;
  +    context = ap_pcalloc(p, sizeof(COMP_CONTEXT));
  +
  +    if (!context)
  +        return -1;
  +
  +    context->lr = lr;
  +    context->Overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 
   
  -    /* AcceptEx needs a pre-allocated accept socket */
       context->accept_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  +    ap_create_context(&context->ptrans, p);
  +//    context->ptrans = ap_make_sub_pool(p);
  +    context->conn_io =  ap_bcreate(context->ptrans, B_RDWR);
  +    context->recv_buf = context->conn_io->inbase;
  +    context->recv_buf_size = context->conn_io->bufsiz - 2*PADDED_ADDR_SIZE;
  +    ap_get_os_sock(context->lr->sd, &nsd);
  +
  +    AcceptEx(nsd,//context->lr->fd, 
  +             context->accept_socket,
  +             context->recv_buf,
  +             context->recv_buf_size,
  +             PADDED_ADDR_SIZE,
  +             PADDED_ADDR_SIZE,
  +             &BytesRead,
  +             (LPOVERLAPPED) context);
   
  -    ap_lock(allowed_globals.jobmutex);
  +    lr->count++;
  +//    num_comp_contexts++;
   
  -    while (!workers_may_exit) {
  -        workers_may_exit |= ((ap_max_requests_per_child != 0) && (requests_this_child > ap_max_requests_per_child));
  -        if (workers_may_exit)
  -            break;
  +    return 0;
  +}
  +static ap_inline void reset_completion_context(PCOMP_CONTEXT context) 
  +{
  +    DWORD BytesRead;
  +    SOCKET nsd;
  +    int rc;
  +    context->lr->count++;
   
  -        tv.tv_sec = wait_time;
  -        tv.tv_usec = 0;
  -        memcpy(&main_fds, &listenfds, sizeof(fd_set));
  +    if (context->accept_socket == -1)
  +        context->accept_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);    
   
  -        rc = ap_select(listenmaxfd + 1, &main_fds, NULL, NULL, &tv);
  +    ap_clear_pool(context->ptrans);
  +    context->conn_io =  ap_bcreate(context->ptrans, B_RDWR);
  +    context->recv_buf = context->conn_io->inbase;
  +    context->recv_buf_size = context->conn_io->bufsiz - 2*PADDED_ADDR_SIZE;
  +    ap_get_os_sock(context->lr->sd, &nsd);
  +
  +    rc = AcceptEx(nsd, //context->lr->fd, 
  +                  context->accept_socket,
  +                  context->recv_buf,
  +                  context->recv_buf_size,
  +                  PADDED_ADDR_SIZE,
  +                  PADDED_ADDR_SIZE,
  +                  &BytesRead,
  +                  (LPOVERLAPPED) context);
  +}
  +static PCOMP_CONTEXT winnt_get_connection(PCOMP_CONTEXT context)
  +{
  +    int requests_this_child = 0;
  +    int rc;
   
  -        if (rc == 0 || (rc == SOCKET_ERROR && h_errno == WSAEINTR)) {
  -            count_select_errors = 0;    /* reset count of errors */            
  -            continue;
  -        }
  -        else if (rc == SOCKET_ERROR) {
  -            /* A "real" error occurred, log it and increment the count of
  -             * select errors. This count is used to ensure we don't go into
  -             * a busy loop of continuous errors.
  -             */
  -            ap_log_error(APLOG_MARK, APLOG_INFO|APLOG_WIN32ERROR, server_conf, "select failed with errno %d", h_errno);
  -            count_select_errors++;
  -            if (count_select_errors > MAX_SELECT_ERRORS) {
  -                workers_may_exit = 1;
  -                ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, server_conf,
  -                             "Too many errors in select loop. Child process exiting.");
  -                break;
  -            }
  +    LPOVERLAPPED pol;
  +    DWORD CompKey;
  +    DWORD BytesRead;
  +
  +    if (context != NULL) {
  +        context->accept_socket = -1; /* Don't reuse the socket */
  +        reset_completion_context(context);
  +    }
  +
  +    rc = GetQueuedCompletionStatus(AcceptExCompPort,
  +                                   &BytesRead,
  +                                   &CompKey,
  +                                   &pol,
  +                                   INFINITE);
  +    context = (PCOMP_CONTEXT) pol;
  +    if (CompKey == 999) {
  +        if (context) {
  +            closesocket(context->accept_socket);
  +            CloseHandle(context->Overlapped.hEvent);
  +            return NULL;
           }
  -        else {
  -            DWORD BytesRead;
  -            ap_listen_rec *lr;
  -            
  -            lr = find_ready_listener(&main_fds);
  -            if (lr != NULL) {
  -                ap_get_os_sock(lr->sd, &nsd);
  -            }
  -            else {
  -                ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, server_conf,
  -                             "select returned but there are no ready listeners! Exiting.");
  -                break;
  -            }
  +    }
   
  -            rc = AcceptEx(nsd, context->accept_socket,
  -                          context->conn_io->inbase,
  -                          context->conn_io->bufsiz - 2*PADDED_ADDR_SIZE,
  -                          PADDED_ADDR_SIZE,
  -                          PADDED_ADDR_SIZE,
  -                          &BytesRead,
  -                          &context->Overlapped);
  -            
  -            if (!rc && (h_errno == WSA_IO_PENDING)) {
  -                rc = GetOverlappedResult(context->Overlapped.hEvent,
  -                                         &context->Overlapped,
  -                                         &BytesRead,
  -                                         INFINITE); /* TODO: get timeout from the config file */
  -            }
  -            if (!rc) {
  -                if (h_errno != WSAECONNABORTED) {
  -                    ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, server_conf,
  -                                 "AcceptEx failed.");
  -                }
  -                continue;  /* go back to select */
  -            }
  -            requests_this_child++;   
  -            context->conn_io->incnt = BytesRead;
  -            GetAcceptExSockaddrs(context->conn_io->inbase, 
  -                                 context->conn_io->bufsiz - 2*PADDED_ADDR_SIZE,
  -                                 PADDED_ADDR_SIZE,
  -                                 PADDED_ADDR_SIZE,
  -                                 &context->sa_server,
  -                                 &context->sa_server_len,
  -                                 &context->sa_client,
  -                                 &context->sa_client_len);
  +    ap_lock(allowed_globals.jobmutex);
   
  -            ap_unlock(allowed_globals.jobmutex);
  -            return context;
  +    context->lr->count--;
  +    if (context->lr->count < 2) {
  +        if (create_and_queue_completion_context(pconf, context->lr) == -1) {
  +            /* log error and continue */
           }
       }
  -    CloseHandle(context->Overlapped.hEvent);
       ap_unlock(allowed_globals.jobmutex);
  +
  +    context->conn_io->incnt = BytesRead;
  +/*
  +    GetAcceptExSockaddrs(context->conn_io->inbase, 
  +                         context->conn_io->bufsiz - 2*PADDED_ADDR_SIZE,
  +                         PADDED_ADDR_SIZE,
  +                         PADDED_ADDR_SIZE,
  +                         &context->sa_server,
  +                         &context->sa_server_len,
  +                         &context->sa_client,
  +                         &context->sa_client_len);
  +
  +*/
  +    return context;
  +/*
  +    CloseHandle(context->Overlapped.hEvent);
       SetEvent(exit_event);
       return NULL;
  +*/
   }
  -
   /*
    * child_main() - this is the main loop for the worker threads
    *
  @@ -844,66 +867,52 @@
    */
   static void child_main(int child_num)
   {
  -    PCOMP_CONTEXT lpCompContext;
  -    ap_iol *iol;
  +    PCOMP_CONTEXT context = NULL;
   
  -    /* Create and initialize the static (unchangeing) portion of the 
  -     * completion context 
  -     */
  -    lpCompContext = ap_pcalloc(pconf, sizeof(COMP_CONTEXT));
  -    lpCompContext->Overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 
  -    ap_create_context(&(lpCompContext->ptrans), pconf);
  +//    ap_create_context(&(lpCompContext->ptrans), pconf);
   
   #if 0
       (void) ap_update_child_status(child_num, SERVER_READY, (request_rec *) NULL);
   #endif
   
       while (1) {
  -        BUFF *conn_io;
  -        ap_context_t *ptrans;
  -        int csd = -1;
           conn_rec *current_conn;
  -
  -        /* Initialize the dynamic portion of the completion context */
  -	ap_clear_pool(lpCompContext->ptrans);
  -        lpCompContext->conn_io =  ap_bcreate(lpCompContext->ptrans, B_RDWR);
  +        ap_iol *iol;
   
           /* Grab a connection off the network */
  -        if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT)
  -            lpCompContext = winnt_get_connection(lpCompContext);
  +        if (osver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
  +//            context = win9x_get_connection(context);
  +        }
           else {
  -//            lpCompContext = win9x_get_connection(lpCompContext);
  +            context = winnt_get_connection(context);
           }
   
  -
  -        if (!lpCompContext)
  +        if (!context)
               break;
   
  -        conn_io = lpCompContext->conn_io;
  -        ptrans = lpCompContext->ptrans;
  -        csd = lpCompContext->accept_socket;
  +//        ap_note_cleanups_for_socket(context->ptrans, context->accept_socket);
   
  -//	ap_note_cleanups_for_socket(ptrans, csd);
   
   #if 0
   	(void) ap_update_child_status(child_num, SERVER_BUSY_READ,
                                         (request_rec *) NULL);
   #endif
  -	sock_disable_nagle(csd);
  +
  +	sock_disable_nagle(context->accept_socket);
   
  -        iol = win32_attach_socket(csd);
  +        iol = win32_attach_socket(context->ptrans, context->accept_socket);
           if (iol == NULL) {
               ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
                            "error attaching to socket");
  -            close(csd);
  +            closesocket(context->accept_socket);
               continue;
           }
   
  -        ap_bpush_iol(conn_io, iol);
  +        ap_bpush_iol(context->conn_io, iol);
   
  -	current_conn = ap_new_connection(ptrans, server_conf, conn_io,
  -                                         (struct sockaddr_in *) &lpCompContext->sa_client,
  -                                         (struct sockaddr_in *) &lpCompContext->sa_server,
  +	current_conn = ap_new_connection(context->ptrans, server_conf, context->conn_io,
  +                                         (struct sockaddr_in *) &context->sa_client,
  +                                         (struct sockaddr_in *) &context->sa_server,
                                            child_num);
   
           ap_process_connection(current_conn);
  @@ -1019,7 +1028,7 @@
   	ap_log_error(APLOG_MARK,APLOG_ERR|APLOG_WIN32ERROR, server_conf,
                        "Waiting for start_mutex or exit_event -- process will exit");
   
  -	ap_destroy_pool(pchild);
  +	ap_destroy_context(pchild); // ap_destroy_pool(pchild):
   #if 0
   	cleanup_scoreboard();
   #endif
  @@ -1028,7 +1037,7 @@
   
       /* start_mutex obtained, continue into the select() loop */
       if (one_process) {
  -        setup_listeners(server_conf);
  +        setup_listeners(pconf, server_conf);
       } else {
           /* Get listeners from the parent process */
           setup_inherited_listeners(pconf, server_conf);
  @@ -1041,7 +1050,8 @@
   
   	signal_parent(0);	/* tell parent to die */
   
  -	ap_destroy_pool(pchild);
  +//	ap_destroy_pool(pchild);
  +        ap_destroy_context(pchild);
   #if 0
   	cleanup_scoreboard();
   #endif
  @@ -1051,33 +1061,71 @@
       allowed_globals.jobsemaphore = create_semaphore(0);
       ap_create_lock(pchild, APR_MUTEX, APR_INTRAPROCESS, NULL, &allowed_globals.jobmutex);
   
  -    /* spawn off the worker threads */
  -    child_handles = (thread *) alloca(nthreads * sizeof(int));
  -    for (i = 0; i < nthreads; i++) {
  -	child_handles[i] = create_thread((void (*)(void *)) child_main, (void *) i);
  -    }
  -
       /* spawn off accept thread (WIN9x only) */
  -//    if (osver.dwPlatformId != VER_PLATFORM_WIN32_NT)
  +    if (osver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
  +        /* spawn off the worker threads */
  +        child_handles = (thread *) alloca(nthreads * sizeof(int));
  +        for (i = 0; i < nthreads; i++) {
  +            child_handles[i] = create_thread((void (*)(void *)) child_main, (void *) i);
  +        }
  +
   //        create_thread((void (*)(void *)) accept_and_queue_connections, (void *) NULL);
  +    }
  +    else {
  +        ap_listen_rec *lr;
  +        SOCKET nsd;
  +        /* Create the AcceptEx completion port */
  +        AcceptExCompPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE,
  +                                                  NULL,
  +                                                  0,
  +                                                  0); /* CONCURRENT ACTIVE THREADS */
   
  +        /* Associate each listener with the completion port */
  +        for (lr = ap_listeners; lr != NULL; lr = lr->next) {
  +            ap_get_os_sock(lr->sd, &nsd);
  +            CreateIoCompletionPort((HANDLE) nsd, //(HANDLE)lr->fd,
  +                                   AcceptExCompPort,
  +                                   0,
  +                                   0);
  +        }
  +
  +        /* spawn off the worker threads */
  +        child_handles = (thread *) alloca(nthreads * sizeof(int));
  +        for (i = 0; i < nthreads; i++) {
  +            child_handles[i] = create_thread((void (*)(void *)) child_main, (void *) i);
  +        }
  +
  +        /* Create an AcceptEx context for each listener and queue it to the 
  +         * AcceptEx completion port
  +         */
  +        for (lr = ap_listeners; lr != NULL; lr = lr->next) {
  +            for(i=0; i<1; i++) {
  +                if (create_and_queue_completion_context(pconf, lr) == -1) {
  +                    /* log error and exit */
  +                }
  +            }
  +        }
  +    }
  +
       rv = WaitForSingleObject(exit_event, INFINITE);
       printf("exit event signalled \n");
       workers_may_exit = 1;      
   
       /* Get ready to shutdown and exit */
       ap_unlock(start_mutex);
  -#if 0
  -    if (osver.dwPlatformId != VER_PLATFORM_WIN32_NT) {
  -        /* This is only needed for platforms that use the accept queue code 
  -         * (WIN9x only). It should work on NT but not as efficiently as the 
  -         * code written specifically for Windows NT.
  -         */
  +
  +    /* Tell the workers to stop */
  +    if (osver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
           for (i = 0; i < nthreads; i++) {
  -            add_job(-1);
  +//            add_job(-1);
           }
       }
  -#endif
  +    else {
  +        for (i=0; i < nthreads; i++) {
  +            PostQueuedCompletionStatus(AcceptExCompPort, 0, 999, NULL);
  +        }
  +    }
  +
       /* Wait for all your children */
       end_time = time(NULL) + 180;
       while (nthreads) {
  @@ -1100,7 +1148,7 @@
       destroy_semaphore(allowed_globals.jobsemaphore);
       ap_destroy_lock(allowed_globals.jobmutex);
   
  -    ap_destroy_pool(pchild);
  +    ap_destroy_context(pchild);
   
   #if 0
       cleanup_scoreboard();
  @@ -1343,7 +1391,7 @@
       HANDLE process_handles[MAX_PROCESSES];
       HANDLE process_kill_events[MAX_PROCESSES];
   
  -    setup_listeners(s);
  +    setup_listeners(pconf, s);
   
       /* Create child process 
        * Should only be one in this version of Apache for WIN32 
  
  
  
  1.4       +16 -1     apache-2.0/src/modules/mpm/winnt/winnt.h
  
  Index: winnt.h
  ===================================================================
  RCS file: /home/cvs/apache-2.0/src/modules/mpm/winnt/winnt.h,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- winnt.h	1999/08/31 05:33:28	1.3
  +++ winnt.h	1999/10/08 19:07:05	1.4
  @@ -64,9 +64,24 @@
   extern int ap_extended_status;
   extern void clean_child_exit(int);
   
  +
   typedef struct CompContext {
       OVERLAPPED Overlapped;
       SOCKET accept_socket;
  +    ap_listen_rec *lr;
  +    BUFF *conn_io;
  +    char *recv_buf;
  +    int  recv_buf_size;
  +    ap_context_t *ptrans;
  +    struct sockaddr sa_server;
  +    int sa_server_len;
  +    struct sockaddr sa_client;
  +    int sa_client_len;
  +} COMP_CONTEXT, *PCOMP_CONTEXT;
  +#if 0
  +typedef struct CompContext {
  +    OVERLAPPED Overlapped;
  +    SOCKET accept_socket;
       BUFF* conn_io;
       ap_context_t *ptrans;
       struct sockaddr sa_server;
  @@ -74,5 +89,5 @@
       struct sockaddr sa_client;
       int sa_client_len;
   } COMP_CONTEXT, *PCOMP_CONTEXT;
  -
  +#endif
   #endif /* APACHE_MPM_WINNT_H */
  
  
  
  1.5       +4 -3      apache-2.0/src/os/win32/iol_socket.c
  
  Index: iol_socket.c
  ===================================================================
  RCS file: /home/cvs/apache-2.0/src/os/win32/iol_socket.c,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- iol_socket.c	1999/10/08 14:35:34	1.4
  +++ iol_socket.c	1999/10/08 19:07:11	1.5
  @@ -116,7 +116,7 @@
   
       rv = closesocket(iol->fd);
   
  -    free(iol);
  +//    free(iol);
   
       return rv;
   }
  @@ -603,11 +603,12 @@
   
   #endif
   
  -ap_iol *win32_attach_socket(int fd)
  +ap_iol *win32_attach_socket(ap_context_t *p, int fd)
   {
       iol_socket *iol;
   
  -    iol = malloc(sizeof(iol_socket));
  +//    iol = malloc(sizeof(iol_socket));
  +    iol = ap_palloc(p,sizeof(iol_socket));
       if (!iol)
           return (ap_iol*) NULL;
       iol->iol.methods = &socket_methods;
  
  
  
  1.3       +1 -1      apache-2.0/src/os/win32/iol_socket.h
  
  Index: iol_socket.h
  ===================================================================
  RCS file: /home/cvs/apache-2.0/src/os/win32/iol_socket.h,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- iol_socket.h	1999/09/24 18:41:11	1.2
  +++ iol_socket.h	1999/10/08 19:07:12	1.3
  @@ -58,7 +58,7 @@
   #ifndef OS_WIN32_IOL_SOCKET_H
   #define OS_WIN32_IOL_SOCKET_H
   
  -ap_iol *win32_attach_socket(int fd);
  +ap_iol *win32_attach_socket(ap_context_t *p, int fd);
   
   #endif