📄 select.c
字号:
#endif } selecttab[s].nfds = fd+1; selecttab[s].filps[fd]->filp_selectors++;#if DEBUG_SELECT printf("[fd %d ops: %d] ", fd, ops);#endif } if (selecttab[s].nreadyfds > 0 || !block) { /* fd's were found that were ready to go right away, and/or * we were instructed not to block at all. Must return * immediately. */ copy_fdsets(&selecttab[s]); select_cancel_all(&selecttab[s]); selecttab[s].requestor = NULL; /* Open Group: * "Upon successful completion, the pselect() and select() * functions shall return the total number of bits * set in the bit masks." */#if DEBUG_SELECT printf("returning\n");#endif return selecttab[s].nreadyfds; }#if DEBUG_SELECT printf("not returning (%d, %d)\n", selecttab[s].nreadyfds, block);#endif /* Convert timeval to ticks and set the timer. If it fails, undo * all, return error. */ if (is_timeout) { int ticks; /* Open Group: * "If the requested timeout interval requires a finer * granularity than the implementation supports, the * actual timeout interval shall be rounded up to the next * supported value." */#define USECPERSEC 1000000 while(timeout.tv_usec >= USECPERSEC) { /* this is to avoid overflow with *HZ below */ timeout.tv_usec -= USECPERSEC; timeout.tv_sec++; } ticks = timeout.tv_sec * HZ + (timeout.tv_usec * HZ + USECPERSEC-1) / USECPERSEC; selecttab[s].expiry = ticks; fs_set_timer(&selecttab[s].timer, ticks, select_timeout_check, s);#if DEBUG_SELECT printf("%d: blocking %d ticks\n", s, ticks);#endif } /* if we're blocking, the table entry is now valid. */ selecttab[s].requestor = fp; /* process now blocked */ suspend(XSELECT); return SUSPEND;}/*===========================================================================* * select_cancel_all * *===========================================================================*/PRIVATE void select_cancel_all(struct selectentry *e){ int fd; for(fd = 0; fd < e->nfds; fd++) { struct filp *fp; fp = e->filps[fd]; if (!fp) {#if DEBUG_SELECT printf("[ fd %d/%d NULL ] ", fd, e->nfds);#endif continue; } if (fp->filp_selectors < 1) {#if DEBUG_SELECT printf("select: %d selectors?!\n", fp->filp_selectors);#endif continue; } fp->filp_selectors--; e->filps[fd] = NULL; select_reevaluate(fp); } if (e->expiry > 0) {#if DEBUG_SELECT printf("cancelling timer %d\n", e - selecttab);#endif fs_cancel_timer(&e->timer); e->expiry = 0; } return;}/*===========================================================================* * select_wakeup * *===========================================================================*/PRIVATE void select_wakeup(struct selectentry *e, int r){ revive(e->req_procnr, r);}/*===========================================================================* * select_reevaluate * *===========================================================================*/PRIVATE int select_reevaluate(struct filp *fp){ int s, remain_ops = 0, fd, type = -1; if (!fp) { printf("fs: select: reevalute NULL fp\n"); return 0; } for(s = 0; s < MAXSELECTS; s++) { if (!selecttab[s].requestor) continue; for(fd = 0; fd < selecttab[s].nfds; fd++) if (fp == selecttab[s].filps[fd]) { remain_ops |= tab2ops(fd, &selecttab[s]); type = selecttab[s].type[fd]; } } /* If there are any select()s open that want any operations on * this fd that haven't been satisfied by this callback, then we're * still in the market for it. */ fp->filp_select_ops = remain_ops;#if DEBUG_SELECT printf("remaining operations on fp are %d\n", fp->filp_select_ops);#endif return remain_ops;}/*===========================================================================* * select_return * *===========================================================================*/PRIVATE void select_return(struct selectentry *s, int r){ select_cancel_all(s); copy_fdsets(s); select_wakeup(s, r ? r : s->nreadyfds); s->requestor = NULL;}/*===========================================================================* * select_callback * *===========================================================================*/PUBLIC int select_callback(struct filp *fp, int ops){ int s, fd, want_ops, type; /* We are being notified that file pointer fp is available for * operations 'ops'. We must re-register the select for * operations that we are still interested in, if any. */ want_ops = 0; type = -1; for(s = 0; s < MAXSELECTS; s++) { int wakehim = 0; if (!selecttab[s].requestor) continue; for(fd = 0; fd < selecttab[s].nfds; fd++) { if (!selecttab[s].filps[fd]) continue; if (selecttab[s].filps[fd] == fp) { int this_want_ops; this_want_ops = tab2ops(fd, &selecttab[s]); want_ops |= this_want_ops; if (this_want_ops & ops) { /* this select() has been satisfied. */ ops2tab(ops, fd, &selecttab[s]); wakehim = 1; } type = selecttab[s].type[fd]; } } if (wakehim) select_return(&selecttab[s], 0); } return 0;}/*===========================================================================* * select_notified * *===========================================================================*/PUBLIC int select_notified(int major, int minor, int selected_ops){ int s, f, t;#if DEBUG_SELECT printf("select callback: %d, %d: %d\n", major, minor, selected_ops);#endif for(t = 0; t < SEL_FDS; t++) if (!fdtypes[t].select_match && fdtypes[t].select_major == major) break; if (t >= SEL_FDS) {#if DEBUG_SELECT printf("select callback: no fdtype found for device %d\n", major);#endif return OK; } /* We have a select callback from major device no. * d, which corresponds to our select type t. */ for(s = 0; s < MAXSELECTS; s++) { int s_minor, ops; if (!selecttab[s].requestor) continue; for(f = 0; f < selecttab[s].nfds; f++) { if (!selecttab[s].filps[f] || !select_major_match(major, selecttab[s].filps[f])) continue; ops = tab2ops(f, &selecttab[s]); s_minor = (selecttab[s].filps[f]->filp_ino->i_zone[0] >> MINOR) & BYTE; if ((s_minor == minor) && (selected_ops & ops)) { select_callback(selecttab[s].filps[f], (selected_ops & ops)); } } } return OK;}/*===========================================================================* * init_select * *===========================================================================*/PUBLIC void init_select(void){ int s; for(s = 0; s < MAXSELECTS; s++) fs_init_timer(&selecttab[s].timer);}/*===========================================================================* * select_forget * *===========================================================================*/PUBLIC void select_forget(int proc){ /* something has happened (e.g. signal delivered that interrupts * select()). totally forget about the select(). */ int s; for(s = 0; s < MAXSELECTS; s++) { if (selecttab[s].requestor && selecttab[s].req_procnr == proc) { break; } } if (s >= MAXSELECTS) {#if DEBUG_SELECT printf("select: cancelled select() not found");#endif return; } select_cancel_all(&selecttab[s]); selecttab[s].requestor = NULL; return;}/*===========================================================================* * select_timeout_check * *===========================================================================*/PUBLIC void select_timeout_check(timer_t *timer){ int s; s = tmr_arg(timer)->ta_int; if (s < 0 || s >= MAXSELECTS) {#if DEBUG_SELECT printf("select: bogus slot arg to watchdog %d\n", s);#endif return; } if (!selecttab[s].requestor) {#if DEBUG_SELECT printf("select: no requestor in watchdog\n");#endif return; } if (selecttab[s].expiry <= 0) {#if DEBUG_SELECT printf("select: strange expiry value in watchdog\n", s);#endif return; } selecttab[s].expiry = 0; select_return(&selecttab[s], 0); return;}/*===========================================================================* * select_unsuspend_by_proc * *===========================================================================*/PUBLIC void select_unsuspend_by_proc(int proc){ struct filp *fp; int fd, s; for(s = 0; s < MAXSELECTS; s++) { if (!selecttab[s].requestor) continue; for(fd = 0; fd < selecttab[s].nfds; fd++) { int maj; if (!selecttab[s].filps[fd] || !selecttab[s].filps[fd]->filp_ino) continue; maj = (selecttab[s].filps[fd]->filp_ino->i_zone[0] >> MAJOR)&BYTE; if(dmap_driver_match(proc, maj)) { select_return(&selecttab[s], EAGAIN); } } } return;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -