cvs commit: src/sys/kern syscalls.master

John Baldwin jhb at FreeBSD.org
Fri Nov 14 08:29:45 PST 2003


On 14-Nov-2003 Jeff Roberson wrote:
> jeff        2003/11/13 19:48:37 PST
> 
>   FreeBSD src repository
> 
>   Modified files:
>     sys/kern             syscalls.master 
>   Log:
>    - Revision 1.156 marked ptrace() SMP safe.  Unfortunately, alpha implements
>      parts of ptrace using proc_rwmem().  proc_rwmem() requires giant, and
>      giant must be acquired prior to the proc lock, so ptrace must require giant
>      still.

        case PT_READ_I:
        case PT_READ_D:
                PROC_UNLOCK(p);
                tmp = 0;
                /* write = 0 set above */
                iov.iov_base = write ? (caddr_t)&data : (caddr_t)&tmp;
                iov.iov_len = sizeof(int);
                uio.uio_iov = &iov;
                uio.uio_iovcnt = 1;
                uio.uio_offset = (off_t)(uintptr_t)addr;
                uio.uio_resid = sizeof(int);
                uio.uio_segflg = UIO_SYSSPACE;  /* i.e.: the uap */
                uio.uio_rw = write ? UIO_WRITE : UIO_READ;
                uio.uio_td = td;
                mtx_lock(&Giant);
                error = proc_rwmem(p, &uio);
                mtx_unlock(&Giant);
                if (uio.uio_resid != 0) {
                        /*
                         * XXX proc_rwmem() doesn't currently return ENOSPC,
                         * so I think write() can bogusly return 0.
                         * XXX what happens for short writes?  We don't want
                         * to write partial data.
                         * XXX proc_rwmem() returns EPERM for other invalid
                         * addresses.  Convert this to EINVAL.  Does this
                         * clobber returns of EPERM for other reasons?
                         */
                        if (error == 0 || error == ENOSPC || error == EPERM)
                                error = EINVAL; /* EOF */
                }
                if (!write)
                        td->td_retval[0] = tmp;
                return (error);


Are there other parts on Alpha that use proc_rwmem()?  Ah.  It should be
fine to drop the proc lock in some places then I think.  For example,
around ptrace_single_step().  Something like:

Index: sys_process.c
===================================================================
RCS file: /usr/cvs/src/sys/kern/sys_process.c,v
retrieving revision 1.115
diff -u -r1.115 sys_process.c
--- sys_process.c       9 Oct 2003 10:17:16 -0000       1.115
+++ sys_process.c       14 Nov 2003 15:47:46 -0000
@@ -522,11 +522,13 @@
 
                switch (req) {
                case PT_STEP:
+                       PROC_UNLOCK(p);
                        error = ptrace_single_step(td2);
                        if (error) {
-                               _PRELE(p);
-                               goto fail;
+                               PRELE(p);
+                               goto fail_noproc;
                        }
+                       PROC_LOCK(p);
                        break;
                case PT_TO_SCE:
                        p->p_stops |= S_PT_SCE;
@@ -540,11 +542,13 @@
                }
 
                if (addr != (void *)1) {
+                       PROC_UNLOCK(p);
                        error = ptrace_set_pc(td2, (u_long)(uintfptr_t)addr);
                        if (error) {
-                               _PRELE(p);
-                               goto fail;
+                               PRELE(p);
+                               goto fail_noproc;
                        }
+                       PROC_LOCK(p);
                }
                _PRELE(p);
 
@@ -703,9 +707,9 @@
 #ifdef __HAVE_PTRACE_MACHDEP
                if (req >= PT_FIRSTMACH) {
                        _PHOLD(p);
-                       error = cpu_ptrace(td2, req, addr, data);
-                       _PRELE(p);
                        PROC_UNLOCK(p);
+                       error = cpu_ptrace(td2, req, addr, data);
+                       PRELE(p);
                        return (error);
                }
 #endif
@@ -717,6 +721,7 @@
 
 fail:
        PROC_UNLOCK(p);
+fail_noproc:
        if (proctree_locked)
                sx_xunlock(&proctree_lock);
        return (error);


We can do the same around the read/write registers stuff as well given
that they use PHOLD/PRELE if need be.

-- 

John Baldwin <jhb at FreeBSD.org>  <><  http://www.FreeBSD.org/~jhb/
"Power Users Use the Power to Serve!"  -  http://www.FreeBSD.org/


More information about the cvs-src mailing list