From owner-freebsd-arch@FreeBSD.ORG Fri Aug 6 22:43:18 2004 Return-Path: Delivered-To: freebsd-arch@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id D1B9B16A4CF for ; Fri, 6 Aug 2004 22:43:18 +0000 (GMT) Received: from mail4.speakeasy.net (mail4.speakeasy.net [216.254.0.204]) by mx1.FreeBSD.org (Postfix) with ESMTP id 6CF5343D49 for ; Fri, 6 Aug 2004 22:43:18 +0000 (GMT) (envelope-from jmg@hydrogen.funkthat.com) Received: (qmail 20215 invoked from network); 6 Aug 2004 22:43:18 -0000 Received: from gate.funkthat.com (HELO hydrogen.funkthat.com) ([69.17.45.168]) (envelope-sender ) by mail4.speakeasy.net (qmail-ldap-1.03) with SMTP for ; 6 Aug 2004 22:43:17 -0000 Received: from hydrogen.funkthat.com (mrgrip@localhost.funkthat.com [127.0.0.1])i76MhGuU002172; Fri, 6 Aug 2004 15:43:17 -0700 (PDT) (envelope-from jmg@hydrogen.funkthat.com) Received: (from jmg@localhost) by hydrogen.funkthat.com (8.12.10/8.12.10/Submit) id i76MhGp3002170; Fri, 6 Aug 2004 15:43:16 -0700 (PDT) Date: Fri, 6 Aug 2004 15:43:16 -0700 From: John-Mark Gurney To: freebsd-arch@freebsd.org Message-ID: <20040806224316.GB991@funkthat.com> Mail-Followup-To: freebsd-arch@freebsd.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="T4sUOijqQbZv57TR" Content-Disposition: inline User-Agent: Mutt/1.4.1i X-Operating-System: FreeBSD 4.2-RELEASE i386 X-PGP-Fingerprint: B7 EC EF F8 AE ED A7 31 96 7A 22 B3 D8 56 36 F4 X-Files: The truth is out there X-URL: http://resnet.uoregon.edu/~gurney_j/ X-Resume: http://resnet.uoregon.edu/~gurney_j/resume.html Subject: valid dup lock logic for witness X-BeenThere: freebsd-arch@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list Reply-To: John-Mark Gurney List-Id: Discussion related to FreeBSD architecture List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 06 Aug 2004 22:43:19 -0000 --T4sUOijqQbZv57TR Content-Type: text/plain; charset=us-ascii Content-Disposition: inline I have been working on kqueue, and to support kq in kq, I need to obtain two kq locks (both of the same type) at the same time. Normally this can cause a deadlock, but using a proper lock ordering strategy, it can be avoided. In the kq case, I chose to aquire a kq global lock before acquiring multiple kq locks. (In the proc case, jhb said you aquire the child's before the parents.) Mutexs have the flag MTX_DUPOK that notify witness that duplicate locks are ok, but this can hide other problems (and in fact would have in my testing). I have created a patch that lets you inform witness the a duplicate lock is valid as long as you hold another lock. The only run time change is that when a duplicate lock is found, it will run through another table to verify it's ok before printing out the back trace. Anyone have objections to this? -- John-Mark Gurney Voice: +1 415 225 5579 "All that I will do, has been done, All that I have, has not." --T4sUOijqQbZv57TR Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="subr_witness.diff" Index: subr_witness.c =================================================================== RCS file: /usr/src/FreeBSD/src/sys/kern/subr_witness.c,v retrieving revision 1.176 diff -u -r1.176 subr_witness.c --- subr_witness.c 10 Jul 2004 21:42:16 -0000 1.176 +++ subr_witness.c 5 Aug 2004 21:22:22 -0000 @@ -155,6 +155,13 @@ struct lock_class *w_class; }; +struct witness_order_dup_list_entry { + const char *w_name_dup; + struct lock_class *w_class_dup; + const char *w_name_parent; + struct lock_class *w_class_parent; +}; + #ifdef BLESSING static int blessed(struct witness *, struct witness *); #endif @@ -183,6 +190,7 @@ static void witness_lock_list_free(struct lock_list_entry *lle); static struct lock_instance *find_instance(struct lock_list_entry *lock_list, struct lock_object *lock); +static int dup_lock_ok(struct lock_list_entry *lock_list); static void witness_list_lock(struct lock_instance *instance); #ifdef DDB static void witness_list(struct thread *td); @@ -366,6 +374,11 @@ { NULL, NULL } }; +static struct witness_order_dup_list_entry dup_order_lists[] = { + { "kqueue", &lock_class_mtx_sleep, + "kqueue order", &lock_class_mtx_sleep }, +}; + #ifdef BLESSING /* * Pairs of locks which have been blessed @@ -764,6 +777,8 @@ if (w1 == w) { if (w->w_same_squawked || (lock->lo_flags & LO_DUPOK)) return; + if (dup_lock_ok(*lock_list)) + return; w->w_same_squawked = 1; printf("acquiring duplicate lock of same type: \"%s\"\n", lock->lo_type); @@ -1692,6 +1707,32 @@ return (instance); } return (NULL); +} + +static int +dup_lock_ok(struct lock_list_entry *lock_list) +{ + struct lock_instance *lock; + struct lock_object *lo; + struct witness_order_dup_list_entry *wdup; + int i, j; + + for (i = 0; i < sizeof dup_order_lists / sizeof *dup_order_lists; i++) { + lock = &lock_list->ll_children[lock_list->ll_count - 1]; + wdup = &dup_order_lists[i]; + lo = lock->li_lock; + if (strcmp(lo->lo_type, wdup->w_name_dup) == 0 && + lo->lo_class == wdup->w_class_dup) { + for (j = lock_list->ll_count - 1; j >= 0; j--) { + lo = lock_list->ll_children[j].li_lock; + if (strcmp(lo->lo_type, wdup->w_name_parent) == + 0 && lo->lo_class == wdup->w_class_parent) + return 1; + } + } + } + + return 0; } static void --T4sUOijqQbZv57TR--