diff options
author | davidxu <davidxu@FreeBSD.org> | 2006-07-12 06:13:18 +0000 |
---|---|---|
committer | davidxu <davidxu@FreeBSD.org> | 2006-07-12 06:13:18 +0000 |
commit | ecacf536b0f70b9b9579910c7d6dd8b5a9608136 (patch) | |
tree | f3ebabe7f0c598fbcd24fc997f7310e276d3efb0 /lib | |
parent | 3117fa3da4d89744ddfe45c3ac759ab430bd2950 (diff) | |
download | FreeBSD-src-ecacf536b0f70b9b9579910c7d6dd8b5a9608136.zip FreeBSD-src-ecacf536b0f70b9b9579910c7d6dd8b5a9608136.tar.gz |
Use kernel facilities to support real-time scheduling.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libthr/thread/thr_attr.c | 12 | ||||
-rw-r--r-- | lib/libthr/thread/thr_create.c | 42 | ||||
-rw-r--r-- | lib/libthr/thread/thr_getschedparam.c | 43 | ||||
-rw-r--r-- | lib/libthr/thread/thr_init.c | 18 | ||||
-rw-r--r-- | lib/libthr/thread/thr_private.h | 30 | ||||
-rw-r--r-- | lib/libthr/thread/thr_setprio.c | 29 | ||||
-rw-r--r-- | lib/libthr/thread/thr_setschedparam.c | 53 |
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(¶m, 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, ¶m)) == 0) { - param.sched_priority = prio; - ret = _pthread_setschedparam(pthread, policy, ¶m); + param.sched_priority = prio; + if (pthread == curthread) { + THR_LOCK(curthread); + ret = sched_setparam((pid_t)curthread->tid, ¶m); + 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, ¶m); + 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); |