summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_thr.c
diff options
context:
space:
mode:
authordavidxu <davidxu@FreeBSD.org>2006-07-11 05:34:35 +0000
committerdavidxu <davidxu@FreeBSD.org>2006-07-11 05:34:35 +0000
commit0ef915a33177cd87c761106e82021560e7ef1458 (patch)
treeee9b7b14416ec6ead8c7f8a0a5b6b2a781832a94 /sys/kern/kern_thr.c
parent294fe32c7ef3a72e7da38813a2c9b2d9fbcecfec (diff)
downloadFreeBSD-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.c61
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, &param, 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);
OpenPOWER on IntegriCloud