Index: sys/compat/linux/linux_misc.c =================================================================== --- sys/compat/linux/linux_misc.c (revision 352213) +++ sys/compat/linux/linux_misc.c (working copy) @@ -1422,6 +1422,30 @@ linux_sched_setscheduler(struct thread *td, if (error) return (error); + switch (policy) { + case SCHED_OTHER: + if (sched_param.sched_priority != 0) + return (EINVAL); + + sched_param.sched_priority = + PRI_MAX_TIMESHARE - PRI_MIN_TIMESHARE; + break; + case SCHED_FIFO: + case SCHED_RR: + if (sched_param.sched_priority < 1 || + sched_param.sched_priority > LINUX_SCHED_RTPRIO_MAX) + return (EINVAL); + + /* + * Map [1, LINUX_SCHED_RTPRIO_MAX] to + * [0, RTP_PRIO_MAX - RTP_PRIO_MIN] (rounding down). + */ + sched_param.sched_priority = (sched_param.sched_priority - 1) * + (RTP_PRIO_MAX - RTP_PRIO_MIN) / + (LINUX_SCHED_RTPRIO_MAX - 1); + break; + } + tdt = linux_tdfind(td, args->pid, -1); if (tdt == NULL) return (ESRCH); @@ -1463,44 +1487,34 @@ int linux_sched_get_priority_max(struct thread *td, struct linux_sched_get_priority_max_args *args) { - struct sched_get_priority_max_args bsd; - switch (args->policy) { case LINUX_SCHED_OTHER: - bsd.policy = SCHED_OTHER; - break; + td->td_retval[0] = 0; + return (0); case LINUX_SCHED_FIFO: - bsd.policy = SCHED_FIFO; - break; case LINUX_SCHED_RR: - bsd.policy = SCHED_RR; - break; + td->td_retval[0] = LINUX_SCHED_RTPRIO_MAX; + return (0); default: return (EINVAL); } - return (sys_sched_get_priority_max(td, &bsd)); } int linux_sched_get_priority_min(struct thread *td, struct linux_sched_get_priority_min_args *args) { - struct sched_get_priority_min_args bsd; - switch (args->policy) { case LINUX_SCHED_OTHER: - bsd.policy = SCHED_OTHER; - break; + td->td_retval[0] = 0; + return (0); case LINUX_SCHED_FIFO: - bsd.policy = SCHED_FIFO; - break; case LINUX_SCHED_RR: - bsd.policy = SCHED_RR; - break; + td->td_retval[0] = 1; + return (0); default: return (EINVAL); } - return (sys_sched_get_priority_min(td, &bsd)); } #define REBOOT_CAD_ON 0x89abcdef @@ -1873,7 +1887,7 @@ linux_sched_setparam(struct thread *td, { struct sched_param sched_param; struct thread *tdt; - int error; + int error, policy; error = copyin(uap->param, &sched_param, sizeof(sched_param)); if (error) @@ -1883,8 +1897,37 @@ linux_sched_setparam(struct thread *td, if (tdt == NULL) return (ESRCH); + error = kern_sched_getscheduler(td, tdt, &policy); + if (error) + goto out; + + switch (policy) { + case SCHED_OTHER: + if (sched_param.sched_priority != 0) { + error = EINVAL; + goto out; + } + sched_param.sched_priority = + PRI_MAX_TIMESHARE - PRI_MIN_TIMESHARE; + break; + case SCHED_FIFO: + case SCHED_RR: + if (sched_param.sched_priority < 1 || + sched_param.sched_priority > LINUX_SCHED_RTPRIO_MAX) { + error = EINVAL; + goto out; + } + /* + * Map [1, LINUX_SCHED_RTPRIO_MAX] to + * [0, RTP_PRIO_MAX - RTP_PRIO_MIN] (rounding down). + */ + sched_param.sched_priority = (sched_param.sched_priority - 1) * + (RTP_PRIO_MAX - RTP_PRIO_MIN) / + (LINUX_SCHED_RTPRIO_MAX - 1); + break; + } error = kern_sched_setparam(td, tdt, &sched_param); - PROC_UNLOCK(tdt->td_proc); +out: PROC_UNLOCK(tdt->td_proc); return (error); } @@ -1894,17 +1937,40 @@ linux_sched_getparam(struct thread *td, { struct sched_param sched_param; struct thread *tdt; - int error; + int error, policy; tdt = linux_tdfind(td, uap->pid, -1); if (tdt == NULL) return (ESRCH); - error = kern_sched_getparam(td, tdt, &sched_param); - PROC_UNLOCK(tdt->td_proc); - if (error == 0) - error = copyout(&sched_param, uap->param, - sizeof(sched_param)); + error = kern_sched_getscheduler(td, tdt, &policy); + if (error) { + PROC_UNLOCK(tdt->td_proc); + return (error); + } + switch (policy) { + case SCHED_OTHER: + PROC_UNLOCK(tdt->td_proc); + sched_param.sched_priority = 0; + break; + case SCHED_FIFO: + case SCHED_RR: + error = kern_sched_getparam(td, tdt, &sched_param); + PROC_UNLOCK(tdt->td_proc); + if (error) + return (error); + + /* + * Map [0, RTP_PRIO_MAX - RTP_PRIO_MIN] to + * [1, LINUX_SCHED_RTPRIO_MAX] (rounding up). + */ + sched_param.sched_priority = (sched_param.sched_priority * + (LINUX_SCHED_RTPRIO_MAX - 1) + + (RTP_PRIO_MAX - RTP_PRIO_MIN - 1)) / + (RTP_PRIO_MAX - RTP_PRIO_MIN) + 1; + break; + } + error = copyout(&sched_param, uap->param, sizeof(sched_param)); return (error); } Index: sys/compat/linux/linux_misc.h =================================================================== --- sys/compat/linux/linux_misc.h (revision 352213) +++ sys/compat/linux/linux_misc.h (working copy) @@ -105,6 +105,8 @@ extern const char *linux_kplatform; #define LINUX_SCHED_FIFO 1 #define LINUX_SCHED_RR 2 +#define LINUX_SCHED_RTPRIO_MAX 99 + struct l_new_utsname { char sysname[LINUX_MAX_UTSNAME]; char nodename[LINUX_MAX_UTSNAME];