void syscall_handler() { uint32_t svc_num, *svc_param1, *svc_param2; svc_param1 = (uint32_t *) caller->ctx.sp; svc_num = ((char *) svc_param1[REG_PC])[-2]; svc_param2 = caller->ctx.regs; if (svc_num == SYS_THREAD_CONTROL) { /* Simply call thread_create * TODO: checking globalid * TODO: pagers and schedulers */ sys_thread_control(svc_param1, svc_param2); caller->state = T_RUNNABLE; } else if (svc_num == SYS_IPC) { sys_ipc(svc_param1); } else { dbg_printf(DL_SYSCALL, "SVC: %d called [%d, %d, %d, %d]\n", svc_num, svc_param1[REG_R0], svc_param1[REG_R1], svc_param1[REG_R2], svc_param1[REG_R3]); caller->state = T_RUNNABLE; } }
asmlinkage int sys_oabi_ipc(uint call, int first, int second, int third, void __user *ptr, long fifth) { switch (call & 0xffff) { case SEMOP: return sys_oabi_semtimedop(first, (struct oabi_sembuf __user *)ptr, second, NULL); case SEMTIMEDOP: return sys_oabi_semtimedop(first, (struct oabi_sembuf __user *)ptr, second, (const struct timespec __user *)fifth); default: return sys_ipc(call, first, second, third, ptr, fifth); } }
unsigned long sys_shmat(int shmid, const void *shmaddr, int shmflg) { unsigned long raddr; int ret; ret = sys_ipc(21 /*SHMAT */, shmid, /* first */ shmflg, /* second */ (unsigned long)&raddr, /* third */ shmaddr, /* ptr */ 0 /* fifth not used */); if (ret) raddr = (unsigned long) ret; return raddr; }
asmlinkage long solaris_shmsys(int cmd, u32 arg1, u32 arg2, u32 arg3) { int (*sys_ipc)(unsigned,int,int,unsigned long,void __user *,long) = (int (*)(unsigned,int,int,unsigned long,void __user *,long))SYS(ipc); mm_segment_t old_fs; unsigned long raddr; int ret; switch (cmd) { case 0: /* shmat */ old_fs = get_fs(); set_fs(KERNEL_DS); ret = sys_ipc(SHMAT, arg1, arg3 & ~0x4000, (unsigned long)&raddr, A(arg2), 0); set_fs(old_fs); if (ret >= 0) return (u32)raddr; else return ret; case 1: /* shmctl */ switch (arg2) { case 3: /* SHM_LOCK */ case 4: /* SHM_UNLOCK */ return sys_ipc(SHMCTL, arg1, (arg2 == 3) ? SHM_LOCK : SHM_UNLOCK, 0, NULL, 0); case 10: /* IPC_RMID */ return sys_ipc(SHMCTL, arg1, IPC_RMID, 0, NULL, 0); case 11: /* IPC_SET */ { struct shmid_ds s; struct solaris_shmid_ds __user *p = A(arg3); if (get_user (s.shm_perm.uid, &p->shm_perm.uid) || __get_user (s.shm_perm.gid, &p->shm_perm.gid) || __get_user (s.shm_perm.mode, &p->shm_perm.mode)) return -EFAULT; old_fs = get_fs(); set_fs(KERNEL_DS); ret = sys_ipc(SHMCTL, arg1, IPC_SET, 0, &s, 0); set_fs(old_fs); return ret; } case 12: /* IPC_STAT */ { struct shmid_ds s; struct solaris_shmid_ds __user *p = A(arg3); old_fs = get_fs(); set_fs(KERNEL_DS); ret = sys_ipc(SHMCTL, arg1, IPC_SET, 0, &s, 0); set_fs(old_fs); if (put_user (s.shm_perm.uid, &(p->shm_perm.uid)) || __put_user (s.shm_perm.gid, &(p->shm_perm.gid)) || __put_user (s.shm_perm.cuid, &(p->shm_perm.cuid)) || __put_user (s.shm_perm.cgid, &(p->shm_perm.cgid)) || __put_user (s.shm_perm.mode, &(p->shm_perm.mode)) || __put_user (s.shm_perm.seq, &(p->shm_perm.seq)) || __put_user (s.shm_perm.key, &(p->shm_perm.key)) || __put_user (s.shm_segsz, &(p->shm_segsz)) || __put_user (s.shm_lpid, &(p->shm_lpid)) || __put_user (s.shm_cpid, &(p->shm_cpid)) || __put_user (s.shm_nattch, &(p->shm_nattch)) || __put_user (s.shm_atime, &(p->shm_atime)) || __put_user (s.shm_dtime, &(p->shm_dtime)) || __put_user (s.shm_ctime, &(p->shm_ctime))) return -EFAULT; return ret; } default: return -EINVAL; } case 2: /* shmdt */ return sys_ipc(SHMDT, 0, 0, 0, A(arg1), 0); case 3: /* shmget */ return sys_ipc(SHMGET, arg1, arg2, arg3, NULL, 0); } return -EINVAL; }
long sys_shmat(int shmid, void *shmaddr, int shmflag) { return sys_ipc(SHMAT, shmid, shmflag, 0, shmaddr, 0); }