PERFORCE change 114791 for review
Roman Divacky
rdivacky at FreeBSD.org
Wed Feb 21 11:13:38 UTC 2007
http://perforce.freebsd.org/chv.cgi?CH=114791
Change 114791 by rdivacky at 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;
}
}
}
More information about the p4-projects
mailing list