home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
rtsi.com
/
2014.01.www.rtsi.com.tar
/
www.rtsi.com
/
OS9
/
OSK
/
NETWORK
/
ISP
/
bind.4.8.3.lzh
/
BIND483
/
RES
/
select.c
< prev
next >
Wrap
Text File
|
1994-09-23
|
6KB
|
287 lines
/* ------------------------------------------------------------------- *
|
| OS9Lib: select()
|
|
| Copyright (c) 1988 by Wolfgang Ocker, Puchheim,
| Ulli Dessauer, Germering and
| Reimer Mellin, Muenchen
| (W-Germany)
|
| This programm can be copied and distributed freely for any
| non-commercial purposes. It can only be incorporated into
| commercial software with the written permission of the authors.
|
| If you should modify this program, the authors would appreciate
| a notice about the changes. Please send a (context) diff or the
| complete source to:
* ----------------------------------------------------------------- */
/* modified by Andrzej Kotanski to works also on socket paths - 1994 */
#include <time.h>
#include <stdio.h>
#include <errno.h>
#include <signal.h>
#define reg register
#define READY_SIG (31)
#define ALM_SIG (2000)
/*#define SEL_PRT_FLG*/
static int sigarrived = 0; /* READY_SIG occurred ? */
extern int ev_id;
static void sighand(sig)
int sig;
{
sigarrived = sig;
}
/*
* S E L E C T
* returns # of fd's ready for read/write/network, -1 if interrupted or
* a bad fd was encountered or 0 if none fd is ready for the action.
*/
int select(fds, rdp, wrp, exp, timeout)
int fds;
reg int *rdp, *wrp, *exp;
struct timeval *timeout;
{
reg int i, ii = -2;
reg unsigned int shift;
int tout;
reg int rd, wr, ex;
int leave = 0;
int tmp = 0;
int signaled = 0;
int alm_id, pid;
int ev_value = 0;
char evname[15];
int poll = 0;
/*
** if required....
*/
pid = getpid();
/*
** Calculate time dependents of action
*/
poll = ( (timeout != NULL) &&
(timeout->tv_sec == 0) &&
(timeout->tv_usec == 0) )
? 1
: 0;
tout = ( timeout != NULL )
? (1 + timeout->tv_sec * CLK_TCK + (timeout->tv_usec *
CLK_TCK) / 1000000)
: 0;
/*
** set pointers to dummy value if unspecified.
** these dummies are important as the value of the pointer is not used
** as a check.
*/
if (rdp == 0) rdp = &tmp;
if (wrp == 0) wrp = &tmp;
if (exp == 0) exp = &tmp;
rd = wr = ex = 0;
/*
** signal handlers....
*/
if ( poll != 1 ) {
signal(READY_SIG, sighand);
signal(ALM_SIG, sighand);
sigarrived = 0;
}
/*
** action
*/
while (leave == 0) {
/*
** check for ready IO on rdp and network if selected
*/
shift = (1 << (fds - 1));
for (i = fds - 1; i >= 0; shift >>= 1, --i) {
/*
** if data is available for reading mark it as ready.
** _gs_rdy() returns the number of bytes on path or -1 if invalid
** path and if no data is present in which case errno is set to 246
** i.e. device not ready.
** E_UNKSVC on this path device you cannot ask for ready bytes
*/
if (*rdp & shift && (_gs_rdy(i) > 0 || (errno == E_UNKSVC))) {
rd |= shift;
leave++;
}
/*
** if network condition is ready mark leave as ready
** ev_value is initialized to 0 and can only be modified later.
** THE LOGIC HERE DOES NOT ALLOW POLLING THE NETWORK - yet
*/
if (*exp & shift && (ev_value > 0)) {
ex |= shift;
leave++;
}
}
/*
** if polling is required then that is all...
*/
if ( poll == 1 ) {
break;
}
/*
** you requested a timeout i.e. now set the signals to break this wait
** state which will be tsleep() for actions without the network
*/
if (leave == 0) {
/*
** prepare for waiting .., block signals
*/
sigmask(1);
shift = (1 << (fds - 1));
for (i = fds - 1; i >= 0; shift >>= 1, --i) {
if (*rdp & shift) {
_ss_ssig(i, READY_SIG);
signaled |= shift;
}
if (*exp & shift) {
signaled |= shift;
}
}
/*
** two possibilities the first (*exp == 0) no network and just
** pipes are envolved, second a network device is also specified.
*/
if (*exp == 0) {
/*
** wait specified timeout (implicit unblock signal !!)
*/
i = 0;
i = tsleep(tout);
ii = i;
/*
** if we are interupted by one of our own signals
** or timed-out then we are finished...
*/
if (sigarrived == 0) {
if (i < 0) { /* error ? */
leave = -1;
}
else if ( i == 0 ) { /* no ticks left */
if ( tout == 0 ) { /* but.infinite timout wanted */
leave = -2;
}
else { /* must have timed out */
leave = 0;
}
}
else { /* ticks remain ? pretend interrupt */
leave = -2;
}
break; /* exit while */
}
}
else {
/*
** network also there then wait on event
*/
if (tout < 50) tout = 50; /* XXX */
alm_id = alm_set(ALM_SIG, tout);
ev_value = _ev_wait(ev_id, 1, 32767);
sigmask(0);
alm_delete(alm_id);
if (sigarrived == ALM_SIG) {
/* printf("select: ALM_SIG ev_value %d\n",ev_value); */
break;
}
else if ( sigarrived == READY_SIG ) {
/* printf("select: READY_SIG ev_value %d\n",ev_value); */
continue;
}
else {
/* printf("select: ELSE ev_value %d\n",ev_value); */
leave++;
ex = *exp;
}
}
} /* if ( leave ) */
} /* while */
/*
** reset signals ..
*/
if ( poll != 1 ) {
shift = (1 << (fds - 1));
for (i = fds - 1; i >= 0; shift >>= 1, --i) {
if (signaled & shift) _ss_rel(i);
}
}
/*
** get results..
*/
*rdp = rd;
*wrp = wr;
*exp = ex;
/*
if ( timeout != NULL && poll != 1 && leave == 0 ) {
printf
("select: timeout %d tout %d ii %d sigarrived %d leave %d poll %d\n",
timeout->tv_sec,tout,ii,sigarrived,leave,poll );
}
*/
if ( poll != 1 && leave == -1 ) {
("select: timeout %d tout %d ii %d sigarrived %d leave %d poll %d\n",
timeout->tv_sec,tout,ii,sigarrived,leave,poll );
}
return leave;
}