diff options
Diffstat (limited to 'lib/libthr/thread/thr_setschedparam.c')
-rw-r--r-- | lib/libthr/thread/thr_setschedparam.c | 153 |
1 files changed, 83 insertions, 70 deletions
diff --git a/lib/libthr/thread/thr_setschedparam.c b/lib/libthr/thread/thr_setschedparam.c index fff1abf..4f0a60d 100644 --- a/lib/libthr/thread/thr_setschedparam.c +++ b/lib/libthr/thread/thr_setschedparam.c @@ -31,93 +31,106 @@ * * $FreeBSD$ */ + #include <errno.h> #include <sys/param.h> #include <pthread.h> -#include <stdlib.h> + #include "thr_private.h" -__weak_reference(_pthread_getschedparam, pthread_getschedparam); __weak_reference(_pthread_setschedparam, pthread_setschedparam); int -_pthread_getschedparam(pthread_t pthread, int *policy, - struct sched_param *param) -{ - if (param == NULL || policy == NULL) - return (EINVAL); - if (_find_thread(pthread) == ESRCH) - return (ESRCH); - param->sched_priority = pthread->base_priority; - *policy = pthread->attr.sched_policy; - return(0); -} - -int _pthread_setschedparam(pthread_t pthread, int policy, const struct sched_param *param) { - struct pthread_mutex *mtx; - int old_prio; + struct pthread *curthread = _get_curthread(); + int in_syncq; + int in_readyq = 0; + int old_prio; + int ret = 0; - mtx = NULL; - old_prio = 0; - if ((param == NULL) || (policy < SCHED_FIFO) || (policy > SCHED_RR)) - return (EINVAL); - if ((param->sched_priority < PTHREAD_MIN_PRIORITY) || - (param->sched_priority > PTHREAD_MAX_PRIORITY)) - return (ENOTSUP); - if (_find_thread(pthread) != 0) - return (ESRCH); - - /* - * If the pthread is waiting on a mutex grab it now. Doing it now - * even though we do not need it immediately greatly simplifies the - * LOR avoidance code. - */ - do { - PTHREAD_LOCK(pthread); - if ((pthread->flags & PTHREAD_FLAGS_IN_MUTEXQ) != 0) { - mtx = pthread->data.mutex; - if (_spintrylock(&mtx->lock) == EBUSY) - PTHREAD_UNLOCK(pthread); - else - break; - } else { - mtx = NULL; - break; - } - } while (1); + if ((param == NULL) || (policy < SCHED_FIFO) || (policy > SCHED_RR)) { + /* Return an invalid argument error: */ + ret = EINVAL; + } else if ((param->sched_priority < THR_MIN_PRIORITY) || + (param->sched_priority > THR_MAX_PRIORITY)) { + /* Return an unsupported value error. */ + ret = ENOTSUP; - PTHREAD_ASSERT(pthread->active_priority >= pthread->inherited_priority, - "active priority cannot be less than inherited priority"); - old_prio = pthread->base_priority; - pthread->base_priority = param->sched_priority; - if (param->sched_priority <= pthread->active_priority) { + /* Find the thread in the list of active threads: */ + } else if ((ret = _thr_ref_add(curthread, pthread, /*include dead*/0)) + == 0) { /* - * Active priority is affected only if it was the - * base priority and the new base priority is lower. + * Lock the threads scheduling queue while we change + * its priority: */ - if (pthread->active_priority == old_prio && - pthread->active_priority != pthread->inherited_priority) { - pthread->active_priority = param->sched_priority; - readjust_priorities(pthread, mtx); + THR_THREAD_LOCK(curthread, pthread); + if (pthread->state == PS_DEAD) { + THR_THREAD_UNLOCK(curthread, pthread); + _thr_ref_delete(curthread, pthread); + return (ESRCH); } + in_syncq = pthread->sflags & THR_FLAGS_IN_SYNCQ; - } else { - /* - * New base priority is greater than active priority. This - * only affects threads that are holding priority inheritance - * mutexes this thread is waiting on and its position in the - * queue. - */ - pthread->active_priority = param->sched_priority; - readjust_priorities(pthread, mtx); + /* Set the scheduling policy: */ + pthread->attr.sched_policy = policy; + + if (param->sched_priority == + THR_BASE_PRIORITY(pthread->base_priority)) + /* + * There is nothing to do; unlock the threads + * scheduling queue. + */ + THR_THREAD_UNLOCK(curthread, pthread); + else { + /* + * Remove the thread from its current priority + * queue before any adjustments are made to its + * active priority: + */ + old_prio = pthread->active_priority; + /* if ((pthread->flags & THR_FLAGS_IN_RUNQ) != 0) */ { + in_readyq = 1; + /* THR_RUNQ_REMOVE(pthread); */ + } + + /* Set the thread base priority: */ + pthread->base_priority &= + (THR_SIGNAL_PRIORITY | THR_RT_PRIORITY); + pthread->base_priority = param->sched_priority; + /* Recalculate the active priority: */ + pthread->active_priority = MAX(pthread->base_priority, + pthread->inherited_priority); + + if (in_readyq) { + if ((pthread->priority_mutex_count > 0) && + (old_prio > pthread->active_priority)) { + /* + * POSIX states that if the priority is + * being lowered, the thread must be + * inserted at the head of the queue for + * its priority if it owns any priority + * protection or inheritence mutexes. + */ + /* THR_RUNQ_INSERT_HEAD(pthread); */ + } + else + /* THR_RUNQ_INSERT_TAIL(pthread)*/ ; + } + + /* Unlock the threads scheduling queue: */ + THR_THREAD_UNLOCK(curthread, pthread); + + /* + * Check for any mutex priority adjustments. This + * includes checking for a priority mutex on which + * this thread is waiting. + */ + _mutex_notify_priochange(curthread, pthread, in_syncq); + } + _thr_ref_delete(curthread, pthread); } - pthread->attr.sched_policy = policy; - PTHREAD_UNLOCK(pthread); - if (mtx != NULL) - _SPINUNLOCK(&mtx->lock); - return(0); + return (ret); } |