summaryrefslogtreecommitdiffstats
path: root/lib/libthr
diff options
context:
space:
mode:
authordavidxu <davidxu@FreeBSD.org>2006-07-12 06:13:18 +0000
committerdavidxu <davidxu@FreeBSD.org>2006-07-12 06:13:18 +0000
commitecacf536b0f70b9b9579910c7d6dd8b5a9608136 (patch)
treef3ebabe7f0c598fbcd24fc997f7310e276d3efb0 /lib/libthr
parent3117fa3da4d89744ddfe45c3ac759ab430bd2950 (diff)
downloadFreeBSD-src-ecacf536b0f70b9b9579910c7d6dd8b5a9608136.zip
FreeBSD-src-ecacf536b0f70b9b9579910c7d6dd8b5a9608136.tar.gz
Use kernel facilities to support real-time scheduling.
Diffstat (limited to 'lib/libthr')
-rw-r--r--lib/libthr/thread/thr_attr.c12
-rw-r--r--lib/libthr/thread/thr_create.c42
-rw-r--r--lib/libthr/thread/thr_getschedparam.c43
-rw-r--r--lib/libthr/thread/thr_init.c18
-rw-r--r--lib/libthr/thread/thr_private.h30
-rw-r--r--lib/libthr/thread/thr_setprio.c29
-rw-r--r--lib/libthr/thread/thr_setschedparam.c53
7 files changed, 103 insertions, 124 deletions
diff --git a/lib/libthr/thread/thr_attr.c b/lib/libthr/thread/thr_attr.c
index 24dd064..1400cc6 100644
--- a/lib/libthr/thread/thr_attr.c
+++ b/lib/libthr/thread/thr_attr.c
@@ -434,9 +434,17 @@ _pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *para
policy = (*attr)->sched_policy;
- if (param->sched_priority < _thr_priorities[policy-1].pri_min ||
- param->sched_priority > _thr_priorities[policy-1].pri_max)
+ if (policy == SCHED_FIFO || policy == SCHED_RR) {
+ if (param->sched_priority < _thr_priorities[policy-1].pri_min ||
+ param->sched_priority > _thr_priorities[policy-1].pri_max)
return (ENOTSUP);
+ } else {
+ /*
+ * Ignore it for SCHED_OTHER now, patches for glib ports
+ * are wrongly using M:N thread library's internal macro
+ * THR_MIN_PRIORITY and THR_MAX_PRIORITY.
+ */
+ }
(*attr)->prio = param->sched_priority;
diff --git a/lib/libthr/thread/thr_create.c b/lib/libthr/thread/thr_create.c
index bb5724a..e74278d 100644
--- a/lib/libthr/thread/thr_create.c
+++ b/lib/libthr/thread/thr_create.c
@@ -50,6 +50,7 @@ _pthread_create(pthread_t * thread, const pthread_attr_t * attr,
{
struct pthread *curthread, *new_thread;
struct thr_param param;
+ struct thr_sched_param sched_param;
int ret = 0, locked, create_suspended;
sigset_t set, oset;
@@ -105,30 +106,6 @@ _pthread_create(pthread_t * thread, const pthread_attr_t * attr,
new_thread->arg = arg;
new_thread->cancelflags = PTHREAD_CANCEL_ENABLE |
PTHREAD_CANCEL_DEFERRED;
- /*
- * Check if this thread is to inherit the scheduling
- * attributes from its parent:
- */
- if (new_thread->attr.sched_inherit == PTHREAD_INHERIT_SCHED) {
- /*
- * Copy the scheduling attributes. Lock the scheduling
- * lock to get consistent scheduling parameters.
- */
- THR_LOCK(curthread);
- new_thread->base_priority = curthread->base_priority;
- new_thread->attr.prio = curthread->base_priority;
- new_thread->attr.sched_policy = curthread->attr.sched_policy;
- THR_UNLOCK(curthread);
- } else {
- /*
- * Use just the thread priority, leaving the
- * other scheduling attributes as their
- * default values:
- */
- new_thread->base_priority = new_thread->attr.prio;
- }
- new_thread->active_priority = new_thread->base_priority;
-
/* Initialize the mutex queue: */
TAILQ_INIT(&new_thread->mutexq);
@@ -166,6 +143,13 @@ _pthread_create(pthread_t * thread, const pthread_attr_t * attr,
param.flags = 0;
if (new_thread->attr.flags & PTHREAD_SCOPE_SYSTEM)
param.flags |= THR_SYSTEM_SCOPE;
+ if (new_thread->attr.sched_inherit == PTHREAD_INHERIT_SCHED)
+ param.sched = NULL;
+ else {
+ param.sched = &sched_param;
+ sched_param.policy = new_thread->attr.sched_policy;
+ sched_param.param.sched_priority = new_thread->attr.prio;
+ }
/* Schedule the new thread. */
if (create_suspended) {
@@ -177,6 +161,15 @@ _pthread_create(pthread_t * thread, const pthread_attr_t * attr,
ret = thr_new(&param, sizeof(param));
+ if (ret != 0) {
+ ret = errno;
+ /*
+ * Translate EPROCLIM into well-known POSIX code EAGAIN.
+ */
+ if (ret == EPROCLIM)
+ ret = EAGAIN;
+ }
+
if (create_suspended)
__sys_sigprocmask(SIG_SETMASK, &oset, NULL);
@@ -196,7 +189,6 @@ _pthread_create(pthread_t * thread, const pthread_attr_t * attr,
_thr_ref_delete_unlocked(curthread, new_thread);
THREAD_LIST_UNLOCK(curthread);
(*thread) = 0;
- ret = EAGAIN;
} else if (locked) {
_thr_report_creation(curthread, new_thread);
THR_THREAD_UNLOCK(curthread, new_thread);
diff --git a/lib/libthr/thread/thr_getschedparam.c b/lib/libthr/thread/thr_getschedparam.c
index 31b3268..acd0235 100644
--- a/lib/libthr/thread/thr_getschedparam.c
+++ b/lib/libthr/thread/thr_getschedparam.c
@@ -46,32 +46,47 @@ _pthread_getschedparam(pthread_t pthread, int *policy,
struct sched_param *param)
{
struct pthread *curthread = _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 = pthread->base_priority;
- tmp = pthread->attr.sched_policy;
- THR_THREAD_UNLOCK(curthread, curthread);
- *policy = tmp;
- ret = 0;
+ THR_LOCK(curthread);
+
+ /*
+ * XXX Here we need two separated syscalls, atomic is only
+ * guaranteed in thread library, a new syscall is needed.
+ */
+
+ *policy = sched_getscheduler((pid_t)curthread->tid);
+ if (*policy == -1)
+ ret = errno;
+ else {
+ ret = sched_getparam((pid_t)curthread->tid, param);
+ if (ret == -1)
+ ret = errno;
+ }
+ THR_UNLOCK(curthread);
}
/* 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 = pthread->base_priority;
- tmp = pthread->attr.sched_policy;
+ *policy = sched_getscheduler((pid_t)pthread->tid);
+ if (*policy == -1)
+ ret = errno;
+ else {
+ ret = sched_getparam((pid_t)pthread->tid, param);
+ if (ret == -1)
+ ret = errno;
+ }
THR_THREAD_UNLOCK(curthread, pthread);
_thr_ref_delete(curthread, pthread);
- *policy = tmp;
}
return (ret);
}
diff --git a/lib/libthr/thread/thr_init.c b/lib/libthr/thread/thr_init.c
index 40365a0..99bcea3 100644
--- a/lib/libthr/thread/thr_init.c
+++ b/lib/libthr/thread/thr_init.c
@@ -40,6 +40,7 @@
#include <sys/sysctl.h>
#include <sys/ttycom.h>
#include <sys/mman.h>
+#include <sys/rtprio.h>
#include <errno.h>
#include <fcntl.h>
#include <paths.h>
@@ -67,14 +68,10 @@ int _thread_active_threads = 1;
atfork_head _thr_atfork_list = TAILQ_HEAD_INITIALIZER(_thr_atfork_list);
umtx_t _thr_atfork_lock;
-/*
- * XXX these values should be updated from kernel at startup,
- * but current they are same.
- */
struct pthread_prio _thr_priorities[3] = {
- {0, 31, 0}, /* FIF0 */
- {-20, 20, 0}, /* OTHER */
- {0, 31, 0} /* RR */
+ {RTP_PRIO_MIN, RTP_PRIO_MAX, 0}, /* FIFO */
+ {0, 0, 63}, /* OTHER */
+ {RTP_PRIO_MIN, RTP_PRIO_MAX, 0} /* RR */
};
struct pthread_attr _pthread_attr_default = {
@@ -156,8 +153,6 @@ STATIC_LIB_REQUIRE(_sendto);
STATIC_LIB_REQUIRE(_sigaction);
STATIC_LIB_REQUIRE(_sigprocmask);
STATIC_LIB_REQUIRE(_sigsuspend);
-STATIC_LIB_REQUIRE(_socket);
-STATIC_LIB_REQUIRE(_socketpair);
STATIC_LIB_REQUIRE(_thread_init_hack);
STATIC_LIB_REQUIRE(_wait4);
STATIC_LIB_REQUIRE(_write);
@@ -407,11 +402,6 @@ init_main_thread(struct pthread *thread)
thread->cancelflags = PTHREAD_CANCEL_ENABLE | PTHREAD_CANCEL_DEFERRED;
thr_set_name(thread->tid, "initial thread");
- /* Default the priority of the initial thread: */
- thread->base_priority = THR_DEF_PRIORITY;
- thread->active_priority = THR_DEF_PRIORITY;
- thread->inherited_priority = 0;
-
/* Initialize the mutex queue: */
TAILQ_INIT(&thread->mutexq);
diff --git a/lib/libthr/thread/thr_private.h b/lib/libthr/thread/thr_private.h
index 778f20b..29993ec 100644
--- a/lib/libthr/thread/thr_private.h
+++ b/lib/libthr/thread/thr_private.h
@@ -262,7 +262,7 @@ struct pthread_attr {
* Define priorities returned by kernel.
*/
#define THR_MIN_PRIORITY (_thr_priorities[SCHED_OTHER-1].pri_min)
-#define THR_MAX_PRIORITY (_thr_priorities[SCHED_OTHER-1].pri_min)
+#define THR_MAX_PRIORITY (_thr_priorities[SCHED_OTHER-1].pri_max)
#define THR_DEF_PRIORITY (_thr_priorities[SCHED_OTHER-1].pri_default)
#define THR_MIN_RR_PRIORITY (_thr_priorities[SCHED_RR-1].pri_min)
@@ -271,7 +271,7 @@ struct pthread_attr {
/* XXX The SCHED_FIFO should have same priority range as SCHED_RR */
#define THR_MIN_FIFO_PRIORITY (_thr_priorities[SCHED_FIFO_1].pri_min)
-#define THR_MAX_FIFO_PRIORITY (_thr_priorities[SCHED_FIFO-1].pri_min)
+#define THR_MAX_FIFO_PRIORITY (_thr_priorities[SCHED_FIFO-1].pri_max)
#define THR_DEF_FIFO_PRIORITY (_thr_priorities[SCHED_FIFO-1].pri_default)
struct pthread_prio {
@@ -413,32 +413,6 @@ struct pthread {
#define TLFLAGS_IN_GCLIST 0x0004 /* thread in gc list */
#define TLFLAGS_DETACHED 0x0008 /* thread is detached */
- /*
- * Base priority is the user setable and retrievable priority
- * of the thread. It is only affected by explicit calls to
- * set thread priority and upon thread creation via a thread
- * attribute or default priority.
- */
- char base_priority;
-
- /*
- * Inherited priority is the priority a thread inherits by
- * taking a priority inheritence or protection mutex. It
- * is not affected by base priority changes. Inherited
- * priority defaults to and remains 0 until a mutex is taken
- * that is being waited on by any other thread whose priority
- * is non-zero.
- */
- char inherited_priority;
-
- /*
- * Active priority is always the maximum of the threads base
- * priority and inherited priority. When there is a change
- * in either the base or inherited priority, the active
- * priority must be recalculated.
- */
- char active_priority;
-
/* Queue of currently owned simple type mutexes. */
TAILQ_HEAD(, pthread_mutex) mutexq;
diff --git a/lib/libthr/thread/thr_setprio.c b/lib/libthr/thread/thr_setprio.c
index bb9a9bf..51a283e 100644
--- a/lib/libthr/thread/thr_setprio.c
+++ b/lib/libthr/thread/thr_setprio.c
@@ -43,14 +43,29 @@ __weak_reference(_pthread_setprio, pthread_setprio);
int
_pthread_setprio(pthread_t pthread, int prio)
{
- int ret, policy;
- struct sched_param param;
+ struct pthread *curthread = _get_curthread();
+ struct sched_param param;
+ int ret;
- if ((ret = _pthread_getschedparam(pthread, &policy, &param)) == 0) {
- param.sched_priority = prio;
- ret = _pthread_setschedparam(pthread, policy, &param);
+ param.sched_priority = prio;
+ if (pthread == curthread) {
+ THR_LOCK(curthread);
+ ret = sched_setparam((pid_t)curthread->tid, &param);
+ if (ret == -1)
+ ret = errno;
+ else
+ curthread->attr.prio = prio;
+ THR_UNLOCK(curthread);
+ } else if ((ret = _thr_ref_add(curthread, pthread, /*include dead*/0))
+ == 0) {
+ THR_THREAD_LOCK(curthread, pthread);
+ ret = sched_setparam((pid_t)pthread->tid, &param);
+ if (ret == -1)
+ ret = errno;
+ else
+ pthread->attr.prio = prio;
+ THR_THREAD_UNLOCK(curthread, pthread);
+ _thr_ref_delete(curthread, pthread);
}
-
- /* Return the error status: */
return (ret);
}
diff --git a/lib/libthr/thread/thr_setschedparam.c b/lib/libthr/thread/thr_setschedparam.c
index eba5017..e04452f 100644
--- a/lib/libthr/thread/thr_setschedparam.c
+++ b/lib/libthr/thread/thr_setschedparam.c
@@ -50,45 +50,30 @@ int
_pthread_setschedparam(pthread_t pthread, int policy,
const struct sched_param *param)
{
- struct pthread *curthread = _get_curthread();
- int ret = 0;
+ struct pthread *curthread = _get_curthread();
+ int ret;
- if ((param == NULL) || (policy < SCHED_FIFO) || (policy > SCHED_RR)) {
- ret = EINVAL;
- } else if (param->sched_priority < _thr_priorities[policy-1].pri_min ||
- param->sched_priority > _thr_priorities[policy-1].pri_max) {
- ret = ENOTSUP;
+ if (pthread == curthread) {
+ THR_LOCK(curthread);
+ ret = sched_setscheduler((pid_t)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) {
- THR_THREAD_UNLOCK(curthread, pthread);
- _thr_ref_delete(curthread, pthread);
- return (ESRCH);
- }
-
- /* Set the scheduling policy: */
- pthread->attr.sched_policy = policy;
-
- if (param->sched_priority == pthread->base_priority)
- /*
- * There is nothing to do; unlock the threads
- * scheduling queue.
- */
- THR_THREAD_UNLOCK(curthread, pthread);
+ ret = sched_setscheduler((pid_t)pthread->tid, policy, param);
+ if (ret == -1)
+ ret = errno;
else {
- pthread->base_priority = param->sched_priority;
-
- /* Recalculate the active priority: */
- pthread->active_priority = MAX(pthread->base_priority,
- pthread->inherited_priority);
-
- 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);
OpenPOWER on IntegriCloud