- Fix ncp_poll() to not panic by faking up enough poll(2) state in the
  current thread.
- Fix the rselect() routines for netncp and netsmb to return EWOULDBLOCK
  if the timeout is elapsed before they can block and to invoke
  pru_sopoll() directly.
This commit is contained in:
jhb 2006-08-11 19:41:51 +00:00
parent b01e8aa321
commit 47cc69d311
2 changed files with 34 additions and 18 deletions

View File

@ -186,10 +186,28 @@ ncp_sock_send(struct socket *so, struct mbuf *top, struct ncp_rq *rqp)
int
ncp_poll(struct socket *so, int events)
{
struct thread *td = curthread;
struct ucred *cred = NULL;
struct thread *td = curthread;
int revents;
return so->so_proto->pr_usrreqs->pru_sopoll(so, events, cred, td);
/* Fake up enough state to look like we are in poll(2). */
mtx_lock(&sellock);
mtx_lock_spin(&sched_lock);
td->td_flags |= TDF_SELECT;
mtx_unlock_spin(&sched_lock);
mtx_unlock(&sellock);
TAILQ_INIT(&td->td_selq);
revents = so->so_proto->pr_usrreqs->pru_sopoll(so, events, NULL, td);
/* Tear down the fake poll(2) state. */
mtx_lock(&sellock);
clear_selinfo_list(td);
mtx_lock_spin(&sched_lock);
td->td_flags &= ~TDF_SELECT;
mtx_unlock_spin(&sched_lock);
mtx_unlock(&sellock);
return (revents);
}
int
@ -197,7 +215,7 @@ ncp_sock_rselect(struct socket *so, struct thread *td, struct timeval *tv,
int events)
{
struct timeval atv, rtv, ttv;
int ncoll, timo, error = 0;
int ncoll, timo, error, revents;
if (tv) {
atv = *tv;
@ -219,16 +237,18 @@ retry:
mtx_unlock(&sellock);
TAILQ_INIT(&td->td_selq);
error = ncp_poll(so, events);
revents = so->so_proto->pr_usrreqs->pru_sopoll(so, events, NULL, td);
mtx_lock(&sellock);
if (error) {
if (revents) {
error = 0;
goto done;
}
if (tv) {
getmicrouptime(&rtv);
if (timevalcmp(&rtv, &atv, >=))
if (timevalcmp(&rtv, &atv, >=)) {
error = EWOULDBLOCK;
goto done;
}
ttv = atv;
timevalsub(&ttv, &rtv);
timo = tvtohz(&ttv);

View File

@ -95,19 +95,12 @@ nb_setsockopt_int(struct socket *so, int level, int name, int val)
return sosetopt(so, &sopt);
}
static __inline int
nb_poll(struct nbpcb *nbp, int events, struct thread *td)
{
return nbp->nbp_tso->so_proto->pr_usrreqs->pru_sopoll(nbp->nbp_tso,
events, NULL, td);
}
static int
nbssn_rselect(struct nbpcb *nbp, struct timeval *tv, int events,
struct thread *td)
{
struct timeval atv, rtv, ttv;
int ncoll, timo, error;
int ncoll, timo, error, revents;
if (tv) {
atv = *tv;
@ -130,16 +123,19 @@ retry:
/* XXX: Should be done when the thread is initialized. */
TAILQ_INIT(&td->td_selq);
error = nb_poll(nbp, events, td);
revents = nbp->nbp_tso->so_proto->pr_usrreqs->pru_sopoll(nbp->nbp_tso,
events, NULL, td);
mtx_lock(&sellock);
if (error) {
if (revents) {
error = 0;
goto done;
}
if (tv) {
getmicrouptime(&rtv);
if (timevalcmp(&rtv, &atv, >=))
if (timevalcmp(&rtv, &atv, >=)) {
error = EWOULDBLOCK;
goto done;
}
ttv = atv;
timevalsub(&ttv, &rtv);
timo = tvtohz(&ttv);