thr_setschedparam.c revision 174112
144963Sjb/*
244963Sjb * Copyright (c) 1998 Daniel Eischen <eischen@vigrid.com>.
344963Sjb * All rights reserved.
444963Sjb *
544963Sjb * Redistribution and use in source and binary forms, with or without
644963Sjb * modification, are permitted provided that the following conditions
744963Sjb * are met:
844963Sjb * 1. Redistributions of source code must retain the above copyright
944963Sjb *    notice, this list of conditions and the following disclaimer.
1044963Sjb * 2. Redistributions in binary form must reproduce the above copyright
1144963Sjb *    notice, this list of conditions and the following disclaimer in the
1244963Sjb *    documentation and/or other materials provided with the distribution.
1344963Sjb * 3. All advertising materials mentioning features or use of this software
1444963Sjb *    must display the following acknowledgement:
1544963Sjb *	This product includes software developed by Daniel Eischen.
1644963Sjb * 4. Neither the name of the author nor the names of any co-contributors
1744963Sjb *    may be used to endorse or promote products derived from this software
1844963Sjb *    without specific prior written permission.
1944963Sjb *
2044963Sjb * THIS SOFTWARE IS PROVIDED BY DANIEL EISCHEN AND CONTRIBUTORS ``AS IS'' AND
2144963Sjb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2244963Sjb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2344963Sjb * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2444963Sjb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2544963Sjb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2644963Sjb * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2744963Sjb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2844963Sjb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2944963Sjb * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3044963Sjb * SUCH DAMAGE.
3144963Sjb *
3250476Speter * $FreeBSD: head/lib/libkse/thread/thr_setschedparam.c 174112 2007-11-30 17:20:29Z deischen $
3344963Sjb */
34174112Sdeischen
35174112Sdeischen#include "namespace.h"
3644963Sjb#include <errno.h>
3744963Sjb#include <sys/param.h>
3844963Sjb#include <pthread.h>
39174112Sdeischen#include "un-namespace.h"
40103388Smini#include "thr_private.h"
4144963Sjb
42156611SdeischenLT10_COMPAT_PRIVATE(_pthread_setschedparam);
43156611SdeischenLT10_COMPAT_DEFAULT(pthread_setschedparam);
44156611Sdeischen
4575369Sdeischen__weak_reference(_pthread_setschedparam, pthread_setschedparam);
4671581Sdeischen
4744963Sjbint
4871581Sdeischen_pthread_setschedparam(pthread_t pthread, int policy,
4953812Salfred	const struct sched_param *param)
5044963Sjb{
51113658Sdeischen	struct pthread *curthread = _get_curthread();
52113658Sdeischen	int	in_syncq;
53113658Sdeischen	int	in_readyq = 0;
54113658Sdeischen	int	old_prio;
55113658Sdeischen	int	ret = 0;
5644963Sjb
5759892Sjasone	if ((param == NULL) || (policy < SCHED_FIFO) || (policy > SCHED_RR)) {
5844963Sjb		/* Return an invalid argument error: */
5944963Sjb		ret = EINVAL;
60113658Sdeischen	} else if ((param->sched_priority < THR_MIN_PRIORITY) ||
61113658Sdeischen	    (param->sched_priority > THR_MAX_PRIORITY)) {
6259892Sjasone		/* Return an unsupported value error. */
6359892Sjasone		ret = ENOTSUP;
6444963Sjb
6544963Sjb	/* Find the thread in the list of active threads: */
66113658Sdeischen	} else if ((ret = _thr_ref_add(curthread, pthread, /*include dead*/0))
67113658Sdeischen	    == 0) {
6844963Sjb		/*
69113658Sdeischen		 * Lock the threads scheduling queue while we change
70113658Sdeischen		 * its priority:
7144963Sjb		 */
72113658Sdeischen		THR_SCHED_LOCK(curthread, pthread);
73113661Sdeischen		if ((pthread->state == PS_DEAD) ||
74113661Sdeischen		    (pthread->state == PS_DEADLOCK) ||
75113661Sdeischen		    ((pthread->flags & THR_FLAGS_EXITING) != 0)) {
76113661Sdeischen			THR_SCHED_UNLOCK(curthread, pthread);
77113661Sdeischen			_thr_ref_delete(curthread, pthread);
78113661Sdeischen			return (ESRCH);
79113661Sdeischen		}
80113786Sdeischen		in_syncq = pthread->sflags & THR_FLAGS_IN_SYNCQ;
8144963Sjb
82113658Sdeischen		/* Set the scheduling policy: */
83113658Sdeischen		pthread->attr.sched_policy = policy;
84113658Sdeischen
85113658Sdeischen		if (param->sched_priority ==
86113658Sdeischen		    THR_BASE_PRIORITY(pthread->base_priority))
8744963Sjb			/*
88113658Sdeischen			 * There is nothing to do; unlock the threads
89113658Sdeischen			 * scheduling queue.
90113658Sdeischen			 */
91113658Sdeischen			THR_SCHED_UNLOCK(curthread, pthread);
92113658Sdeischen		else {
93113658Sdeischen			/*
9444963Sjb			 * Remove the thread from its current priority
9544963Sjb			 * queue before any adjustments are made to its
9644963Sjb			 * active priority:
9744963Sjb			 */
9855194Sdeischen			old_prio = pthread->active_priority;
99113658Sdeischen			if ((pthread->flags & THR_FLAGS_IN_RUNQ) != 0) {
10044963Sjb				in_readyq = 1;
101113658Sdeischen				THR_RUNQ_REMOVE(pthread);
10244963Sjb			}
10344963Sjb
10444963Sjb			/* Set the thread base priority: */
10567097Sdeischen			pthread->base_priority &=
106113658Sdeischen			    (THR_SIGNAL_PRIORITY | THR_RT_PRIORITY);
10744963Sjb			pthread->base_priority = param->sched_priority;
10844963Sjb
10944963Sjb			/* Recalculate the active priority: */
11044963Sjb			pthread->active_priority = MAX(pthread->base_priority,
11144963Sjb			    pthread->inherited_priority);
11244963Sjb
11344963Sjb			if (in_readyq) {
11444963Sjb				if ((pthread->priority_mutex_count > 0) &&
11544963Sjb				    (old_prio > pthread->active_priority)) {
11644963Sjb					/*
11744963Sjb					 * POSIX states that if the priority is
11844963Sjb					 * being lowered, the thread must be
11944963Sjb					 * inserted at the head of the queue for
12044963Sjb					 * its priority if it owns any priority
12144963Sjb					 * protection or inheritence mutexes.
12244963Sjb					 */
123113658Sdeischen					THR_RUNQ_INSERT_HEAD(pthread);
12444963Sjb				}
12544963Sjb				else
126113658Sdeischen					THR_RUNQ_INSERT_TAIL(pthread);
12744963Sjb			}
12844963Sjb
129113658Sdeischen			/* Unlock the threads scheduling queue: */
130113658Sdeischen			THR_SCHED_UNLOCK(curthread, pthread);
131113658Sdeischen
13244963Sjb			/*
13344963Sjb			 * Check for any mutex priority adjustments.  This
13444963Sjb			 * includes checking for a priority mutex on which
13544963Sjb			 * this thread is waiting.
13644963Sjb			 */
137113658Sdeischen			_mutex_notify_priochange(curthread, pthread, in_syncq);
13844963Sjb		}
139113658Sdeischen		_thr_ref_delete(curthread, pthread);
14044963Sjb	}
141113658Sdeischen	return (ret);
14244963Sjb}
143