|
Packit Service |
a8c26c |
/***********************************************************************
|
|
Packit Service |
a8c26c |
* *
|
|
Packit Service |
a8c26c |
* This software is part of the ast package *
|
|
Packit Service |
a8c26c |
* Copyright (c) 1985-2011 AT&T Intellectual Property *
|
|
Packit Service |
a8c26c |
* and is licensed under the *
|
|
Packit Service |
a8c26c |
* Eclipse Public License, Version 1.0 *
|
|
Packit Service |
a8c26c |
* by AT&T Intellectual Property *
|
|
Packit Service |
a8c26c |
* *
|
|
Packit Service |
a8c26c |
* A copy of the License is available at *
|
|
Packit Service |
a8c26c |
* http://www.eclipse.org/org/documents/epl-v10.html *
|
|
Packit Service |
a8c26c |
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
|
|
Packit Service |
a8c26c |
* *
|
|
Packit Service |
a8c26c |
* Information and Software Systems Research *
|
|
Packit Service |
a8c26c |
* AT&T Research *
|
|
Packit Service |
a8c26c |
* Florham Park NJ *
|
|
Packit Service |
a8c26c |
* *
|
|
Packit Service |
a8c26c |
* Glenn Fowler <gsf@research.att.com> *
|
|
Packit Service |
a8c26c |
* David Korn <dgk@research.att.com> *
|
|
Packit Service |
a8c26c |
* Phong Vo <kpv@research.att.com> *
|
|
Packit Service |
a8c26c |
* *
|
|
Packit Service |
a8c26c |
***********************************************************************/
|
|
Packit Service |
a8c26c |
#include "sfhdr.h"
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
/* Poll a set of streams to see if any is available for I/O.
|
|
Packit Service |
a8c26c |
** Ready streams are moved to front of array but retain the
|
|
Packit Service |
a8c26c |
** same relative order.
|
|
Packit Service |
a8c26c |
**
|
|
Packit Service |
a8c26c |
** Written by Kiem-Phong Vo.
|
|
Packit Service |
a8c26c |
*/
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
#if __STD_C
|
|
Packit Service |
a8c26c |
int sfpoll(Sfio_t** fa, reg int n, int tm)
|
|
Packit Service |
a8c26c |
#else
|
|
Packit Service |
a8c26c |
int sfpoll(fa, n, tm)
|
|
Packit Service |
a8c26c |
Sfio_t** fa; /* array of streams to poll */
|
|
Packit Service |
a8c26c |
reg int n; /* number of streams in array */
|
|
Packit Service |
a8c26c |
int tm; /* time in millisecs for select/poll */
|
|
Packit Service |
a8c26c |
#endif
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
reg int r, c, m, np, eintr;
|
|
Packit Service |
a8c26c |
reg Sfio_t* f;
|
|
Packit Service |
a8c26c |
reg int *status, *check;
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
if(n <= 0 || !fa)
|
|
Packit Service |
a8c26c |
return -1;
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
if(!(status = (int*)malloc(2*n*sizeof(int))) )
|
|
Packit Service |
a8c26c |
return -1;
|
|
Packit Service |
a8c26c |
check = status+n; /* streams that need polling */
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
/* a SF_READ stream is ready if there is buffered read data */
|
|
Packit Service |
a8c26c |
#define RDREADY(f) (((f->mode&SF_READ) && f->next < f->endb) || \
|
|
Packit Service |
a8c26c |
((f->mode&SF_WRITE) && f->proc && f->proc->ndata > 0) )
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
/* a SF_WRITE stream is ready if there is no write data */
|
|
Packit Service |
a8c26c |
#define WRREADY(f) (!(f->mode&SF_WRITE) || f->next == f->data)
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
#define HASAUXFD(f) (f->proc && f->proc->file >= 0 && f->proc->file != f->file)
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
for(r = c = eintr = 0; r < n; ++r) /* compute streams that must be checked */
|
|
Packit Service |
a8c26c |
{ f = fa[r];
|
|
Packit Service |
a8c26c |
status[r] = 0;
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
/* terminate poll on interrupt? */
|
|
Packit Service |
a8c26c |
if(f->flags&SF_IOINTR)
|
|
Packit Service |
a8c26c |
eintr++;
|
|
Packit Service |
a8c26c |
/* check accessibility */
|
|
Packit Service |
a8c26c |
m = f->mode&SF_RDWR;
|
|
Packit Service |
a8c26c |
if((int)f->mode != m && _sfmode(f,m,0) < 0)
|
|
Packit Service |
a8c26c |
continue;
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
if((f->flags&SF_READ) && RDREADY(f))
|
|
Packit Service |
a8c26c |
status[r] |= SF_READ;
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
if((f->flags&SF_WRITE) && WRREADY(f))
|
|
Packit Service |
a8c26c |
status[r] |= SF_WRITE;
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
if((f->flags&SF_RDWR) == status[r])
|
|
Packit Service |
a8c26c |
continue;
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
/* has discipline, ask its opinion */
|
|
Packit Service |
a8c26c |
if(f->disc && f->disc->exceptf)
|
|
Packit Service |
a8c26c |
{ if((m = (*f->disc->exceptf)(f,SF_DPOLL,&tm,f->disc)) < 0)
|
|
Packit Service |
a8c26c |
continue;
|
|
Packit Service |
a8c26c |
else if(m > 0)
|
|
Packit Service |
a8c26c |
{ status[r] = m&SF_RDWR;
|
|
Packit Service |
a8c26c |
continue;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
if(f->extent < 0) /* unseekable stream, must poll/select */
|
|
Packit Service |
a8c26c |
check[c++] = r;
|
|
Packit Service |
a8c26c |
else /* seekable streams are always ready */
|
|
Packit Service |
a8c26c |
{ if(f->flags&SF_READ)
|
|
Packit Service |
a8c26c |
status[r] |= SF_READ;
|
|
Packit Service |
a8c26c |
if(f->flags&SF_WRITE)
|
|
Packit Service |
a8c26c |
status[r] |= SF_WRITE;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
/* terminate poll on interrupt only if all streams marked SF_IOINTR */
|
|
Packit Service |
a8c26c |
eintr = eintr == n ? -1 : EINTR;
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
np = -1;
|
|
Packit Service |
a8c26c |
#if _lib_poll
|
|
Packit Service |
a8c26c |
if(c > 0)
|
|
Packit Service |
a8c26c |
{ struct pollfd* fds;
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
/* construct the poll array */
|
|
Packit Service |
a8c26c |
for(m = 0, r = 0; r < c; ++r, ++m)
|
|
Packit Service |
a8c26c |
{ f = fa[check[r]];
|
|
Packit Service |
a8c26c |
if(HASAUXFD(f))
|
|
Packit Service |
a8c26c |
m += 1;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
if(!(fds = (struct pollfd*)malloc(m*sizeof(struct pollfd))) )
|
|
Packit Service |
a8c26c |
return -1;
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
for(m = 0, r = 0; r < c; ++r, ++m)
|
|
Packit Service |
a8c26c |
{ f = fa[check[r]];
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
fds[m].fd = f->file;
|
|
Packit Service |
a8c26c |
fds[m].events = fds[m].revents = 0;
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
if((f->flags&SF_WRITE) && !WRREADY(f) )
|
|
Packit Service |
a8c26c |
fds[m].events |= POLLOUT;
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
if((f->flags&SF_READ) && !RDREADY(f) )
|
|
Packit Service |
a8c26c |
{ /* a sfpopen situation with two file descriptors */
|
|
Packit Service |
a8c26c |
if((f->mode&SF_WRITE) && HASAUXFD(f))
|
|
Packit Service |
a8c26c |
{ m += 1;
|
|
Packit Service |
a8c26c |
fds[m].fd = f->proc->file;
|
|
Packit Service |
a8c26c |
fds[m].revents = 0;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
fds[m].events |= POLLIN;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
while((np = SFPOLL(fds,m,tm)) < 0 )
|
|
Packit Service |
a8c26c |
{ if(errno == eintr || errno == EAGAIN)
|
|
Packit Service |
a8c26c |
errno = 0;
|
|
Packit Service |
a8c26c |
else break;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
if(np > 0) /* poll succeeded */
|
|
Packit Service |
a8c26c |
np = c;
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
for(m = 0, r = 0; r < np; ++r, ++m)
|
|
Packit Service |
a8c26c |
{ f = fa[check[r]];
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
if((f->flags&SF_WRITE) && !WRREADY(f) )
|
|
Packit Service |
a8c26c |
{ if(fds[m].revents&POLLOUT)
|
|
Packit Service |
a8c26c |
status[check[r]] |= SF_WRITE;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
if((f->flags&SF_READ) && !RDREADY(f))
|
|
Packit Service |
a8c26c |
{ if((f->mode&SF_WRITE) && HASAUXFD(f))
|
|
Packit Service |
a8c26c |
m += 1;
|
|
Packit Service |
a8c26c |
if(fds[m].revents&POLLIN)
|
|
Packit Service |
a8c26c |
status[check[r]] |= SF_READ;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
free((Void_t*)fds);
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
#endif /*_lib_poll*/
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
#if _lib_select
|
|
Packit Service |
a8c26c |
if(np < 0 && c > 0)
|
|
Packit Service |
a8c26c |
{ fd_set rd, wr;
|
|
Packit Service |
a8c26c |
struct timeval tmb, *tmp;
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
FD_ZERO(&rd);
|
|
Packit Service |
a8c26c |
FD_ZERO(&wr);
|
|
Packit Service |
a8c26c |
m = 0;
|
|
Packit Service |
a8c26c |
for(r = 0; r < c; ++r)
|
|
Packit Service |
a8c26c |
{ f = fa[check[r]];
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
if(f->file > m)
|
|
Packit Service |
a8c26c |
m = f->file;
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
if((f->flags&SF_WRITE) && !WRREADY(f))
|
|
Packit Service |
a8c26c |
FD_SET(f->file,&wr);
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
if((f->flags&SF_READ) && !RDREADY(f))
|
|
Packit Service |
a8c26c |
{ if((f->mode&SF_WRITE) && HASAUXFD(f))
|
|
Packit Service |
a8c26c |
{ if(f->proc->file > m)
|
|
Packit Service |
a8c26c |
m = f->proc->file;
|
|
Packit Service |
a8c26c |
FD_SET(f->proc->file, &rd);
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
else FD_SET(f->file,&rd);
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
if(tm < 0)
|
|
Packit Service |
a8c26c |
tmp = NIL(struct timeval*);
|
|
Packit Service |
a8c26c |
else
|
|
Packit Service |
a8c26c |
{ tmp = &tm;;
|
|
Packit Service |
a8c26c |
tmb.tv_sec = tm/SECOND;
|
|
Packit Service |
a8c26c |
tmb.tv_usec = (tm%SECOND)*SECOND;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
while((np = select(m+1,&rd,&wr,NIL(fd_set*),tmp)) < 0 )
|
|
Packit Service |
a8c26c |
{ if(errno == eintr)
|
|
Packit Service |
a8c26c |
errno = 0;
|
|
Packit Service |
a8c26c |
else break;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
if(np > 0)
|
|
Packit Service |
a8c26c |
np = c;
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
for(r = 0; r < np; ++r)
|
|
Packit Service |
a8c26c |
{ f = fa[check[r]];
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
if((f->flags&SF_WRITE) && !WRREADY(f) )
|
|
Packit Service |
a8c26c |
{ if(FD_ISSET(f->file,&wr) )
|
|
Packit Service |
a8c26c |
status[check[r]] |= SF_WRITE;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
if((f->flags&SF_READ) && !RDREADY(f) )
|
|
Packit Service |
a8c26c |
{ if((f->mode&SF_WRITE) && HASAUXFD(f) )
|
|
Packit Service |
a8c26c |
{ if(FD_ISSET(f->proc->file, &rd) )
|
|
Packit Service |
a8c26c |
status[check[r]] |= SF_READ;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
else
|
|
Packit Service |
a8c26c |
{ if(FD_ISSET(f->file,&rd) )
|
|
Packit Service |
a8c26c |
status[check[r]] |= SF_READ;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
#endif /*_lib_select*/
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
for(r = c = 0; c < n; ++c)
|
|
Packit Service |
a8c26c |
{ if(status[c] == 0)
|
|
Packit Service |
a8c26c |
continue;
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
f = fa[c];
|
|
Packit Service |
a8c26c |
f->val = (ssize_t)status[c];
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
/* announce status */
|
|
Packit Service |
a8c26c |
if(f->disc && f->disc->exceptf)
|
|
Packit Service |
a8c26c |
(*f->disc->exceptf)(f,SF_READY,(Void_t*)(long)status[c],f->disc);
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
if(c > r) /* move to front of list */
|
|
Packit Service |
a8c26c |
{ fa[c] = fa[r];
|
|
Packit Service |
a8c26c |
fa[r] = f;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
r += 1;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
free((Void_t*)status);
|
|
Packit Service |
a8c26c |
return r ? r : np < 0 ? -1 : 0;
|
|
Packit Service |
a8c26c |
}
|