Index: thread/thr_attr.c
===================================================================
RCS file: /home/aggelos/imports/vcs/dcvs/src/lib/libthread_xu/thread/thr_attr.c,v
retrieving revision 1.7
diff -u -u -r1.7 thr_attr.c
--- thread/thr_attr.c	6 Apr 2006 13:03:09 -0000	1.7
+++ thread/thr_attr.c	27 Apr 2007 21:37:04 -0000
@@ -49,7 +49,6 @@
 struct pthread_attr _pthread_attr_default = {
 	.sched_policy = SCHED_OTHER,
 	.sched_inherit = 0,
-	.sched_interval = TIMESLICE_USEC,
 	.prio = THR_DEFAULT_PRIORITY,
 	.suspend = THR_CREATE_RUNNING,
 	.flags = 0,
Index: thread/thr_getschedparam.c
===================================================================
RCS file: /home/aggelos/imports/vcs/dcvs/src/lib/libthread_xu/thread/thr_getschedparam.c,v
retrieving revision 1.4
diff -u -u -r1.4 thr_getschedparam.c
--- thread/thr_getschedparam.c	6 Apr 2006 13:03:09 -0000	1.4
+++ thread/thr_getschedparam.c	28 Apr 2007 09:46:01 -0000
@@ -46,34 +46,30 @@
 	struct sched_param *param)
 {
 	struct pthread *curthread = tls_get_curthread();
-	int ret, tmp;
+	int ret;
 
-	if ((param == NULL) || (policy == NULL))
-		/* Return an invalid argument error: */
-		ret = EINVAL;
-	else if (pthread == curthread) {
+	if (policy == NULL || param == NULL)
+		return (EINVAL);
+
+	if (pthread == curthread) {
 		/*
 		 * Avoid searching the thread list when it is the current
 		 * thread.
 		 */
-		THR_THREAD_LOCK(curthread, curthread);
-		param->sched_priority =
-		    THR_BASE_PRIORITY(pthread->base_priority);
-		tmp = pthread->attr.sched_policy;
-		THR_THREAD_UNLOCK(curthread, curthread);
-		*policy = tmp;
+		THR_LOCK(curthread);
+		*policy = curthread->attr.sched_policy;
+		param->sched_priority = curthread->attr.prio;
+		THR_UNLOCK(curthread);
 		ret = 0;
 	}
 	/* Find the thread in the list of active threads. */
 	else if ((ret = _thr_ref_add(curthread, pthread, /*include dead*/0))
 	    == 0) {
 		THR_THREAD_LOCK(curthread, pthread);
-		param->sched_priority =
-		    THR_BASE_PRIORITY(pthread->base_priority);
-		tmp = pthread->attr.sched_policy;
+		*policy = pthread->attr.sched_policy;
+		param->sched_priority = pthread->attr.prio;
 		THR_THREAD_UNLOCK(curthread, pthread);
 		_thr_ref_delete(curthread, pthread);
-		*policy = tmp;
 	}
 	return (ret);
 }
Index: thread/thr_kern.c
===================================================================
RCS file: /home/aggelos/imports/vcs/dcvs/src/lib/libthread_xu/thread/thr_kern.c,v
retrieving revision 1.2
diff -u -u -r1.2 thr_kern.c
--- thread/thr_kern.c	13 Mar 2007 00:19:29 -0000	1.2
+++ thread/thr_kern.c	30 Apr 2007 11:17:45 -0000
@@ -29,6 +29,7 @@
 #include <sys/cdefs.h>
 #include <sys/types.h>
 #include <sys/signalvar.h>
+#include <sys/rtprio.h>
 #include <pthread.h>
 #include "thr_private.h"
 
@@ -103,3 +104,114 @@
 {
 	return (lwp_gettid());
 }
+
+/*
+ * We don't use the priority for SCHED_OTHER, but
+ * some programs may depend on getting an error when
+ * setting a priority that is out of the range returned
+ * by sched_get_priority_{min,max}. Not sure if this
+ * falls into implementation defined behavior or not.
+ */
+int
+_thr_set_sched_other_prio(struct pthread *pth, int prio)
+{
+	static int max, min, init_status;
+
+	/*
+	 * switch (init_status) {
+	 * case 0: need initialization
+	 * case 1: initialization successful
+	 * case 2: initialization failed. can't happen, but if
+	 * 	   it does, accept all and hope for the best.
+	 * 	   It's not like we use it anyway.
+	 */
+	if (!init_status) {
+		int tmp = errno;
+
+		errno = 0;
+		init_status = 1;
+		if (((min = sched_get_priority_min(SCHED_OTHER)) == -1) &&
+								(errno != 0))
+			init_status = 2;
+		if (((max = sched_get_priority_max(SCHED_OTHER)) == -1) &&
+								(errno != 0))
+			init_status = 2;
+		errno = tmp;
+	}
+	if ((init_status == 2) || ((prio >= min) && (prio <= max))) {
+		return 0;
+	}
+	errno = EINVAL;
+	return -1;
+}
+
+int
+_rtp_to_schedparam(const struct rtprio *rtp, int *policy,
+	struct sched_param *param)
+{
+	switch(rtp->type) {
+	case RTP_PRIO_REALTIME:
+		*policy = SCHED_RR;
+		param->sched_priority = RTP_PRIO_MAX - rtp->prio;
+		break;
+	case RTP_PRIO_FIFO:
+		*policy = SCHED_FIFO;
+		param->sched_priority = RTP_PRIO_MAX - rtp->prio;
+		break;
+	default:
+		*policy = SCHED_OTHER;
+		param->sched_priority = 0;
+		break;
+	}
+	return (0);
+}
+
+int
+_schedparam_to_rtp(int policy, const struct sched_param *param,
+	struct rtprio *rtp)
+{
+	switch(policy) {
+	case SCHED_RR:
+		rtp->type = RTP_PRIO_REALTIME;
+		rtp->prio = RTP_PRIO_MAX - param->sched_priority;
+		break;
+	case SCHED_FIFO:
+		rtp->type = RTP_PRIO_FIFO;
+		rtp->prio = RTP_PRIO_MAX - param->sched_priority;
+		break;
+	case SCHED_OTHER:
+	default:
+		rtp->type = RTP_PRIO_NORMAL;
+		rtp->prio = 0;
+		break;
+	}
+	return (0);
+}
+
+int
+_thr_getscheduler(lwpid_t lwpid, int *policy, struct sched_param *param)
+{
+	struct pthread *curthread = tls_get_curthread();
+	struct rtprio rtp;
+	int ret;
+
+	if (lwpid == curthread->tid)
+		lwpid = -1;
+	ret = lwp_rtprio(RTP_LOOKUP, 0, lwpid, &rtp);
+	if (ret == -1)
+		return (ret);
+	_rtp_to_schedparam(&rtp, policy, param);
+	return (0);
+}
+
+int
+_thr_setscheduler(lwpid_t lwpid, int policy, const struct sched_param *param)
+{
+	struct pthread *curthread = tls_get_curthread();
+	struct rtprio rtp;
+
+	if (lwpid == curthread->tid)
+		lwpid = -1;
+	_schedparam_to_rtp(policy, param, &rtp);
+	return (lwp_rtprio(RTP_SET, 0, lwpid, &rtp));
+}
Index: thread/thr_private.h
===================================================================
RCS file: /home/aggelos/imports/vcs/dcvs/src/lib/libthread_xu/thread/thr_private.h,v
retrieving revision 1.15
diff -u -u -r1.15 thr_private.h
--- thread/thr_private.h	13 Apr 2006 11:48:01 -0000	1.15
+++ thread/thr_private.h	30 Apr 2007 10:38:54 -0000
@@ -236,7 +236,6 @@
 struct pthread_attr {
 	int	sched_policy;
 	int	sched_inherit;
-	int	sched_interval;
 	int	prio;
 	int	suspend;
 #define	THR_STACK_USER		0x100	/* 0xFF reserved for <pthread.h> */
@@ -691,6 +690,9 @@
 void	_thr_report_death(struct pthread *curthread);
 void	_thread_bp_create(void);
 void	_thread_bp_death(void);
+int	_thr_getscheduler(lwpid_t, int *, struct sched_param *);
+int	_thr_setscheduler(lwpid_t, int, const struct sched_param *);
+int	_thr_set_sched_other_prio(struct pthread *, int);
 
 /* #include <sys/aio.h> */
 #ifdef _SYS_AIO_H_
Index: thread/thr_setschedparam.c
===================================================================
RCS file: /home/aggelos/imports/vcs/dcvs/src/lib/libthread_xu/thread/thr_setschedparam.c,v
retrieving revision 1.5
diff -u -u -r1.5 thr_setschedparam.c
--- thread/thr_setschedparam.c	6 Apr 2006 13:03:09 -0000	1.5
+++ thread/thr_setschedparam.c	30 Apr 2007 10:40:46 -0000
@@ -49,49 +49,47 @@
 	struct pthread *curthread = tls_get_curthread();
 	int	ret = 0;
 
-	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;
-
-	/* Find the thread in the list of active threads: */
+	if (pthread == curthread) {
+		THR_LOCK(curthread);
+		if (curthread->attr.sched_policy == policy &&
+		     curthread->attr.prio == param->sched_priority) {
+			THR_UNLOCK(curthread);
+			return (0);
+		}
+		if (policy == SCHED_OTHER) {
+			ret = _thr_set_sched_other_prio(curthread,
+						param->sched_priority);
+		} else {
+			ret = _thr_setscheduler(curthread->tid, policy, param);
+		}
+		if (ret == -1)
+			ret = errno;
+		else {
+			curthread->attr.sched_policy = policy;
+			curthread->attr.prio = param->sched_priority;
+		}
+		THR_UNLOCK(curthread);
 	} else if ((ret = _thr_ref_add(curthread, pthread, /*include dead*/0))
-	    == 0) {
-		/*
-		 * Lock the threads scheduling queue while we change
-		 * its priority:
-		 */
+		== 0) {
 		THR_THREAD_LOCK(curthread, pthread);
-		if (pthread->state == PS_DEAD) {
+		if (pthread->attr.sched_policy == policy &&
+		     pthread->attr.prio == param->sched_priority) {
 			THR_THREAD_UNLOCK(curthread, pthread);
-			_thr_ref_delete(curthread, pthread);
-			return (ESRCH);
+			return (0);
 		}
-
-		/* 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);
+		if (policy == SCHED_OTHER) {
+			ret = _thr_set_sched_other_prio(curthread,
+						param->sched_priority);
+		} else {
+			ret = _thr_setscheduler(curthread->tid, policy, param);
+		}
+		if (ret == -1)
+			ret = errno;
 		else {
-			/* Set the thread base priority: */
-			pthread->base_priority = param->sched_priority;
-
-			/* Recalculate the active priority: */
-			pthread->active_priority = MAX(pthread->base_priority,
-			    pthread->inherited_priority);
-
-			/* Unlock the threads scheduling queue: */
-			THR_THREAD_UNLOCK(curthread, pthread);
+			pthread->attr.sched_policy = policy;
+			pthread->attr.prio = param->sched_priority;
 		}
+		THR_THREAD_UNLOCK(curthread, pthread);
 		_thr_ref_delete(curthread, pthread);
 	}
 	return (ret);

