diff options
author | davidxu <davidxu@FreeBSD.org> | 2006-07-11 05:34:35 +0000 |
---|---|---|
committer | davidxu <davidxu@FreeBSD.org> | 2006-07-11 05:34:35 +0000 |
commit | 0ef915a33177cd87c761106e82021560e7ef1458 (patch) | |
tree | ee9b7b14416ec6ead8c7f8a0a5b6b2a781832a94 /sys/kern/kern_thr.c | |
parent | 294fe32c7ef3a72e7da38813a2c9b2d9fbcecfec (diff) | |
download | FreeBSD-src-0ef915a33177cd87c761106e82021560e7ef1458.zip FreeBSD-src-0ef915a33177cd87c761106e82021560e7ef1458.tar.gz |
Add POSIX scheduler parameters support to thr_new syscall, this permits
privileged process to create realtime thread.
Diffstat (limited to 'sys/kern/kern_thr.c')
-rw-r--r-- | sys/kern/kern_thr.c | 61 |
1 files changed, 57 insertions, 4 deletions
diff --git a/sys/kern/kern_thr.c b/sys/kern/kern_thr.c index 14a768e..fab27be 100644 --- a/sys/kern/kern_thr.c +++ b/sys/kern/kern_thr.c @@ -42,6 +42,8 @@ __FBSDID("$FreeBSD$"); #include <sys/signalvar.h> #include <sys/ucontext.h> #include <sys/thr.h> +#include <sys/rtprio.h> +#include <posix4/sched.h> #include <sys/umtx.h> #include <sys/limits.h> @@ -54,7 +56,7 @@ static int create_thread(struct thread *td, mcontext_t *ctx, char *stack_base, size_t stack_size, char *tls_base, long *child_tid, long *parent_tid, - int flags); + int flags, struct thr_sched_param *sched); /* * System call interface. @@ -70,7 +72,7 @@ thr_create(struct thread *td, struct thr_create_args *uap) return (error); error = create_thread(td, &ctx.uc_mcontext, NULL, NULL, - NULL, 0, NULL, uap->id, NULL, uap->flags); + NULL, 0, NULL, uap->id, NULL, uap->flags, NULL); return (error); } @@ -79,15 +81,26 @@ thr_new(struct thread *td, struct thr_new_args *uap) /* struct thr_param * */ { struct thr_param param; + struct thr_sched_param sched_param, *sched; int error; if (uap->param_size < sizeof(param)) return (EINVAL); if ((error = copyin(uap->param, ¶m, sizeof(param)))) return (error); + sched = NULL; + if (param.sched != NULL) { + error = copyin(param.sched, &sched_param, + sizeof(sched_param)); + if (error) + return (error); + sched = &sched_param; + } + error = create_thread(td, NULL, param.start_func, param.arg, param.stack_base, param.stack_size, param.tls_base, - param.child_tid, param.parent_tid, param.flags); + param.child_tid, param.parent_tid, param.flags, + sched); return (error); } @@ -97,7 +110,7 @@ create_thread(struct thread *td, mcontext_t *ctx, char *stack_base, size_t stack_size, char *tls_base, long *child_tid, long *parent_tid, - int flags) + int flags, struct thr_sched_param *sched) { stack_t stack; struct thread *newtd; @@ -114,6 +127,22 @@ create_thread(struct thread *td, mcontext_t *ctx, if (p->p_numthreads >= max_threads_per_proc) return (EPROCLIM); + if (sched != NULL) { + /* Only root can set scheduler policy */ + if (sched->policy != SCHED_OTHER) { + if (suser(td) != 0) + return (EPERM); + + if (sched->policy != SCHED_FIFO && + sched->policy != SCHED_RR) + return (EINVAL); + + if (sched->param.sched_priority < RTP_PRIO_MIN || + sched->param.sched_priority > RTP_PRIO_MAX) + return (EINVAL); + } + } + /* Initialize our td and new ksegrp.. */ newtd = thread_alloc(); @@ -182,6 +211,30 @@ create_thread(struct thread *td, mcontext_t *ctx, /* let the scheduler know about these things. */ sched_fork_ksegrp(td, newkg); sched_fork_thread(td, newtd); + if (sched != NULL) { + struct rtprio rtp; + switch (sched->policy) { + case SCHED_FIFO: + rtp.type = PRI_FIFO; + rtp.prio = sched->param.sched_priority; + break; + case SCHED_RR: + rtp.type = PRI_REALTIME; + rtp.prio = sched->param.sched_priority; + break; + case SCHED_OTHER: + rtp.type = PRI_TIMESHARE; + if (curthread->td_ksegrp->kg_pri_class == PRI_TIMESHARE) + rtp.prio = curthread->td_ksegrp->kg_user_pri; + else + rtp.prio = 0; + break; + default: + panic("sched policy"); + } + rtp_to_pri(&rtp, newkg); + sched_prio(newtd, newkg->kg_user_pri); + } TD_SET_CAN_RUN(newtd); /* if ((flags & THR_SUSPENDED) == 0) */ setrunqueue(newtd, SRQ_BORING); |