This is select.c in view mode; [Download] [Up]
#include <stdio.h> #include <errno.h> #include <sys/syscall.h> #include <sys/time.h> #include "pthread_socket.h" #include "pthread_io_delay.h" const struct timespec delay_interval = { 0, 100000 }; int syscall_select( int nd, fd_set * in, fd_set * out, fd_set * ex, struct timeval * tv); #define MAKE_TIMEVAL(t,ms) \ { \ (t)->tv_sec = (ms) / 1000000; \ (t)->tv_usec = (ms) % 1000000; \ } #define MICROSECONDS(t) ((t)->tv_sec * 1000000 + (t)->tv_usec) #define TV_CLEAR(t) \ { \ (t)->tv_sec = 0; (t)->tv_usec = 0; \ } static long diff_timevals( const struct timeval *t1, const struct timeval *t2 ) { return( MICROSECONDS(t1) - MICROSECONDS(t2) ); } static int timeout_expired( struct timeval *xt ) { int expired = FALSE; struct timeval curr, *t_ptr; if( xt == NULL || xt->tv_sec == -1 ) return( FALSE ); gettimeofday( &curr, NULL ); t_ptr = &curr; if( MICROSECONDS(t_ptr) > MICROSECONDS(xt) ) expired = TRUE; return( expired ); } static void update_timeout_interval( const struct timeval *start, struct timeval *interval ) { struct timeval current; long elapsed_usec, interval_usec; if( interval == NULL ) return; gettimeofday( ¤t, NULL ); elapsed_usec = diff_timevals( ¤t, start ); interval_usec = MICROSECONDS( interval ); if( elapsed_usec >= interval_usec ) { interval->tv_sec = 0; interval->tv_usec = 0; } else MAKE_TIMEVAL(interval, (interval_usec - elapsed_usec)); } static void get_expiration_time( struct timeval *xt, struct timeval *st, const struct timeval *it ) { unsigned long usecs; if( it == NULL ) return; /* expiration_time = {-1, -1} */ gettimeofday( st, NULL ); usecs = MICROSECONDS(st) + MICROSECONDS(it); xt->tv_sec = usecs / 1000000; xt->tv_usec = usecs % 1000000; } /*-------------------------------------------------------------------------- * @@ S E L E C T *-------------------------------------------------------------------------*/ int select( int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout_interval ) { int result = 0; struct timeval expiration_time = {-1, -1}; struct timeval no_wait = {0, 0}; struct timeval start; long id; /* * If the caller wants a zero timeout interval, return after * one call to select. Evidently, the caller is setting up * her own polling mechanism. */ if( timeout_interval != NULL && MICROSECONDS( timeout_interval ) == 0 ) return( syscall_select( nfds, readfds, writefds, exceptfds, &no_wait )); get_expiration_time( &expiration_time, &start, timeout_interval ); id = pthread_getsequence_np( pthread_self()); while( (result = syscall_select( nfds, readfds, writefds, exceptfds, &no_wait )) <= 0 ) { if( result < OK ) break; pthread_delay_np( &delay_interval ); if( timeout_expired( &expiration_time )) break; } /* * Update the timeout interval because that's what Linux does. * @@ Not all systems do this @@ */ update_timeout_interval( &start, timeout_interval ); return( result ); } /* * syscall_select() is a wrapper around the select() system call. Note * that this service returns -1 on error with errno set appropriately. * Because errno gets set in this call, we have to surround it with * a lock. */ int syscall_select( int nd, fd_set * in, fd_set * out, fd_set * ex, struct timeval * tv) { long __res; #if defined(__PIC__) || defined (__pic__) __asm__ volatile ("pushl %%ebx\n\t" "movl %%ecx,%%ebx\n\t" "int $0x80\n\t" "popl %%ebx" : "=a" (__res) : "0" (SYS_select),"c" ((long) &nd)); #else __asm__ volatile ("int $0x80" : "=a" (__res) : "0" (SYS_select),"b" ((long) &nd)); #endif if (__res >= 0) return (int) __res; pthread_lock_global_np(); errno = -__res; /* Make errno a positive number */ pthread_set_errno_np( errno ); pthread_unlock_global_np(); return( -1 ); } #include <gnu-stabs.h> #ifdef weak_alias weak_alias (__select, select); #endif
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.