Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/kern Split off the backend of the shmat system call, and...



details:   https://anonhg.NetBSD.org/src/rev/ec6c100b9840
branches:  trunk
changeset: 525002:ec6c100b9840
user:      fvdl <fvdl%NetBSD.org@localhost>
date:      Wed Apr 03 11:53:01 2002 +0000

description:
Split off the backend of the shmat system call, and find removed segments
if requested. This enables the linux compat code to be bug compatible
(under Linux, shmat() to a removed segment works).

diffstat:

 sys/kern/sysv_shm.c |  59 ++++++++++++++++++++++++++++++++++++----------------
 1 files changed, 41 insertions(+), 18 deletions(-)

diffs (140 lines):

diff -r 8cdcc1b8223d -r ec6c100b9840 sys/kern/sysv_shm.c
--- a/sys/kern/sysv_shm.c       Wed Apr 03 11:50:51 2002 +0000
+++ b/sys/kern/sysv_shm.c       Wed Apr 03 11:53:01 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: sysv_shm.c,v 1.63 2001/11/15 09:48:20 lukem Exp $      */
+/*     $NetBSD: sysv_shm.c,v 1.64 2002/04/03 11:53:01 fvdl Exp $       */
 
 /*-
  * Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -68,7 +68,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sysv_shm.c,v 1.63 2001/11/15 09:48:20 lukem Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sysv_shm.c,v 1.64 2002/04/03 11:53:01 fvdl Exp $");
 
 #define SYSVSHM
 
@@ -84,7 +84,7 @@
 
 #include <uvm/uvm_extern.h>
 
-struct shmid_ds *shm_find_segment_by_shmid __P((int));
+struct shmid_ds *shm_find_segment_by_shmid __P((int, int));
 
 /*
  * Provides the following externally accessible functions:
@@ -137,8 +137,9 @@
 }
 
 struct shmid_ds *
-shm_find_segment_by_shmid(shmid)
+shm_find_segment_by_shmid(shmid, findremoved)
        int shmid;
+       int findremoved;
 {
        int segnum;
        struct shmid_ds *shmseg;
@@ -147,9 +148,11 @@
        if (segnum < 0 || segnum >= shminfo.shmmni)
                return NULL;
        shmseg = &shmsegs[segnum];
-       if ((shmseg->shm_perm.mode & (SHMSEG_ALLOCATED | SHMSEG_REMOVED))
-           != SHMSEG_ALLOCATED ||
-           shmseg->shm_perm._seq != IPCID_TO_SEQ(shmid))
+       if ((shmseg->shm_perm.mode & SHMSEG_ALLOCATED) == 0)
+               return NULL;
+       if (!findremoved && ((shmseg->shm_perm.mode & SHMSEG_REMOVED) != 0))
+               return NULL;
+       if (shmseg->shm_perm._seq != IPCID_TO_SEQ(shmid))
                return NULL;
        return shmseg;
 }
@@ -230,6 +233,26 @@
                syscallarg(const void *) shmaddr;
                syscallarg(int) shmflg;
        } */ *uap = v;
+       vaddr_t attach_va;
+       int error;
+
+       error = shmat1(p, SCARG(uap, shmid), SCARG(uap, shmaddr),
+           SCARG(uap, shmflg), &attach_va, 0);
+       if (error != 0)
+               return error;
+       retval[0] = attach_va;
+       return 0;
+}
+
+int
+shmat1(p, shmid, shmaddr, shmflg, attachp, findremoved)
+       struct proc *p;
+       int shmid;
+       const void *shmaddr;
+       int shmflg;
+       vaddr_t *attachp;
+       int findremoved;
+{
        int error, i, flags;
        struct ucred *cred = p->p_ucred;
        struct shmid_ds *shmseg;
@@ -247,11 +270,11 @@
                        shmmap_s[i].shmid = -1;
                p->p_vmspace->vm_shm = (caddr_t)shmmap_s;
        }
-       shmseg = shm_find_segment_by_shmid(SCARG(uap, shmid));
+       shmseg = shm_find_segment_by_shmid(shmid, findremoved);
        if (shmseg == NULL)
                return EINVAL;
        error = ipcperm(cred, &shmseg->shm_perm,
-                   (SCARG(uap, shmflg) & SHM_RDONLY) ? IPC_R : IPC_R|IPC_W);
+                   (shmflg & SHM_RDONLY) ? IPC_R : IPC_R|IPC_W);
        if (error)
                return error;
        for (i = 0; i < shminfo.shmseg; i++) {
@@ -263,16 +286,16 @@
                return EMFILE;
        size = (shmseg->shm_segsz + PGOFSET) & ~PGOFSET;
        prot = VM_PROT_READ;
-       if ((SCARG(uap, shmflg) & SHM_RDONLY) == 0)
+       if ((shmflg & SHM_RDONLY) == 0)
                prot |= VM_PROT_WRITE;
        flags = MAP_ANON | MAP_SHARED;
-       if (SCARG(uap, shmaddr)) {
+       if (shmaddr) {
                flags |= MAP_FIXED;
-               if (SCARG(uap, shmflg) & SHM_RND) 
+               if (shmflg & SHM_RND) 
                        attach_va =
-                           (vaddr_t)SCARG(uap, shmaddr) & ~(SHMLBA-1);
-               else if (((vaddr_t)SCARG(uap, shmaddr) & (SHMLBA-1)) == 0)
-                       attach_va = (vaddr_t)SCARG(uap, shmaddr);
+                           (vaddr_t)shmaddr & ~(SHMLBA-1);
+               else if (((vaddr_t)shmaddr & (SHMLBA-1)) == 0)
+                       attach_va = (vaddr_t)shmaddr;
                else
                        return EINVAL;
        } else {
@@ -290,11 +313,11 @@
                return error;
        }
        shmmap_s->va = attach_va;
-       shmmap_s->shmid = SCARG(uap, shmid);
+       shmmap_s->shmid = shmid;
        shmseg->shm_lpid = p->p_pid;
        shmseg->shm_atime = time.tv_sec;
        shmseg->shm_nattch++;
-       *retval = attach_va;
+       *attachp = attach_va;
        return 0;
 }
 
@@ -340,7 +363,7 @@
        struct shmid_ds *shmseg;
        int error = 0;
 
-       shmseg = shm_find_segment_by_shmid(shmid);
+       shmseg = shm_find_segment_by_shmid(shmid, 0);
        if (shmseg == NULL)
                return EINVAL;
        switch (cmd) {



Home | Main Index | Thread Index | Old Index