diff options
author | ps <ps@FreeBSD.org> | 2006-03-30 07:42:32 +0000 |
---|---|---|
committer | ps <ps@FreeBSD.org> | 2006-03-30 07:42:32 +0000 |
commit | 82f0faf08691e602d759d4e2455cfcfef9fe2cbe (patch) | |
tree | 048c7e74fc0cae58e8a30c0ef3db1df5a4d347f9 | |
parent | 469f432d987f41f5538a5ec954b5570ed1c23a48 (diff) | |
download | FreeBSD-src-82f0faf08691e602d759d4e2455cfcfef9fe2cbe.zip FreeBSD-src-82f0faf08691e602d759d4e2455cfcfef9fe2cbe.tar.gz |
Properly support for FreeBSD 4 32bit System V shared memory.
Submitted by: peter
Obtained from: Yahoo!
MFC after: 3 weeks
-rw-r--r-- | sys/compat/freebsd32/freebsd32_misc.c | 170 | ||||
-rw-r--r-- | sys/compat/freebsd32/syscalls.master | 6 | ||||
-rw-r--r-- | sys/kern/sysv_shm.c | 10 |
3 files changed, 179 insertions, 7 deletions
diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c index 472ef24..ce6ab69 100644 --- a/sys/compat/freebsd32/freebsd32_misc.c +++ b/sys/compat/freebsd32/freebsd32_misc.c @@ -69,6 +69,8 @@ __FBSDID("$FreeBSD$"); #include <sys/unistd.h> #include <sys/vnode.h> #include <sys/wait.h> +#include <sys/ipc.h> +#include <sys/shm.h> #include <vm/vm.h> #include <vm/vm_kern.h> @@ -1365,10 +1367,170 @@ freebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap) int freebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap) { - /* - * Vector through to shmsys if it is loaded. - */ - return sysent[SYS_shmsys].sy_call(td, uap); + + switch (uap->which) { + case 0: { /* shmat */ + struct shmat_args ap; + + ap.shmid = uap->a2; + ap.shmaddr = PTRIN(uap->a3); + ap.shmflg = uap->a4; + return (sysent[SYS_shmat].sy_call(td, &ap)); + } + case 2: { /* shmdt */ + struct shmdt_args ap; + + ap.shmaddr = PTRIN(uap->a2); + return (sysent[SYS_shmdt].sy_call(td, &ap)); + } + case 3: { /* shmget */ + struct shmget_args ap; + + ap.key = uap->a2; + ap.size = uap->a3; + ap.shmflg = uap->a4; + return (sysent[SYS_shmget].sy_call(td, &ap)); + } + case 4: { /* shmctl */ + struct freebsd32_shmctl_args ap; + + ap.shmid = uap->a2; + ap.cmd = uap->a3; + ap.buf = PTRIN(uap->a4); + return (freebsd32_shmctl(td, &ap)); + } + case 1: /* oshmctl */ + default: + return (EINVAL); + } +} + +struct ipc_perm32 { + uint16_t cuid; + uint16_t cgid; + uint16_t uid; + uint16_t gid; + uint16_t mode; + uint16_t seq; + uint32_t key; +}; +struct shmid_ds32 { + struct ipc_perm32 shm_perm; + int32_t shm_segsz; + int32_t shm_lpid; + int32_t shm_cpid; + int16_t shm_nattch; + int32_t shm_atime; + int32_t shm_dtime; + int32_t shm_ctime; + uint32_t shm_internal; +}; +struct shm_info32 { + int32_t used_ids; + uint32_t shm_tot; + uint32_t shm_rss; + uint32_t shm_swp; + uint32_t swap_attempts; + uint32_t swap_successes; +}; +struct shminfo32 { + uint32_t shmmax; + uint32_t shmmin; + uint32_t shmmni; + uint32_t shmseg; + uint32_t shmall; +}; + +int +freebsd32_shmctl(struct thread *td, struct freebsd32_shmctl_args *uap) +{ + int error = 0; + union { + struct shmid_ds shmid_ds; + struct shm_info shm_info; + struct shminfo shminfo; + } u; + union { + struct shmid_ds32 shmid_ds32; + struct shm_info32 shm_info32; + struct shminfo32 shminfo32; + } u32; + size_t sz; + + if (uap->cmd == IPC_SET) { + if ((error = copyin(uap->buf, &u32.shmid_ds32, + sizeof(u32.shmid_ds32)))) + goto done; + CP(u32.shmid_ds32, u.shmid_ds, shm_perm.cuid); + CP(u32.shmid_ds32, u.shmid_ds, shm_perm.cgid); + CP(u32.shmid_ds32, u.shmid_ds, shm_perm.uid); + CP(u32.shmid_ds32, u.shmid_ds, shm_perm.gid); + CP(u32.shmid_ds32, u.shmid_ds, shm_perm.mode); + CP(u32.shmid_ds32, u.shmid_ds, shm_perm.seq); + CP(u32.shmid_ds32, u.shmid_ds, shm_perm.key); + CP(u32.shmid_ds32, u.shmid_ds, shm_segsz); + CP(u32.shmid_ds32, u.shmid_ds, shm_lpid); + CP(u32.shmid_ds32, u.shmid_ds, shm_cpid); + CP(u32.shmid_ds32, u.shmid_ds, shm_nattch); + CP(u32.shmid_ds32, u.shmid_ds, shm_atime); + CP(u32.shmid_ds32, u.shmid_ds, shm_dtime); + CP(u32.shmid_ds32, u.shmid_ds, shm_ctime); + PTRIN_CP(u32.shmid_ds32, u.shmid_ds, shm_internal); + } + + error = kern_shmctl(td, uap->shmid, uap->cmd, (void *)&u, &sz); + if (error) + goto done; + + /* Cases in which we need to copyout */ + switch (uap->cmd) { + case IPC_INFO: + CP(u.shminfo, u32.shminfo32, shmmax); + CP(u.shminfo, u32.shminfo32, shmmin); + CP(u.shminfo, u32.shminfo32, shmmni); + CP(u.shminfo, u32.shminfo32, shmseg); + CP(u.shminfo, u32.shminfo32, shmall); + error = copyout(&u32.shminfo32, uap->buf, + sizeof(u32.shminfo32)); + break; + case SHM_INFO: + CP(u.shm_info, u32.shm_info32, used_ids); + CP(u.shm_info, u32.shm_info32, shm_rss); + CP(u.shm_info, u32.shm_info32, shm_tot); + CP(u.shm_info, u32.shm_info32, shm_swp); + CP(u.shm_info, u32.shm_info32, swap_attempts); + CP(u.shm_info, u32.shm_info32, swap_successes); + error = copyout(&u32.shm_info32, uap->buf, + sizeof(u32.shm_info32)); + break; + case SHM_STAT: + case IPC_STAT: + CP(u.shmid_ds, u32.shmid_ds32, shm_perm.cuid); + CP(u.shmid_ds, u32.shmid_ds32, shm_perm.cgid); + CP(u.shmid_ds, u32.shmid_ds32, shm_perm.uid); + CP(u.shmid_ds, u32.shmid_ds32, shm_perm.gid); + CP(u.shmid_ds, u32.shmid_ds32, shm_perm.mode); + CP(u.shmid_ds, u32.shmid_ds32, shm_perm.seq); + CP(u.shmid_ds, u32.shmid_ds32, shm_perm.key); + CP(u.shmid_ds, u32.shmid_ds32, shm_segsz); + CP(u.shmid_ds, u32.shmid_ds32, shm_lpid); + CP(u.shmid_ds, u32.shmid_ds32, shm_cpid); + CP(u.shmid_ds, u32.shmid_ds32, shm_nattch); + CP(u.shmid_ds, u32.shmid_ds32, shm_atime); + CP(u.shmid_ds, u32.shmid_ds32, shm_dtime); + CP(u.shmid_ds, u32.shmid_ds32, shm_ctime); + PTROUT_CP(u.shmid_ds, u32.shmid_ds32, shm_internal); + error = copyout(&u32.shmid_ds32, uap->buf, + sizeof(u32.shmid_ds32)); + break; + } + +done: + if (error) { + /* Invalidate the return value */ + td->td_retval[0] = -1; + } + return (error); } int diff --git a/sys/compat/freebsd32/syscalls.master b/sys/compat/freebsd32/syscalls.master index d6797c2..a39e38c 100644 --- a/sys/compat/freebsd32/syscalls.master +++ b/sys/compat/freebsd32/syscalls.master @@ -305,8 +305,8 @@ int a3, int a4, int a5); } 170 AUE_MSGSYS MSTD { int freebsd32_msgsys(int which, int a2, \ int a3, int a4, int a5, int a6); } -171 AUE_SHMSYS MSTD { int freebsd32_shmsys(int which, int a2, \ - int a3, int a4); } +171 AUE_SHMSYS MSTD { int freebsd32_shmsys(uint32_t which, uint32_t a2, \ + uint32_t a3, uint32_t a4); } 172 AUE_NULL UNIMPL nosys 173 AUE_PREAD MSTD { ssize_t freebsd32_pread(int fd, void *buf, \ size_t nbyte, int pad, \ @@ -415,7 +415,7 @@ size_t msgsz, long msgtyp, int msgflg); } 228 AUE_SHMAT MNOPROTO { int shmat(int shmid, void *shmaddr, \ int shmflg); } -229 AUE_SHMCTL MNOPROTO { int shmctl(int shmid, int cmd, \ +229 AUE_SHMCTL MSTD { int freebsd32_shmctl(int shmid, int cmd, \ struct shmid_ds *buf); } 230 AUE_SHMDT MNOPROTO { int shmdt(void *shmaddr); } 231 AUE_SHMGET MNOPROTO { int shmget(key_t key, int size, \ diff --git a/sys/kern/sysv_shm.c b/sys/kern/sysv_shm.c index c52f79d..d785891 100644 --- a/sys/kern/sysv_shm.c +++ b/sys/kern/sysv_shm.c @@ -102,20 +102,24 @@ __FBSDID("$FreeBSD$"); static MALLOC_DEFINE(M_SHM, "shm", "SVID compatible shared memory segments"); +#if defined(__i386__) && (defined(COMPAT_FREEBSD4) || defined(COMPAT_43)) struct oshmctl_args; static int oshmctl(struct thread *td, struct oshmctl_args *uap); +#endif static int shmget_allocate_segment(struct thread *td, struct shmget_args *uap, int mode); static int shmget_existing(struct thread *td, struct shmget_args *uap, int mode, int segnum); +#if defined(__i386__) && (defined(COMPAT_FREEBSD4) || defined(COMPAT_43)) /* XXX casting to (sy_call_t *) is bogus, as usual. */ static sy_call_t *shmcalls[] = { (sy_call_t *)shmat, (sy_call_t *)oshmctl, (sy_call_t *)shmdt, (sy_call_t *)shmget, (sy_call_t *)shmctl }; +#endif #define SHMSEG_FREE 0x0200 #define SHMSEG_REMOVED 0x0400 @@ -464,6 +468,7 @@ shmat(td, uap) return kern_shmat(td, uap->shmid, uap->shmaddr, uap->shmflg); } +#if defined(__i386__) && (defined(COMPAT_FREEBSD4) || defined(COMPAT_43)) struct oshmid_ds { struct ipc_perm shm_perm; /* operation perms */ int shm_segsz; /* size of segment (bytes) */ @@ -540,6 +545,7 @@ done2: return (EINVAL); #endif } +#endif #ifndef _SYS_SYSPROTO_H_ struct shmctl_args { @@ -876,6 +882,7 @@ shmsys(td, uap) int a4; } */ *uap; { +#if defined(__i386__) && (defined(COMPAT_FREEBSD4) || defined(COMPAT_43)) int error; if (!jail_sysvipc_allowed && jailed(td->td_ucred)) @@ -887,6 +894,9 @@ shmsys(td, uap) error = (*shmcalls[uap->which])(td, &uap->a2); mtx_unlock(&Giant); return (error); +#else + return (nosys(td, NULL)); +#endif } static void |