diff options
author | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2003-03-23 01:06:05 +0000 |
---|---|---|
committer | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2003-03-23 01:06:05 +0000 |
commit | 66fb9763af9cd743158957e8c9c2559d922b1c22 (patch) | |
tree | 34a6524fbd51076c6ecbd5fd5d548f9b11302a12 /linux-user/syscall.c | |
parent | 1b6b029e40c4297ce9c27e0f8b8ae177085c990a (diff) |
basic signal handling
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@41 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'linux-user/syscall.c')
-rw-r--r-- | linux-user/syscall.c | 294 |
1 files changed, 231 insertions, 63 deletions
diff --git a/linux-user/syscall.c b/linux-user/syscall.c index da54a0a186..dbe3de3fdf 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -75,12 +75,18 @@ #include "syscall-i386.h" #endif +void host_to_target_siginfo(target_siginfo_t *tinfo, siginfo_t *info); +void target_to_host_siginfo(siginfo_t *info, target_siginfo_t *tinfo); +long do_sigreturn(CPUX86State *env); +long do_rt_sigreturn(CPUX86State *env); + #define __NR_sys_uname __NR_uname #define __NR_sys_getcwd1 __NR_getcwd #define __NR_sys_statfs __NR_statfs #define __NR_sys_fstatfs __NR_fstatfs #define __NR_sys_getdents __NR_getdents #define __NR_sys_getdents64 __NR_getdents64 +#define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo #ifdef __NR_gettid _syscall0(int, gettid) @@ -97,6 +103,9 @@ _syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo, loff_t *, res, uint, wh); _syscall2(int,sys_statfs,const char *,path,struct kernel_statfs *,buf) _syscall2(int,sys_fstatfs,int,fd,struct kernel_statfs *,buf) +_syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo) + +extern int personality(int); static inline long get_errno(long ret) { @@ -199,18 +208,18 @@ static inline void host_to_target_fds(target_long *target_fds, #endif } -/* XXX: incorrect for some archs */ -static void host_to_target_old_sigset(target_ulong *old_sigset, - const sigset_t *sigset) +static inline void target_to_host_timeval(struct timeval *tv, + struct target_timeval *target_tv) { - *old_sigset = tswap32(*(unsigned long *)sigset & 0xffffffff); + tv->tv_sec = tswapl(target_tv->tv_sec); + tv->tv_usec = tswapl(target_tv->tv_usec); } -static void target_to_host_old_sigset(sigset_t *sigset, - const target_ulong *old_sigset) +static inline void host_to_target_timeval(struct target_timeval *target_tv, + struct timeval *tv) { - sigemptyset(sigset); - *(unsigned long *)sigset = tswapl(*old_sigset); + target_tv->tv_sec = tswapl(tv->tv_sec); + target_tv->tv_usec = tswapl(tv->tv_usec); } @@ -1042,28 +1051,195 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, ret = get_errno(setsid()); break; case TARGET_NR_sigaction: -#if 1 { - ret = 0; + struct target_old_sigaction *old_act = (void *)arg2; + struct target_old_sigaction *old_oact = (void *)arg3; + struct target_sigaction act, oact, *pact; + if (old_act) { + act._sa_handler = old_act->_sa_handler; + target_siginitset(&act.sa_mask, old_act->sa_mask); + act.sa_flags = old_act->sa_flags; + act.sa_restorer = old_act->sa_restorer; + pact = &act; + } else { + pact = NULL; + } + ret = get_errno(do_sigaction(arg1, pact, &oact)); + if (!is_error(ret) && old_oact) { + old_oact->_sa_handler = oact._sa_handler; + old_oact->sa_mask = oact.sa_mask.sig[0]; + old_oact->sa_flags = oact.sa_flags; + old_oact->sa_restorer = oact.sa_restorer; + } } break; -#else - goto unimplemented; -#endif + case TARGET_NR_rt_sigaction: + ret = get_errno(do_sigaction(arg1, (void *)arg2, (void *)arg3)); + break; case TARGET_NR_sgetmask: - goto unimplemented; + { + sigset_t cur_set; + target_ulong target_set; + sigprocmask(0, NULL, &cur_set); + host_to_target_old_sigset(&target_set, &cur_set); + ret = target_set; + } + break; case TARGET_NR_ssetmask: - goto unimplemented; + { + sigset_t set, oset, cur_set; + target_ulong target_set = arg1; + sigprocmask(0, NULL, &cur_set); + target_to_host_old_sigset(&set, &target_set); + sigorset(&set, &set, &cur_set); + sigprocmask(SIG_SETMASK, &set, &oset); + host_to_target_old_sigset(&target_set, &oset); + ret = target_set; + } + break; + case TARGET_NR_sigprocmask: + { + int how = arg1; + sigset_t set, oldset, *set_ptr; + target_ulong *pset = (void *)arg2, *poldset = (void *)arg3; + + if (pset) { + switch(how) { + case TARGET_SIG_BLOCK: + how = SIG_BLOCK; + break; + case TARGET_SIG_UNBLOCK: + how = SIG_UNBLOCK; + break; + case TARGET_SIG_SETMASK: + how = SIG_SETMASK; + break; + default: + ret = -EINVAL; + goto fail; + } + target_to_host_old_sigset(&set, pset); + set_ptr = &set; + } else { + how = 0; + set_ptr = NULL; + } + ret = get_errno(sigprocmask(arg1, set_ptr, &oldset)); + if (!is_error(ret) && poldset) { + host_to_target_old_sigset(poldset, &oldset); + } + } + break; + case TARGET_NR_rt_sigprocmask: + { + int how = arg1; + sigset_t set, oldset, *set_ptr; + target_sigset_t *pset = (void *)arg2; + target_sigset_t *poldset = (void *)arg3; + + if (pset) { + switch(how) { + case TARGET_SIG_BLOCK: + how = SIG_BLOCK; + break; + case TARGET_SIG_UNBLOCK: + how = SIG_UNBLOCK; + break; + case TARGET_SIG_SETMASK: + how = SIG_SETMASK; + break; + default: + ret = -EINVAL; + goto fail; + } + target_to_host_sigset(&set, pset); + set_ptr = &set; + } else { + how = 0; + set_ptr = NULL; + } + ret = get_errno(sigprocmask(how, set_ptr, &oldset)); + if (!is_error(ret) && poldset) { + host_to_target_sigset(poldset, &oldset); + } + } + break; + case TARGET_NR_sigpending: + { + sigset_t set; + ret = get_errno(sigpending(&set)); + if (!is_error(ret)) { + host_to_target_old_sigset((target_ulong *)arg1, &set); + } + } + break; + case TARGET_NR_rt_sigpending: + { + sigset_t set; + ret = get_errno(sigpending(&set)); + if (!is_error(ret)) { + host_to_target_sigset((target_sigset_t *)arg1, &set); + } + } + break; + case TARGET_NR_sigsuspend: + { + sigset_t set; + target_to_host_old_sigset(&set, (target_ulong *)arg1); + ret = get_errno(sigsuspend(&set)); + } + break; + case TARGET_NR_rt_sigsuspend: + { + sigset_t set; + target_to_host_sigset(&set, (target_sigset_t *)arg1); + ret = get_errno(sigsuspend(&set)); + } + break; + case TARGET_NR_rt_sigtimedwait: + { + target_sigset_t *target_set = (void *)arg1; + target_siginfo_t *target_uinfo = (void *)arg2; + struct target_timespec *target_uts = (void *)arg3; + sigset_t set; + struct timespec uts, *puts; + siginfo_t uinfo; + + target_to_host_sigset(&set, target_set); + if (target_uts) { + puts = &uts; + puts->tv_sec = tswapl(target_uts->tv_sec); + puts->tv_nsec = tswapl(target_uts->tv_nsec); + } else { + puts = NULL; + } + ret = get_errno(sigtimedwait(&set, &uinfo, puts)); + if (!is_error(ret) && target_uinfo) { + host_to_target_siginfo(target_uinfo, &uinfo); + } + } + break; + case TARGET_NR_rt_sigqueueinfo: + { + siginfo_t uinfo; + target_to_host_siginfo(&uinfo, (target_siginfo_t *)arg3); + ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo)); + } + break; + case TARGET_NR_sigreturn: + /* NOTE: ret is eax, so not transcoding must be done */ + ret = do_sigreturn(cpu_env); + break; + case TARGET_NR_rt_sigreturn: + /* NOTE: ret is eax, so not transcoding must be done */ + ret = do_rt_sigreturn(cpu_env); + break; case TARGET_NR_setreuid: ret = get_errno(setreuid(arg1, arg2)); break; case TARGET_NR_setregid: ret = get_errno(setregid(arg1, arg2)); break; - case TARGET_NR_sigsuspend: - goto unimplemented; - case TARGET_NR_sigpending: - goto unimplemented; case TARGET_NR_sethostname: ret = get_errno(sethostname((const char *)arg1, arg2)); break; @@ -1190,9 +1366,43 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, case TARGET_NR_syslog: goto unimplemented; case TARGET_NR_setitimer: - goto unimplemented; + { + struct target_itimerval *target_value = (void *)arg2; + struct target_itimerval *target_ovalue = (void *)arg3; + struct itimerval value, ovalue, *pvalue; + + if (target_value) { + pvalue = &value; + target_to_host_timeval(&pvalue->it_interval, + &target_value->it_interval); + target_to_host_timeval(&pvalue->it_value, + &target_value->it_value); + } else { + pvalue = NULL; + } + ret = get_errno(setitimer(arg1, pvalue, &ovalue)); + if (!is_error(ret) && target_ovalue) { + host_to_target_timeval(&target_ovalue->it_interval, + &ovalue.it_interval); + host_to_target_timeval(&target_ovalue->it_value, + &ovalue.it_value); + } + } + break; case TARGET_NR_getitimer: - goto unimplemented; + { + struct target_itimerval *target_value = (void *)arg2; + struct itimerval value; + + ret = get_errno(getitimer(arg1, &value)); + if (!is_error(ret) && target_value) { + host_to_target_timeval(&target_value->it_interval, + &value.it_interval); + host_to_target_timeval(&target_value->it_value, + &value.it_value); + } + } + break; case TARGET_NR_stat: ret = get_errno(stat((const char *)arg1, &st)); goto do_stat; @@ -1279,8 +1489,6 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, case TARGET_NR_fsync: ret = get_errno(fsync(arg1)); break; - case TARGET_NR_sigreturn: - goto unimplemented; case TARGET_NR_clone: ret = get_errno(do_fork(cpu_env, arg1, arg2)); break; @@ -1301,39 +1509,6 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, case TARGET_NR_mprotect: ret = get_errno(mprotect((void *)arg1, arg2, arg3)); break; - case TARGET_NR_sigprocmask: - { - int how = arg1; - sigset_t set, oldset, *set_ptr; - target_ulong *pset = (void *)arg2, *poldset = (void *)arg3; - - switch(how) { - case TARGET_SIG_BLOCK: - how = SIG_BLOCK; - break; - case TARGET_SIG_UNBLOCK: - how = SIG_UNBLOCK; - break; - case TARGET_SIG_SETMASK: - how = SIG_SETMASK; - break; - default: - ret = -EINVAL; - goto fail; - } - - if (pset) { - target_to_host_old_sigset(&set, pset); - set_ptr = &set; - } else { - set_ptr = NULL; - } - ret = get_errno(sigprocmask(arg1, set_ptr, &oldset)); - if (!is_error(ret) && poldset) { - host_to_target_old_sigset(poldset, &oldset); - } - } - break; case TARGET_NR_create_module: case TARGET_NR_init_module: case TARGET_NR_delete_module: @@ -1516,13 +1691,6 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, case TARGET_NR_setresgid: case TARGET_NR_getresgid: case TARGET_NR_prctl: - case TARGET_NR_rt_sigreturn: - case TARGET_NR_rt_sigaction: - case TARGET_NR_rt_sigprocmask: - case TARGET_NR_rt_sigpending: - case TARGET_NR_rt_sigtimedwait: - case TARGET_NR_rt_sigqueueinfo: - case TARGET_NR_rt_sigsuspend: case TARGET_NR_pread: case TARGET_NR_pwrite: goto unimplemented; |