/* ------------------------------------------------------------------- * | | 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: * ----------------------------------------------------------------- */ #include #include #include #define reg register #define READY_SIG (31) /* tune this ... */ #define ONLYRDY (1) /* select only on reading */ static char sigarrived = 0; /* READY_SIG occured ? */ static void sighand() { sigarrived = 1; } /* * S E L E C T * returns # of fd's ready for read/write/exeption, -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; reg unsigned int shift; int tout; reg int rd, wr, ex; int leave = 0; int tmp = 0; int signaled = 0; signal( READY_SIG, sighand); /* Calculate the timeout in Ticks .. * add one tick (for the polling case) * if timeout == (struct timeval *)0 set to 0, */ tout = timeout ? ( 1 + timeout->tv_sec * CLK_TCK + ( timeout->tv_usec * CLK_TCK) / 1000 ) : 0; /* set pointers to dummy value if unspecified */ if( rdp == 0) rdp = &tmp; if( wrp == 0) wrp = &tmp; if( exp == 0) exp = &tmp; rd = wr = ex = 0; sigarrived = 0; while( leave == 0) { shift = ( 1 << (fds-1)); for( i = fds-1; i >= 0; shift >>= 1, --i) { /* if data is available for reading mark it as ready */ if( *rdp & shift && ( _gs_rdy(i) > 0 || (errno == E_UNKSVC))) { rd |= shift; leave++; } #ifndef ONLYRDY /* if data is available for writing mark it as ready */ if( *wrp & shift && ( _gs_wrdy(i) > 0 || (errno == E_UNKSVC))) { wr |= shift; leave++; } /* if exeption condition is ready mark it as ready */ if( *exp & shift && ( _gs_erdy(i) > 0 || (errno == E_UNKSVC))) { ex |= shift; leave++; } #endif } 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; } #ifndef ONLYRDY if( *wrp & shift) { _ss_wssig(i, READY_SIG); signaled |= shift; } if( *exp & shift) { _ss_essig(i, READY_SIG); signaled |= shift; } #endif } /* wait specified timeout (implicit unblock signal !!) */ i = tsleep(tout); /* if we are interupted, or timed-out get out of here */ if( sigarrived == 0) { if( i < 0) leave = -1; break; } } } /* reset signals .. */ 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; return leave; }