PageRenderTime 29ms CodeModel.GetById 12ms app.highlight 14ms RepoModel.GetById 1ms app.codeStats 0ms

/src/common/xpoll.c

https://code.google.com/
C | 207 lines | 148 code | 27 blank | 32 comment | 44 complexity | d0a03a4427b3a9c7620e586fc9a6850e MD5 | raw file
  1/*****************************************************************************\
  2 *  $Id$
  3 *****************************************************************************
  4 *  Copyright (C) 2001-2006 The Regents of the University of California.
  5 *  Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
  6 *  Written by Jim Garlick <garlick@llnl.gov>.
  7 *  UCRL-CODE-2003-005.
  8 *  
  9 *  This file is part of Pdsh, a parallel remote shell program.
 10 *  For details, see <http://www.llnl.gov/linux/pdsh/>.
 11 *  
 12 *  Pdsh is free software; you can redistribute it and/or modify it under
 13 *  the terms of the GNU General Public License as published by the Free
 14 *  Software Foundation; either version 2 of the License, or (at your option)
 15 *  any later version.
 16 *  
 17 *  Pdsh is distributed in the hope that it will be useful, but WITHOUT ANY
 18 *  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 19 *  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 20 *  details.
 21 *  
 22 *  You should have received a copy of the GNU General Public License along
 23 *  with Pdsh; if not, write to the Free Software Foundation, Inc.,
 24 *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
 25\*****************************************************************************/
 26
 27#if HAVE_CONFIG_H
 28#  include <config.h>
 29#endif 
 30
 31#if HAVE_POLL_H
 32#include <poll.h>
 33#else
 34#if HAVE_SYS_POLL_H
 35#include <sys/poll.h>
 36#endif /* HAVE_SYS_POLL_H */
 37#endif /* HAVE_POLL_H */
 38
 39#include <sys/types.h>
 40#include <sys/select.h>
 41#include <sys/time.h>
 42#if HAVE_UNISTD_H
 43#include <unistd.h>
 44#endif
 45#include <errno.h>
 46#include <stdio.h>
 47#include <stdlib.h>
 48
 49#include "xpoll.h"
 50#include "xmalloc.h"
 51
 52#if HAVE_POLL
 53static int 
 54_poll(struct xpollfd *xfds, unsigned int nfds, int timeout) {
 55    int i, rv;
 56    struct pollfd *pfds = Malloc(nfds * sizeof(struct pollfd));
 57
 58    for (i = 0; i < nfds; i++) {
 59        pfds[i].fd = xfds[i].fd;
 60        pfds[i].events = 0;
 61        pfds[i].revents = 0; 
 62
 63        if (xfds[i].events & XPOLLREAD)
 64            pfds[i].events |= POLLIN;
 65        if (xfds[i].events & XPOLLWRITE)
 66            pfds[i].events |= POLLOUT;
 67    }
 68
 69    if ((rv = poll(pfds, nfds, timeout)) < 0) {
 70        Free((void **)&pfds);
 71        return -1;
 72    }
 73
 74    for (i = 0; i < nfds; i++) {
 75        if (pfds[i].revents & POLLIN)
 76            xfds[i].revents |= XPOLLREAD;
 77        if (pfds[i].revents & POLLOUT)
 78            xfds[i].revents |= XPOLLWRITE;
 79        if (pfds[i].revents & POLLERR || pfds[i].revents & POLLHUP)
 80            xfds[i].revents |= XPOLLERR;
 81        if (pfds[i].revents & POLLNVAL)
 82            xfds[i].revents |= XPOLLINVAL;
 83    }
 84    
 85    Free((void **)&pfds);
 86    errno = 0;
 87    return rv;
 88}
 89
 90#else /* !HAVE_POLL */
 91
 92static int 
 93_select(struct xpollfd *xfds, unsigned int nfds, int timeout) {
 94    int i, maxfd = -1, inval = 0, rv = -1;
 95    struct timeval tv;
 96    struct timeval *tptr = &tv;
 97    fd_set reads, writes;
 98
 99    if (timeout < 0)
100        tptr = NULL;
101    else {
102        tv.tv_sec = timeout;
103        tv.tv_usec = 0;
104    }
105
106    /* setup for select() */
107    FD_ZERO(&reads);
108    FD_ZERO(&writes);
109    for (i = 0; i < nfds; i++) {
110        if (xfds[i].fd >= FD_SETSIZE || xfds[i].fd < 0) {
111            xfds[i].revents |= XPOLLINVAL; 
112            inval++;
113            continue;
114        }
115        if (xfds[i].events & XPOLLREAD)
116            FD_SET(xfds[i].fd, &reads);
117        if (xfds[i].events & XPOLLWRITE)
118            FD_SET(xfds[i].fd, &writes);
119        if (xfds[i].fd > maxfd)
120            maxfd = xfds[i].fd;
121    }
122
123    while (rv == -1) {
124        if ((rv = select(maxfd + 1, &reads, &writes, NULL, tptr)) < 0) {
125            if (errno != EBADF)
126                return -1;
127            else {
128                /* check for and remove bad fds */
129                struct timeval ttv = {0, 1};  /* very very short timeout */
130                fd_set rds, wrs;
131
132                maxfd = -1;
133                FD_ZERO(&reads);
134                FD_ZERO(&writes);
135                for (i = 0; i < nfds; i++) {
136                    if (xfds[i].revents & XPOLLINVAL)
137                        continue;
138
139                    FD_ZERO(&rds);
140                    FD_ZERO(&wrs);
141                    if (xfds[i].events & XPOLLREAD)
142                        FD_SET(xfds[i].fd, &rds);
143                    if (xfds[i].events & XPOLLWRITE)
144                        FD_SET(xfds[i].fd, &wrs);
145
146                    if (select(xfds[i].fd + 1, &rds, &wrs, NULL, &ttv) < 0) {
147                        if (errno != EBADF)
148                            return -1;
149                        else {
150                            xfds[i].revents |= XPOLLINVAL;
151                            inval++;
152                        }
153                    }
154                    else {
155                        /* prepare for next select */
156                        if (xfds[i].events & XPOLLREAD)
157                            FD_SET(xfds[i].fd, &reads);
158                        if (xfds[i].events & XPOLLWRITE)
159                            FD_SET(xfds[i].fd, &writes);
160                        if (xfds[i].fd > maxfd)
161                            maxfd = xfds[i].fd;
162                    }
163                }
164            }
165        }
166    }
167
168    for (i = 0; i < nfds; i++) {
169        /* protect segfault prone FD_ISSET */
170        if (xfds[i].revents & XPOLLINVAL)  
171            continue;
172
173        if (FD_ISSET(xfds[i].fd, &reads))
174            xfds[i].revents |= XPOLLREAD;
175        if (FD_ISSET(xfds[i].fd, &writes))
176            xfds[i].revents |= XPOLLWRITE;
177    }
178    
179    errno = 0;
180    return (rv + inval);
181}
182#endif /* HAVE_POLL */
183
184int xpoll(struct xpollfd *xfds, int nfds, int timeout) {
185    int i;
186
187    errno = 0;
188
189    if (xfds == NULL || nfds <= 0) {
190        errno = EINVAL;
191        return -1;
192    }  
193
194    for (i = 0; i < nfds; i++) {
195        xfds[i].revents = 0;
196    }
197
198#if HAVE_POLL
199    return _poll(xfds, nfds, timeout);
200#else
201    return _select(xfds, nfds, timeout);
202#endif     
203}
204   
205/*
206 * vi: tabstop=4 shiftwidth=4 expandtab
207 */