#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/posix4.h>
#include <sys/proc.h>
#include <sys/kernel.h>
#include <sys/resource.h>
#include <machine/cpu.h>
struct ksched {
struct timespec rr_interval;
};
int
ksched_attach(struct ksched **p)
{
struct ksched *ksched;
ksched = kmalloc(sizeof(*ksched), M_P31B, M_WAITOK);
ksched->rr_interval.tv_sec = 0;
ksched->rr_interval.tv_nsec = 1000000000L / 10;
*p = ksched;
return 0;
}
int
ksched_detach(struct ksched *p)
{
kfree(p, M_P31B);
return 0;
}
#define p4prio_to_rtpprio(P) (RTP_PRIO_MAX - (P))
#define rtpprio_to_p4prio(P) (RTP_PRIO_MAX - (P))
#define P1B_PRIO_MIN rtpprio_to_p4prio(RTP_PRIO_MAX)
#define P1B_PRIO_MAX rtpprio_to_p4prio(RTP_PRIO_MIN)
static __inline int
getscheduler(register_t *ret, struct ksched *ksched, struct lwp *lp)
{
int e = 0;
switch (lp->lwp_rtprio.type) {
case RTP_PRIO_FIFO:
*ret = SCHED_FIFO;
break;
case RTP_PRIO_REALTIME:
*ret = SCHED_RR;
break;
default:
*ret = SCHED_OTHER;
break;
}
return e;
}
int
ksched_setparam(register_t *ret, struct ksched *ksched,
struct lwp *lp, const struct sched_param *param)
{
register_t policy;
int e;
e = getscheduler(&policy, ksched, lp);
if (e == 0) {
if (policy == SCHED_OTHER)
e = EINVAL;
else
e = ksched_setscheduler(ret, ksched, lp, policy, param);
}
return e;
}
int
ksched_getparam(register_t *ret, struct ksched *ksched,
struct lwp *lp, struct sched_param *param)
{
if (RTP_PRIO_IS_REALTIME(lp->lwp_rtprio.type))
param->sched_priority = rtpprio_to_p4prio(lp->lwp_rtprio.prio);
return 0;
}
int
ksched_setscheduler(register_t *ret, struct ksched *ksched,
struct lwp *lp, int policy, const struct sched_param *param)
{
int e = 0;
struct rtprio rtp;
switch(policy) {
case SCHED_RR:
case SCHED_FIFO:
if (param->sched_priority >= P1B_PRIO_MIN &&
param->sched_priority <= P1B_PRIO_MAX) {
rtp.prio = p4prio_to_rtpprio(param->sched_priority);
rtp.type = (policy == SCHED_FIFO) ?
RTP_PRIO_FIFO : RTP_PRIO_REALTIME;
lp->lwp_rtprio = rtp;
need_user_resched();
} else {
e = EINVAL;
}
break;
case SCHED_OTHER:
rtp.type = RTP_PRIO_NORMAL;
rtp.prio = p4prio_to_rtpprio(param->sched_priority);
lp->lwp_rtprio = rtp;
need_user_resched();
break;
}
return e;
}
int
ksched_getscheduler(register_t *ret, struct ksched *ksched, struct lwp *lp)
{
return getscheduler(ret, ksched, lp);
}
int
ksched_yield(register_t *ret, struct ksched *ksched)
{
struct lwp *lp;
if ((lp = curthread->td_lwp) != NULL)
lp->lwp_proc->p_usched->yield(lp);
return 0;
}
int
ksched_get_priority_max(register_t*ret, struct ksched *ksched, int policy)
{
int e = 0;
switch (policy) {
case SCHED_FIFO:
case SCHED_RR:
*ret = RTP_PRIO_MAX;
break;
case SCHED_OTHER:
*ret = PRIO_MAX;
break;
default:
e = EINVAL;
break;
}
return e;
}
int
ksched_get_priority_min(register_t *ret, struct ksched *ksched, int policy)
{
int e = 0;
switch (policy) {
case SCHED_FIFO:
case SCHED_RR:
*ret = P1B_PRIO_MIN;
break;
case SCHED_OTHER:
*ret = PRIO_MIN;
break;
default:
e = EINVAL;
break;
}
return e;
}
int
ksched_rr_get_interval(register_t *ret, struct ksched *ksched,
struct lwp *lp, struct timespec *timespec)
{
*timespec = ksched->rr_interval;
return 0;
}