-struct target_shmid_ds
-{
- struct target_ipc_perm shm_perm;
- abi_ulong shm_segsz;
- abi_ulong shm_atime;
-#if TARGET_ABI_BITS == 32
- abi_ulong __unused1;
-#endif
- abi_ulong shm_dtime;
-#if TARGET_ABI_BITS == 32
- abi_ulong __unused2;
-#endif
- abi_ulong shm_ctime;
-#if TARGET_ABI_BITS == 32
- abi_ulong __unused3;
-#endif
- int shm_cpid;
- int shm_lpid;
- abi_ulong shm_nattch;
- unsigned long int __unused4;
- unsigned long int __unused5;
-};
-
-static inline abi_long target_to_host_shmid_ds(struct shmid_ds *host_sd,
- abi_ulong target_addr)
-{
- struct target_shmid_ds *target_sd;
-
- if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
- return -TARGET_EFAULT;
- if (target_to_host_ipc_perm(&(host_sd->shm_perm), target_addr))
- return -TARGET_EFAULT;
- __put_user(target_sd->shm_segsz, &host_sd->shm_segsz);
- __put_user(target_sd->shm_atime, &host_sd->shm_atime);
- __put_user(target_sd->shm_dtime, &host_sd->shm_dtime);
- __put_user(target_sd->shm_ctime, &host_sd->shm_ctime);
- __put_user(target_sd->shm_cpid, &host_sd->shm_cpid);
- __put_user(target_sd->shm_lpid, &host_sd->shm_lpid);
- __put_user(target_sd->shm_nattch, &host_sd->shm_nattch);
- unlock_user_struct(target_sd, target_addr, 0);
- return 0;
-}
-
-static inline abi_long host_to_target_shmid_ds(abi_ulong target_addr,
- struct shmid_ds *host_sd)
-{
- struct target_shmid_ds *target_sd;
-
- if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
- return -TARGET_EFAULT;
- if (host_to_target_ipc_perm(target_addr, &(host_sd->shm_perm)))
- return -TARGET_EFAULT;
- __put_user(host_sd->shm_segsz, &target_sd->shm_segsz);
- __put_user(host_sd->shm_atime, &target_sd->shm_atime);
- __put_user(host_sd->shm_dtime, &target_sd->shm_dtime);
- __put_user(host_sd->shm_ctime, &target_sd->shm_ctime);
- __put_user(host_sd->shm_cpid, &target_sd->shm_cpid);
- __put_user(host_sd->shm_lpid, &target_sd->shm_lpid);
- __put_user(host_sd->shm_nattch, &target_sd->shm_nattch);
- unlock_user_struct(target_sd, target_addr, 1);
- return 0;
-}
-
-struct target_shminfo {
- abi_ulong shmmax;
- abi_ulong shmmin;
- abi_ulong shmmni;
- abi_ulong shmseg;
- abi_ulong shmall;
-};
-
-static inline abi_long host_to_target_shminfo(abi_ulong target_addr,
- struct shminfo *host_shminfo)
-{
- struct target_shminfo *target_shminfo;
- if (!lock_user_struct(VERIFY_WRITE, target_shminfo, target_addr, 0))
- return -TARGET_EFAULT;
- __put_user(host_shminfo->shmmax, &target_shminfo->shmmax);
- __put_user(host_shminfo->shmmin, &target_shminfo->shmmin);
- __put_user(host_shminfo->shmmni, &target_shminfo->shmmni);
- __put_user(host_shminfo->shmseg, &target_shminfo->shmseg);
- __put_user(host_shminfo->shmall, &target_shminfo->shmall);
- unlock_user_struct(target_shminfo, target_addr, 1);
- return 0;
-}
-
-struct target_shm_info {
- int used_ids;
- abi_ulong shm_tot;
- abi_ulong shm_rss;
- abi_ulong shm_swp;
- abi_ulong swap_attempts;
- abi_ulong swap_successes;
-};
-
-static inline abi_long host_to_target_shm_info(abi_ulong target_addr,
- struct shm_info *host_shm_info)
-{
- struct target_shm_info *target_shm_info;
- if (!lock_user_struct(VERIFY_WRITE, target_shm_info, target_addr, 0))
- return -TARGET_EFAULT;
- __put_user(host_shm_info->used_ids, &target_shm_info->used_ids);
- __put_user(host_shm_info->shm_tot, &target_shm_info->shm_tot);
- __put_user(host_shm_info->shm_rss, &target_shm_info->shm_rss);
- __put_user(host_shm_info->shm_swp, &target_shm_info->shm_swp);
- __put_user(host_shm_info->swap_attempts, &target_shm_info->swap_attempts);
- __put_user(host_shm_info->swap_successes, &target_shm_info->swap_successes);
- unlock_user_struct(target_shm_info, target_addr, 1);
- return 0;
-}
-
-static inline abi_long do_shmctl(int shmid, int cmd, abi_long buf)
-{
- struct shmid_ds dsarg;
- struct shminfo shminfo;
- struct shm_info shm_info;
- abi_long ret = -TARGET_EINVAL;
-
- cmd &= 0xff;
-
- switch(cmd) {
- case IPC_STAT:
- case IPC_SET:
- case SHM_STAT:
- if (target_to_host_shmid_ds(&dsarg, buf))
- return -TARGET_EFAULT;
- ret = get_errno(shmctl(shmid, cmd, &dsarg));
- if (host_to_target_shmid_ds(buf, &dsarg))
- return -TARGET_EFAULT;
- break;
- case IPC_INFO:
- ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shminfo));
- if (host_to_target_shminfo(buf, &shminfo))
- return -TARGET_EFAULT;
- break;
- case SHM_INFO:
- ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shm_info));
- if (host_to_target_shm_info(buf, &shm_info))
- return -TARGET_EFAULT;
- break;
- case IPC_RMID:
- case SHM_LOCK:
- case SHM_UNLOCK:
- ret = get_errno(shmctl(shmid, cmd, NULL));
- break;
- }
-
- return ret;
-}
-
-static inline abi_long do_shmat(int shmid, abi_ulong shmaddr, int shmflg,
- unsigned long *raddr)
-{
- abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size);
- abi_long ret;
- struct shmid_ds shm_info;
- int i;
-
- /* find out the length of the shared memory segment */
- ret = get_errno(shmctl(shmid, IPC_STAT, &shm_info));
- if (is_error(ret)) {
- /* can't get length, bail out */
- return get_errno(ret);
- }
-
- mmap_lock();
-
- if (shmaddr)
- *raddr = (unsigned long) shmat(shmid, g2h(shmaddr), shmflg);
- else {
- abi_ulong mmap_start;
-
- mmap_start = mmap_find_vma(0, shm_info.shm_segsz);
-
- if (mmap_start == -1) {
- errno = ENOMEM;
- *raddr = -1;
- } else
- *raddr = (unsigned long) shmat(shmid, g2h(mmap_start),
- shmflg | SHM_REMAP);
- }
-
- if (*raddr == -1) {
- mmap_unlock();
- return get_errno(*raddr);
- }
-
- page_set_flags(h2g(*raddr), h2g(*raddr) + shm_info.shm_segsz,
- PAGE_VALID | PAGE_READ |
- ((shmflg & SHM_RDONLY)? 0 : PAGE_WRITE));
-
- for (i = 0; i < N_SHM_REGIONS; i++) {
- if (shm_regions[i].start == 0) {
- shm_regions[i].start = h2g(*raddr);
- shm_regions[i].size = shm_info.shm_segsz;
- break;
- }
- }
-
- mmap_unlock();
- return 0;
-}
-
-static inline abi_long do_shmdt(abi_ulong shmaddr)
-{
- int i;
-
- for (i = 0; i < N_SHM_REGIONS; ++i) {
- if (shm_regions[i].start == shmaddr) {
- shm_regions[i].start = 0;
- page_set_flags(shmaddr, shm_regions[i].size, 0);
- break;
- }
- }
-
- return get_errno(shmdt(g2h(shmaddr)));
-}
-