PERFORCE change 103234 for review
Roman Divacky
rdivacky at FreeBSD.org
Sat Aug 5 09:09:24 UTC 2006
http://perforce.freebsd.org/chv.cgi?CH=103234
Change 103234 by rdivacky at 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);
}
}
More information about the p4-projects
mailing list