From owner-svn-src-all@FreeBSD.ORG Thu Jan 1 00:31:47 2009 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 5B608106566B; Thu, 1 Jan 2009 00:31:47 +0000 (UTC) (envelope-from alc@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 489F98FC08; Thu, 1 Jan 2009 00:31:47 +0000 (UTC) (envelope-from alc@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n010Vk8C039267; Thu, 1 Jan 2009 00:31:46 GMT (envelope-from alc@svn.freebsd.org) Received: (from alc@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n010Vk34039265; Thu, 1 Jan 2009 00:31:46 GMT (envelope-from alc@svn.freebsd.org) Message-Id: <200901010031.n010Vk34039265@svn.freebsd.org> From: Alan Cox Date: Thu, 1 Jan 2009 00:31:46 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r186665 - head/sys/vm X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 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: Thu, 01 Jan 2009 00:31:47 -0000 Author: alc Date: Thu Jan 1 00:31:46 2009 New Revision: 186665 URL: http://svn.freebsd.org/changeset/base/186665 Log: Resurrect shared map locks allowing greater concurrency during some map operations, such as page faults. An earlier version of this change was ... Reviewed by: kib Tested by: pho MFC after: 6 weeks Modified: head/sys/vm/vm_map.c head/sys/vm/vm_map.h Modified: head/sys/vm/vm_map.c ============================================================================== --- head/sys/vm/vm_map.c Thu Jan 1 00:19:51 2009 (r186664) +++ head/sys/vm/vm_map.c Thu Jan 1 00:31:46 2009 (r186665) @@ -470,7 +470,7 @@ _vm_map_lock_read(vm_map_t map, const ch if (map->system_map) _mtx_lock_flags(&map->system_mtx, 0, file, line); else - (void)_sx_xlock(&map->lock, 0, file, line); + (void)_sx_slock(&map->lock, 0, file, line); } void @@ -480,7 +480,7 @@ _vm_map_unlock_read(vm_map_t map, const if (map->system_map) _mtx_unlock_flags(&map->system_mtx, 0, file, line); else - _sx_xunlock(&map->lock, file, line); + _sx_sunlock(&map->lock, file, line); } int @@ -503,20 +503,44 @@ _vm_map_trylock_read(vm_map_t map, const error = map->system_map ? !_mtx_trylock(&map->system_mtx, 0, file, line) : - !_sx_try_xlock(&map->lock, file, line); + !_sx_try_slock(&map->lock, file, line); return (error == 0); } +/* + * _vm_map_lock_upgrade: [ internal use only ] + * + * Tries to upgrade a read (shared) lock on the specified map to a write + * (exclusive) lock. Returns the value "0" if the upgrade succeeds and a + * non-zero value if the upgrade fails. If the upgrade fails, the map is + * returned without a read or write lock held. + * + * Requires that the map be read locked. + */ int _vm_map_lock_upgrade(vm_map_t map, const char *file, int line) { + unsigned int last_timestamp; -#ifdef INVARIANTS if (map->system_map) { +#ifdef INVARIANTS _mtx_assert(&map->system_mtx, MA_OWNED, file, line); - } else - _sx_assert(&map->lock, SX_XLOCKED, file, line); #endif + } else { + if (!_sx_try_upgrade(&map->lock, file, line)) { + last_timestamp = map->timestamp; + _sx_sunlock(&map->lock, file, line); + /* + * If the map's timestamp does not change while the + * map is unlocked, then the upgrade succeeds. + */ + (void)_sx_xlock(&map->lock, 0, file, line); + if (last_timestamp != map->timestamp) { + _sx_xunlock(&map->lock, file, line); + return (1); + } + } + } map->timestamp++; return (0); } @@ -525,12 +549,28 @@ void _vm_map_lock_downgrade(vm_map_t map, const char *file, int line) { -#ifdef INVARIANTS if (map->system_map) { +#ifdef INVARIANTS _mtx_assert(&map->system_mtx, MA_OWNED, file, line); - } else - _sx_assert(&map->lock, SX_XLOCKED, file, line); #endif + } else + _sx_downgrade(&map->lock, file, line); +} + +/* + * vm_map_locked: + * + * Returns a non-zero value if the caller holds a write (exclusive) lock + * on the specified map and the value "0" otherwise. + */ +int +vm_map_locked(vm_map_t map) +{ + + if (map->system_map) + return (mtx_owned(&map->system_mtx)); + else + return (sx_xlocked(&map->lock)); } /* @@ -902,6 +942,7 @@ vm_map_lookup_entry( vm_map_entry_t *entry) /* OUT */ { vm_map_entry_t cur; + boolean_t locked; /* * If the map is empty, then the map entry immediately preceding @@ -913,8 +954,17 @@ vm_map_lookup_entry( else if (address >= cur->start && cur->end > address) { *entry = cur; return (TRUE); - } else { + } else if ((locked = vm_map_locked(map)) || + sx_try_upgrade(&map->lock)) { + /* + * Splay requires a write lock on the map. However, it only + * restructures the binary search tree; it does not otherwise + * change the map. Thus, the map's timestamp need not change + * on a temporary upgrade. + */ map->root = cur = vm_map_entry_splay(address, cur); + if (!locked) + sx_downgrade(&map->lock); /* * If "address" is contained within a map entry, the new root @@ -927,7 +977,29 @@ vm_map_lookup_entry( return (TRUE); } else *entry = cur->prev; - } + } else + /* + * Since the map is only locked for read access, perform a + * standard binary search tree lookup for "address". + */ + for (;;) { + if (address < cur->start) { + if (cur->left == NULL) { + *entry = cur->prev; + break; + } + cur = cur->left; + } else if (cur->end > address) { + *entry = cur; + return (TRUE); + } else { + if (cur->right == NULL) { + *entry = cur; + break; + } + cur = cur->right; + } + } return (FALSE); } Modified: head/sys/vm/vm_map.h ============================================================================== --- head/sys/vm/vm_map.h Thu Jan 1 00:19:51 2009 (r186664) +++ head/sys/vm/vm_map.h Thu Jan 1 00:31:46 2009 (r186665) @@ -269,6 +269,7 @@ int _vm_map_trylock(vm_map_t map, const int _vm_map_trylock_read(vm_map_t map, const char *file, int line); int _vm_map_lock_upgrade(vm_map_t map, const char *file, int line); void _vm_map_lock_downgrade(vm_map_t map, const char *file, int line); +int vm_map_locked(vm_map_t map); int vm_map_unlock_and_wait(vm_map_t map, int timo); void vm_map_wakeup(vm_map_t map);