/* Must be called with nklock locked irqs off */ int __xnselect_signal(struct xnselect *select_block, unsigned state) { xnholder_t *holder; int resched; for(resched = 0, holder = getheadq(&select_block->bindings); holder; holder = nextq(&select_block->bindings, holder)) { struct xnselect_binding *binding; struct xnselector *selector; binding = link2binding(holder, link); selector = binding->selector; if (state) { if (!__FD_ISSET(binding->bit_index, &selector->fds[binding->type].pending)) { __FD_SET(binding->bit_index, &selector->fds[binding->type].pending); if (xnselect_wakeup(selector)) resched = 1; } } else __FD_CLR(binding->bit_index, &selector->fds[binding->type].pending); } return resched; }
/** * Destroy the @a xnselect structure associated with a file descriptor. * * Any binding with a @a xnselector block is destroyed. * * @param select_block pointer to the @a xnselect structure associated with a file descriptor */ void xnselect_destroy(struct xnselect *select_block) { xnholder_t *holder; int resched = 0; spl_t s; xnlock_get_irqsave(&nklock, s); while ((holder = getq(&select_block->bindings))) { struct xnselect_binding *binding; struct xnselector *selector; binding = link2binding(holder, link); selector = binding->selector; __FD_CLR(binding->bit_index, &selector->fds[binding->type].expected); if (!__FD_ISSET(binding->bit_index, &selector->fds[binding->type].pending)) { __FD_SET(binding->bit_index, &selector->fds[binding->type].pending); if (xnselect_wakeup(selector)) resched = 1; } removeq(&selector->bindings, &binding->slink); xnlock_put_irqrestore(&nklock, s); xnfree(binding); xnlock_get_irqsave(&nklock, s); } if (resched) xnpod_schedule(); xnlock_put_irqrestore(&nklock, s); }
static int exa_select(struct exa_select *sel) { int i; int one=0; int ret = -EFAULT; /* first phase register on each queue */ for (i = 0; i < __FD_SETSIZE; i++) { __FD_CLR(i, &sel->result); if (__FD_ISSET(i, &sel->select)) { sel->elt[i].socket = exa_getsock(i); if (sel->elt[i].socket == NULL) { ret = -EINVAL; continue; } set_callbacks(sel->elt[i].socket, &sel->elt[i]); if (sel->operation == EXA_SELECT_IN) { if (sock_readable(sel->elt[i].socket) == 1) one = 1; } if (sel->operation == EXA_SELECT_OUT) if (sock_writable(sel->elt[i].socket) == 1) one = 1; } } /* second phase : check if nothing arrived and wait if nothing arrived */ if (one==0) { int timeout = SELECT_TIMEOUT ; set_current_state(TASK_INTERRUPTIBLE); for (i = 0; i < __FD_SETSIZE; i++) { if (__FD_ISSET(i, &sel->select) && (sel->elt[i].socket != NULL)) { if (sel->operation == EXA_SELECT_IN) { if (sock_readable(sel->elt[i].socket) == 1) one = 1; } if (sel->operation == EXA_SELECT_OUT) { if (sock_writable(sel->elt[i].socket) == 1) one = 1; } } } if (one == 0) /* if some data already pending, we must not wait (or some race can occur)*/ timeout = schedule_timeout(timeout); set_current_state(TASK_RUNNING); } /* third : find wich socket receive/sent something */ for (i = __FD_SETSIZE - 1; i >= 0; i--) { if (__FD_ISSET(i, &sel->select)) { if (sel->elt[i].socket == NULL) continue; if (sel->operation == EXA_SELECT_IN) { if (sock_readable(sel->elt[i].socket) == 1) __FD_SET(i, &sel->result); } if (sel->operation == EXA_SELECT_OUT) { if (sock_writable(sel->elt[i].socket) == 1) __FD_SET(i, &sel->result); } if ((__FD_ISSET(i, &sel->result)) && (ret == -EFAULT)) ret = 0; restore_callbacks(sel->elt[i].socket, &sel->elt[i]); fput(sel->elt[i].socket->file); sel->elt[i].socket = NULL; } } /* XXX this is not an error, -EFAULT is used here as the timeout return * value.... * FIXME use ETIME to have an explicit timeout. */ if (ret == -EFAULT) __FD_ZERO(&sel->result); return ret; }