linux emu - MPSAFE work
authorAlex Hornung <ahornung@gmail.com>
Sat, 3 Jul 2010 17:40:10 +0000 (18:40 +0100)
committerAlex Hornung <ahornung@gmail.com>
Sat, 3 Jul 2010 17:43:06 +0000 (18:43 +0100)
* Reduce the uses of the mplock to a bare minimum, such as when calling
  exit1.

* Change the emuldata lock to lockmgr; it shouldn't have been mplock in
  the first place.

* Reduce the scope locked by the emuldata lock as much as possible.

sys/emulation/linux/Makefile
sys/emulation/linux/i386/linux_machdep.c
sys/emulation/linux/linux_emuldata.c
sys/emulation/linux/linux_emuldata.h
sys/emulation/linux/linux_futex.c
sys/emulation/linux/linux_misc.c
sys/emulation/linux/linux_signal.c

index 7a8974b..7b4ebad 100644 (file)
@@ -12,6 +12,7 @@ SRCS= linux_dummy.c linux_emuldata.c linux_epoll.c \
        linux_socket.c \
        linux_stats.c linux_sysctl.c linux_sysent.c linux_sysvec.c \
        linux_util.c opt_compat.h opt_global.h opt_vmpage.h
+SRCS+= opt_nfs.h assym.s
 OBJS=  linux_support.o linux_locore.o
 
 SUBDIR= i386/linprocfs
@@ -22,6 +23,7 @@ SRCS+=        linux_ptrace.c linux_uid16.c imgact_linux.c opt_cpu.h
 CLEANFILES=    linux_assym.h linux_genassym.o
 
 linux_assym.h: linux_genassym.o
+
 .if exists(@)
 linux_assym.h: @/kern/genassym.sh
 .endif
@@ -31,7 +33,7 @@ linux_locore.o: linux_locore.s linux_assym.h
        ${CC} -c -x assembler-with-cpp -DLOCORE ${CFLAGS} \
            ${.IMPSRC} -o ${.TARGET}
 
-linux_support.o: linux_support.s linux_assym.h
+linux_support.o: linux_support.s linux_assym.h assym.s
        ${CC} -c -x assembler-with-cpp -DLOCORE ${CFLAGS} \
            ${.IMPSRC} -o ${.TARGET}
 
index d8d3ecb..dad054f 100644 (file)
@@ -398,19 +398,15 @@ sys_linux_exit_group(struct linux_exit_group_args *args)
        int rval;
 
        rval = args->rval;
-
-       get_mplock();
-
        EMUL_LOCK();
 
        em = emuldata_get(curproc);
 
        if (em->s->refs == 1) {
+               EMUL_UNLOCK();
+               get_mplock();
                exit1(W_EXITCODE(rval, 0));
                /* notreached */
-
-               EMUL_UNLOCK();
-
                rel_mplock();
                return (0);
        }
@@ -421,7 +417,7 @@ sys_linux_exit_group(struct linux_exit_group_args *args)
 
        LIST_REMOVE(em, threads);
        LIST_INSERT_HEAD(&em->s->threads, em, threads);
-       
+
        while ((e = LIST_NEXT(em, threads)) != NULL) {
                LIST_REMOVE(em, threads);
                LIST_INSERT_AFTER(e, em, threads);
@@ -432,9 +428,8 @@ sys_linux_exit_group(struct linux_exit_group_args *args)
                }
        }
 
-
        EMUL_UNLOCK();
-
+       get_mplock();
        exit1(W_EXITCODE(rval, 0));
        rel_mplock();
        /* notreached */
index 56f57b8..7daf8f5 100644 (file)
@@ -191,6 +191,9 @@ emuldata_exit(void *unused, struct proc *p)
                return;
        }
 
+       LIST_REMOVE(em, threads);
+       p->p_emuldata = NULL;
+
        /*
         * Members of the thread groups others than the leader should
         * exit quietely: no zombie stage, no signal. We do that by
@@ -205,6 +208,20 @@ emuldata_exit(void *unused, struct proc *p)
                proc_reparent(p, initproc); /* XXX: might be dangerous */
        }
 
+       if ((em->s->group_pid == p->p_pid) &&
+           (em->s->flags & LINUX_LES_INEXITGROUP)) {
+               p->p_xstat = em->s->xstat;
+       }
+
+       if (atomic_fetchadd_int(&em->s->refs, -1) == 1) {
+               kfree(em->s, M_LINUX);
+               em->s = NULL;
+       }
+       if (em->s)
+               KKASSERT(em->s->refs >= 0);
+
+       EMUL_UNLOCK();
+
        if (em->clear_tid != NULL) {
                int tid = 0;
                copyout(&tid, em->clear_tid, sizeof(tid));
@@ -219,23 +236,6 @@ emuldata_exit(void *unused, struct proc *p)
                        kprintf("emuldata_exit futex stuff failed miserably\n");
        }
 
-       LIST_REMOVE(em, threads);
-
-       p->p_emuldata = NULL;
-
-       if ((em->s->group_pid == p->p_pid) &&
-           (em->s->flags & LINUX_LES_INEXITGROUP)) {
-               p->p_xstat = em->s->xstat;
-       }
-
-       if (atomic_fetchadd_int(&em->s->refs, -1) == 1) {
-               kfree(em->s, M_LINUX);
-               em->s = NULL;
-       }
-       if (em->s)
-               KKASSERT(em->s->refs >= 0);
-
-       EMUL_UNLOCK();
        kfree(em, M_LINUX);
 }
 
index e976114..b2978ba 100644 (file)
 #include <sys/lock.h>
 #endif
 
-#ifndef _SYS_MPLOCK2_H
-#include <sys/mplock2.h>
-#endif
-
 #ifndef _COMMON_LINUX_EMULDATA_H
 #define _COMMON_LINUX_EMULDATA_H
 
@@ -91,13 +87,8 @@ struct linux_emuldata {
 #define        EMUL_LOCKINIT(x)        lockinit(&emul_lock, "tux_emul", 0, LK_CANRECURSE)
 #define        EMUL_LOCKUNINIT(x)      lockuninit(&emul_lock)
 
-#if 0
 #define EMUL_LOCK(x)   lockmgr(&emul_lock, LK_EXCLUSIVE)
 #define        EMUL_UNLOCK(x)  lockmgr(&emul_lock, LK_RELEASE)
-#endif
-
-#define EMUL_LOCK(x)   get_mplock()
-#define        EMUL_UNLOCK(x)  rel_mplock()
 
 extern struct lock emul_lock;
 
index c4cf129..0f3db5c 100644 (file)
@@ -708,8 +708,9 @@ sys_linux_get_robust_list(struct linux_get_robust_list_args *args)
        if (ldebug(get_robust_list))
                kprintf(ARGS(get_robust_list, ""));
 #endif
-       EMUL_LOCK();
+
        if (args->pid == 0) {
+               EMUL_LOCK();
                em = emuldata_get(curproc);
                KKASSERT(em != NULL);
                if (em->robust_futexes == NULL) {
@@ -718,27 +719,28 @@ sys_linux_get_robust_list(struct linux_get_robust_list_args *args)
                } else {
                        head = em->robust_futexes;
                }
+               EMUL_UNLOCK();
        } else {
                struct proc *p;
 
                p = pfind(args->pid);
                if (p == NULL) {
-                       EMUL_UNLOCK();
                        return (ESRCH);
                }
 
+               EMUL_LOCK();
                em = emuldata_get(p);
+               head = em->robust_futexes;
+               EMUL_UNLOCK();
                /* XXX: ptrace? p_candebug?*/
                if (priv_check(curthread, PRIV_CRED_SETUID) ||
                    priv_check(curthread, PRIV_CRED_SETEUID)/* ||
                    p_candebug(curproc, p) */) {
-                       EMUL_UNLOCK();
                        return (EPERM);
                }
-               head = em->robust_futexes;
+               
 
        }
-       EMUL_UNLOCK();
 
        error = copyout(&len, args->len, sizeof(l_size_t));
        if (error)
index ab480fa..cb032fb 100644 (file)
@@ -1660,7 +1660,7 @@ sys_linux_getpid(struct linux_getpid_args *args)
        struct linux_emuldata *em;
        struct proc *p = curproc;
 
-       get_mplock();
+
        EMUL_LOCK();
        em = emuldata_get(p);
        if (em == NULL) /* this should never happen */
@@ -1668,7 +1668,7 @@ sys_linux_getpid(struct linux_getpid_args *args)
        else
                args->sysmsg_result = em->s->group_pid;
        EMUL_UNLOCK();
-       rel_mplock();
+
        return (0);
 }
 
@@ -1681,27 +1681,30 @@ sys_linux_getppid(struct linux_getppid_args *args)
        struct linux_emuldata *em;
        struct proc *parent;
        struct proc *p;
+       pid_t group_pid;
 
-       get_mplock();
        EMUL_LOCK();
        em = emuldata_get(curproc);
        KKASSERT(em != NULL);
+       group_pid = em->s->group_pid;
+       EMUL_UNLOCK();
 
-       p = pfind(em->s->group_pid);
+       p = pfind(group_pid);
        /* We are not allowed to fail */
        if (p == NULL)
                goto out;
 
        parent = p->p_pptr;
        if (parent->p_sysent == &elf_linux_sysvec) {
+               EMUL_LOCK();
                em = emuldata_get(parent);
                args->sysmsg_result = em->s->group_pid;
+               EMUL_UNLOCK();
        } else {
                args->sysmsg_result = parent->p_pid;
        }
+
 out:
-       EMUL_UNLOCK();
-       rel_mplock();
        return (0);
 }
 
index d1e14b7..f7a1ff6 100644 (file)
@@ -423,7 +423,6 @@ linux_do_tkill(l_int tgid, l_int pid, l_int sig)
        if (sig > 0 && sig <= LINUX_SIGTBLSZ)
                sig = linux_to_bsd_signal[_SIG_IDX(sig)];
 
-       get_mplock();
        lwkt_gettoken(&proc_token);
        if ((p = pfind(pid)) == NULL) {
                if ((p = zpfind(pid)) == NULL) {
@@ -448,13 +447,15 @@ linux_do_tkill(l_int tgid, l_int pid, l_int sig)
                goto done1;
        }
        EMUL_UNLOCK();
-       
+
+       get_mplock();
        error = kern_kill(sig, pid, -1);
+       rel_mplock();
+
 done1:
        PRELE(p);
 done2:
        lwkt_reltoken(&proc_token);
-       rel_mplock();
 
        return (error);
 }