select.c

Go to the documentation of this file.
00001 /* Implement entry point to select system call.
00002  *
00003  * The entry points into this file are
00004  *   do_select:        perform the SELECT system call
00005  *   select_callback:  notify select system of possible fd operation 
00006  *   select_notified:  low-level entry for device notifying select
00007  *   select_unsuspend_by_endpt: cancel a blocking select on exiting driver
00008  * 
00009  * Changes:
00010  *   6 june 2005  Created (Ben Gras)
00011  */
00012 
00013 #define DEBUG_SELECT 0
00014 
00015 #include "fs.h"
00016 #include "select.h"
00017 #include "file.h"
00018 #include "inode.h"
00019 
00020 #include <sys/time.h>
00021 #include <sys/select.h>
00022 #include <minix/com.h>
00023 #include <string.h>
00024 
00025 /* max. number of simultaneously pending select() calls */
00026 #define MAXSELECTS 25
00027 
00028 PRIVATE struct selectentry {
00029         struct fproc *requestor;        /* slot is free iff this is NULL */
00030         int req_endpt;
00031         fd_set readfds, writefds, errorfds;
00032         fd_set ready_readfds, ready_writefds, ready_errorfds;
00033         fd_set *vir_readfds, *vir_writefds, *vir_errorfds;
00034         struct filp *filps[FD_SETSIZE];
00035         int type[FD_SETSIZE];
00036         int nfds, nreadyfds;
00037         clock_t expiry;
00038         timer_t timer;  /* if expiry > 0 */
00039 } selecttab[MAXSELECTS];
00040 
00041 #define SELFD_FILE      0
00042 #define SELFD_PIPE      1
00043 #define SELFD_TTY       2
00044 #define SELFD_INET      3
00045 #define SELFD_LOG       4
00046 #define SEL_FDS         5
00047 
00048 FORWARD _PROTOTYPE(int select_reevaluate, (struct filp *fp));
00049 
00050 FORWARD _PROTOTYPE(int select_request_file,
00051          (struct filp *f, int *ops, int block));
00052 FORWARD _PROTOTYPE(int select_match_file, (struct filp *f));
00053 
00054 FORWARD _PROTOTYPE(int select_request_general,
00055          (struct filp *f, int *ops, int block));
00056 FORWARD _PROTOTYPE(int select_major_match,
00057         (int match_major, struct filp *file));
00058 
00059 FORWARD _PROTOTYPE(void select_cancel_all, (struct selectentry *e));
00060 FORWARD _PROTOTYPE(void select_wakeup, (struct selectentry *e, int r));
00061 FORWARD _PROTOTYPE(void select_return, (struct selectentry *, int));
00062 
00063 /* The Open Group:
00064  * "The pselect() and select() functions shall support
00065  * regular files, terminal and pseudo-terminal devices,
00066  * STREAMS-based files, FIFOs, pipes, and sockets."
00067  */
00068 
00069 PRIVATE struct fdtype {
00070         int (*select_request)(struct filp *, int *ops, int block);      
00071         int (*select_match)(struct filp *);
00072         int select_major;
00073 } fdtypes[SEL_FDS] = {
00074                 /* SELFD_FILE */
00075         { select_request_file, select_match_file, 0 },
00076                 /* SELFD_TTY (also PTY) */
00077         { select_request_general, NULL, TTY_MAJOR },
00078                 /* SELFD_INET */
00079         { select_request_general, NULL, INET_MAJOR },
00080                 /* SELFD_PIPE (pipe(2) pipes and FS FIFOs) */
00081         { select_request_pipe, select_match_pipe, 0 },
00082                 /* SELFD_LOG (/dev/klog) */
00083         { select_request_general, NULL, LOG_MAJOR },
00084 };
00085 
00086 /* Open Group:
00087  * "File descriptors associated with regular files shall always select true
00088  * for ready to read, ready to write, and error conditions."
00089  */
00090 
00091 /*===========================================================================*
00092  *                              select_request_file                          *
00093  *===========================================================================*/
00094 PRIVATE int select_request_file(struct filp *f, int *ops, int block)
00095 {
00096         /* output *ops is input *ops */
00097         return SEL_OK;
00098 }
00099 
00100 /*===========================================================================*
00101  *                              select_match_file                            *
00102  *===========================================================================*/
00103 PRIVATE int select_match_file(struct filp *file)
00104 {
00105         if (file && file->filp_ino && (file->filp_ino->i_mode & I_REGULAR))
00106                 return 1;
00107         return 0;
00108 }
00109 
00110 /*===========================================================================*
00111  *                              select_request_general                       *
00112  *===========================================================================*/
00113 PRIVATE int select_request_general(struct filp *f, int *ops, int block)
00114 {
00115         int rops = *ops;
00116         if (block) rops |= SEL_NOTIFY;
00117         *ops = dev_io(DEV_SELECT, f->filp_ino->i_zone[0], rops, NULL, 0, 0, 0);
00118         if (*ops < 0)
00119                 return SEL_ERR;
00120         return SEL_OK;
00121 }
00122 
00123 /*===========================================================================*
00124  *                              select_major_match                           *
00125  *===========================================================================*/
00126 PRIVATE int select_major_match(int match_major, struct filp *file)
00127 {
00128         int major;
00129         if (!(file && file->filp_ino &&
00130                 (file->filp_ino->i_mode & I_TYPE) == I_CHAR_SPECIAL))
00131                 return 0;
00132         major = (file->filp_ino->i_zone[0] >> MAJOR) & BYTE;
00133         if (major == match_major)
00134                 return 1;
00135         return 0;
00136 }
00137 
00138 /*===========================================================================*
00139  *                              tab2ops                                      *
00140  *===========================================================================*/
00141 PRIVATE int tab2ops(int fd, struct selectentry *e)
00142 {
00143         return (FD_ISSET(fd, &e->readfds) ? SEL_RD : 0) |
00144                 (FD_ISSET(fd, &e->writefds) ? SEL_WR : 0) |
00145                 (FD_ISSET(fd, &e->errorfds) ? SEL_ERR : 0);
00146 }
00147 
00148 /*===========================================================================*
00149  *                              ops2tab                                      *
00150  *===========================================================================*/
00151 PRIVATE void ops2tab(int ops, int fd, struct selectentry *e)
00152 {
00153         if ((ops & SEL_RD) && e->vir_readfds && FD_ISSET(fd, &e->readfds)
00154                 && !FD_ISSET(fd, &e->ready_readfds)) {
00155                 FD_SET(fd, &e->ready_readfds);
00156                 e->nreadyfds++;
00157         }
00158         if ((ops & SEL_WR) && e->vir_writefds && FD_ISSET(fd, &e->writefds) 
00159                 && !FD_ISSET(fd, &e->ready_writefds)) {
00160                 FD_SET(fd, &e->ready_writefds);
00161                 e->nreadyfds++;
00162         }
00163         if ((ops & SEL_ERR) && e->vir_errorfds && FD_ISSET(fd, &e->errorfds)
00164                 && !FD_ISSET(fd, &e->ready_errorfds)) {
00165                 FD_SET(fd, &e->ready_errorfds);
00166                 e->nreadyfds++;
00167         }
00168 
00169         return;
00170 }
00171 
00172 /*===========================================================================*
00173  *                              copy_fdsets                                  *
00174  *===========================================================================*/
00175 PRIVATE void copy_fdsets(struct selectentry *e)
00176 {
00177         if (e->vir_readfds)
00178                 sys_vircopy(SELF, D, (vir_bytes) &e->ready_readfds,
00179                 e->req_endpt, D, (vir_bytes) e->vir_readfds, sizeof(fd_set));
00180         if (e->vir_writefds)
00181                 sys_vircopy(SELF, D, (vir_bytes) &e->ready_writefds,
00182                 e->req_endpt, D, (vir_bytes) e->vir_writefds, sizeof(fd_set));
00183         if (e->vir_errorfds)
00184                 sys_vircopy(SELF, D, (vir_bytes) &e->ready_errorfds,
00185                 e->req_endpt, D, (vir_bytes) e->vir_errorfds, sizeof(fd_set));
00186 
00187         return;
00188 }
00189 
00190 /*===========================================================================*
00191  *                              do_select                                     *
00192  *===========================================================================*/
00193 PUBLIC int do_select(void)
00194 {
00195         int r, nfds, is_timeout = 1, nonzero_timeout = 0,
00196                 fd, s, block = 0;
00197         struct timeval timeout;
00198         nfds = m_in.SEL_NFDS;
00199 
00200         if (nfds < 0 || nfds > FD_SETSIZE)
00201                 return EINVAL;
00202 
00203         for(s = 0; s < MAXSELECTS; s++)
00204                 if (!selecttab[s].requestor)
00205                         break;
00206 
00207         if (s >= MAXSELECTS)
00208                 return ENOSPC;
00209 
00210         selecttab[s].req_endpt = who_e;
00211         selecttab[s].nfds = 0;
00212         selecttab[s].nreadyfds = 0;
00213         memset(selecttab[s].filps, 0, sizeof(selecttab[s].filps));
00214 
00215         /* defaults */
00216         FD_ZERO(&selecttab[s].readfds);
00217         FD_ZERO(&selecttab[s].writefds);
00218         FD_ZERO(&selecttab[s].errorfds);
00219         FD_ZERO(&selecttab[s].ready_readfds);
00220         FD_ZERO(&selecttab[s].ready_writefds);
00221         FD_ZERO(&selecttab[s].ready_errorfds);
00222 
00223         selecttab[s].vir_readfds = (fd_set *) m_in.SEL_READFDS;
00224         selecttab[s].vir_writefds = (fd_set *) m_in.SEL_WRITEFDS;
00225         selecttab[s].vir_errorfds = (fd_set *) m_in.SEL_ERRORFDS;
00226 
00227         /* copy args */
00228         if (selecttab[s].vir_readfds
00229          && (r=sys_vircopy(who_e, D, (vir_bytes) m_in.SEL_READFDS,
00230                 SELF, D, (vir_bytes) &selecttab[s].readfds, sizeof(fd_set))) != OK)
00231                 return r;
00232 
00233         if (selecttab[s].vir_writefds
00234          && (r=sys_vircopy(who_e, D, (vir_bytes) m_in.SEL_WRITEFDS,
00235                 SELF, D, (vir_bytes) &selecttab[s].writefds, sizeof(fd_set))) != OK)
00236                 return r;
00237 
00238         if (selecttab[s].vir_errorfds
00239          && (r=sys_vircopy(who_e, D, (vir_bytes) m_in.SEL_ERRORFDS,
00240                 SELF, D, (vir_bytes) &selecttab[s].errorfds, sizeof(fd_set))) != OK)
00241                 return r;
00242 
00243         if (!m_in.SEL_TIMEOUT)
00244                 is_timeout = nonzero_timeout = 0;
00245         else
00246                 if ((r=sys_vircopy(who_e, D, (vir_bytes) m_in.SEL_TIMEOUT,
00247                         SELF, D, (vir_bytes) &timeout, sizeof(timeout))) != OK)
00248                         return r;
00249 
00250         /* No nonsense in the timeval please. */
00251         if (is_timeout && (timeout.tv_sec < 0 || timeout.tv_usec < 0))
00252                 return EINVAL;
00253 
00254         /* if is_timeout if 0, we block forever. otherwise, if nonzero_timeout
00255          * is 0, we do a poll (don't block). otherwise, we block up to the
00256          * specified time interval.
00257          */
00258         if (is_timeout && (timeout.tv_sec > 0 || timeout.tv_usec > 0))
00259                 nonzero_timeout = 1;
00260 
00261         if (nonzero_timeout || !is_timeout)
00262                 block = 1;
00263         else
00264                 block = 0; /* timeout set as (0,0) - this effects a poll */
00265 
00266         /* no timeout set (yet) */
00267         selecttab[s].expiry = 0;
00268 
00269         for(fd = 0; fd < nfds; fd++) {
00270                 int orig_ops, ops, t, type = -1, r;
00271                 struct filp *filp;
00272         
00273                 if (!(orig_ops = ops = tab2ops(fd, &selecttab[s])))
00274                         continue;
00275                 if (!(filp = selecttab[s].filps[fd] = get_filp(fd))) {
00276                         select_cancel_all(&selecttab[s]);
00277                         return EBADF;
00278                 }
00279 
00280                 for(t = 0; t < SEL_FDS; t++) {
00281                         if (fdtypes[t].select_match) {
00282                            if (fdtypes[t].select_match(filp)) {
00283 #if DEBUG_SELECT
00284                                 printf("select: fd %d is type %d ", fd, t);
00285 #endif
00286                                 if (type != -1)
00287                                         printf("select: double match\n");
00288                                 type = t;
00289                           }
00290                         } else if (select_major_match(fdtypes[t].select_major, filp)) {
00291                                 type = t;
00292                         }
00293                 }
00294 
00295                 /* Open Group:
00296                  * "The pselect() and select() functions shall support
00297                  * regular files, terminal and pseudo-terminal devices,
00298                  * STREAMS-based files, FIFOs, pipes, and sockets. The
00299                  * behavior of pselect() and select() on file descriptors
00300                  * that refer to other types of file is unspecified."
00301                  *
00302                  * If all types are implemented, then this is another
00303                  * type of file and we get to do whatever we want.
00304                  */
00305                 if (type == -1)
00306                 {
00307 #if DEBUG_SELECT
00308                         printf("do_select: bad type\n");
00309 #endif
00310                         return EBADF;
00311                 }
00312 
00313                 selecttab[s].type[fd] = type;
00314 
00315                 if ((selecttab[s].filps[fd]->filp_select_ops & ops) != ops) {
00316                         int wantops;
00317                         /* Request the select on this fd.  */
00318 #if DEBUG_SELECT
00319                         printf("%p requesting ops %d -> ",
00320                                 selecttab[s].filps[fd],
00321                                 selecttab[s].filps[fd]->filp_select_ops);
00322 #endif
00323                         wantops = (selecttab[s].filps[fd]->filp_select_ops |= ops);
00324 #if DEBUG_SELECT
00325                         printf("%d\n", selecttab[s].filps[fd]->filp_select_ops);
00326 #endif
00327                         if ((r = fdtypes[type].select_request(filp,
00328                                 &wantops, block)) != SEL_OK) {
00329                                 /* error or bogus return code.. backpaddle */
00330                                 select_cancel_all(&selecttab[s]);
00331                                 printf("select: select_request returned error\n");
00332                                 return EINVAL;
00333                         }
00334                         if (wantops) {
00335                                 if (wantops & ops) {
00336                                         /* operations that were just requested
00337                                          * are ready to go right away
00338                                          */
00339                                         ops2tab(wantops, fd, &selecttab[s]);
00340                                 }
00341                                 /* if there are any other select()s blocking
00342                                  * on these operations of this fp, they can
00343                                  * be awoken too
00344                                  */
00345                                 select_callback(filp, ops);
00346                         }
00347 #if DEBUG_SELECT
00348                         printf("select request ok; ops returned %d\n", wantops);
00349 #endif
00350                 } else {
00351 #if DEBUG_SELECT
00352                         printf("select already happening on that filp\n");
00353 #endif
00354                 }
00355 
00356                 selecttab[s].nfds = fd+1;
00357                 selecttab[s].filps[fd]->filp_selectors++;
00358 
00359 #if DEBUG_SELECT
00360                 printf("[fd %d ops: %d] ", fd, ops);
00361 #endif
00362         }
00363 
00364         if (selecttab[s].nreadyfds > 0 || !block) {
00365                 /* fd's were found that were ready to go right away, and/or
00366                  * we were instructed not to block at all. Must return
00367                  * immediately.
00368                  */
00369                 copy_fdsets(&selecttab[s]);
00370                 select_cancel_all(&selecttab[s]);
00371                 selecttab[s].requestor = NULL;
00372 
00373                 /* Open Group:
00374                  * "Upon successful completion, the pselect() and select()
00375                  * functions shall return the total number of bits
00376                  * set in the bit masks."
00377                  */
00378 #if DEBUG_SELECT
00379                 printf("returning\n");
00380 #endif
00381 
00382                 return selecttab[s].nreadyfds;
00383         }
00384 #if DEBUG_SELECT
00385                 printf("not returning (%d, %d)\n", selecttab[s].nreadyfds, block);
00386 #endif
00387  
00388         /* Convert timeval to ticks and set the timer. If it fails, undo
00389          * all, return error.
00390          */
00391         if (is_timeout) {
00392                 int ticks;
00393                 /* Open Group:
00394                  * "If the requested timeout interval requires a finer
00395                  * granularity than the implementation supports, the
00396                  * actual timeout interval shall be rounded up to the next
00397                  * supported value."
00398                  */
00399 #define USECPERSEC 1000000
00400                 while(timeout.tv_usec >= USECPERSEC) {
00401                         /* this is to avoid overflow with *HZ below */
00402                         timeout.tv_usec -= USECPERSEC;
00403                         timeout.tv_sec++;
00404                 }
00405                 ticks = timeout.tv_sec * HZ +
00406                         (timeout.tv_usec * HZ + USECPERSEC-1) / USECPERSEC;
00407                 selecttab[s].expiry = ticks;
00408                 fs_set_timer(&selecttab[s].timer, ticks, select_timeout_check, s);
00409 #if DEBUG_SELECT
00410                 printf("%d: blocking %d ticks\n", s, ticks);
00411 #endif
00412         }
00413 
00414         /* if we're blocking, the table entry is now valid. */
00415         selecttab[s].requestor = fp;
00416 
00417         /* process now blocked */
00418         suspend(XSELECT);
00419         return SUSPEND;
00420 }
00421 
00422 /*===========================================================================*
00423  *                              select_cancel_all                            *
00424  *===========================================================================*/
00425 PRIVATE void select_cancel_all(struct selectentry *e)
00426 {
00427         int fd;
00428 
00429         for(fd = 0; fd < e->nfds; fd++) {
00430                 struct filp *fp;
00431                 fp = e->filps[fd];
00432                 if (!fp) {
00433 #if DEBUG_SELECT
00434                         printf("[ fd %d/%d NULL ] ", fd, e->nfds);
00435 #endif
00436                         continue;
00437                 }
00438                 if (fp->filp_selectors < 1) {
00439 #if DEBUG_SELECT
00440                         printf("select: %d selectors?!\n", fp->filp_selectors);
00441 #endif
00442                         continue;
00443                 }
00444                 fp->filp_selectors--;
00445                 e->filps[fd] = NULL;
00446                 select_reevaluate(fp);
00447         }
00448 
00449         if (e->expiry > 0) {
00450 #if DEBUG_SELECT
00451                 printf("cancelling timer %d\n", e - selecttab);
00452 #endif
00453                 fs_cancel_timer(&e->timer); 
00454                 e->expiry = 0;
00455         }
00456 
00457         return;
00458 }
00459 
00460 /*===========================================================================*
00461  *                              select_wakeup                                *
00462  *===========================================================================*/
00463 PRIVATE void select_wakeup(struct selectentry *e, int r)
00464 {
00465         revive(e->req_endpt, r);
00466 }
00467 
00468 /*===========================================================================*
00469  *                              select_reevaluate                            *
00470  *===========================================================================*/
00471 PRIVATE int select_reevaluate(struct filp *fp)
00472 {
00473         int s, remain_ops = 0, fd, type = -1;
00474 
00475         if (!fp) {
00476                 printf("fs: select: reevalute NULL fp\n");
00477                 return 0;
00478         }
00479 
00480         for(s = 0; s < MAXSELECTS; s++) {
00481                 if (!selecttab[s].requestor)
00482                         continue;
00483                 for(fd = 0; fd < selecttab[s].nfds; fd++)
00484                         if (fp == selecttab[s].filps[fd]) {
00485                                 remain_ops |= tab2ops(fd, &selecttab[s]);
00486                                 type = selecttab[s].type[fd];
00487                         }
00488         }
00489 
00490         /* If there are any select()s open that want any operations on
00491          * this fd that haven't been satisfied by this callback, then we're
00492          * still in the market for it.
00493          */
00494         fp->filp_select_ops = remain_ops;
00495 #if DEBUG_SELECT
00496         printf("remaining operations on fp are %d\n", fp->filp_select_ops);
00497 #endif
00498 
00499         return remain_ops;
00500 }
00501 
00502 /*===========================================================================*
00503  *                              select_return                                *
00504  *===========================================================================*/
00505 PRIVATE void select_return(struct selectentry *s, int r)
00506 {
00507         select_cancel_all(s);
00508         copy_fdsets(s);
00509         select_wakeup(s, r ? r : s->nreadyfds);
00510         s->requestor = NULL;
00511 }
00512 
00513 /*===========================================================================*
00514  *                              select_callback                              *
00515  *===========================================================================*/
00516 PUBLIC int select_callback(struct filp *fp, int ops)
00517 {
00518         int s, fd, want_ops, type;
00519 
00520         /* We are being notified that file pointer fp is available for
00521          * operations 'ops'. We must re-register the select for
00522          * operations that we are still interested in, if any.
00523          */
00524 
00525         want_ops = 0;
00526         type = -1;
00527         for(s = 0; s < MAXSELECTS; s++) {
00528                 int wakehim = 0;
00529                 if (!selecttab[s].requestor)
00530                         continue;
00531                 for(fd = 0; fd < selecttab[s].nfds; fd++) {
00532                         if (!selecttab[s].filps[fd])
00533                                 continue;
00534                         if (selecttab[s].filps[fd] == fp) {
00535                                 int this_want_ops;
00536                                 this_want_ops = tab2ops(fd, &selecttab[s]);
00537                                 want_ops |= this_want_ops;
00538                                 if (this_want_ops & ops) {
00539                                         /* this select() has been satisfied. */
00540                                         ops2tab(ops, fd, &selecttab[s]);
00541                                         wakehim = 1;
00542                                 }
00543                                 type = selecttab[s].type[fd];
00544                         }
00545                 }
00546                 if (wakehim)
00547                         select_return(&selecttab[s], 0);
00548         }
00549 
00550         return 0;
00551 }
00552 
00553 /*===========================================================================*
00554  *                              select_notified                              *
00555  *===========================================================================*/
00556 PUBLIC int select_notified(int major, int minor, int selected_ops)
00557 {
00558         int s, f, t;
00559 
00560 #if DEBUG_SELECT
00561         printf("select callback: %d, %d: %d\n", major, minor, selected_ops);
00562 #endif
00563 
00564         for(t = 0; t < SEL_FDS; t++)
00565                 if (!fdtypes[t].select_match && fdtypes[t].select_major == major)
00566                         break;
00567 
00568         if (t >= SEL_FDS) {
00569 #if DEBUG_SELECT
00570                 printf("select callback: no fdtype found for device %d\n", major);
00571 #endif
00572                 return OK;
00573         }
00574 
00575         /* We have a select callback from major device no.
00576          * d, which corresponds to our select type t.
00577          */
00578 
00579         for(s = 0; s < MAXSELECTS; s++) {
00580                 int s_minor, ops;
00581                 if (!selecttab[s].requestor)
00582                         continue;
00583                 for(f = 0; f < selecttab[s].nfds; f++) {
00584                         if (!selecttab[s].filps[f] ||
00585                            !select_major_match(major, selecttab[s].filps[f]))
00586                                 continue;
00587                         ops = tab2ops(f, &selecttab[s]);
00588                         s_minor =
00589                         (selecttab[s].filps[f]->filp_ino->i_zone[0] >> MINOR)
00590                                 & BYTE;
00591                         if ((s_minor == minor) &&
00592                                 (selected_ops & ops)) {
00593                                 select_callback(selecttab[s].filps[f], (selected_ops & ops));
00594                         }
00595                 }
00596         }
00597 
00598         return OK;
00599 }
00600 
00601 /*===========================================================================*
00602  *                              init_select                                  *
00603  *===========================================================================*/
00604 PUBLIC void init_select(void)
00605 {
00606         int s;
00607 
00608         for(s = 0; s < MAXSELECTS; s++)
00609                 fs_init_timer(&selecttab[s].timer);
00610 }
00611 
00612 /*===========================================================================*
00613  *                              select_forget                                *
00614  *===========================================================================*/
00615 PUBLIC void select_forget(int proc_e)
00616 {
00617         /* something has happened (e.g. signal delivered that interrupts
00618          * select()). totally forget about the select().
00619          */
00620         int s;
00621 
00622         for(s = 0; s < MAXSELECTS; s++) {
00623                 if (selecttab[s].requestor &&
00624                         selecttab[s].req_endpt == proc_e) {
00625                         break;
00626                 }
00627 
00628         }
00629 
00630         if (s >= MAXSELECTS) {
00631 #if DEBUG_SELECT
00632                 printf("select: cancelled select() not found");
00633 #endif
00634                 return;
00635         }
00636 
00637         select_cancel_all(&selecttab[s]);
00638         selecttab[s].requestor = NULL;
00639 
00640         return;
00641 }
00642 
00643 /*===========================================================================*
00644  *                              select_timeout_check                         *
00645  *===========================================================================*/
00646 PUBLIC void select_timeout_check(timer_t *timer)
00647 {
00648         int s;
00649 
00650         s = tmr_arg(timer)->ta_int;
00651 
00652         if (s < 0 || s >= MAXSELECTS) {
00653 #if DEBUG_SELECT
00654                 printf("select: bogus slot arg to watchdog %d\n", s);
00655 #endif
00656                 return;
00657         }
00658 
00659         if (!selecttab[s].requestor) {
00660 #if DEBUG_SELECT
00661                 printf("select: no requestor in watchdog\n");
00662 #endif
00663                 return;
00664         }
00665 
00666         if (selecttab[s].expiry <= 0) {
00667 #if DEBUG_SELECT
00668                 printf("select: strange expiry value in watchdog\n", s);
00669 #endif
00670                 return;
00671         }
00672 
00673         selecttab[s].expiry = 0;
00674         select_return(&selecttab[s], 0);
00675 
00676         return;
00677 }
00678 
00679 /*===========================================================================*
00680  *                              select_unsuspend_by_endpt                    *
00681  *===========================================================================*/
00682 PUBLIC void select_unsuspend_by_endpt(int proc_e)
00683 {
00684         int fd, s;
00685 
00686         for(s = 0; s < MAXSELECTS; s++) {
00687           if (!selecttab[s].requestor)
00688                   continue;
00689           for(fd = 0; fd < selecttab[s].nfds; fd++) {
00690             int maj;
00691             if (!selecttab[s].filps[fd] || !selecttab[s].filps[fd]->filp_ino)
00692                 continue;
00693             maj = (selecttab[s].filps[fd]->filp_ino->i_zone[0] >> MAJOR)&BYTE;
00694             if(dmap_driver_match(proc_e, maj)) {
00695                         select_return(&selecttab[s], EAGAIN);
00696             }
00697           }
00698         }
00699 
00700         return;
00701 }
00702 

Generated on Fri Apr 14 22:57:30 2006 for minix by  doxygen 1.4.6