Expand os-misc.h with scheduler functions (sched_setparam, sched_getparam, sched_setscheduler, sched_getscheduler, sched_rr_get_interval) and CPU affinity functions (cpuset, cpuset_setid, cpuset_getid, cpuset_getaffinity, cpuset_setaffinity). Also add sched_yield, sched_get_priority_min, and sched_get_priority_max to bsd-proc.h.
Signed-off-by: Stacey Son <[email protected]> Signed-off-by: Sean Bruno <[email protected]> Signed-off-by: Mikaƫl Urankar <[email protected]> Signed-off-by: Warner Losh <[email protected]> Assisted-by: Claude Opus 4.6 (1M context) --- bsd-user/bsd-proc.h | 20 +++- bsd-user/freebsd/os-misc.h | 288 +++++++++++++++++++++++++++++++++++++-------- 2 files changed, 257 insertions(+), 51 deletions(-) diff --git a/bsd-user/bsd-proc.h b/bsd-user/bsd-proc.h index 62052c70b9..b9973dbedf 100644 --- a/bsd-user/bsd-proc.h +++ b/bsd-user/bsd-proc.h @@ -400,4 +400,22 @@ static inline abi_long do_bsd_setpriority(abi_long which, abi_long who, return get_errno(setpriority(which, who, prio)); } -#endif /* !BSD_PROC_H_ */ +/* sched_yield(2) */ +static inline abi_long do_bsd_sched_yield(void) +{ + return get_errno(sched_yield()); +} + +/* sched_get_priority_min(2) */ +static inline abi_long do_bsd_sched_get_priority_min(int policy) +{ + return get_errno(sched_get_priority_min(policy)); +} + +/* sched_get_priority_max(2) */ +static inline abi_long do_bsd_sched_get_priority_max(int policy) +{ + return get_errno(sched_get_priority_max(policy)); +} + +#endif /* !BSD_PROC_H */ diff --git a/bsd-user/freebsd/os-misc.h b/bsd-user/freebsd/os-misc.h index d9979b2a8b..74ed1d2f47 100644 --- a/bsd-user/freebsd/os-misc.h +++ b/bsd-user/freebsd/os-misc.h @@ -11,76 +11,264 @@ #include <sys/cpuset.h> #include <sys/random.h> #include <sched.h> +#include <kenv.h> -/* - * shm_open2 isn't exported, but the __sys_ alias is. We can use either for the - * static version, but to dynamically link we have to use the sys version. - */ -int __sys_shm_open2(const char *path, int flags, mode_t mode, int shmflags, +int shm_open2(const char *path, int flags, mode_t mode, int shmflags, const char *); -#if defined(__FreeBSD_version) && __FreeBSD_version >= 1300048 -/* shm_open2(2) */ -static inline abi_long do_freebsd_shm_open2(abi_ulong pathptr, abi_ulong flags, - abi_long mode, abi_ulong shmflags, abi_ulong nameptr) +/* sched_setparam(2) */ +static inline abi_long do_freebsd_sched_setparam(pid_t pid, + abi_ulong target_sp_addr) { - int ret; - void *uname, *upath; + abi_long ret; + struct sched_param host_sp; - if (pathptr == (uintptr_t)SHM_ANON) { - upath = SHM_ANON; - } else { - upath = lock_user_string(pathptr); - if (upath == NULL) { - return -TARGET_EFAULT; - } + ret = get_user_s32(host_sp.sched_priority, target_sp_addr); + if (!is_error(ret)) { + ret = get_errno(sched_setparam(pid, &host_sp)); } + return ret; +} - uname = NULL; - if (nameptr != 0) { - uname = lock_user_string(nameptr); - if (uname == NULL) { - unlock_user(upath, pathptr, 0); - return -TARGET_EFAULT; - } +/* sched_get_param(2) */ +static inline abi_long do_freebsd_sched_getparam(pid_t pid, + abi_ulong target_sp_addr) +{ + abi_long ret; + struct sched_param host_sp; + + ret = get_errno(sched_getparam(pid, &host_sp)); + if (!is_error(ret)) { + ret = put_user_s32(host_sp.sched_priority, target_sp_addr); } - ret = get_errno(__sys_shm_open2(upath, - target_to_host_bitmask(flags, fcntl_flags_tbl), mode, - target_to_host_bitmask(shmflags, shmflag_flags_tbl), uname)); + return ret; +} + +/* sched_setscheduler(2) */ +static inline abi_long do_freebsd_sched_setscheduler(pid_t pid, int policy, + abi_ulong target_sp_addr) +{ + abi_long ret; + struct sched_param host_sp; - if (upath != SHM_ANON) { - unlock_user(upath, pathptr, 0); + ret = get_user_s32(host_sp.sched_priority, target_sp_addr); + if (!is_error(ret)) { + ret = get_errno(sched_setscheduler(pid, policy, &host_sp)); } - if (uname != NULL) { - unlock_user(uname, nameptr, 0); + return ret; +} + +/* sched_getscheduler(2) */ +static inline abi_long do_freebsd_sched_getscheduler(pid_t pid) +{ + + return get_errno(sched_getscheduler(pid)); +} + +/* sched_getscheduler(2) */ +static inline abi_long do_freebsd_sched_rr_get_interval(pid_t pid, + abi_ulong target_ts_addr) +{ + abi_long ret; + struct timespec host_ts; + + ret = get_errno(sched_rr_get_interval(pid, &host_ts)); + if (!is_error(ret)) { + ret = h2t_freebsd_timespec(target_ts_addr, &host_ts); } return ret; } -#endif /* __FreeBSD_version >= 1300048 */ -#if defined(__FreeBSD_version) && __FreeBSD_version >= 1300049 -/* shm_rename(2) */ -static inline abi_long do_freebsd_shm_rename(abi_ulong fromptr, abi_ulong toptr, - abi_ulong flags) +/* cpuset(2) */ +static inline abi_long do_freebsd_cpuset(abi_ulong target_cpuid) { - int ret; - void *ufrom, *uto; + abi_long ret; + cpusetid_t setid; - ufrom = lock_user_string(fromptr); - if (ufrom == NULL) { - return -TARGET_EFAULT; + ret = get_errno(cpuset(&setid)); + if (is_error(ret)) { + return ret; } - uto = lock_user_string(toptr); - if (uto == NULL) { - unlock_user(ufrom, fromptr, 0); - return -TARGET_EFAULT; + return put_user_s32(setid, target_cpuid); +} + +#define target_to_host_cpuset_which(hp, t) { \ + (*hp) = t; \ +} while (0) + +#define target_to_host_cpuset_level(hp, t) { \ + (*hp) = t; \ +} while (0) + +/* cpuset_setid(2) */ +static inline abi_long do_freebsd_cpuset_setid(CPUArchState *env, abi_long arg1, + abi_ulong arg2, abi_ulong arg3, abi_ulong arg4, abi_ulong arg5) +{ + id_t id; /* 64-bit value */ + cpusetid_t setid; + cpuwhich_t which; + + target_to_host_cpuset_which(&which, arg1); +#if TARGET_ABI_BITS == 32 + /* See if we need to align the register pairs */ + if (regpairs_aligned(env)) { + id = target_arg64(arg3, arg4); + setid = arg5; + } else { + id = target_arg64(arg2, arg3); + setid = arg4; } - ret = get_errno(shm_rename(ufrom, uto, flags)); - unlock_user(ufrom, fromptr, 0); - unlock_user(uto, toptr, 0); +#else + id = arg2; + setid = arg3; +#endif + return get_errno(cpuset_setid(which, id, setid)); +} + +/* cpuset_getid(2) */ +static inline abi_long do_freebsd_cpuset_getid(abi_long arg1, abi_ulong arg2, + abi_ulong arg3, abi_ulong arg4, abi_ulong arg5) +{ + abi_long ret; + id_t id; /* 64-bit value */ + cpusetid_t setid; + cpuwhich_t which; + cpulevel_t level; + abi_ulong target_setid; + + target_to_host_cpuset_which(&which, arg1) + ; + target_to_host_cpuset_level(&level, arg2); +#if TARGET_ABI_BITS == 32 + id = target_arg64(arg3, arg4); + target_setid = arg5; +#else + id = arg3; + target_setid = arg4; +#endif + ret = get_errno(cpuset_getid(level, which, id, &setid)); + if (is_error(ret)) { + return ret; + } + return put_user_s32(setid, target_setid); +} + +static abi_ulong copy_from_user_cpuset_mask(cpuset_t *mask, + abi_ulong target_mask_addr) +{ + int i, j, k; + abi_ulong b, *target_mask; + + target_mask = lock_user(VERIFY_READ, target_mask_addr, + CPU_SETSIZE / 8, 1); + if (target_mask == NULL) { + return -TARGET_EFAULT; + } + CPU_ZERO(mask); + k = 0; + for (i = 0; i < ((CPU_SETSIZE / 8) / sizeof(abi_ulong)); i++) { + __get_user(b, &target_mask[i]); + for (j = 0; j < TARGET_ABI_BITS; j++) { + if ((b >> j) & 1) { + CPU_SET(k, mask); + } + k++; + } + } + unlock_user(target_mask, target_mask_addr, 0); + + return 0; +} + +static abi_ulong copy_to_user_cpuset_mask(abi_ulong target_mask_addr, + cpuset_t *mask) +{ + int i, j, k; + abi_ulong b, *target_mask; + + target_mask = lock_user(VERIFY_WRITE, target_mask_addr, + CPU_SETSIZE / 8, 0); + if (target_mask == NULL) { + return -TARGET_EFAULT; + } + k = 0; + for (i = 0; i < ((CPU_SETSIZE / 8) / sizeof(abi_ulong)); i++) { + b = 0; + for (j = 0; j < TARGET_ABI_BITS; j++) { + b |= ((CPU_ISSET(k, mask) != 0) << j); + k++; + } + __put_user(b, &target_mask[i]); + } + unlock_user(target_mask, target_mask_addr, (CPU_SETSIZE / 8)); + + return 0; +} + +/* cpuset_getaffinity(2) */ +/* cpuset_getaffinity(cpulevel_t, cpuwhich_t, id_t, size_t, cpuset_t *); */ +static inline abi_long do_freebsd_cpuset_getaffinity(cpulevel_t level, + cpuwhich_t which, abi_ulong arg3, abi_ulong arg4, abi_ulong arg5, + abi_ulong arg6) +{ + cpuset_t mask; + abi_long ret; + id_t id; /* 64-bit */ + abi_ulong setsize, target_mask; + +#if TARGET_ABI_BITS == 32 + id = (id_t)target_arg64(arg3, arg4); + setsize = arg5; + target_mask = arg6; +#else + id = (id_t)arg3; + setsize = arg4; + target_mask = arg5; +#endif + + ret = get_errno(cpuset_getaffinity(level, which, id, setsize, &mask)); + if (ret == 0) { + ret = copy_to_user_cpuset_mask(target_mask, &mask); + } return ret; } -#endif /* __FreeBSD_version >= 1300049 */ + +/* cpuset_setaffinity(2) */ +/* cpuset_setaffinity(cpulevel_t, cpuwhich_t, id_t, size_t, const cpuset_t *);*/ +static inline abi_long do_freebsd_cpuset_setaffinity(cpulevel_t level, + cpuwhich_t which, abi_ulong arg3, abi_ulong arg4, abi_ulong arg5, + abi_ulong arg6) +{ + cpuset_t mask; + abi_long ret; + id_t id; /* 64-bit */ + abi_ulong setsize, target_mask; + +#if TARGET_ABI_BITS == 32 + id = (id_t)target_arg64(arg3, arg4); + setsize = arg5; + target_mask = arg6; +#else + id = (id_t)arg3; + setsize = arg4; + target_mask = arg5; +#endif + + ret = copy_from_user_cpuset_mask(&mask, target_mask); + if (ret == 0) { + ret = get_errno(cpuset_setaffinity(level, which, id, setsize, + &mask)); + } + + return ret; +} + +/* + * Pretend there are no modules loaded into the kernel. Don't allow loading or + * unloading of modules. This works well for tests, and little else seems to + * care. Will reevaluate if examples are found that do matter. + */ + #endif /* OS_MISC_H */ -- 2.52.0
