From owner-svn-src-all@FreeBSD.ORG Wed Jan 22 23:47:30 2014 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 5CC8EA4A; Wed, 22 Jan 2014 23:47:30 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id 3D10F110B; Wed, 22 Jan 2014 23:47:30 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.7/8.14.7) with ESMTP id s0MNlU6q025477; Wed, 22 Jan 2014 23:47:30 GMT (envelope-from mav@svn.freebsd.org) Received: (from mav@localhost) by svn.freebsd.org (8.14.7/8.14.7/Submit) id s0MNlTce025474; Wed, 22 Jan 2014 23:47:29 GMT (envelope-from mav@svn.freebsd.org) Message-Id: <201401222347.s0MNlTce025474@svn.freebsd.org> From: Alexander Motin Date: Wed, 22 Jan 2014 23:47:29 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r261048 - in stable/10/sys: nfs rpc X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.17 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 22 Jan 2014 23:47:30 -0000 Author: mav Date: Wed Jan 22 23:47:29 2014 New Revision: 261048 URL: http://svnweb.freebsd.org/changeset/base/261048 Log: MFC r259659, r259662: Remove several linear list traversals per request from RPC server code. Do not insert active ports into pool->sp_active list if they are success- fully assigned to some thread. This makes that list include only ports that really require attention, and so traversal can be reduced to simple taking the first one. Remove idle thread from pool->sp_idlethreads list when assigning some work (port of requests) to it. That again makes possible to replace list traversals with simple taking the first element. Modified: stable/10/sys/nfs/nfs_fha.c stable/10/sys/rpc/svc.c stable/10/sys/rpc/svc.h Directory Properties: stable/10/ (props changed) Modified: stable/10/sys/nfs/nfs_fha.c ============================================================================== --- stable/10/sys/nfs/nfs_fha.c Wed Jan 22 23:46:19 2014 (r261047) +++ stable/10/sys/nfs/nfs_fha.c Wed Jan 22 23:47:29 2014 (r261048) @@ -289,19 +289,6 @@ fha_hash_entry_add_op(struct fha_hash_en fhe->num_rw += count; } -static SVCTHREAD * -get_idle_thread(SVCPOOL *pool) -{ - SVCTHREAD *st; - - LIST_FOREACH(st, &pool->sp_idlethreads, st_ilink) { - if (st->st_xprt == NULL && STAILQ_EMPTY(&st->st_reqs)) - return (st); - } - return (NULL); -} - - /* * Get the service thread currently associated with the fhe that is * appropriate to handle this operation. @@ -386,7 +373,7 @@ fha_hash_entry_choose_thread(struct fha_ ITRACE_CURPROC(ITRACE_NFS, ITRACE_INFO, "fha: %p(%d)t", thread, thread->st_reqcount); #endif - } else if ((thread = get_idle_thread(pool))) { + } else if ((thread = LIST_FIRST(&pool->sp_idlethreads))) { #if 0 ITRACE_CURPROC(ITRACE_NFS, ITRACE_INFO, "fha: %p(%d)i", thread, thread->st_reqcount); @@ -418,7 +405,6 @@ SVCTHREAD * fha_assign(SVCTHREAD *this_thread, struct svc_req *req, struct fha_params *softc) { - SVCPOOL *pool; SVCTHREAD *thread; struct fha_info i; struct fha_hash_entry *fhe; @@ -439,7 +425,6 @@ fha_assign(SVCTHREAD *this_thread, struc if (req->rq_vers != 2 && req->rq_vers != 3) return (this_thread); - pool = req->rq_xprt->xp_pool; fha_extract_info(req, &i, cb); /* Modified: stable/10/sys/rpc/svc.c ============================================================================== --- stable/10/sys/rpc/svc.c Wed Jan 22 23:46:19 2014 (r261047) +++ stable/10/sys/rpc/svc.c Wed Jan 22 23:47:29 2014 (r261048) @@ -293,12 +293,10 @@ xprt_unregister_locked(SVCXPRT *xprt) { SVCPOOL *pool = xprt->xp_pool; + mtx_assert(&pool->sp_lock, MA_OWNED); KASSERT(xprt->xp_registered == TRUE, ("xprt_unregister_locked: not registered")); - if (xprt->xp_active) { - TAILQ_REMOVE(&pool->sp_active, xprt, xp_alink); - xprt->xp_active = FALSE; - } + xprt_inactive_locked(xprt); TAILQ_REMOVE(&pool->sp_xlist, xprt, xp_link); xprt->xp_registered = FALSE; } @@ -320,25 +318,25 @@ xprt_unregister(SVCXPRT *xprt) SVC_RELEASE(xprt); } -static void +/* + * Attempt to assign a service thread to this transport. + */ +static int xprt_assignthread(SVCXPRT *xprt) { SVCPOOL *pool = xprt->xp_pool; SVCTHREAD *st; - /* - * Attempt to assign a service thread to this - * transport. - */ - LIST_FOREACH(st, &pool->sp_idlethreads, st_ilink) { - if (st->st_xprt == NULL && STAILQ_EMPTY(&st->st_reqs)) - break; - } + mtx_assert(&pool->sp_lock, MA_OWNED); + st = LIST_FIRST(&pool->sp_idlethreads); if (st) { + LIST_REMOVE(st, st_ilink); + st->st_idle = FALSE; SVC_ACQUIRE(xprt); xprt->xp_thread = st; st->st_xprt = xprt; cv_signal(&st->st_cond); + return (TRUE); } else { /* * See if we can create a new thread. The @@ -354,6 +352,7 @@ xprt_assignthread(SVCXPRT *xprt) pool->sp_state = SVCPOOL_THREADWANTED; } } + return (FALSE); } void @@ -372,9 +371,12 @@ xprt_active(SVCXPRT *xprt) } if (!xprt->xp_active) { - TAILQ_INSERT_TAIL(&pool->sp_active, xprt, xp_alink); xprt->xp_active = TRUE; - xprt_assignthread(xprt); + if (xprt->xp_thread == NULL) { + if (!xprt_assignthread(xprt)) + TAILQ_INSERT_TAIL(&pool->sp_active, xprt, + xp_alink); + } } mtx_unlock(&pool->sp_lock); @@ -385,8 +387,10 @@ xprt_inactive_locked(SVCXPRT *xprt) { SVCPOOL *pool = xprt->xp_pool; + mtx_assert(&pool->sp_lock, MA_OWNED); if (xprt->xp_active) { - TAILQ_REMOVE(&pool->sp_active, xprt, xp_alink); + if (xprt->xp_thread == NULL) + TAILQ_REMOVE(&pool->sp_active, xprt, xp_alink); xprt->xp_active = FALSE; } } @@ -948,10 +952,11 @@ svc_assign_waiting_sockets(SVCPOOL *pool { SVCXPRT *xprt; - TAILQ_FOREACH(xprt, &pool->sp_active, xp_alink) { - if (!xprt->xp_thread) { - xprt_assignthread(xprt); - } + while ((xprt = TAILQ_FIRST(&pool->sp_active)) != NULL) { + if (xprt_assignthread(xprt)) + TAILQ_REMOVE(&pool->sp_active, xprt, xp_alink); + else + break; } } @@ -1042,21 +1047,17 @@ svc_run_internal(SVCPOOL *pool, bool_t i * active transport which isn't being serviced * by a thread. */ - if (svc_request_space_available(pool)) { - TAILQ_FOREACH(xprt, &pool->sp_active, - xp_alink) { - if (!xprt->xp_thread) { - SVC_ACQUIRE(xprt); - xprt->xp_thread = st; - st->st_xprt = xprt; - break; - } - } - } - if (st->st_xprt) + if (svc_request_space_available(pool) && + (xprt = TAILQ_FIRST(&pool->sp_active)) != NULL) { + TAILQ_REMOVE(&pool->sp_active, xprt, xp_alink); + SVC_ACQUIRE(xprt); + xprt->xp_thread = st; + st->st_xprt = xprt; continue; + } LIST_INSERT_HEAD(&pool->sp_idlethreads, st, st_ilink); + st->st_idle = TRUE; if (ismaster || (!ismaster && pool->sp_threadcount > pool->sp_minthreads)) error = cv_timedwait_sig(&st->st_cond, @@ -1064,7 +1065,10 @@ svc_run_internal(SVCPOOL *pool, bool_t i else error = cv_wait_sig(&st->st_cond, &pool->sp_lock); - LIST_REMOVE(st, st_ilink); + if (st->st_idle) { + LIST_REMOVE(st, st_ilink); + st->st_idle = FALSE; + } /* * Reduce worker thread count when idle. @@ -1132,11 +1136,12 @@ svc_run_internal(SVCPOOL *pool, bool_t i * execute the request * immediately. */ - if (stpref != st) { - cv_signal(&stpref->st_cond); - continue; - } else { + if (stpref == st) break; + if (stpref->st_idle) { + LIST_REMOVE(stpref, st_ilink); + stpref->st_idle = FALSE; + cv_signal(&stpref->st_cond); } } } while (stat == XPRT_MOREREQS @@ -1153,10 +1158,9 @@ svc_run_internal(SVCPOOL *pool, bool_t i xprt->xp_thread = NULL; st->st_xprt = NULL; if (xprt->xp_active) { - xprt_assignthread(xprt); - TAILQ_REMOVE(&pool->sp_active, xprt, xp_alink); - TAILQ_INSERT_TAIL(&pool->sp_active, xprt, - xp_alink); + if (!xprt_assignthread(xprt)) + TAILQ_INSERT_TAIL(&pool->sp_active, + xprt, xp_alink); } mtx_unlock(&pool->sp_lock); SVC_RELEASE(xprt); Modified: stable/10/sys/rpc/svc.h ============================================================================== --- stable/10/sys/rpc/svc.h Wed Jan 22 23:46:19 2014 (r261047) +++ stable/10/sys/rpc/svc.h Wed Jan 22 23:47:29 2014 (r261048) @@ -278,6 +278,7 @@ typedef struct __rpc_svcthread { SVCXPRT *st_xprt; /* transport we are processing */ struct svc_reqlist st_reqs; /* RPC requests to execute */ int st_reqcount; /* number of queued reqs */ + int st_idle; /* thread is on idle list */ struct cv st_cond; /* sleeping for work */ LIST_ENTRY(__rpc_svcthread) st_link; /* all threads list */ LIST_ENTRY(__rpc_svcthread) st_ilink; /* idle threads list */