#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/sysent.h>
#include <sys/malloc.h>
#include <sys/posix4.h>
#include <sys/proc.h>
#include <sys/syslog.h>
#include <sys/module.h>
#include <sys/sysmsg.h>
#include <sys/sysctl.h>
#include <sys/unistd.h>
MALLOC_DEFINE(M_P31B, "p1003.1b", "Posix 1003.1B");
#if 0
#define CAN_AFFECT(p, cr, q) \
((cr)->cr_uid == 0 || \
(cr)->cr_ruid == (q)->p_ucred->cr_ruid || \
(cr)->cr_uid == (q)->p_ucred->cr_ruid || \
(cr)->cr_ruid == (q)->p_ucred->cr_uid || \
(cr)->cr_uid == (q)->p_ucred->cr_uid)
#else
#define CAN_AFFECT(p, cr, q) ((cr)->cr_uid == 0)
#endif
#if !defined(_KPOSIX_PRIORITY_SCHEDULING)
int syscall_not_present(const char *s);
int syscall_not_present(const char *s)
{
struct proc *p = curproc;
log(LOG_ERR, "cmd %s pid %d tried to use non-present %s\n",
p->p_comm, p->p_pid, s);
return ENOSYS;
}
static int sched_attach(void)
{
return 0;
}
#define SYSCALL_NOT_PRESENT_GEN(SC) \
int sys_##SC (struct sysmsg *sysmsg, const struct SC##_args *uap) \
{ \
return syscall_not_present(#SC); \
}
SYSCALL_NOT_PRESENT_GEN(sched_setparam)
SYSCALL_NOT_PRESENT_GEN(sched_getparam)
SYSCALL_NOT_PRESENT_GEN(sched_setscheduler)
SYSCALL_NOT_PRESENT_GEN(sched_getscheduler)
SYSCALL_NOT_PRESENT_GEN(sched_yield)
SYSCALL_NOT_PRESENT_GEN(sched_get_priority_max)
SYSCALL_NOT_PRESENT_GEN(sched_get_priority_min)
SYSCALL_NOT_PRESENT_GEN(sched_rr_get_interval)
#else
static
int
p31b_proc(pid_t pid, struct proc **pp)
{
int ret = 0;
struct proc *p = curproc;
struct proc *other_proc;
if (pid == 0) {
other_proc = p;
if (other_proc)
PHOLD(other_proc);
} else {
other_proc = pfind(pid);
}
if (other_proc) {
if (CAN_AFFECT(p, p->p_ucred, other_proc)) {
*pp = other_proc;
lwkt_gettoken(&other_proc->p_token);
} else {
*pp = NULL;
ret = EPERM;
PRELE(other_proc);
}
} else {
*pp = NULL;
ret = ESRCH;
}
return ret;
}
static
void
p31b_proc_done(struct proc *other_proc)
{
if (other_proc) {
lwkt_reltoken(&other_proc->p_token);
PRELE(other_proc);
}
}
static struct ksched *ksched;
static int sched_attach(void)
{
int ret = ksched_attach(&ksched);
if (ret == 0)
p31b_setcfg(CTL_P1003_1B_PRIORITY_SCHEDULING, 1);
return ret;
}
int
sys_sched_setparam(struct sysmsg *sysmsg,
const struct sched_setparam_args *uap)
{
struct proc *p;
struct lwp *lp;
struct sched_param sched_param;
int e;
copyin(uap->param, &sched_param, sizeof(sched_param));
if ((e = p31b_proc(uap->pid, &p)) == 0) {
lp = FIRST_LWP_IN_PROC(p);
if (lp) {
LWPHOLD(lp);
lwkt_gettoken(&lp->lwp_token);
e = ksched_setparam(&sysmsg->sysmsg_reg, ksched, lp,
(const struct sched_param *)&sched_param);
lwkt_reltoken(&lp->lwp_token);
LWPRELE(lp);
} else {
e = ESRCH;
}
p31b_proc_done(p);
}
return e;
}
int
sys_sched_getparam(struct sysmsg *sysmsg,
const struct sched_getparam_args *uap)
{
struct proc *targetp;
struct lwp *lp;
struct sched_param sched_param;
int e;
if ((e = p31b_proc(uap->pid, &targetp)) == 0) {
lp = FIRST_LWP_IN_PROC(targetp);
if (lp) {
LWPHOLD(lp);
lwkt_gettoken(&lp->lwp_token);
e = ksched_getparam(&sysmsg->sysmsg_reg, ksched,
lp, &sched_param);
lwkt_reltoken(&lp->lwp_token);
LWPRELE(lp);
} else {
e = ESRCH;
}
p31b_proc_done(targetp);
}
if (e == 0)
copyout(&sched_param, uap->param, sizeof(sched_param));
return e;
}
int
sys_sched_setscheduler(struct sysmsg *sysmsg,
const struct sched_setscheduler_args *uap)
{
struct proc *p;
struct lwp *lp;
int e;
struct sched_param sched_param;
copyin(uap->param, &sched_param, sizeof(sched_param));
if ((e = p31b_proc(uap->pid, &p)) == 0) {
lp = FIRST_LWP_IN_PROC(p);
if (lp) {
LWPHOLD(lp);
lwkt_gettoken(&lp->lwp_token);
e = ksched_setscheduler(&sysmsg->sysmsg_reg, ksched,
lp, uap->policy,
(const struct sched_param *)&sched_param);
lwkt_reltoken(&lp->lwp_token);
LWPRELE(lp);
} else {
e = ESRCH;
}
p31b_proc_done(p);
}
return e;
}
int
sys_sched_getscheduler(struct sysmsg *sysmsg,
const struct sched_getscheduler_args *uap)
{
struct proc *targetp;
struct lwp *lp;
int e;
if ((e = p31b_proc(uap->pid, &targetp)) == 0) {
lp = FIRST_LWP_IN_PROC(targetp);
if (lp) {
LWPHOLD(lp);
lwkt_gettoken(&lp->lwp_token);
e = ksched_getscheduler(&sysmsg->sysmsg_reg, ksched, lp);
lwkt_reltoken(&lp->lwp_token);
LWPRELE(lp);
} else {
e = ESRCH;
}
p31b_proc_done(targetp);
}
return e;
}
int
sys_sched_yield(struct sysmsg *sysmsg,
const struct sched_yield_args *uap)
{
return ksched_yield(&sysmsg->sysmsg_reg, ksched);
}
int
sys_sched_get_priority_max(struct sysmsg *sysmsg,
const struct sched_get_priority_max_args *uap)
{
return ksched_get_priority_max(&sysmsg->sysmsg_reg, ksched, uap->policy);
}
int
sys_sched_get_priority_min(struct sysmsg *sysmsg,
const struct sched_get_priority_min_args *uap)
{
return ksched_get_priority_min(&sysmsg->sysmsg_reg, ksched, uap->policy);
}
int
sys_sched_rr_get_interval(struct sysmsg *sysmsg,
const struct sched_rr_get_interval_args *uap)
{
int e;
struct proc *p;
struct lwp *lp;
struct timespec ts;
if ((e = p31b_proc(uap->pid, &p)) == 0) {
lp = FIRST_LWP_IN_PROC(p);
if (lp) {
LWPHOLD(lp);
lwkt_gettoken(&lp->lwp_token);
e = ksched_rr_get_interval(&sysmsg->sysmsg_reg, ksched,
lp, &ts);
if (e == 0)
e = copyout(&ts, uap->interval, sizeof(ts));
lwkt_reltoken(&lp->lwp_token);
LWPRELE(lp);
} else {
e = ESRCH;
}
p31b_proc_done(p);
}
return e;
}
#endif
static void
p31binit(void *notused)
{
sched_attach();
p31b_setcfg(CTL_P1003_1B_ASYNCHRONOUS_IO, -1);
p31b_setcfg(CTL_P1003_1B_FSYNC, _POSIX_FSYNC);
p31b_setcfg(CTL_P1003_1B_MAPPED_FILES, _POSIX_MAPPED_FILES);
p31b_setcfg(CTL_P1003_1B_MESSAGE_PASSING, _POSIX_MESSAGE_PASSING);
p31b_setcfg(CTL_P1003_1B_PAGESIZE, PAGE_SIZE);
p31b_setcfg(CTL_P1003_1B_SEMAPHORES, _POSIX_SEMAPHORES);
p31b_setcfg(CTL_P1003_1B_SEM_NSEMS_MAX, 256);
p31b_setcfg(CTL_P1003_1B_SHARED_MEMORY_OBJECTS,
_POSIX_SHARED_MEMORY_OBJECTS);
#if 0
p31b_setcfg(CTL_P1003_1B_ASYNCHRONOUS_IO, _POSIX_ASYNCHRONOUS_IO);
p31b_setcfg(CTL_P1003_1B_AIO_PRIO_DELTA_MAX, 0);
p31b_setcfg(CTL_P1003_1B_AIO_MAX, 0);
p31b_setcfg(CTL_P1003_1B_AIO_LISTIO_MAX, 0);
p31b_setcfg(CTL_P1003_1B_DELAYTIMER_MAX, 0);
p31b_setcfg(CTL_P1003_1B_MEMLOCK, 0);
p31b_setcfg(CTL_P1003_1B_MEMLOCK_RANGE, 0);
p31b_setcfg(CTL_P1003_1B_MEMORY_PROTECTION, 0);
p31b_setcfg(CTL_P1003_1B_PRIORITIZED_IO, _POSIX_PRIORITIZED_IO);
p31b_setcfg(CTL_P1003_1B_REALTIME_SIGNALS, _POSIX_REALTIME_SIGNALS);
p31b_setcfg(CTL_P1003_1B_RTSIG_MAX, SIGRTMAX - SIGRTMIN + 1);
p31b_setcfg(CTL_P1003_1B_SIGQUEUE_MAX, 0);
p31b_setcfg(CTL_P1003_1B_SYNCHRONIZED_IO, _POSIX_SYNCHRONIZED_IO);
p31b_setcfg(CTL_P1003_1B_TIMERS, _POSIX_TIMERS);
p31b_setcfg(CTL_P1003_1B_TIMER_MAX, 0);
#endif
}
SYSINIT(p31b, SI_SUB_P1003_1B, SI_ORDER_FIRST, p31binit, NULL);