Date: Sat, 5 Aug 2006 09:09:23 GMT From: Roman Divacky <rdivacky@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 103234 for review Message-ID: <200608050909.k7599NIR042528@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
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); } }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200608050909.k7599NIR042528>