sys_parisc.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:6k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * linux/arch/parisc/kernel/sys_parisc.c
  3.  *
  4.  * this implements syscalls which are handled per-arch.
  5.  */
  6. #include <asm/uaccess.h>
  7. #include <linux/file.h>
  8. #include <linux/fs.h>
  9. #include <linux/linkage.h>
  10. #include <linux/mm.h>
  11. #include <linux/mman.h>
  12. #include <linux/shm.h>
  13. #include <linux/smp_lock.h>
  14. int sys_pipe(int *fildes)
  15. {
  16. int fd[2];
  17. int error;
  18. error = do_pipe(fd);
  19. if (!error) {
  20. if (copy_to_user(fildes, fd, 2*sizeof(int)))
  21. error = -EFAULT;
  22. }
  23. return error;
  24. }
  25. int sys_pause(void)
  26. {
  27. current->state = TASK_INTERRUPTIBLE;
  28. schedule();
  29. return -ERESTARTNOHAND;
  30. }
  31. static unsigned long get_unshared_area(unsigned long addr, unsigned long len)
  32. {
  33. struct vm_area_struct *vma;
  34. if (!addr)
  35. addr = TASK_UNMAPPED_BASE;
  36. addr = PAGE_ALIGN(addr);
  37. for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) {
  38. /* At this point:  (!vma || addr < vma->vm_end). */
  39. if (TASK_SIZE - len < addr)
  40. return -ENOMEM;
  41. if (!vma || addr + len <= vma->vm_start)
  42. return addr;
  43. addr = vma->vm_end;
  44. }
  45. }
  46. #define DCACHE_ALIGN(addr) (((addr) + (SHMLBA - 1)) &~ (SHMLBA - 1))
  47. static unsigned long get_shared_area(struct inode *inode, unsigned long addr,
  48. unsigned long len, unsigned long pgoff)
  49. {
  50. struct vm_area_struct *vma, *first_vma;
  51. int offset;
  52. first_vma = inode->i_mapping->i_mmap_shared;
  53. offset = (first_vma->vm_start + ((pgoff - first_vma->vm_pgoff) << PAGE_SHIFT)) & (SHMLBA - 1);
  54. if (!addr)
  55. addr = TASK_UNMAPPED_BASE;
  56. addr = DCACHE_ALIGN(addr - offset) + offset;
  57. for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) {
  58. /* At this point:  (!vma || addr < vma->vm_end). */
  59. if (TASK_SIZE - len < addr)
  60. return -ENOMEM;
  61. if (!vma || addr + len <= vma->vm_start)
  62. return addr;
  63. addr = DCACHE_ALIGN(vma->vm_end - offset) + offset;
  64. if (addr < vma->vm_end) /* handle wraparound */
  65. return -ENOMEM;
  66. }
  67. }
  68. unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
  69. unsigned long len, unsigned long pgoff, unsigned long flags)
  70. {
  71. struct inode *inode = NULL;
  72. if (len > TASK_SIZE)
  73. return -ENOMEM;
  74. if (filp) {
  75. inode = filp->f_dentry->d_inode;
  76. }
  77. if (inode && (flags & MAP_SHARED) && (inode->i_mapping->i_mmap_shared)) {
  78. addr = get_shared_area(inode, addr, len, pgoff);
  79. } else {
  80. addr = get_unshared_area(addr, len);
  81. }
  82. return addr;
  83. }
  84. static unsigned long do_mmap2(unsigned long addr, unsigned long len,
  85. unsigned long prot, unsigned long flags, unsigned long fd,
  86. unsigned long pgoff)
  87. {
  88. struct file * file = NULL;
  89. unsigned long error = -EBADF;
  90. if (!(flags & MAP_ANONYMOUS)) {
  91. file = fget(fd);
  92. if (!file)
  93. goto out;
  94. }
  95. flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
  96. down_write(&current->mm->mmap_sem);
  97. error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
  98. up_write(&current->mm->mmap_sem);
  99. if (file != NULL)
  100. fput(file);
  101. out:
  102. return error;
  103. }
  104. asmlinkage unsigned long sys_mmap2(unsigned long addr, unsigned long len,
  105. unsigned long prot, unsigned long flags, unsigned long fd,
  106. unsigned long pgoff)
  107. {
  108. /* Make sure the shift for mmap2 is constant (12), no matter what PAGE_SIZE
  109.    we have. */
  110. return do_mmap2(addr, len, prot, flags, fd, pgoff >> (PAGE_SHIFT - 12));
  111. }
  112. asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len,
  113. unsigned long prot, unsigned long flags, unsigned long fd,
  114. unsigned long offset)
  115. {
  116. if (!(offset & ~PAGE_MASK)) {
  117. return do_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
  118. } else {
  119. return -EINVAL;
  120. }
  121. }
  122. long sys_shmat_wrapper(int shmid, char *shmaddr, int shmflag)
  123. {
  124. unsigned long raddr;
  125. int r;
  126. r = sys_shmat(shmid, shmaddr, shmflag, &raddr);
  127. if (r < 0)
  128. return r;
  129. return raddr;
  130. }
  131. /*
  132.  * FIXME, please remove this crap as soon as possible
  133.  *
  134.  * This is here to fix up broken glibc structures, 
  135.  * which are already fixed in newer glibcs
  136.  */
  137. #include <linux/msg.h>
  138. #include <linux/sem.h>
  139. #include <linux/shm.h>
  140. #include "sys32.h"
  141. struct broken_ipc_perm
  142. {
  143.     key_t key; /* Key.  */
  144.     uid_t uid; /* Owner's user ID.  */
  145.     gid_t gid; /* Owner's group ID.  */
  146.     uid_t cuid; /* Creator's user ID.  */
  147.     gid_t cgid; /* Creator's group ID.  */
  148.     unsigned short int mode; /* Read/write permission.  */
  149.     unsigned short int __pad1;
  150.     unsigned short int seq; /* Sequence number.  */
  151.     unsigned short int __pad2;
  152.     unsigned long int __unused1;
  153.     unsigned long int __unused2;
  154. };
  155.     
  156. struct broken_shmid64_ds {
  157. struct broken_ipc_perm shm_perm; /* operation perms */
  158. size_t shm_segsz; /* size of segment (bytes) */
  159. #ifndef __LP64__
  160. unsigned int __pad1;
  161. #endif
  162. __kernel_time_t shm_atime; /* last attach time */
  163. #ifndef __LP64__
  164. unsigned int __pad2;
  165. #endif
  166. __kernel_time_t shm_dtime; /* last detach time */
  167. #ifndef __LP64__
  168. unsigned int __pad3;
  169. #endif
  170. __kernel_time_t shm_ctime; /* last change time */
  171. __kernel_pid_t shm_cpid; /* pid of creator */
  172. __kernel_pid_t shm_lpid; /* pid of last operator */
  173. unsigned int shm_nattch; /* no. of current attaches */
  174. unsigned int __unused1;
  175. unsigned int __unused2;
  176. };
  177. static void convert_broken_perm (struct broken_ipc_perm *out, struct ipc64_perm *in)
  178. {
  179. out->key  = in->key;
  180. out->uid  = in->uid;
  181. out->gid  = in->gid;
  182. out->cuid = in->cuid;
  183. out->cgid = in->cgid;
  184. out->mode = in->mode;
  185. out->seq  = in->seq;
  186. }
  187. static int copyout_broken_shmid64(struct broken_shmid64_ds *buf, struct shmid64_ds *sbuf)
  188. {
  189. struct broken_shmid64_ds tbuf;
  190. memset(&tbuf, 0, sizeof tbuf);
  191. convert_broken_perm (&tbuf.shm_perm, &sbuf->shm_perm);
  192. tbuf.shm_segsz = sbuf->shm_segsz;
  193. tbuf.shm_atime = sbuf->shm_atime;
  194. tbuf.shm_dtime = sbuf->shm_dtime;
  195. tbuf.shm_ctime = sbuf->shm_ctime;
  196. tbuf.shm_cpid = sbuf->shm_cpid;
  197. tbuf.shm_lpid = sbuf->shm_lpid;
  198. tbuf.shm_nattch = sbuf->shm_nattch;
  199. return copy_to_user(buf, &tbuf, sizeof tbuf);
  200. }
  201. int sys_msgctl_broken(int msqid, int cmd, struct msqid_ds *buf)
  202. {
  203. return sys_msgctl (msqid, cmd & ~IPC_64, buf);
  204. }
  205. int sys_semctl_broken(int semid, int semnum, int cmd, union semun arg)
  206. {
  207. return sys_semctl (semid, semnum, cmd & ~IPC_64, arg);
  208. }
  209. int sys_shmctl_broken(int shmid, int cmd, struct shmid64_ds *buf)
  210. {
  211. struct shmid64_ds sbuf;
  212. int err;
  213. if (cmd & IPC_64) {
  214. cmd &= ~IPC_64;
  215. if (cmd == IPC_STAT || cmd == SHM_STAT) {
  216. KERNEL_SYSCALL(err, sys_shmctl, shmid, cmd, (struct shmid_ds *)&sbuf);
  217. if (err == 0)
  218. err = copyout_broken_shmid64((struct broken_shmid64_ds *)buf, &sbuf);
  219. return err;
  220. }
  221. }
  222. return sys_shmctl (shmid, cmd, (struct shmid_ds *)buf);
  223. }