PERFORCE change 102853 for review
Roman Divacky
rdivacky at FreeBSD.org
Mon Jul 31 15:22:35 UTC 2006
http://perforce.freebsd.org/chv.cgi?CH=102853
Change 102853 by rdivacky at rdivacky_witten on 2006/07/31 15:22:00
Implement FUTEX_WAKE_OP. This should be correct but doesnt seem to let realplay work.
Affected files ...
.. //depot/projects/soc2006/rdivacky_linuxolator/compat/linux/linux_futex.c#11 edit
.. //depot/projects/soc2006/rdivacky_linuxolator/compat/linux/linux_futex.h#5 edit
.. //depot/projects/soc2006/rdivacky_linuxolator/i386/i386/support.s#2 edit
Differences ...
==== //depot/projects/soc2006/rdivacky_linuxolator/compat/linux/linux_futex.c#11 (text+ko) ====
@@ -77,6 +77,14 @@
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_atomic_op(struct thread *td, int encoded_op, caddr_t uaddr);
+
+/* support.s */
+int futex_xchgl(int oparg, caddr_t uaddr, int *oldval);
+int futex_addl(int oparg, caddr_t uaddr, int *oldval);
+int futex_orl(int oparg, caddr_t uaddr, int *oldval);
+int futex_andnl(int oparg, caddr_t uaddr, int *oldval);
+int futex_xorl(int oparg, caddr_t uaddr, int *oldval);
int
linux_sys_futex(struct thread *td, struct linux_sys_futex_args *args)
@@ -85,10 +93,11 @@
int ret;
struct timespec timeout = { 0, 0 };
int error = 0;
- struct futex *f;
+ struct futex *f, *f2;
struct futex *newf;
int timeout_hz;
struct timeval tv = {0, 0};
+ int op_ret;
#ifdef DEBUG
if (ldebug(sys_futex))
@@ -209,11 +218,46 @@
printf("linux_sys_futex: unimplemented op %d\n",
args->op);
break;
+
case LINUX_FUTEX_WAKE_OP:
- /* XXX: it seems necessary for realplay */
- printf("linux_sys_futex: unimplemented op %d\n",
- args->op);
+#ifdef DEBUG
+ if (ldebug(sys_futex))
+ 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);
+
+ op_ret = futex_atomic_op(td, args->val3, args->uaddr2);
+ if (op_ret < 0) {
+
+ /* XXX: ? */
+ if (op_ret != -EFAULT) {
+ futex_put(f);
+ futex_put(f2);
+ return (-op_ret);
+ }
+
+ futex_put(f);
+ futex_put(f2);
+
+ return (EFAULT);
+
+ }
+
+ ret = futex_wake(f, args->val, NULL);
+ futex_put(f);
+ if (op_ret > 0) {
+ printf("second wakeup\n");
+ op_ret = 0;
+ /* Linux always puts there 0 retries */
+ op_ret += futex_wake(f2, 0, NULL);
+ futex_put(f2);
+ ret += op_ret;
+ }
+ td->td_retval[0] = ret;
break;
+
default:
printf("linux_sys_futex: unknown op %d\n",
args->op);
@@ -321,3 +365,71 @@
return count;
}
+
+static int
+futex_atomic_op(struct thread *td, int encoded_op, caddr_t uaddr)
+{
+ int op = (encoded_op >> 28) & 7;
+ int cmp = (encoded_op >> 24) & 15;
+ int oparg = (encoded_op << 8) >> 20;
+ int cmparg = (encoded_op << 20) >> 20;
+ int oldval = 0, ret;
+
+ if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+ oparg = 1 << oparg;
+
+#ifdef DEBUG
+ printf("futex_atomic_op: op = %d, cmp = %d, oparg = %d, cmparg = %d\n",
+ op, cmp, oparg, cmparg);
+#endif
+ /* XXX: linux verifies access here and returns EFAULT */
+
+ critical_enter();
+
+ switch (op) {
+ case FUTEX_OP_SET:
+ ret = futex_xchgl(oparg, uaddr, &oldval);
+ break;
+ case FUTEX_OP_ADD:
+ ret = futex_addl(oparg, uaddr, &oldval);
+ break;
+ case FUTEX_OP_OR:
+ ret = futex_orl(oparg, uaddr, &oldval);
+ break;
+ case FUTEX_OP_ANDN:
+ ret = futex_andnl(oparg, uaddr, &oldval);
+ break;
+ case FUTEX_OP_XOR:
+ ret = futex_xorl(oparg, uaddr, &oldval);
+ break;
+ default:
+ ret = -ENOSYS;
+ }
+
+ critical_exit();
+
+ if (!ret)
+ switch (cmp) {
+ case FUTEX_OP_CMP_EQ:
+ ret = (oldval == cmparg);
+ break;
+ case FUTEX_OP_CMP_NE:
+ ret = (oldval != cmparg);
+ break;
+ case FUTEX_OP_CMP_LT:
+ ret = (oldval < cmparg);
+ break;
+ case FUTEX_OP_CMP_GE:
+ ret = (oldval >= cmparg);
+ break;
+ case FUTEX_OP_CMP_LE:
+ ret = (oldval <= cmparg);
+ break;
+ case FUTEX_OP_CMP_GT:
+ ret = (oldval > cmparg);
+ break;
+ default: ret = -ENOSYS;
+ }
+
+ return (ret);
+}
==== //depot/projects/soc2006/rdivacky_linuxolator/compat/linux/linux_futex.h#5 (text+ko) ====
@@ -47,4 +47,13 @@
#define FUTEX_OP_ANDN 3 /* *(int *)UADDR2 &= ~OPARG; */
#define FUTEX_OP_XOR 4 /* *(int *)UADDR2 ^= OPARG; */
+#define FUTEX_OP_OPARG_SHIFT 8 /* Use (1 << OPARG) instead of OPARG. */
+
+#define FUTEX_OP_CMP_EQ 0 /* if (oldval == CMPARG) wake */
+#define FUTEX_OP_CMP_NE 1 /* if (oldval != CMPARG) wake */
+#define FUTEX_OP_CMP_LT 2 /* if (oldval < CMPARG) wake */
+#define FUTEX_OP_CMP_LE 3 /* if (oldval <= CMPARG) wake */
+#define FUTEX_OP_CMP_GT 4 /* if (oldval > CMPARG) wake */
+#define FUTEX_OP_CMP_GE 5 /* if (oldval >= CMPARG) wake */
+
#endif /* !_LINUX_FUTEX_H */
==== //depot/projects/soc2006/rdivacky_linuxolator/i386/i386/support.s#2 (text+ko) ====
@@ -1522,6 +1522,12 @@
bbhead:
.long 0
+#if defined(SMP) || !defined(_KERNEL)
+#define MPLOCKED lock ;
+#else
+#define MPLOCKED
+#endif
+
.text
NON_GPROF_ENTRY(__bb_init_func)
movl 4(%esp),%eax
@@ -1530,3 +1536,98 @@
movl %edx,16(%eax)
movl %eax,bbhead
NON_GPROF_RET
+
+/* necessary for linux_futex support */
+ .text
+
+futex_fault:
+ movl PCPU(CURPCB), %edx
+ movl $0, PCB_ONFAULT(%edx)
+ movl $-EFAULT, %eax
+ ret
+
+/* int futex_xchgl(int oparg, caddr_t uaddr, int *oldval); */
+ .globl futex_xchgl
+futex_xchgl:
+ movl PCPU(CURPCB), %eax
+ movl $futex_fault, PCB_ONFAULT(%eax)
+ movl 4(%esp), %eax
+ movl 8(%esp), %edx
+
+ xchgl %eax, (%edx)
+ movl 0xc(%esp), %edx
+ movl %eax, (%edx)
+ xorl %eax, %eax
+
+ movl PCPU(CURPCB), %edx
+ movl $0, PCB_ONFAULT(%edx)
+ ret
+
+/* int futex_addl(int oparg, caddr_t uaddr, int *oldval); */
+ .globl futex_addl
+futex_addl:
+ movl PCPU(CURPCB), %eax
+ movl $futex_fault, PCB_ONFAULT(%eax)
+ movl 4(%esp), %eax
+ movl 8(%esp), %edx
+
+ MPLOCKED xaddl %eax, (%edx)
+ movl 0xc(%esp), %edx
+ movl %eax, (%edx)
+ xorl %eax, %eax
+
+ movl PCPU(CURPCB), %edx
+ movl $0, PCB_ONFAULT(%edx)
+ ret
+
+/* int futex_orl(int oparg, caddr_t uaddr, int *oldval); */
+ .globl futex_orl
+futex_orl:
+ movl PCPU(CURPCB), %eax
+ movl $futex_fault, PCB_ONFAULT(%eax)
+ movl 4(%esp), %eax
+ movl 8(%esp), %edx
+
+ orl %eax, (%edx)
+ movl 0xc(%esp), %edx
+ movl %eax, (%edx)
+ xorl %eax, %eax
+
+ movl PCPU(CURPCB), %edx
+ movl $0, PCB_ONFAULT(%edx)
+ ret
+
+/* int futex_andnl(int oparg, caddr_t uaddr, int *oldval); */
+ .globl futex_andnl
+futex_andnl:
+ movl PCPU(CURPCB), %eax
+ movl $futex_fault, PCB_ONFAULT(%eax)
+ movl 4(%esp), %eax
+ movl 8(%esp), %edx
+
+ notl (%edx)
+ andl %eax, (%edx)
+ movl 0xc(%esp), %edx
+ movl %eax, (%edx)
+ xorl %eax, %eax
+
+ movl PCPU(CURPCB), %edx
+ movl $0, PCB_ONFAULT(%edx)
+ ret
+
+/* int futex_xorl(int oparg, caddr_t uaddr, int *oldval); */
+ .globl futex_xorl
+futex_xorl:
+ movl PCPU(CURPCB), %eax
+ movl $futex_fault, PCB_ONFAULT(%eax)
+ movl 4(%esp), %eax
+ movl 8(%esp), %edx
+
+ xorl %eax, (%edx)
+ movl 0xc(%esp), %edx
+ movl %eax, (%edx)
+ xorl %eax, %eax
+
+ movl PCPU(CURPCB), %edx
+ movl $0, PCB_ONFAULT(%edx)
+ ret
More information about the p4-projects
mailing list