summaryrefslogtreecommitdiffstats
path: root/sys/kern
diff options
context:
space:
mode:
authordavidxu <davidxu@FreeBSD.org>2006-07-13 06:26:43 +0000
committerdavidxu <davidxu@FreeBSD.org>2006-07-13 06:26:43 +0000
commitaf8c97a3f875a673bf0e9cf881a1b5f07fae16e0 (patch)
tree90748ff8e487df1febcb275ba4fc1ad489da1d2e /sys/kern
parentd49c8aec47f9333c0b7fa3cb2790bbe28aa72e87 (diff)
downloadFreeBSD-src-af8c97a3f875a673bf0e9cf881a1b5f07fae16e0.zip
FreeBSD-src-af8c97a3f875a673bf0e9cf881a1b5f07fae16e0.tar.gz
Add syscalls thr_setscheduler, thr_getscheduler, and thr_setschedparam,
these syscalls are designed to set thread's scheduling parameters and policy, because each syscall contains a size parameter, it is possible to support future scheduling option, e.g SCHED_SPORADIC, this option needs other fields in structure sched_param, current they are not avaiblable.
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/kern_thr.c160
-rw-r--r--sys/kern/syscalls.master9
2 files changed, 167 insertions, 2 deletions
diff --git a/sys/kern/kern_thr.c b/sys/kern/kern_thr.c
index 70d0e24..a57e4a1 100644
--- a/sys/kern/kern_thr.c
+++ b/sys/kern/kern_thr.c
@@ -27,6 +27,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_posix.h"
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/lock.h>
@@ -44,6 +45,7 @@ __FBSDID("$FreeBSD$");
#include <sys/thr.h>
#include <sys/rtprio.h>
#include <posix4/sched.h>
+#include <posix4/posix4.h>
#include <sys/umtx.h>
#include <sys/limits.h>
@@ -89,8 +91,11 @@ thr_new(struct thread *td, struct thr_new_args *uap)
if ((error = copyin(uap->param, &param, sizeof(param))))
return (error);
sched = NULL;
- if (param.sched != NULL) {
- error = copyin(param.sched, &sched_param,
+ if (param.sched_param != NULL) {
+ if (param.sched_param_size != sizeof(struct thr_sched_param))
+ return (EINVAL);
+
+ error = copyin(param.sched_param, &sched_param,
sizeof(sched_param));
if (error)
return (error);
@@ -431,3 +436,154 @@ thr_set_name(struct thread *td, struct thr_set_name_args *uap)
PROC_UNLOCK(p);
return (error);
}
+
+int
+thr_setscheduler(struct thread *td, struct thr_setscheduler_args *uap)
+{
+ struct proc *p;
+ struct thread *ttd;
+ struct rtprio rtp;
+ struct sched_param param;
+ int ret;
+
+ if (uap->param_size != sizeof(struct sched_param))
+ return (EINVAL);
+
+ ret = copyin(uap->param, &param, sizeof(struct sched_param));
+ if (ret)
+ return (ret);
+
+ switch(uap->policy) {
+ case SCHED_FIFO:
+ if (suser(td) != 0)
+ return (EPERM);
+ rtp.type = PRI_FIFO;
+ break;
+ case SCHED_RR:
+ if (suser(td) != 0)
+ return (EPERM);
+ rtp.type = PRI_REALTIME;
+ break;
+ case SCHED_OTHER:
+ rtp.type = PRI_TIMESHARE;
+ break;
+ default:
+ return (EINVAL);
+ }
+ rtp.prio = param.sched_priority;
+
+ p = td->td_proc;
+ PROC_LOCK(p);
+ ret = p_cansched(td, p);
+ if (ret != 0) {
+ PROC_UNLOCK(p);
+ return (ret);
+ }
+
+ ttd = thread_find(p, uap->id);
+ if (ttd == NULL) {
+ PROC_UNLOCK(p);
+ return (ESRCH);
+ }
+ mtx_lock_spin(&sched_lock);
+ ret = rtp_to_pri(&rtp, ttd->td_ksegrp);
+ if (ret == 0) {
+ if (TD_IS_RUNNING(ttd))
+ ttd->td_flags |= TDF_NEEDRESCHED;
+ else if (ttd->td_priority > ttd->td_ksegrp->kg_user_pri)
+ sched_prio(ttd, ttd->td_ksegrp->kg_user_pri);
+ }
+ mtx_unlock_spin(&sched_lock);
+ PROC_UNLOCK(p);
+ return (ret);
+}
+
+int
+thr_getscheduler(struct thread *td, struct thr_getscheduler_args *uap)
+{
+ struct proc *p;
+ struct thread *ttd;
+ struct rtprio rtp;
+ struct sched_param param;
+ int policy;
+ int ret;
+
+ if (uap->param_size != sizeof(struct sched_param))
+ return (EINVAL);
+
+ p = td->td_proc;
+ PROC_LOCK(p);
+ ttd = thread_find(p, uap->id);
+ if (ttd == NULL) {
+ PROC_UNLOCK(p);
+ return (ESRCH);
+ }
+ mtx_lock_spin(&sched_lock);
+ switch(ttd->td_ksegrp->kg_pri_class) {
+ case PRI_TIMESHARE:
+ policy = SCHED_OTHER;
+ break;
+ case PRI_FIFO:
+ policy = SCHED_FIFO;
+ break;
+ case PRI_REALTIME:
+ policy = SCHED_RR;
+ break;
+ default:
+ policy = SCHED_OTHER; /* XXX SCHED_IDLE */
+ }
+ pri_to_rtp(ttd->td_ksegrp, &rtp);
+ mtx_unlock_spin(&sched_lock);
+ PROC_UNLOCK(p);
+
+ param.sched_priority = rtp.prio;
+ ret = copyout(&policy, uap->policy, sizeof(policy));
+ if (ret == 0)
+ ret = copyout(&param, uap->param, sizeof(param));
+ return (ret);
+}
+
+int
+thr_setschedparam(struct thread *td, struct thr_setschedparam_args *uap)
+{
+ struct proc *p;
+ struct thread *ttd;
+ struct rtprio rtp;
+ struct sched_param param;
+ int ret;
+
+ if (uap->param_size != sizeof(struct sched_param))
+ return (EINVAL);
+
+ ret = copyin(uap->param, &param, sizeof(struct sched_param));
+ if (ret)
+ return (ret);
+
+ p = td->td_proc;
+ PROC_LOCK(p);
+ ret = p_cansched(td, p);
+ if (ret != 0) {
+ PROC_UNLOCK(p);
+ return (ret);
+ }
+
+ ttd = thread_find(p, uap->id);
+ if (ttd == NULL) {
+ PROC_UNLOCK(p);
+ return (ESRCH);
+ }
+
+ mtx_lock_spin(&sched_lock);
+ pri_to_rtp(ttd->td_ksegrp, &rtp);
+ rtp.prio = param.sched_priority;
+ ret = rtp_to_pri(&rtp, ttd->td_ksegrp);
+ if (ret == 0) {
+ if (TD_IS_RUNNING(ttd))
+ ttd->td_flags |= TDF_NEEDRESCHED;
+ else if (ttd->td_priority > ttd->td_ksegrp->kg_user_pri)
+ sched_prio(ttd, ttd->td_ksegrp->kg_user_pri);
+ }
+ mtx_unlock_spin(&sched_lock);
+ PROC_UNLOCK(p);
+ return (ret);
+}
diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master
index ecd8c8f..fd73f1c 100644
--- a/sys/kern/syscalls.master
+++ b/sys/kern/syscalls.master
@@ -822,5 +822,14 @@
463 AUE_NULL MSTD { int abort2(const char *why, int nargs, void **args); }
464 AUE_NULL MSTD { int thr_set_name(long id, const char *name); }
465 AUE_NULL MNOSTD { int aio_fsync(int op, struct aiocb *aiocbp); }
+466 AUE_NULL MSTD { int thr_setscheduler(long id, int policy,\
+ const struct sched_param *param, \
+ int param_size); }
+467 AUE_NULL MSTD { int thr_getscheduler(long id, int *policy,\
+ struct sched_param *param, \
+ int param_size); }
+468 AUE_NULL MSTD { int thr_setschedparam(long id, \
+ const struct sched_param *param, \
+ int param_size); }
; Please copy any additions and changes to the following compatability tables:
; sys/compat/freebsd32/syscalls.master
OpenPOWER on IntegriCloud