From owner-p4-projects@FreeBSD.ORG Sat Aug 5 09:09:24 2006 Return-Path: X-Original-To: p4-projects@freebsd.org Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 6C06016A4E1; Sat, 5 Aug 2006 09:09:24 +0000 (UTC) X-Original-To: perforce@FreeBSD.org Delivered-To: perforce@FreeBSD.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 2FACA16A4DA for ; Sat, 5 Aug 2006 09:09:24 +0000 (UTC) (envelope-from rdivacky@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id DE68843D49 for ; Sat, 5 Aug 2006 09:09:23 +0000 (GMT) (envelope-from rdivacky@FreeBSD.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.6/8.13.6) with ESMTP id k7599NUK042531 for ; Sat, 5 Aug 2006 09:09:23 GMT (envelope-from rdivacky@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.6/8.13.4/Submit) id k7599NIR042528 for perforce@freebsd.org; Sat, 5 Aug 2006 09:09:23 GMT (envelope-from rdivacky@FreeBSD.org) Date: Sat, 5 Aug 2006 09:09:23 GMT Message-Id: <200608050909.k7599NIR042528@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to rdivacky@FreeBSD.org using -f From: Roman Divacky To: Perforce Change Reviews Cc: Subject: PERFORCE change 103234 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 05 Aug 2006 09:09:24 -0000 http://perforce.freebsd.org/chv.cgi?CH=103234 Change 103234 by rdivacky@rdivacky_witten on 2006/08/05 09:09:22 Fix the deadlock in futex_wake() which holds FUTEX_LOCK and calls futex_get() which wants to acquire FUTEX_LOCK as well. So I add flag which indicates wheter the lock should be acquired. I prefer this over a recursive mutex. Affected files ... .. //depot/projects/soc2006/rdivacky_linuxolator/compat/linux/linux_futex.c#17 edit Differences ... ==== //depot/projects/soc2006/rdivacky_linuxolator/compat/linux/linux_futex.c#17 (text+ko) ==== @@ -73,7 +73,10 @@ #define FUTEX_LOCK mtx_lock(&futex_mtx) #define FUTEX_UNLOCK mtx_unlock(&futex_mtx) -static struct futex *futex_get(void *); +#define FUTEX_LOCKED 1 +#define FUTEX_UNLOCKED 0 + +static struct futex *futex_get(void *, int); static void futex_put(struct futex *); static int futex_sleep(struct futex *, struct thread *, unsigned long); static int futex_wake(struct futex *, int, struct futex *); @@ -144,7 +147,7 @@ timeout_hz = 1; - f = futex_get(args->uaddr); + f = futex_get(args->uaddr, FUTEX_UNLOCKED); ret = futex_sleep(f, td, timeout_hz); futex_put(f); @@ -191,7 +194,7 @@ printf("FUTEX_WAKE %d: uaddr = %p, val = %d\n", td->td_proc->p_pid, args->uaddr, args->val); #endif - f = futex_get(args->uaddr); + f = futex_get(args->uaddr, FUTEX_UNLOCKED); td->td_retval[0] = futex_wake(f, args->val, NULL); futex_put(f); break; @@ -206,8 +209,8 @@ /* FALLTHROUGH */ case LINUX_FUTEX_REQUEUE: - f = futex_get(args->uaddr); - newf = futex_get(args->uaddr2); + f = futex_get(args->uaddr, FUTEX_UNLOCKED); + newf = futex_get(args->uaddr2, FUTEX_UNLOCKED); td->td_retval[0] = futex_wake(f, args->val, newf); futex_put(f); futex_put(newf); @@ -225,8 +228,8 @@ printf("FUTEX_WAKE_OP: %d: uaddr = %p, op = %d, val = %d, uaddr2 = %p, val3 = %d\n", td->td_proc->p_pid, args->uaddr, args->op, args->val, args->uaddr2, args->val3); #endif - f = futex_get(args->uaddr); - f2 = futex_get(args->uaddr2); + f = futex_get(args->uaddr, FUTEX_UNLOCKED); + f2 = futex_get(args->uaddr2, FUTEX_UNLOCKED); op_ret = futex_atomic_op(td, args->val3, args->uaddr2); if (op_ret < 0) { @@ -267,28 +270,33 @@ } static struct futex * -futex_get(void *uaddr) +futex_get(void *uaddr, int locked) { struct futex *f; - FUTEX_LOCK; + if (locked == FUTEX_UNLOCKED) + FUTEX_LOCK; LIST_FOREACH(f, &futex_list, f_list) { if (f->f_uaddr == uaddr) { f->f_refcount++; - FUTEX_UNLOCK; + if (locked == FUTEX_UNLOCKED) + FUTEX_UNLOCK; return f; } } - FUTEX_UNLOCK; + if (locked == FUTEX_UNLOCKED) + FUTEX_UNLOCK; /* Not found, create it */ f = malloc(sizeof(*f), M_LINUX, M_WAITOK); f->f_uaddr = uaddr; f->f_refcount = 1; TAILQ_INIT(&f->f_waiting_proc); - FUTEX_LOCK; + if (locked == FUTEX_UNLOCKED) + FUTEX_LOCK; LIST_INSERT_HEAD(&futex_list, f, f_list); - FUTEX_UNLOCK; + if (locked == FUTEX_UNLOCKED) + FUTEX_UNLOCK; return f; } @@ -356,7 +364,7 @@ } else { if (newf != NULL) { /* futex_put called after tsleep */ - wp->wp_new_futex = futex_get(newf->f_uaddr); + wp->wp_new_futex = futex_get(newf->f_uaddr, FUTEX_LOCKED); wakeup(wp); } }