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


Reply via email to