From owner-svn-soc-all@FreeBSD.ORG Wed Jul 18 15:16:10 2012 Return-Path: Delivered-To: svn-soc-all@FreeBSD.org Received: from socsvn.FreeBSD.org (unknown [IPv6:2001:4f8:fff6::2f]) by hub.freebsd.org (Postfix) with SMTP id EECE01065672 for ; Wed, 18 Jul 2012 15:16:07 +0000 (UTC) (envelope-from gmiller@FreeBSD.org) Received: by socsvn.FreeBSD.org (sSMTP sendmail emulation); Wed, 18 Jul 2012 15:16:07 +0000 Date: Wed, 18 Jul 2012 15:16:07 +0000 From: gmiller@FreeBSD.org To: svn-soc-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Message-Id: <20120718151607.EECE01065672@hub.freebsd.org> Cc: Subject: socsvn commit: r239546 - in soc2012/gmiller/locking-head: . lib/libwitness X-BeenThere: svn-soc-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the entire Summer of Code repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 18 Jul 2012 15:16:10 -0000 Author: gmiller Date: Wed Jul 18 15:16:07 2012 New Revision: 239546 URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=239546 Log: r239588@FreeBSD-dev: root | 2012-07-15 01:23:43 -0500 Implement pthread_lockorder_begin_np(), pthread_lockorder_next_np(), and pthread_lockorder_end_np() to obtain a lock order graph. Modified: soc2012/gmiller/locking-head/ (props changed) soc2012/gmiller/locking-head/lib/libwitness/graph.c Modified: soc2012/gmiller/locking-head/lib/libwitness/graph.c ============================================================================== --- soc2012/gmiller/locking-head/lib/libwitness/graph.c Wed Jul 18 12:41:09 2012 (r239545) +++ soc2012/gmiller/locking-head/lib/libwitness/graph.c Wed Jul 18 15:16:07 2012 (r239546) @@ -27,6 +27,15 @@ #include "witness.h" +struct lock_iter { + SLIST_ENTRY(lock_iter) iter_next; + void *lock; +}; + +struct _pthread_lockorder_private { + SLIST_HEAD(lock_iter_head, lock_iter) lock_iter_head; +}; + struct lock_info *root = NULL; static int @@ -79,3 +88,72 @@ return (0); } + +static void +add_graph(struct pthread_lockorder_np *iter_node, struct lock_info *graph_node) +{ + struct lock_iter *iter; + + if (graph_node != NULL) { + iter = malloc(sizeof(struct pthread_lockorder_np)); + iter->lock = graph_node->lock; + SLIST_INSERT_HEAD(&iter_node->_pvt->lock_iter_head, iter, + iter_next); + + add_graph(iter_node, graph_node->sibling); + add_graph(iter_node, graph_node->child); + } +} + +void +pthread_lockorder_begin_np(struct pthread_lockorder_np *node) +{ + /* + The lock isn't needed to prevent races, but it is needed to ensure + that any locks grabbed by malloc() don't get logged. + */ + pthread_mutex_lock(&witness_mtx); + + node->_pvt = malloc(sizeof(struct _pthread_lockorder_private)); + + add_graph(node, root); + + pthread_mutex_unlock(&witness_mtx); +} + +int +pthread_lockorder_next_np(struct pthread_lockorder_np *node) +{ + struct lock_iter *iter; + + iter = SLIST_FIRST(&node->_pvt->lock_iter_head); + if (iter != NULL) { + SLIST_REMOVE_HEAD(&node->_pvt->lock_iter_head, iter_next); + + node->lock = iter->lock; + + free(iter); + + return (1); + } else { + return (0); + } +} + +void +pthread_lockorder_end_np(struct pthread_lockorder_np *node) +{ + struct lock_iter *iter; + + if (node->_pvt != NULL) { + while (!SLIST_EMPTY(&node->_pvt->lock_iter_head)) { + iter = SLIST_FIRST(&node->_pvt->lock_iter_head); + SLIST_REMOVE_HEAD(&node->_pvt->lock_iter_head, + iter_next); + free(iter); + } + + free(node->_pvt); + node->_pvt = NULL; + } +}