select.c
来自「eCos操作系统源码」· C语言 代码 · 共 213 行
C
213 行
//==========================================================================//// lib/select.c//// 'select()' system call////==========================================================================//####BSDCOPYRIGHTBEGIN####//// -------------------------------------------//// Portions of this software may have been derived from OpenBSD or other sources,// and are covered by the appropriate copyright disclaimers included herein.//// -------------------------------------------////####BSDCOPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN####//// Author(s): gthomas// Contributors: gthomas// Date: 2000-01-10// Purpose: // Description: eCos implementation of 'select()' system call// ////####DESCRIPTIONEND####////==========================================================================#include <sys/param.h>#include <cyg/io/file.h>#include <cyg/kernel/kapi.h>#include <sys/select.h>#include <sys/bsdselect.h>static cyg_flag_t select_flag;static cyg_bool select_flag_init = false;#define SELECT_WAKE 0x01#define SELECT_ABORT 0x02//// Private function which does all the work for 'select()'//static int_cyg_select(int nfd, fd_set *in, fd_set *out, fd_set *ex, struct timeval *tv, cyg_bool_t abortable){ int fd, mode, num, ticks; struct file *fp; fd_set in_res, out_res, ex_res; // Result sets fd_set *selection[3], *result[3]; cyg_tick_count_t now, then; int mode_type[] = {FREAD, FWRITE, 0}; cyg_flag_value_t flag, wait_flag; // Note: since this is called by application programs, it needs no protection if (!select_flag_init) { select_flag_init = true; cyg_flag_init(&select_flag); } wait_flag = SELECT_WAKE; if (abortable) wait_flag |= SELECT_ABORT; FD_ZERO(&in_res); FD_ZERO(&out_res); FD_ZERO(&ex_res); // Set up sets selection[0] = in; result[0] = &in_res; selection[1] = out; result[1] = &out_res; selection[2] = ex; result[2] = &ex_res; // Compute end time if (tv) { now = cyg_current_time(); ticks = (tv->tv_sec * 100) + (tv->tv_usec / 10000); then = now + ticks; } else { then = 0; // Compiler warnings :-( ticks = 0; } // Scan sets for possible I/O until something found, timeout or error. while (true) { num = 0; // Total file descriptors "ready" cyg_scheduler_lock(); // Scan the list atomically wrt electing to sleep for (mode = 0; mode < 3; mode++) { if (selection[mode]) { for (fd = 0; fd < nfd; fd++) { if (FD_ISSET(fd, selection[mode])) { if (getfp(fd, &fp)) { cyg_scheduler_unlock(); // return. errno = EBADF; return -1; } if ((*fp->f_ops->fo_select)(fp, mode_type[mode])) { FD_SET(fd, result[mode]); num++; } } } } } if (num) { cyg_scheduler_unlock(); // Happy, about to return. // Found something, update user's sets if (in) { memcpy(in, &in_res, sizeof(in_res)); } if (out) { memcpy(out, &out_res, sizeof(out_res)); } if (ex) { memcpy(ex, &ex_res, sizeof(ex_res)); } return num; } // Nothing found, see if we want to wait if (tv) { if (ticks == 0) { // Special case of "poll" cyg_scheduler_unlock(); // About to return. return 0; } flag = cyg_flag_timed_wait(&select_flag, wait_flag, CYG_FLAG_WAITMODE_OR, then); } else { // Wait forever (until something happens) flag = cyg_flag_wait(&select_flag, wait_flag, CYG_FLAG_WAITMODE_OR); } cyg_scheduler_unlock(); // waited atomically if (flag & SELECT_ABORT) { errno = EINTR; return -1; } if (!flag) { return 0; // meaning no activity, ergo timeout occurred } } errno = ENOSYS; return -1;}//// This function is called by the lower layers to record the// fact that a particular 'select' event is being requested.//void selrecord(void *selector, struct selinfo *info){ // Unused by this implementation}//// This function is called to indicate that a 'select' event// may have occurred.//void selwakeup(struct selinfo *info){ // Need these ops to be atomic to make sure the clear occurs - // otherwise a higher prio thread could hog the CPU when its fds are // not ready, but the flag is (already) set, or set for someone else. cyg_scheduler_lock(); cyg_flag_setbits(&select_flag, SELECT_WAKE); cyg_flag_maskbits(&select_flag, 0 ); // clear all cyg_scheduler_unlock();}//// The public function used by 'normal' programs. This interface does not allow// the 'select()' to be externally interrupted.//intselect(int nfd, fd_set *in, fd_set *out, fd_set *ex, struct timeval *tv){ return _cyg_select(nfd, in, out, ex, tv, false);}//// The public function used by programs which wish to allow interruption,// using the 'cyg_select_abort()' function below.//intcyg_select_with_abort(int nfd, fd_set *in, fd_set *out, fd_set *ex, struct timeval *tv){ return _cyg_select(nfd, in, out, ex, tv, true);}//// This function can be called by the user to forceably abort any// current selects.//voidcyg_select_abort(void){ // See comments in selwakeup()... cyg_scheduler_lock(); cyg_flag_setbits(&select_flag, SELECT_ABORT); cyg_flag_maskbits(&select_flag, 0 ); cyg_scheduler_unlock();}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?