diff options
Diffstat (limited to 'sys')
| -rw-r--r-- | sys/kern/sys_sched.c | 223 | ||||
| -rw-r--r-- | sys/sys/lwp.h | 3 | ||||
| -rw-r--r-- | sys/sys/pset.h | 28 | ||||
| -rw-r--r-- | sys/sys/sched.h | 28 |
4 files changed, 173 insertions, 109 deletions
diff --git a/sys/kern/sys_sched.c b/sys/kern/sys_sched.c index d90a51bc3da..263c4b432a6 100644 --- a/sys/kern/sys_sched.c +++ b/sys/kern/sys_sched.c @@ -1,4 +1,4 @@ -/* $NetBSD: sys_sched.c,v 1.6 2008/01/24 14:41:12 rmind Exp $ */ +/* $NetBSD: sys_sched.c,v 1.7 2008/01/26 17:55:29 rmind Exp $ */ /* * Copyright (c) 2008, Mindaugas Rasiukevicius <rmind at NetBSD org> @@ -33,7 +33,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sys_sched.c,v 1.6 2008/01/24 14:41:12 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sys_sched.c,v 1.7 2008/01/26 17:55:29 rmind Exp $"); #include <sys/param.h> @@ -52,6 +52,51 @@ __KERNEL_RCSID(0, "$NetBSD: sys_sched.c,v 1.6 2008/01/24 14:41:12 rmind Exp $"); #include <sys/unistd.h> /* + * Convert user priority or the in-kernel priority or convert the current + * priority to the appropriate range according to the policy change. + */ +static pri_t +convert_pri(lwp_t *l, int policy, pri_t pri) +{ + int delta = 0; + + if (policy == SCHED_NONE) + policy = l->l_class; + + switch (policy) { + case SCHED_OTHER: + delta = PRI_USER; + break; + case SCHED_FIFO: + case SCHED_RR: + delta = PRI_USER_RT; + break; + default: + panic("upri_to_kpri"); + } + + if (pri != PRI_NONE) { + /* Convert user priority to the in-kernel */ + KASSERT(pri >= SCHED_PRI_MIN && pri <= SCHED_PRI_MAX); + return pri + delta; + } + if (l->l_class == policy) + return l->l_priority; + + /* Change the current priority to the appropriate range */ + if (l->l_class == SCHED_OTHER) { + KASSERT(policy == SCHED_FIFO || policy == SCHED_RR); + return l->l_priority + delta; + } + if (policy == SCHED_OTHER) { + KASSERT(l->l_class == SCHED_FIFO || l->l_class == SCHED_RR); + return l->l_priority - delta; + } + KASSERT(l->l_class != SCHED_OTHER && policy != SCHED_OTHER); + return l->l_class; +} + +/* * Set scheduling parameters. */ int @@ -66,103 +111,87 @@ sys__sched_setparam(struct lwp *l, const struct sys__sched_setparam_args *uap, struct sched_param *sp; struct proc *p; struct lwp *t; - pid_t pid; lwpid_t lid; u_int lcnt; + int policy; pri_t pri; int error; /* Available only for super-user */ if (kauth_authorize_generic(l->l_cred, KAUTH_GENERIC_ISSUSER, NULL)) - return EACCES; + return EPERM; /* Get the parameters from the user-space */ sp = kmem_zalloc(sizeof(struct sched_param), KM_SLEEP); error = copyin(SCARG(uap, params), sp, sizeof(struct sched_param)); - if (error) - goto error; - - /* - * Validate scheduling class and priority. - * Convert the user priority to the in-kernel value. - */ - pri = sp->sched_priority; - if (pri != PRI_NONE && (pri < SCHED_PRI_MIN || pri > SCHED_PRI_MAX)) { - error = EINVAL; - goto error; - } - switch (sp->sched_class) { - case SCHED_OTHER: - if (pri == PRI_NONE) - pri = PRI_USER; - else - pri += PRI_USER; - break; - case SCHED_RR: - case SCHED_FIFO: - if (pri == PRI_NONE) - pri = PRI_USER_RT; - else - pri += PRI_USER_RT; - break; - case SCHED_NONE: - break; - default: - error = EINVAL; - goto error; + if (error) { + kmem_free(sp, sizeof(struct sched_param)); + return error; } + pri = sp->sched_priority; + policy = sp->sched_class; + kmem_free(sp, sizeof(struct sched_param)); - /* Find the process */ - pid = SCARG(uap, pid); - p = p_find(pid, PFIND_UNLOCK_FAIL); - if (p == NULL) { - error = ESRCH; - goto error; - } - mutex_enter(&p->p_smutex); - mutex_exit(&proclist_lock); + /* If no parameters specified, just return (this should not happen) */ + if (pri == PRI_NONE && policy == SCHED_NONE) + return 0; - /* Disallow modification of system processes */ - if (p->p_flag & PK_SYSTEM) { - mutex_exit(&p->p_smutex); - error = EACCES; - goto error; + /* Validate scheduling class */ + if (policy != SCHED_NONE && (policy < SCHED_OTHER || policy > SCHED_RR)) + return EINVAL; + + /* Validate priority */ + if (pri != PRI_NONE && (pri < SCHED_PRI_MIN || pri > SCHED_PRI_MAX)) + return EINVAL; + + if (SCARG(uap, pid) != 0) { + /* Find the process */ + p = p_find(SCARG(uap, pid), PFIND_UNLOCK_FAIL); + if (p == NULL) + return ESRCH; + mutex_enter(&p->p_smutex); + mutex_exit(&proclist_lock); + /* Disallow modification of system processes */ + if (p->p_flag & PK_SYSTEM) { + mutex_exit(&p->p_smutex); + return EPERM; + } + } else { + /* Use the calling process */ + p = l->l_proc; + mutex_enter(&p->p_smutex); } /* Find the LWP(s) */ lcnt = 0; lid = SCARG(uap, lid); LIST_FOREACH(t, &p->p_lwps, l_sibling) { - bool chpri; + pri_t kpri; if (lid && lid != t->l_lid) continue; + KASSERT(pri != PRI_NONE || policy != SCHED_NONE); + lwp_lock(t); + + /* + * Note that, priority may need to be changed to get into + * the correct priority range of the new scheduling class. + */ + kpri = convert_pri(t, policy, pri); /* Set the scheduling class */ - lwp_lock(t); - if (sp->sched_class != SCHED_NONE) { - /* - * Priority must be changed to get into the correct - * priority range of the new scheduling class. - */ - chpri = (t->l_class != sp->sched_class); - t->l_class = sp->sched_class; - } else - chpri = false; + if (policy != SCHED_NONE) + t->l_class = policy; /* Change the priority */ - if (sp->sched_priority != PRI_NONE || chpri) - lwp_changepri(t, pri); + if (t->l_priority != kpri) + lwp_changepri(t, kpri); lwp_unlock(t); lcnt++; } mutex_exit(&p->p_smutex); - if (lcnt == 0) - error = ESRCH; -error: - kmem_free(sp, sizeof(struct sched_param)); - return error; + return (lcnt == 0) ? ESRCH : error; } /* @@ -179,12 +208,26 @@ sys__sched_getparam(struct lwp *l, const struct sys__sched_getparam_args *uap, } */ struct sched_param *sp; struct lwp *t; + lwpid_t lid; int error; sp = kmem_zalloc(sizeof(struct sched_param), KM_SLEEP); - /* Locks the LWP */ - t = lwp_find2(SCARG(uap, pid), SCARG(uap, lid)); + /* If not specified, use the first LWP */ + lid = SCARG(uap, lid) == 0 ? 1 : SCARG(uap, lid); + + if (SCARG(uap, pid) != 0) { + /* Locks the LWP */ + t = lwp_find2(SCARG(uap, pid), lid); + } else { + struct proc *p = l->l_proc; + /* Use the calling process */ + mutex_enter(&p->p_smutex); + t = lwp_find(p, lid); + if (t != NULL) + lwp_lock(t); + mutex_exit(&p->p_smutex); + } if (t == NULL) { kmem_free(sp, sizeof(struct sched_param)); return ESRCH; @@ -231,7 +274,7 @@ sys__sched_setaffinity(struct lwp *l, /* Available only for super-user */ if (kauth_authorize_generic(l->l_cred, KAUTH_GENERIC_ISSUSER, NULL)) - return EACCES; + return EPERM; if (SCARG(uap, size) <= 0) return EINVAL; @@ -253,19 +296,25 @@ sys__sched_setaffinity(struct lwp *l, cpuset = NULL; } - /* Find the process */ - p = p_find(SCARG(uap, pid), PFIND_UNLOCK_FAIL); - if (p == NULL) { - error = ESRCH; - goto error; + if (SCARG(uap, pid) != 0) { + /* Find the process */ + p = p_find(SCARG(uap, pid), PFIND_UNLOCK_FAIL); + if (p == NULL) { + error = ESRCH; + goto error; + } + mutex_enter(&p->p_smutex); + mutex_exit(&proclist_lock); + } else { + /* Use the calling process */ + p = l->l_proc; + mutex_enter(&p->p_smutex); } - mutex_enter(&p->p_smutex); - mutex_exit(&proclist_lock); /* Disallow modification of system processes */ if (p->p_flag & PK_SYSTEM) { mutex_exit(&p->p_smutex); - error = EACCES; + error = EPERM; goto error; } @@ -313,6 +362,7 @@ sys__sched_getaffinity(struct lwp *l, } */ struct lwp *t; void *cpuset; + lwpid_t lid; int error; if (SCARG(uap, size) <= 0) @@ -320,8 +370,21 @@ sys__sched_getaffinity(struct lwp *l, cpuset = kmem_zalloc(sizeof(cpuset_t), KM_SLEEP); - /* Locks the LWP */ - t = lwp_find2(SCARG(uap, pid), SCARG(uap, lid)); + /* If not specified, use the first LWP */ + lid = SCARG(uap, lid) == 0 ? 1 : SCARG(uap, lid); + + if (SCARG(uap, pid) != 0) { + /* Locks the LWP */ + t = lwp_find2(SCARG(uap, pid), lid); + } else { + struct proc *p = l->l_proc; + /* Use the calling process */ + mutex_enter(&p->p_smutex); + t = lwp_find(p, lid); + if (t != NULL) + lwp_lock(t); + mutex_exit(&p->p_smutex); + } if (t == NULL) { kmem_free(cpuset, sizeof(cpuset_t)); return ESRCH; diff --git a/sys/sys/lwp.h b/sys/sys/lwp.h index ea9bceff97f..1c367310754 100644 --- a/sys/sys/lwp.h +++ b/sys/sys/lwp.h @@ -1,4 +1,4 @@ -/* $NetBSD: lwp.h,v 1.77 2008/01/15 03:37:12 rmind Exp $ */ +/* $NetBSD: lwp.h,v 1.78 2008/01/26 17:55:29 rmind Exp $ */ /*- * Copyright (c) 2001, 2006, 2007 The NetBSD Foundation, Inc. @@ -46,6 +46,7 @@ #include <sys/condvar.h> #include <sys/pset.h> #include <sys/signalvar.h> +#include <sys/sched.h> #include <sys/specificdata.h> #include <sys/syncobj.h> diff --git a/sys/sys/pset.h b/sys/sys/pset.h index 7f07b147187..f54349157bb 100644 --- a/sys/sys/pset.h +++ b/sys/sys/pset.h @@ -1,4 +1,4 @@ -/* $NetBSD: pset.h,v 1.1 2008/01/15 03:41:50 rmind Exp $ */ +/* $NetBSD: pset.h,v 1.2 2008/01/26 17:55:29 rmind Exp $ */ /* * Copyright (c) 2008, Mindaugas Rasiukevicius <rmind at NetBSD org> @@ -52,32 +52,6 @@ int pset_create(psetid_t *); int pset_destroy(psetid_t); __END_DECLS -/* Size of the CPU set bitmap */ -#define CPUSET_SHIFT 5 -#define CPUSET_MASK 31 -#if MAXCPUS > 32 -#define CPUSET_SIZE (MAXCPUS >> CPUSET_SHIFT) -#else -#define CPUSET_SIZE 1 -#endif - -/* Bitmap of the CPUs */ -typedef struct { - uint32_t bits[CPUSET_SIZE]; -} cpuset_t; - -#define CPU_ZERO(c) \ - (memset(c, 0, sizeof(cpuset_t))) - -#define CPU_ISSET(i, c) \ - ((1 << (i & CPUSET_MASK)) & (c)->bits[i >> CPUSET_SHIFT]) - -#define CPU_SET(i, c) \ - ((c)->bits[i >> CPUSET_SHIFT] |= 1 << (i & CPUSET_MASK)) - -#define CPU_CLR(i, c) \ - ((c)->bits[i >> CPUSET_SHIFT] &= ~(1 << (i & CPUSET_MASK))) - #ifdef _NETBSD_SOURCE int _pset_bind(idtype_t, id_t, id_t, psetid_t, psetid_t *); #endif /* _NETBSD_SOURCE */ diff --git a/sys/sys/sched.h b/sys/sys/sched.h index 9fff1196df5..4bd88fde069 100644 --- a/sys/sys/sched.h +++ b/sys/sys/sched.h @@ -1,4 +1,4 @@ -/* $NetBSD: sched.h,v 1.45 2008/01/15 03:37:12 rmind Exp $ */ +/* $NetBSD: sched.h,v 1.46 2008/01/26 17:55:29 rmind Exp $ */ /*- * Copyright (c) 1999, 2000, 2001, 2002, 2007 The NetBSD Foundation, Inc. @@ -101,6 +101,32 @@ struct sched_param { #if defined(_NETBSD_SOURCE) +/* XXX: Size of the CPU set bitmap */ +#define CPUSET_SHIFT 5 +#define CPUSET_MASK 31 +#if MAXCPUS > 32 +#define CPUSET_SIZE (MAXCPUS >> CPUSET_SHIFT) +#else +#define CPUSET_SIZE 1 +#endif + +/* Bitmap of the CPUs */ +typedef struct { + uint32_t bits[CPUSET_SIZE]; +} cpuset_t; + +#define CPU_ZERO(c) \ + (memset(c, 0, sizeof(cpuset_t))) + +#define CPU_ISSET(i, c) \ + ((1 << (i & CPUSET_MASK)) & (c)->bits[i >> CPUSET_SHIFT]) + +#define CPU_SET(i, c) \ + ((c)->bits[i >> CPUSET_SHIFT] |= 1 << (i & CPUSET_MASK)) + +#define CPU_CLR(i, c) \ + ((c)->bits[i >> CPUSET_SHIFT] &= ~(1 << (i & CPUSET_MASK))) + int _sched_getaffinity(pid_t, lwpid_t, size_t, void *); int _sched_setaffinity(pid_t, lwpid_t, size_t, void *); int _sched_getparam(pid_t, lwpid_t, struct sched_param *); |
