Properly support for FreeBSD 4 32bit System V shared memory.

Submitted by:	peter
Obtained from:	Yahoo!
MFC after:	3 weeks
This commit is contained in:
Paul Saab 2006-03-30 07:42:32 +00:00
parent 844f9220aa
commit fbb273bc05
3 changed files with 179 additions and 7 deletions

View File

@ -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

View File

@ -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, \

View File

@ -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