summaryrefslogtreecommitdiffstats
path: root/lib/libthr/thread/thr_setschedparam.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libthr/thread/thr_setschedparam.c')
-rw-r--r--lib/libthr/thread/thr_setschedparam.c153
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);
}
OpenPOWER on IntegriCloud