diff -r -w -u5 -p ecos_prev/packages/io/fileio/current/src/select.cxx ecos/packages/io/fileio/current/src/select.cxx --- ecos_prev/packages/io/fileio/current/src/select.cxx Wed Jan 2 15:43:16 2002 +++ ecos/packages/io/fileio/current/src/select.cxx Thu Jan 3 19:18:50 2002 @@ -55,10 +55,11 @@ #include // for fcntl() #include "fio.h" // Private header #include // select header +#include // poll header #include // scheduler definitions #include // thread definitions #include // mutex definitions #include // clock definitions @@ -248,10 +249,205 @@ select(int nfd, fd_set *in, fd_set *out, FILEIO_RETURN(error); } //========================================================================== +// milliseconds to ticks conversion support + +static cyg_tick_count cyg_milliseconds_to_ticks(long milliseconds) +{ + + // Converter from ms to ticks + + static struct Cyg_Clock::converter ms_converter; + static cyg_bool ms_converter_initialized = false; + + if (!ms_converter_initialized) + { + + // Create the converter we need. + + Cyg_Clock::real_time_clock + ->get_other_to_clock_converter(1000000, &ms_converter); + ms_converter_initialized = true; + } + + // Convert the milliseconds to ticks. + + return Cyg_Clock::convert(milliseconds, &ms_converter); +} + +//========================================================================== +// poll API function + +__externC int +poll(struct pollfd fds[], nfds_t nfds, int timeout) +{ + FILEIO_ENTRY(); + int error = ENOERR; + static const int mode_type[] = + { + CYG_FREAD, // POLLIN 0x01 + 0, // POLLRDNORM 0x02 + 0, // POLLRDBAND 0x04 + 0, // POLLPRI 0x08 + CYG_FWRITE, // POLLOUT 0x10 + 0, // POLLWRBAND 0x20 + 0, // POLLERR 0x40 + 0, // POLLHUP 0x80 + 0 // POLLNVAL 0x100 + }; + const short supported_event_mask = POLLOUT|POLLIN; + + // Compute end time + + cyg_tick_count ticks = 0; + if (timeout > 0) + { + ticks = (Cyg_Clock::real_time_clock->current_value() + + cyg_milliseconds_to_ticks(timeout)); + } + + // Lock the mutex + + select_mutex.lock(); + + // Scan sets for possible I/O until something found, timeout or error. + + while (!error) + { + cyg_uint32 wake_count = selwake_count; + + // Count the number of files with events. + + int ready_count = 0; + + // Loop though all file descriptors. + + pollfd * fd_vec_p = fds; + nfds_t fds_left = nfds; + while (fds_left-- > 0 && error == ENOERR) + { + cyg_file * fp = cyg_fp_get(fd_vec_p->fd); + if (!fp) + { + error = EBADF; + break; + } + + // Always clear the returned events. + + fd_vec_p->revents = 0; + + // Mask off any events that we do not handle. + + short events_to_check = fd_vec_p->events & supported_event_mask; + + // Loop through the event bits until they are all clear. Keep a + // pointer to the corresponding entry in the mode table. + + const int * mode_type_p = mode_type; + short cur_event = 0x1; + while (events_to_check) + { + if (events_to_check & cur_event) + { + + // Call the file's select routine with the current mode + // type, and set the current output event bit accordingly. + + if ((*fp->f_ops->fo_select)(fp, *mode_type_p, 0)) + { + fd_vec_p->revents |= cur_event; + } + events_to_check &= ~cur_event; + } + mode_type_p++; + cur_event <<= 1; + } + + // If any of the output event bits are set, increment the count + // of the number of files with events. + + if (fd_vec_p->revents) + { + ready_count++; + } + + cyg_fp_free(fp); + fd_vec_p++; + } + + if (ready_count) + { + + // Found something + + select_mutex.unlock(); + FILEIO_RETURN_VALUE(ready_count); + } + + Cyg_Scheduler::lock(); + + if (wake_count == selwake_count) + { + + // Nothing found, see if we want to wait + + if (timeout >= 0) + { + if (ticks == 0) + { + + // Special case of "poll" + + select_mutex.unlock(); + Cyg_Scheduler::unlock(); + FILEIO_RETURN_VALUE(0); + } + + if (!selwait.wait(ticks)) + { + + // A non-standard wakeup, if the current time is equal + // to or past the timeout, return zero. Otherwise return + // EINTR, since we have been released. + + if (Cyg_Clock::real_time_clock->current_value() >= ticks) + { + select_mutex.unlock(); + Cyg_Scheduler::unlock(); + FILEIO_RETURN_VALUE(0); + } + else + { + error = EINTR; + } + } + } + else + { + + // Wait forever (until something happens) + + if (!selwait.wait()) + { + error = EINTR; + } + } + } + + Cyg_Scheduler::unlock(); + + } // while(!error) + + select_mutex.unlock(); + + FILEIO_RETURN(error); +} + +//========================================================================== // Select support functions. // ------------------------------------------------------------------------- // cyg_selinit() is used to initialize a selinfo structure Only in ecos/packages/isoinfra/current/include/sys: poll.h