Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/sys/compat/linux/common/Attic/linux_futex.c,v rcsdiff: /ftp/cvs/cvsroot/src/sys/compat/linux/common/Attic/linux_futex.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.27.2.2 retrieving revision 1.28 diff -u -p -r1.27.2.2 -r1.28 --- src/sys/compat/linux/common/Attic/linux_futex.c 2014/05/22 11:40:16 1.27.2.2 +++ src/sys/compat/linux/common/Attic/linux_futex.c 2011/11/18 04:07:44 1.28 @@ -1,4 +1,4 @@ -/* $NetBSD: linux_futex.c,v 1.27.2.2 2014/05/22 11:40:16 yamt Exp $ */ +/* $NetBSD: linux_futex.c,v 1.28 2011/11/18 04:07:44 christos Exp $ */ /*- * Copyright (c) 2005 Emmanuel Dreyfus, all rights reserved. @@ -32,7 +32,7 @@ */ #include -__KERNEL_RCSID(1, "$NetBSD: linux_futex.c,v 1.27.2.2 2014/05/22 11:40:16 yamt Exp $"); +__KERNEL_RCSID(1, "$NetBSD: linux_futex.c,v 1.28 2011/11/18 04:07:44 christos Exp $"); #include #include @@ -67,7 +67,6 @@ struct waiting_proc { struct futex { void *f_uaddr; int f_refcount; - uint32_t f_bitset; LIST_ENTRY(futex) f_list; TAILQ_HEAD(, waiting_proc) f_waiting_proc; TAILQ_HEAD(, waiting_proc) f_requeue_proc; @@ -106,7 +105,7 @@ linux_futex_fini(void) static struct waiting_proc *futex_wp_alloc(void); static void futex_wp_free(struct waiting_proc *); -static struct futex *futex_get(void *, uint32_t); +static struct futex *futex_get(void *); static void futex_ref(struct futex *); static void futex_put(struct futex *); static int futex_sleep(struct futex **, lwp_t *, int, struct waiting_proc *); @@ -128,7 +127,7 @@ linux_sys_futex(struct lwp *l, const str struct timespec ts = { 0, 0 }; int error; - if ((SCARG(uap, op) & LINUX_FUTEX_CMD_MASK) == LINUX_FUTEX_WAIT && + if ((SCARG(uap, op) & ~LINUX_FUTEX_PRIVATE_FLAG) == LINUX_FUTEX_WAIT && SCARG(uap, timeout) != NULL) { if ((error = copyin(SCARG(uap, timeout), <s, sizeof(lts))) != 0) { @@ -150,31 +149,15 @@ linux_do_futex(struct lwp *l, const stru syscallarg(int *) uaddr2; syscallarg(int) val3; } */ - int val, val3; + int val; int ret; int error = 0; struct futex *f; struct futex *newf; - int tout; + int timeout_hz; struct futex *f2; struct waiting_proc *wp; - int op_ret, cmd; - clockid_t clk; - - cmd = SCARG(uap, op) & LINUX_FUTEX_CMD_MASK; - val3 = SCARG(uap, val3); - - if (SCARG(uap, op) & LINUX_FUTEX_CLOCK_REALTIME) { - switch (cmd) { - case LINUX_FUTEX_WAIT_BITSET: - case LINUX_FUTEX_WAIT: - clk = CLOCK_REALTIME; - break; - default: - return ENOSYS; - } - } else - clk = CLOCK_MONOTONIC; + int op_ret; /* * Our implementation provides only private futexes. Most of the apps @@ -182,35 +165,11 @@ linux_do_futex(struct lwp *l, const stru * all futexes as private by clearing the FUTEX_PRIVATE_FLAG. It works * in most cases (ie. when futexes are not shared on file descriptor * or between different processes). - * - * Note that we don't handle bitsets at all at the moment. We need - * to move from refcounting uaddr's to handling multiple futex entries - * pointing to the same uaddr, but having possibly different bitmask. - * Perhaps move to an implementation where each uaddr has a list of - * futexes. */ - switch (cmd) { + switch (SCARG(uap, op) & ~LINUX_FUTEX_PRIVATE_FLAG) { case LINUX_FUTEX_WAIT: - val3 = FUTEX_BITSET_MATCH_ANY; - /*FALLTHROUGH*/ - case LINUX_FUTEX_WAIT_BITSET: - if ((error = ts2timo(clk, 0, ts, &tout, NULL)) != 0) { - if (error != ETIMEDOUT) - return error; - /* - * If the user process requests a non null timeout, - * make sure we do not turn it into an infinite - * timeout because tout is 0. - * - * We use a minimal timeout of 1/hz. Maybe it would make - * sense to just return ETIMEDOUT without sleeping. - */ - if (SCARG(uap, timeout) != NULL) - tout = 1; - else - tout = 0; - } FUTEX_SYSTEM_LOCK; + if ((error = copyin(SCARG(uap, uaddr), &val, sizeof(val))) != 0) { FUTEX_SYSTEM_UNLOCK; @@ -228,11 +187,27 @@ linux_do_futex(struct lwp *l, const stru SCARG(uap, uaddr), val, (long long)ts->tv_sec, ts->tv_nsec)); + if ((error = itimespecfix(ts)) != 0) { + FUTEX_SYSTEM_UNLOCK; + return error; + } + timeout_hz = tstohz(ts); + + /* + * If the user process requests a non null timeout, + * make sure we do not turn it into an infinite + * timeout because timeout_hz is 0. + * + * We use a minimal timeout of 1/hz. Maybe it would make + * sense to just return ETIMEDOUT without sleeping. + */ + if (SCARG(uap, timeout) != NULL && timeout_hz == 0) + timeout_hz = 1; wp = futex_wp_alloc(); FUTEX_LOCK; - f = futex_get(SCARG(uap, uaddr), val3); - ret = futex_sleep(&f, l, tout, wp); + f = futex_get(SCARG(uap, uaddr)); + ret = futex_sleep(&f, l, timeout_hz, wp); futex_put(f); FUTEX_UNLOCK; futex_wp_free(wp); @@ -263,9 +238,6 @@ linux_do_futex(struct lwp *l, const stru break; case LINUX_FUTEX_WAKE: - val = FUTEX_BITSET_MATCH_ANY; - /*FALLTHROUGH*/ - case LINUX_FUTEX_WAKE_BITSET: /* * XXX: Linux is able cope with different addresses * corresponding to the same mapped memory in the sleeping @@ -277,7 +249,7 @@ linux_do_futex(struct lwp *l, const stru FUTEX_SYSTEM_LOCK; FUTEX_LOCK; - f = futex_get(SCARG(uap, uaddr), val3); + f = futex_get(SCARG(uap, uaddr)); *retval = futex_wake(f, SCARG(uap, val), NULL, 0); futex_put(f); FUTEX_UNLOCK; @@ -294,7 +266,7 @@ linux_do_futex(struct lwp *l, const stru return error; } - if (val != val3) { + if (val != SCARG(uap, val3)) { FUTEX_SYSTEM_UNLOCK; return EAGAIN; } @@ -306,8 +278,8 @@ linux_do_futex(struct lwp *l, const stru (int)(unsigned long)SCARG(uap, timeout))); FUTEX_LOCK; - f = futex_get(SCARG(uap, uaddr), val3); - newf = futex_get(SCARG(uap, uaddr2), val3); + f = futex_get(SCARG(uap, uaddr)); + newf = futex_get(SCARG(uap, uaddr2)); *retval = futex_wake(f, SCARG(uap, val), newf, (int)(unsigned long)SCARG(uap, timeout)); futex_put(f); @@ -327,8 +299,8 @@ linux_do_futex(struct lwp *l, const stru (int)(unsigned long)SCARG(uap, timeout))); FUTEX_LOCK; - f = futex_get(SCARG(uap, uaddr), val3); - newf = futex_get(SCARG(uap, uaddr2), val3); + f = futex_get(SCARG(uap, uaddr)); + newf = futex_get(SCARG(uap, uaddr2)); *retval = futex_wake(f, SCARG(uap, val), newf, (int)(unsigned long)SCARG(uap, timeout)); futex_put(f); @@ -339,7 +311,8 @@ linux_do_futex(struct lwp *l, const stru break; case LINUX_FUTEX_FD: - FUTEXPRINTF(("%s: unimplemented op %d\n", __func__, cmd)); + FUTEXPRINTF(("linux_sys_futex: unimplemented op %d\n", + SCARG(uap, op))); return ENOSYS; case LINUX_FUTEX_WAKE_OP: FUTEX_SYSTEM_LOCK; @@ -347,20 +320,20 @@ linux_do_futex(struct lwp *l, const stru FUTEXPRINTF(("FUTEX_WAKE_OP %d.%d: uaddr = %p, op = %d, " "val = %d, uaddr2 = %p, val2 = %d\n", l->l_proc->p_pid, l->l_lid, - SCARG(uap, uaddr), cmd, SCARG(uap, val), + SCARG(uap, uaddr), SCARG(uap, op), SCARG(uap, val), SCARG(uap, uaddr2), (int)(unsigned long)SCARG(uap, timeout))); FUTEX_LOCK; - f = futex_get(SCARG(uap, uaddr), val3); - f2 = futex_get(SCARG(uap, uaddr2), val3); + f = futex_get(SCARG(uap, uaddr)); + f2 = futex_get(SCARG(uap, uaddr2)); FUTEX_UNLOCK; /* * This function returns positive number as results and * negative as errors */ - op_ret = futex_atomic_op(l, val3, SCARG(uap, uaddr2)); + op_ret = futex_atomic_op(l, SCARG(uap, val3), SCARG(uap, uaddr2)); FUTEX_LOCK; if (op_ret < 0) { futex_put(f); @@ -388,7 +361,8 @@ linux_do_futex(struct lwp *l, const stru *retval = ret; break; default: - FUTEXPRINTF(("%s: unknown op %d\n", __func__, cmd)); + FUTEXPRINTF(("linux_sys_futex: unknown op %d\n", + SCARG(uap, op))); return ENOSYS; } return 0; @@ -413,7 +387,7 @@ futex_wp_free(struct waiting_proc *wp) } static struct futex * -futex_get(void *uaddr, uint32_t bitset) +futex_get(void *uaddr) { struct futex *f; @@ -429,7 +403,6 @@ futex_get(void *uaddr, uint32_t bitset) /* Not found, create it */ f = kmem_zalloc(sizeof(*f), KM_SLEEP); f->f_uaddr = uaddr; - f->f_bitset = bitset; f->f_refcount = 1; TAILQ_INIT(&f->f_waiting_proc); TAILQ_INIT(&f->f_requeue_proc); @@ -510,8 +483,8 @@ futex_wake(struct futex *f, int n, struc TAILQ_FOREACH(wp, &f->f_waiting_proc, wp_list) { KASSERT(wp->wp_new_futex == NULL); - FUTEXPRINTF(("%s: signal f %p l %p ref %d\n", __func__, - f, wp->wp_l, f->f_refcount)); + FUTEXPRINTF(("futex_wake: signal f %p l %p ref %d\n", + f, wp->wp_l, f->f_refcount)); cv_signal(&wp->wp_futex_cv); if (count <= n) { count++; @@ -523,8 +496,8 @@ futex_wake(struct futex *f, int n, struc futex_ref(newf); wp->wp_new_futex = newf; TAILQ_INSERT_TAIL(&newf->f_requeue_proc, wp, wp_rqlist); - FUTEXPRINTF(("%s: requeue newf %p l %p ref %d\n", - __func__, newf, wp->wp_l, newf->f_refcount)); + FUTEXPRINTF(("futex_wake: requeue newf %p l %p ref %d\n", + newf, wp->wp_l, newf->f_refcount)); if (count - n >= n2) goto out; } @@ -542,8 +515,8 @@ futex_wake(struct futex *f, int n, struc TAILQ_FOREACH_SAFE(wp, &f->f_requeue_proc, wp_rqlist, wpnext) { KASSERT(wp->wp_new_futex == f); - FUTEXPRINTF(("%s: unrequeue f %p l %p ref %d\n", __func__, - f, wp->wp_l, f->f_refcount)); + FUTEXPRINTF(("futex_wake: unrequeue f %p l %p ref %d\n", + f, wp->wp_l, f->f_refcount)); wp->wp_new_futex = NULL; TAILQ_REMOVE(&f->f_requeue_proc, wp, wp_rqlist); futex_put(f); @@ -558,8 +531,8 @@ futex_wake(struct futex *f, int n, struc futex_ref(newf); wp->wp_new_futex = newf; TAILQ_INSERT_TAIL(&newf->f_requeue_proc, wp, wp_rqlist); - FUTEXPRINTF(("%s: rerequeue newf %p l %p ref %d\n", - __func__, newf, wp->wp_l, newf->f_refcount)); + FUTEXPRINTF(("futex_wake: rerequeue newf %p l %p ref %d\n", + newf, wp->wp_l, newf->f_refcount)); if (count - n >= n2) break; } @@ -610,7 +583,7 @@ futex_atomic_op(lwp_t *l, int encoded_op } error = ucas_int(uaddr, cval, nval, &oldval); - if (error || oldval == cval) { + if (oldval == cval || error) { break; } cval = oldval; @@ -728,7 +701,7 @@ retry: if (!pi && (uval & FUTEX_WAITERS)) { FUTEX_LOCK; - f = futex_get(uaddr, FUTEX_BITSET_MATCH_ANY); + f = futex_get(uaddr); futex_wake(f, 1, NULL, 0); FUTEX_UNLOCK; } @@ -741,8 +714,10 @@ static int fetch_robust_entry(struct lwp *l, struct linux_robust_list **entry, struct linux_robust_list **head, int *pi) { + struct linux_emuldata *led; unsigned long uentry; + led = l->l_emuldata; #ifdef __arch64__ if (l->l_proc->p_flag & PK_32) { uint32_t u32;