diff options
Diffstat (limited to 'lib/libthr/thread/thr_setschedparam.c')
-rw-r--r-- | lib/libthr/thread/thr_setschedparam.c | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/lib/libthr/thread/thr_setschedparam.c b/lib/libthr/thread/thr_setschedparam.c new file mode 100644 index 0000000..e90def4 --- /dev/null +++ b/lib/libthr/thread/thr_setschedparam.c @@ -0,0 +1,122 @@ +/* + * Copyright (c) 1998 Daniel Eischen <eischen@vigrid.com>. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Daniel Eischen. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY DANIEL EISCHEN AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $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; + + 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 { + _thread_critical_enter(pthread); + if (pthread->state == PS_MUTEX_WAIT) { + mtx = pthread->data.mutex; + if (_spintrylock(&mtx->lock) == EBUSY) + _thread_critical_exit(pthread); + else + break; + } else { + break; + } + } while (1); + + 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) { + /* + * Active priority is affected only if it was the + * base priority and the new base priority is lower. + */ + if (pthread->active_priority == old_prio && + pthread->active_priority != pthread->inherited_priority) { + pthread->active_priority = param->sched_priority; + readjust_priorities(pthread, mtx); + } + + } 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); + + } + pthread->attr.sched_policy = policy; + _thread_critical_exit(pthread); + if (mtx != NULL) + _SPINUNLOCK(&mtx->lock); + return(0); +} |