From owner-svn-src-head@FreeBSD.ORG Tue Oct 21 19:05:45 2014 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 9B78179D; Tue, 21 Oct 2014 19:05:45 +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)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 87B029A2; Tue, 21 Oct 2014 19:05:45 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id s9LJ5jlf032493; Tue, 21 Oct 2014 19:05:45 GMT (envelope-from mjg@FreeBSD.org) Received: (from mjg@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id s9LJ5jDb032492; Tue, 21 Oct 2014 19:05:45 GMT (envelope-from mjg@FreeBSD.org) Message-Id: <201410211905.s9LJ5jDb032492@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: mjg set sender to mjg@FreeBSD.org using -f From: Mateusz Guzik Date: Tue, 21 Oct 2014 19:05:45 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r273401 - head/sys/kern X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 21 Oct 2014 19:05:45 -0000 Author: mjg Date: Tue Oct 21 19:05:44 2014 New Revision: 273401 URL: https://svnweb.freebsd.org/changeset/base/273401 Log: Implement shared locking for sysctl. Modified: head/sys/kern/kern_sysctl.c Modified: head/sys/kern/kern_sysctl.c ============================================================================== --- head/sys/kern/kern_sysctl.c Tue Oct 21 19:02:26 2014 (r273400) +++ head/sys/kern/kern_sysctl.c Tue Oct 21 19:05:44 2014 (r273401) @@ -91,6 +91,10 @@ static struct sx sysctlmemlock; #define SYSCTL_XLOCK() sx_xlock(&sysctllock) #define SYSCTL_XUNLOCK() sx_xunlock(&sysctllock) +#define SYSCTL_SLOCK() sx_slock(&sysctllock) +#define SYSCTL_SUNLOCK() sx_sunlock(&sysctllock) +#define SYSCTL_XLOCKED() sx_xlocked(&sysctllock) +#define SYSCTL_ASSERT_LOCKED() sx_assert(&sysctllock, SA_LOCKED) #define SYSCTL_ASSERT_XLOCKED() sx_assert(&sysctllock, SA_XLOCKED) #define SYSCTL_INIT() sx_init(&sysctllock, "sysctl lock") #define SYSCTL_SLEEP(ch, wmesg, timo) \ @@ -106,12 +110,35 @@ static int sysctl_remove_oid_locked(stru static int sysctl_old_kernel(struct sysctl_req *, const void *, size_t); static int sysctl_new_kernel(struct sysctl_req *, void *, size_t); +static void +sysctl_lock(bool xlock) +{ + + if (xlock) + SYSCTL_XLOCK(); + else + SYSCTL_SLOCK(); +} + +static bool +sysctl_unlock(void) +{ + bool xlocked; + + xlocked = SYSCTL_XLOCKED(); + if (xlocked) + SYSCTL_XUNLOCK(); + else + SYSCTL_SUNLOCK(); + return (xlocked); +} + static struct sysctl_oid * sysctl_find_oidname(const char *name, struct sysctl_oid_list *list) { struct sysctl_oid *oidp; - SYSCTL_ASSERT_XLOCKED(); + SYSCTL_ASSERT_LOCKED(); SLIST_FOREACH(oidp, list, oid_link) { if (strcmp(oidp->oid_name, name) == 0) { return (oidp); @@ -144,9 +171,10 @@ sysctl_root_handler_locked(struct sysctl struct sysctl_req *req) { int error; + bool xlocked; - oid->oid_running++; - SYSCTL_XUNLOCK(); + atomic_add_int(&oid->oid_running, 1); + xlocked = sysctl_unlock(); if (!(oid->oid_kind & CTLFLAG_MPSAFE)) mtx_lock(&Giant); @@ -154,9 +182,9 @@ sysctl_root_handler_locked(struct sysctl if (!(oid->oid_kind & CTLFLAG_MPSAFE)) mtx_unlock(&Giant); - SYSCTL_XLOCK(); - oid->oid_running--; - if (oid->oid_running == 0 && (oid->oid_kind & CTLFLAG_DYING) != 0) + sysctl_lock(xlocked); + if (atomic_fetchadd_int(&oid->oid_running, -1) == 1 && + (oid->oid_kind & CTLFLAG_DYING) != 0) wakeup(&oid->oid_running); return (error); @@ -852,7 +880,7 @@ sysctl_sysctl_next_ls(struct sysctl_oid_ { struct sysctl_oid *oidp; - SYSCTL_ASSERT_XLOCKED(); + SYSCTL_ASSERT_LOCKED(); *len = level; SLIST_FOREACH(oidp, lsp, oid_link) { *next = oidp->oid_number; @@ -939,7 +967,7 @@ name2oid(char *name, int *oid, int *len, struct sysctl_oid_list *lsp = &sysctl__children; char *p; - SYSCTL_ASSERT_XLOCKED(); + SYSCTL_ASSERT_LOCKED(); for (*len = 0; *len < CTL_MAXNAME;) { p = strsep(&name, "."); @@ -1364,9 +1392,9 @@ kernel_sysctl(struct thread *td, int *na req.newfunc = sysctl_new_kernel; req.lock = REQ_UNWIRED; - SYSCTL_XLOCK(); + SYSCTL_SLOCK(); error = sysctl_root(0, name, namelen, &req); - SYSCTL_XUNLOCK(); + SYSCTL_SUNLOCK(); if (req.lock == REQ_WIRED && req.validlen > 0) vsunlock(req.oldptr, req.validlen); @@ -1498,7 +1526,7 @@ sysctl_find_oid(int *name, u_int namelen struct sysctl_oid *oid; int indx; - SYSCTL_ASSERT_XLOCKED(); + SYSCTL_ASSERT_LOCKED(); lsp = &sysctl__children; indx = 0; while (indx < CTL_MAXNAME) { @@ -1545,7 +1573,7 @@ sysctl_root(SYSCTL_HANDLER_ARGS) struct sysctl_oid *oid; int error, indx, lvl; - SYSCTL_ASSERT_XLOCKED(); + SYSCTL_ASSERT_LOCKED(); error = sysctl_find_oid(arg1, arg2, &oid, &indx, req); if (error) @@ -1729,9 +1757,9 @@ userland_sysctl(struct thread *td, int * for (;;) { req.oldidx = 0; req.newidx = 0; - SYSCTL_XLOCK(); + SYSCTL_SLOCK(); error = sysctl_root(0, name, namelen, &req); - SYSCTL_XUNLOCK(); + SYSCTL_SUNLOCK(); if (error != EAGAIN) break; kern_yield(PRI_USER);