You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by bj...@hyperreal.org on 1999/10/18 13:36:04 UTC

cvs commit: apache-2.0/src/lib/apr/network_io/os2 networkio.h poll.c

bjh         99/10/18 04:36:04

  Modified:    src/lib/apr/network_io/os2 networkio.h poll.c
  Log:
  OS/2: Rework ap_poll() to use native thread safe select instead of the EMX C
  library select which isn't thread safe.
  
  Revision  Changes    Path
  1.3       +24 -5     apache-2.0/src/lib/apr/network_io/os2/networkio.h
  
  Index: networkio.h
  ===================================================================
  RCS file: /home/cvs/apache-2.0/src/lib/apr/network_io/os2/networkio.h,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- networkio.h	1999/10/08 21:27:52	1.2
  +++ networkio.h	1999/10/18 11:36:03	1.3
  @@ -64,17 +64,36 @@
       int socketdes;
       struct sockaddr_in *addr;
       int addr_len;
  +    int timeout; 
   };
   
   struct pollfd_t {
       ap_context_t *cntxt;
  -    struct socket_t *sock;
  -    ap_int16_t events;
  -    ap_int16_t revents;
  -    int curpos;
  +    int *socket_list;
  +    int *r_socket_list;
  +    int num_read;
  +    int num_write;
  +    int num_except;
  +    int num_total;
   };
   
  -ap_int16_t get_event(ap_int16_t);
  +/* Pointers to dynamically linked API functions */
  +extern int (*os2_select)(int *, int, int, int, long);
  +extern int (*os2_sock_errno)();
  +
  +/* Error codes returned from sock_errno() */
  +#define SOCBASEERR              10000
  +#define SOCEPERM                (SOCBASEERR+1)             /* Not owner */
  +#define SOCESRCH                (SOCBASEERR+3)             /* No such process */
  +#define SOCEINTR                (SOCBASEERR+4)             /* Interrupted system call */
  +#define SOCENXIO                (SOCBASEERR+6)             /* No such device or address */
  +#define SOCEBADF                (SOCBASEERR+9)             /* Bad file number */
  +#define SOCEACCES               (SOCBASEERR+13)            /* Permission denied */
  +#define SOCEFAULT               (SOCBASEERR+14)            /* Bad address */
  +#define SOCEINVAL               (SOCBASEERR+22)            /* Invalid argument */
  +#define SOCEMFILE               (SOCBASEERR+24)            /* Too many open files */
  +#define SOCEPIPE                (SOCBASEERR+32)            /* Broken pipe */
  +#define SOCEOS2ERR              (SOCBASEERR+100)            /* OS/2 Error */
   
   #endif  /* ! NETWORK_IO_H */
   
  
  
  
  1.5       +170 -54   apache-2.0/src/lib/apr/network_io/os2/poll.c
  
  Index: poll.c
  ===================================================================
  RCS file: /home/cvs/apache-2.0/src/lib/apr/network_io/os2/poll.c,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- poll.c	1999/10/10 20:34:56	1.4
  +++ poll.c	1999/10/18 11:36:04	1.5
  @@ -57,40 +57,79 @@
   #include "networkio.h"
   #include "apr_network_io.h"
   #include "apr_general.h"
  +#include "apr_portable.h"
   #include "apr_lib.h"
   #include <sys/time.h>
  +#include <stdlib.h>
  +#define INCL_DOS
  +#include <os2.h>
   
  -/*  OS/2 doesn't have a poll function, implement using select */
  +/*  OS/2 doesn't have a poll function, implement using OS/2 style select */
    
  +static int os2_select_init( int *s, int noreads, int nowrites, int noexcepts, long timeout );
  +static int os2_sock_errno_init();
  +
  +int (*os2_select)(int *, int, int, int, long) = os2_select_init;
  +int (*os2_sock_errno)() = os2_sock_errno_init;
  +static HMODULE hSO32DLL;
  +
   ap_status_t ap_setup_poll(struct pollfd_t **new, ap_int32_t num, ap_context_t *cont)
   {
  -    (*new) = (struct pollfd_t *)ap_palloc(cont, sizeof(struct pollfd_t) * num);
  +    *new = (struct pollfd_t *)ap_palloc(cont, sizeof(struct pollfd_t));
   
  -    if ((*new) == NULL) {
  +    if (*new == NULL) {
           return APR_ENOMEM;
       }
   
  +    (*new)->socket_list = ap_palloc(cont, sizeof(int) * num);
  +    
  +    if ((*new)->socket_list == NULL) {
  +        return APR_ENOMEM;
  +    }
  +    
  +    (*new)->r_socket_list = ap_palloc(cont, sizeof(int) * num);
  +    
  +    if ((*new)->r_socket_list == NULL) {
  +        return APR_ENOMEM;
  +    }
  +    
       (*new)->cntxt = cont;
  -    (*new)->curpos = 0;
  +    (*new)->num_total = 0;
  +    (*new)->num_read = 0;
  +    (*new)->num_write = 0;
  +    (*new)->num_except = 0;
  +    
       return APR_SUCCESS;
   }
   
   
   
   ap_status_t ap_add_poll_socket(struct pollfd_t *aprset, 
  -			       struct socket_t *sock, ap_int16_t event)
  +			       struct socket_t *sock, ap_int16_t events)
   {
  -    int i = 0;
  +    int i;
       
  -    while (i < aprset->curpos && aprset[i].sock->socketdes != sock->socketdes) {
  -        i++;
  +    if (events & APR_POLLIN) {
  +        for (i=aprset->num_total; i>aprset->num_read; i--)
  +            aprset->socket_list[i] = aprset->socket_list[i-1];
  +        aprset->socket_list[i] = sock->socketdes;
  +        aprset->num_read++;
  +        aprset->num_total++;
       }
  -    if (i >= aprset->curpos) {
  -        aprset->curpos++;
  -    } 
  -    aprset[i].sock = sock;
  -    aprset[i].events = event;
  -
  +            
  +    if (events & APR_POLLOUT) {
  +        for (i=aprset->num_total; i>aprset->num_read + aprset->num_write; i--)
  +            aprset->socket_list[i] = aprset->socket_list[i-1];
  +        aprset->socket_list[i] = sock->socketdes;
  +        aprset->num_write++;
  +        aprset->num_total++;
  +    }            
  +        
  +    if (events &APR_POLLPRI) {
  +        aprset->socket_list[aprset->num_total] = sock->socketdes;
  +        aprset->num_except++;
  +        aprset->num_total++;
  +    }
       return APR_SUCCESS;
   }
   
  @@ -99,71 +138,148 @@
   ap_status_t ap_poll(struct pollfd_t *pollfdset, ap_int32_t *nsds, ap_int32_t timeout)
   {
       int i;
  -    int rv = 0, maxfd = 0;
  +    int rv = 0;
       time_t starttime;
       struct timeval tv;
  -    fd_set readfds, writefds, exceptfds;
  -
  -    FD_ZERO(&readfds);
  -    FD_ZERO(&writefds);
  -    FD_ZERO(&exceptfds);
       
  -    for (i = 0; i < *nsds; i++) {
  -        if (pollfdset[i].sock->socketdes > maxfd)
  -            maxfd = pollfdset[i].sock->socketdes;
  -
  -        if (pollfdset[i].events & APR_POLLIN)
  -            FD_SET(pollfdset[i].sock->socketdes, &readfds);
  -
  -        if (pollfdset[i].events & APR_POLLOUT)
  -            FD_SET(pollfdset[i].sock->socketdes, &writefds);
  -
  -        if (pollfdset[i].events & APR_POLLPRI)
  -            FD_SET(pollfdset[i].sock->socketdes, &exceptfds);
  -    }
  -
       tv.tv_sec = timeout;
       tv.tv_usec = 0;
       time(&starttime);
   
       do {
  -        rv = select(maxfd + 1, &readfds, &writefds, &exceptfds, timeout >= 0 ? &tv : NULL);
  +        for (i=0; i<pollfdset->num_total; i++) {
  +            pollfdset->r_socket_list[i] = _getsockhandle(pollfdset->socket_list[i]);
  +        }
  +        
  +        rv = os2_select(pollfdset->r_socket_list, 
  +                        pollfdset->num_read, 
  +                        pollfdset->num_write, 
  +                        pollfdset->num_except, 
  +                        timeout > 0 ? timeout * 1000 : -1);
   
  -        if (rv < 0 && errno == EINTR && timeout >= 0 ) {
  +        if (rv < 0 && os2_sock_errno() == SOCEINTR && timeout >= 0 ) {
               time_t elapsed = time(NULL) - starttime;
   
               if (timeout <= elapsed)
                   break;
   
  -            tv.tv_sec = timeout - elapsed;
  +            timeout -= elapsed;
           }
  -    } while ( rv < 0 && errno == EINTR );
  +    } while ( rv < 0 && os2_sock_errno() == SOCEINTR );
   
  -    if (rv >= 0) {
  -        for (i = 0; i < *nsds; i++) {
  -            pollfdset[i].revents =
  -                (FD_ISSET(pollfdset[i].sock->socketdes, &readfds) ? APR_POLLIN : 0) +
  -                (FD_ISSET(pollfdset[i].sock->socketdes, &writefds) ? APR_POLLOUT : 0) +
  -                (FD_ISSET(pollfdset[i].sock->socketdes, &exceptfds) ? APR_POLLPRI : 0);
  -        }
  -    }
  -    
       (*nsds) = rv;
  -    return rv < 0 ? errno : APR_SUCCESS;
  +    return rv < 0 ? os2errno(os2_sock_errno()) : APR_SUCCESS;
   }
   
   
   
   ap_status_t ap_get_revents(ap_int16_t *event, struct socket_t *sock, struct pollfd_t *aprset)
   {
  -    int i = 0;
  +    int i;
       
  -    while (i < aprset->curpos && aprset[i].sock->socketdes != sock->socketdes) {
  -        i++;
  -    }
  -    if (i >= aprset->curpos) {
  +    for (i=0; i < aprset->num_total && aprset->socket_list[i] != sock->socketdes; i++);
  +    
  +    if (i == aprset->num_total) {
           return APR_INVALSOCK;
       } 
  -    (*event) = aprset[i].revents;
  +    
  +    if (i < aprset->num_read)
  +        *event = APR_POLLIN;
  +    else if (i < aprset->num_read + aprset->num_write)
  +        *event = APR_POLLOUT;
  +    else
  +        *event = APR_POLLPRI;
  +
       return APR_SUCCESS;
  +}
  +
  +
  +
  +ap_status_t ap_remove_poll_socket(struct pollfd_t *aprset, 
  +                                  struct socket_t *sock, ap_int16_t events)
  +{
  +    int start, *count, pos;
  +
  +    while (events) {
  +        if (events & APR_POLLIN) {
  +            start = 0;
  +            count = &aprset->num_read;
  +            events -= APR_POLLIN;
  +        } else if (events & APR_POLLOUT) {
  +            start = aprset->num_read;
  +            count = &aprset->num_write;
  +            events -= APR_POLLOUT;
  +        } else if (events & APR_POLLPRI) {
  +            start = aprset->num_read + aprset->num_write;
  +            count = &aprset->num_except;
  +            events -= APR_POLLPRI;
  +        } else
  +            break;
  +
  +        for (pos=start; pos < start+(*count) && aprset->socket_list[pos] != sock->socketdes; pos++);
  +
  +        if (pos < start+(*count)) {
  +            aprset->num_total--;
  +            (*count)--;
  +
  +            for (;pos<aprset->num_total; pos++) {
  +                aprset->socket_list[pos] = aprset->socket_list[pos+1];
  +            }
  +        } else {
  +            return APR_NOTFOUND;
  +        }
  +    }
  +
  +    return APR_SUCCESS;
  +}
  +
  +
  +
  +static int os2_fn_link()
  +{
  +    if (os2_select == os2_select_init || os2_select == NULL) {
  +        DosEnterCritSec(); /* Stop two threads doing this at the same time */
  +
  +        if (os2_select == os2_select_init || os2_select == NULL) {
  +            ULONG rc;
  +            char errorstr[200];
  +            
  +            rc = DosLoadModule(errorstr, sizeof(errorstr), "SO32DLL", &hSO32DLL);
  +            
  +            if (rc)
  +                return os2errno(rc);
  +
  +            rc = DosQueryProcAddr(hSO32DLL, 0, "SELECT", &os2_select);
  +            
  +            if (rc)
  +                return os2errno(rc);
  +
  +            rc = DosQueryProcAddr(hSO32DLL, 0, "SOCK_ERRNO", &os2_sock_errno);
  +            
  +            if (rc)
  +                return os2errno(rc);
  +        }
  +        DosExitCritSec();
  +    }
  +    return APR_SUCCESS;
  +}   
  +
  +
  +
  +static int os2_select_init(int *s, int noreads, int nowrites, int noexcepts, long timeout)
  +{
  +    int rc = os2_fn_link();
  +    if (rc == APR_SUCCESS)
  +        return os2_select(s, noreads, nowrites, noexcepts, timeout);
  +    return rc;
  +}
  +
  +
  +
  +static int os2_sock_errno_init()
  +{
  +    int rc = os2_fn_link();
  +    if (rc == APR_SUCCESS)
  +        return os2_sock_errno();
  +    return rc;
   }