Date: Mon, 31 Jan 2011 05:59:05 +0000 (UTC) From: Dmitry Chagin <dchagin@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r218117 - head/sys/compat/linux Message-ID: <201101310559.p0V5x5kt009269@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: dchagin Date: Mon Jan 31 05:59:05 2011 New Revision: 218117 URL: http://svn.freebsd.org/changeset/base/218117 Log: Implement a futex BITSET op. Submitted by: arundel MFC after: 1 month. Modified: head/sys/compat/linux/linux_futex.c head/sys/compat/linux/linux_futex.h Modified: head/sys/compat/linux/linux_futex.c ============================================================================== --- head/sys/compat/linux/linux_futex.c Mon Jan 31 00:29:11 2011 (r218116) +++ head/sys/compat/linux/linux_futex.c Mon Jan 31 05:59:05 2011 (r218117) @@ -79,6 +79,7 @@ struct futex { struct sx f_lck; uint32_t *f_uaddr; uint32_t f_refcount; + uint32_t f_bitset; LIST_ENTRY(futex) f_list; TAILQ_HEAD(lf_waiting_proc, waiting_proc) f_waiting_proc; }; @@ -264,15 +265,25 @@ futex_sleep(struct futex *f, struct wait } static int -futex_wake(struct futex *f, int n) +futex_wake(struct futex *f, int n, uint32_t bitset) { struct waiting_proc *wp, *wpt; int count = 0; + if (bitset == 0) + return (EINVAL); + FUTEX_ASSERT_LOCKED(f); TAILQ_FOREACH_SAFE(wp, &f->f_waiting_proc, wp_list, wpt) { LINUX_CTR3(sys_futex, "futex_wake uaddr %p wp %p ref %d", f->f_uaddr, wp, f->f_refcount); + /* + * Unless we find a matching bit in + * the bitset, continue searching. + */ + if (!(wp->wp_futex->f_bitset & bitset)) + continue; + wp->wp_flags |= FUTEX_WP_REMOVED; TAILQ_REMOVE(&f->f_waiting_proc, wp, wp_list); wakeup_one(wp); @@ -325,13 +336,18 @@ futex_requeue(struct futex *f, int n, st } static int -futex_wait(struct futex *f, struct waiting_proc *wp, struct l_timespec *ts) +futex_wait(struct futex *f, struct waiting_proc *wp, struct l_timespec *ts, + uint32_t bitset) { struct l_timespec timeout; struct timeval tv; int timeout_hz; int error; + if (bitset == 0) + return (EINVAL); + f->f_bitset = bitset; + if (ts != NULL) { error = copyin(ts, &timeout, sizeof(timeout)); if (error) @@ -445,13 +461,18 @@ linux_sys_futex(struct thread *td, struc switch (args->op) { case LINUX_FUTEX_WAIT: + args->val3 = FUTEX_BITSET_MATCH_ANY; + /* FALLTHROUGH */ + + case LINUX_FUTEX_WAIT_BITSET: - LINUX_CTR2(sys_futex, "WAIT val %d uaddr %p", - args->val, args->uaddr); + LINUX_CTR3(sys_futex, "WAIT uaddr %p val %d val3 %d", + args->uaddr, args->val, args->val3); #ifdef DEBUG if (ldebug(sys_futex)) - printf(ARGS(sys_futex, "futex_wait val %d uaddr %p"), - args->val, args->uaddr); + printf(ARGS(sys_futex, + "futex_wait uaddr %p val %d val3 %d"), + args->uaddr, args->val, args->val3); #endif error = futex_get(args->uaddr, &wp, &f, FUTEX_CREATE_WP); if (error) @@ -464,19 +485,24 @@ linux_sys_futex(struct thread *td, struc return (error); } if (val != args->val) { - LINUX_CTR3(sys_futex, "WAIT uaddr %p val %d != uval %d", - args->uaddr, args->val, val); + LINUX_CTR4(sys_futex, + "WAIT uaddr %p val %d != uval %d val3 %d", + args->uaddr, args->val, val, args->val3); futex_put(f, wp); return (EWOULDBLOCK); } - error = futex_wait(f, wp, args->timeout); + error = futex_wait(f, wp, args->timeout, args->val3); break; case LINUX_FUTEX_WAKE: + args->val3 = FUTEX_BITSET_MATCH_ANY; + /* FALLTHROUGH */ + + case LINUX_FUTEX_WAKE_BITSET: - LINUX_CTR2(sys_futex, "WAKE val %d uaddr %p", - args->val, args->uaddr); + LINUX_CTR3(sys_futex, "WAKE uaddr %p val % d val3 %d", + args->uaddr, args->val, args->val3); /* * XXX: Linux is able to cope with different addresses @@ -485,8 +511,8 @@ linux_sys_futex(struct thread *td, struc */ #ifdef DEBUG if (ldebug(sys_futex)) - printf(ARGS(sys_futex, "futex_wake val %d uaddr %p"), - args->val, args->uaddr); + printf(ARGS(sys_futex, "futex_wake uaddr %p val %d val3 %d"), + args->uaddr, args->val, args->val3); #endif error = futex_get(args->uaddr, NULL, &f, FUTEX_DONTCREATE); if (error) @@ -495,7 +521,7 @@ linux_sys_futex(struct thread *td, struc td->td_retval[0] = 0; return (error); } - td->td_retval[0] = futex_wake(f, args->val); + td->td_retval[0] = futex_wake(f, args->val, args->val3); futex_put(f, NULL); break; @@ -603,16 +629,16 @@ linux_sys_futex(struct thread *td, struc return (EFAULT); } - ret = futex_wake(f, args->val); + ret = futex_wake(f, args->val, args->val3); if (op_ret > 0) { op_ret = 0; nrwake = (int)(unsigned long)args->timeout; if (f2 != NULL) - op_ret += futex_wake(f2, nrwake); + op_ret += futex_wake(f2, nrwake, args->val3); else - op_ret += futex_wake(f, nrwake); + op_ret += futex_wake(f, nrwake, args->val3); ret += op_ret; } @@ -660,13 +686,6 @@ linux_sys_futex(struct thread *td, struc } return (EINVAL); - case LINUX_FUTEX_WAIT_BITSET: - /* not yet implemented */ - linux_msg(td, - "linux_sys_futex: " - "op FUTEX_WAIT_BITSET not implemented\n"); - return (ENOSYS); - case LINUX_FUTEX_WAIT_REQUEUE_PI: /* not yet implemented */ linux_msg(td, @@ -775,7 +794,7 @@ retry: if (error) return (error); if (f != NULL) { - futex_wake(f, 1); + futex_wake(f, 1, FUTEX_BITSET_MATCH_ANY); futex_put(f, NULL); } } Modified: head/sys/compat/linux/linux_futex.h ============================================================================== --- head/sys/compat/linux/linux_futex.h Mon Jan 31 00:29:11 2011 (r218116) +++ head/sys/compat/linux/linux_futex.h Mon Jan 31 05:59:05 2011 (r218117) @@ -49,6 +49,7 @@ extern struct mtx futex_mtx; #define LINUX_FUTEX_UNLOCK_PI 7 #define LINUX_FUTEX_TRYLOCK_PI 8 #define LINUX_FUTEX_WAIT_BITSET 9 +#define LINUX_FUTEX_WAKE_BITSET 10 #define LINUX_FUTEX_WAIT_REQUEUE_PI 11 #define LINUX_FUTEX_PRIVATE_FLAG 128 @@ -72,6 +73,7 @@ extern struct mtx futex_mtx; #define FUTEX_WAITERS 0x80000000 #define FUTEX_OWNER_DIED 0x40000000 #define FUTEX_TID_MASK 0x3fffffff +#define FUTEX_BITSET_MATCH_ANY 0xffffffff void release_futexes(struct proc *);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201101310559.p0V5x5kt009269>