Date: Wed, 21 Feb 2007 11:13:37 GMT From: Roman Divacky <rdivacky@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 114791 for review Message-ID: <200702211113.l1LBDbCg005053@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=114791 Change 114791 by rdivacky@rdivacky_witten on 2007/02/21 11:12:41 o revert the previous change. linux wakes up N threads for all operations BUT requeue ones. mimic this by checking for newf being non-NULL and setting count accordingly. o introduce one more param to futex_wake which mimics the nr_requeue in linux thats wake up N+1 threads then requeue upto N2 on the new futex. note that the code doing the requeueing is likely to be rewritten (pending discussion with the original author). Affected files ... .. //depot/projects/linuxolator/src/sys/compat/linux/linux_futex.c#12 edit Differences ... ==== //depot/projects/linuxolator/src/sys/compat/linux/linux_futex.c#12 (text+ko) ==== @@ -88,7 +88,7 @@ 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 *); +static int futex_wake(struct futex *, int, struct futex *, int); static int futex_atomic_op(struct thread *td, int encoded_op, caddr_t uaddr); static int futex_orl(int oparg, caddr_t uaddr, int *oldval); static int futex_andl(int oparg, caddr_t uaddr, int *oldval); @@ -218,7 +218,7 @@ td->td_proc->p_pid, args->uaddr, args->val); #endif f = futex_get(args->uaddr, FUTEX_UNLOCKED); - td->td_retval[0] = futex_wake(f, args->val, NULL); + td->td_retval[0] = futex_wake(f, args->val, NULL, 0); futex_put(f); FUTEX_SYSTEM_UNLOCK; @@ -240,7 +240,7 @@ f = futex_get(args->uaddr, FUTEX_UNLOCKED); newf = futex_get(args->uaddr2, FUTEX_UNLOCKED); - td->td_retval[0] = futex_wake(f, args->val, newf); + td->td_retval[0] = futex_wake(f, args->val, newf, (int)(unsigned long)args->timeout); futex_put(f); futex_put(newf); @@ -252,7 +252,7 @@ f = futex_get(args->uaddr, FUTEX_UNLOCKED); newf = futex_get(args->uaddr2, FUTEX_UNLOCKED); - td->td_retval[0] = futex_wake(f, args->val, newf); + td->td_retval[0] = futex_wake(f, args->val, newf, (int)(unsigned long)args->timeout); futex_put(f); futex_put(newf); @@ -299,7 +299,7 @@ } - ret = futex_wake(f, args->val, NULL); + ret = futex_wake(f, args->val, NULL, 0); futex_put(f); if (op_ret > 0) { op_ret = 0; @@ -307,7 +307,7 @@ * Linux abuses the address of the timespec parameter * as the number of retries. */ - op_ret += futex_wake(f2, (int) (unsigned long) args->timeout, NULL); + op_ret += futex_wake(f2, (int) (unsigned long) args->timeout, NULL, 0); ret += op_ret; } futex_put(f2); @@ -406,14 +406,24 @@ } static int -futex_wake(struct futex *f, int n, struct futex *newf) +futex_wake(struct futex *f, int n, struct futex *newf, int n2) { struct waiting_proc *wp; - int count = 0; + int count; + + /* + * Linux is very strange it wakes up N threads for + * all operations BUT requeue ones where its N+1 + * mimic this. + */ + if (newf) + count = 0; + else + count = 1; FUTEX_LOCK; TAILQ_FOREACH(wp, &f->f_waiting_proc, wp_list) { - if (count < n) { + if (count <= n) { wakeup_one(wp); count++; } else { @@ -421,6 +431,8 @@ /* futex_put called after tsleep */ wp->wp_new_futex = futex_get(newf->f_uaddr, FUTEX_LOCKED); wakeup_one(wp); + if (count - n >= n2) + break; } } }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200702211113.l1LBDbCg005053>