From owner-p4-projects@FreeBSD.ORG Mon Jul 31 15:22:35 2006 Return-Path: <owner-p4-projects@FreeBSD.ORG> X-Original-To: p4-projects@freebsd.org Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 0C9B016A4E5; Mon, 31 Jul 2006 15:22:35 +0000 (UTC) X-Original-To: perforce@FreeBSD.org Delivered-To: perforce@FreeBSD.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id C4D4A16A4DA for <perforce@FreeBSD.org>; Mon, 31 Jul 2006 15:22:34 +0000 (UTC) (envelope-from rdivacky@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id 7E81243D46 for <perforce@FreeBSD.org>; Mon, 31 Jul 2006 15:22:34 +0000 (GMT) (envelope-from rdivacky@FreeBSD.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.6/8.13.6) with ESMTP id k6VFMYCv034416 for <perforce@FreeBSD.org>; Mon, 31 Jul 2006 15:22:34 GMT (envelope-from rdivacky@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.6/8.13.4/Submit) id k6VFMYxY034413 for perforce@freebsd.org; Mon, 31 Jul 2006 15:22:34 GMT (envelope-from rdivacky@FreeBSD.org) Date: Mon, 31 Jul 2006 15:22:34 GMT Message-Id: <200607311522.k6VFMYxY034413@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to rdivacky@FreeBSD.org using -f From: Roman Divacky <rdivacky@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Cc: Subject: PERFORCE change 102853 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes <p4-projects.freebsd.org> List-Unsubscribe: <http://lists.freebsd.org/mailman/listinfo/p4-projects>, <mailto:p4-projects-request@freebsd.org?subject=unsubscribe> List-Archive: <http://lists.freebsd.org/pipermail/p4-projects> List-Post: <mailto:p4-projects@freebsd.org> List-Help: <mailto:p4-projects-request@freebsd.org?subject=help> List-Subscribe: <http://lists.freebsd.org/mailman/listinfo/p4-projects>, <mailto:p4-projects-request@freebsd.org?subject=subscribe> X-List-Received-Date: Mon, 31 Jul 2006 15:22:35 -0000 http://perforce.freebsd.org/chv.cgi?CH=102853 Change 102853 by rdivacky@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