| /* | 
 |  *  BSD process related system call helpers | 
 |  * | 
 |  *  Copyright (c) 2013-14 Stacey D. Son | 
 |  * | 
 |  *  This program is free software; you can redistribute it and/or modify | 
 |  *  it under the terms of the GNU General Public License as published by | 
 |  *  the Free Software Foundation; either version 2 of the License, or | 
 |  *  (at your option) any later version. | 
 |  * | 
 |  *  This program is distributed in the hope that it will be useful, | 
 |  *  but WITHOUT ANY WARRANTY; without even the implied warranty of | 
 |  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
 |  *  GNU General Public License for more details. | 
 |  * | 
 |  *  You should have received a copy of the GNU General Public License | 
 |  *  along with this program; if not, see <http://www.gnu.org/licenses/>. | 
 |  */ | 
 | #include "qemu/osdep.h" | 
 |  | 
 | #include <sys/param.h> | 
 | #include <sys/types.h> | 
 | #include <sys/cpuset.h> | 
 | #include <sys/resource.h> | 
 | #include <sys/wait.h> | 
 |  | 
 | #include "qemu.h" | 
 | #include "qemu-bsd.h" | 
 | #include "signal-common.h" | 
 |  | 
 | #include "bsd-proc.h" | 
 |  | 
 | /* | 
 |  * resource/rusage conversion | 
 |  */ | 
 | int target_to_host_resource(int code) | 
 | { | 
 |     return code; | 
 | } | 
 |  | 
 | rlim_t target_to_host_rlim(abi_llong target_rlim) | 
 | { | 
 |     return tswap64(target_rlim); | 
 | } | 
 |  | 
 | abi_llong host_to_target_rlim(rlim_t rlim) | 
 | { | 
 |     return tswap64(rlim); | 
 | } | 
 |  | 
 | void h2g_rusage(const struct rusage *rusage, | 
 |                 struct target_freebsd_rusage *target_rusage) | 
 | { | 
 |     __put_user(rusage->ru_utime.tv_sec, &target_rusage->ru_utime.tv_sec); | 
 |     __put_user(rusage->ru_utime.tv_usec, &target_rusage->ru_utime.tv_usec); | 
 |  | 
 |     __put_user(rusage->ru_stime.tv_sec, &target_rusage->ru_stime.tv_sec); | 
 |     __put_user(rusage->ru_stime.tv_usec, &target_rusage->ru_stime.tv_usec); | 
 |  | 
 |     __put_user(rusage->ru_maxrss, &target_rusage->ru_maxrss); | 
 |     __put_user(rusage->ru_idrss, &target_rusage->ru_idrss); | 
 |     __put_user(rusage->ru_idrss, &target_rusage->ru_idrss); | 
 |     __put_user(rusage->ru_isrss, &target_rusage->ru_isrss); | 
 |     __put_user(rusage->ru_minflt, &target_rusage->ru_minflt); | 
 |     __put_user(rusage->ru_majflt, &target_rusage->ru_majflt); | 
 |     __put_user(rusage->ru_nswap, &target_rusage->ru_nswap); | 
 |     __put_user(rusage->ru_inblock, &target_rusage->ru_inblock); | 
 |     __put_user(rusage->ru_oublock, &target_rusage->ru_oublock); | 
 |     __put_user(rusage->ru_msgsnd, &target_rusage->ru_msgsnd); | 
 |     __put_user(rusage->ru_msgrcv, &target_rusage->ru_msgrcv); | 
 |     __put_user(rusage->ru_nsignals, &target_rusage->ru_nsignals); | 
 |     __put_user(rusage->ru_nvcsw, &target_rusage->ru_nvcsw); | 
 |     __put_user(rusage->ru_nivcsw, &target_rusage->ru_nivcsw); | 
 | } | 
 |  | 
 | abi_long host_to_target_rusage(abi_ulong target_addr, | 
 |         const struct rusage *rusage) | 
 | { | 
 |     struct target_freebsd_rusage *target_rusage; | 
 |  | 
 |     if (!lock_user_struct(VERIFY_WRITE, target_rusage, target_addr, 0)) { | 
 |         return -TARGET_EFAULT; | 
 |     } | 
 |     h2g_rusage(rusage, target_rusage); | 
 |     unlock_user_struct(target_rusage, target_addr, 1); | 
 |  | 
 |     return 0; | 
 | } | 
 |  | 
 | abi_long host_to_target_wrusage(abi_ulong target_addr, | 
 |                                 const struct __wrusage *wrusage) | 
 | { | 
 |     struct target_freebsd__wrusage *target_wrusage; | 
 |  | 
 |     if (!lock_user_struct(VERIFY_WRITE, target_wrusage, target_addr, 0)) { | 
 |         return -TARGET_EFAULT; | 
 |     } | 
 |     h2g_rusage(&wrusage->wru_self, &target_wrusage->wru_self); | 
 |     h2g_rusage(&wrusage->wru_children, &target_wrusage->wru_children); | 
 |     unlock_user_struct(target_wrusage, target_addr, 1); | 
 |  | 
 |     return 0; | 
 | } | 
 |  | 
 | /* | 
 |  * wait status conversion. | 
 |  * | 
 |  * Map host to target signal numbers for the wait family of syscalls. | 
 |  * Assume all other status bits are the same. | 
 |  */ | 
 | int host_to_target_waitstatus(int status) | 
 | { | 
 |     if (WIFSIGNALED(status)) { | 
 |         return host_to_target_signal(WTERMSIG(status)) | (status & ~0x7f); | 
 |     } | 
 |     if (WIFSTOPPED(status)) { | 
 |         return (host_to_target_signal(WSTOPSIG(status)) << 8) | (status & 0xff); | 
 |     } | 
 |     return status; | 
 | } | 
 |  | 
 | int bsd_get_ncpu(void) | 
 | { | 
 |     int ncpu = -1; | 
 |     cpuset_t mask; | 
 |  | 
 |     CPU_ZERO(&mask); | 
 |  | 
 |     if (cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID, -1, sizeof(mask), | 
 |                            &mask) == 0) { | 
 |         ncpu = CPU_COUNT(&mask); | 
 |     } | 
 |  | 
 |     if (ncpu == -1) { | 
 |         ncpu = sysconf(_SC_NPROCESSORS_ONLN); | 
 |     } | 
 |  | 
 |     if (ncpu == -1) { | 
 |         gemu_log("XXX Missing bsd_get_ncpu() implementation\n"); | 
 |         ncpu = 1; | 
 |     } | 
 |  | 
 |     return ncpu; | 
 | } | 
 |  |