diff options
author | jeff <jeff@FreeBSD.org> | 2007-12-16 06:21:20 +0000 |
---|---|---|
committer | jeff <jeff@FreeBSD.org> | 2007-12-16 06:21:20 +0000 |
commit | 4ec9caf00c407884fc51ff18adb8ff16a5eb75c0 (patch) | |
tree | e3b97a4fccf98fcc3311ea54b086b57edb1abb4d /sys/netsmb | |
parent | 436e8270ebc964cc1f1effe79ac5c10e92e78f7b (diff) | |
download | FreeBSD-src-4ec9caf00c407884fc51ff18adb8ff16a5eb75c0.zip FreeBSD-src-4ec9caf00c407884fc51ff18adb8ff16a5eb75c0.tar.gz |
Refactor select to reduce contention and hide internal implementation
details from consumers.
- Track individual selecters on a per-descriptor basis such that there
are no longer collisions and after sleeping for events only those
descriptors which triggered events must be rescaned.
- Protect the selinfo (per descriptor) structure with a mtx pool mutex.
mtx pool mutexes were chosen to preserve api compatibility with
existing code which does nothing but bzero() to setup selinfo
structures.
- Use a per-thread wait channel rather than a global wait channel.
- Hide select implementation details in a seltd structure which is
opaque to the rest of the kernel.
- Provide a 'selsocket' interface for those kernel consumers who wish to
select on a socket when they have no fd so they no longer have to
be aware of select implementation details.
Tested by: kris
Reviewed on: arch
Diffstat (limited to 'sys/netsmb')
-rw-r--r-- | sys/netsmb/smb_trantcp.c | 80 |
1 files changed, 1 insertions, 79 deletions
diff --git a/sys/netsmb/smb_trantcp.c b/sys/netsmb/smb_trantcp.c index 7bdf211..5e34943 100644 --- a/sys/netsmb/smb_trantcp.c +++ b/sys/netsmb/smb_trantcp.c @@ -95,84 +95,6 @@ nb_setsockopt_int(struct socket *so, int level, int name, int val) } static int -nbssn_rselect(struct nbpcb *nbp, struct timeval *tv, int events, - struct thread *td) -{ - struct timeval atv, rtv, ttv; - int ncoll, timo, error, revents; - - if (tv) { - atv = *tv; - if (itimerfix(&atv)) { - error = EINVAL; - goto done_noproclock; - } - getmicrouptime(&rtv); - timevaladd(&atv, &rtv); - } - timo = 0; - mtx_lock(&sellock); -retry: - - ncoll = nselcoll; - thread_lock(td); - td->td_flags |= TDF_SELECT; - thread_unlock(td); - mtx_unlock(&sellock); - - /* XXX: Should be done when the thread is initialized. */ - TAILQ_INIT(&td->td_selq); - revents = sopoll(nbp->nbp_tso, events, NULL, td); - mtx_lock(&sellock); - if (revents) { - error = 0; - goto done; - } - if (tv) { - getmicrouptime(&rtv); - if (timevalcmp(&rtv, &atv, >=)) { - error = EWOULDBLOCK; - goto done; - } - ttv = atv; - timevalsub(&ttv, &rtv); - timo = tvtohz(&ttv); - } - /* - * An event of our interest may occur during locking a process. - * In order to avoid missing the event that occurred during locking - * the process, test P_SELECT and rescan file descriptors if - * necessary. - */ - thread_lock(td); - if ((td->td_flags & TDF_SELECT) == 0 || nselcoll != ncoll) { - thread_unlock(td); - goto retry; - } - thread_unlock(td); - - if (timo > 0) - error = cv_timedwait(&selwait, &sellock, timo); - else { - cv_wait(&selwait, &sellock); - error = 0; - } - -done: - clear_selinfo_list(td); - - thread_lock(td); - td->td_flags &= ~TDF_SELECT; - thread_unlock(td); - mtx_unlock(&sellock); - -done_noproclock: - if (error == ERESTART) - return 0; - return error; -} - -static int nb_intr(struct nbpcb *nbp, struct proc *p) { return 0; @@ -302,7 +224,7 @@ nbssn_rq_request(struct nbpcb *nbp, struct thread *td) if (error) return error; TIMESPEC_TO_TIMEVAL(&tv, &nbp->nbp_timo); - error = nbssn_rselect(nbp, &tv, POLLIN, td); + error = selsocket(nbp->nbp_tso, POLLIN, &tv, td); if (error == EWOULDBLOCK) { /* Timeout */ NBDEBUG("initial request timeout\n"); return ETIMEDOUT; |